Merge "Add boot@1.1 to VNDK"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index a84e793..4e06d80 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -614,6 +614,10 @@
 # Clean up old location of system_other.avbpubkey
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/security/avb/)
 
+# Clean up bufferhub files
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/hw/android.frameworks.bufferhub@1.0-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/android.frameworks.bufferhub@1.0-service.rc)
+
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/super.img)
 
 $(call add-clean-step, find $(PRODUCT_OUT) -type f -name "generated_*_image_info.txt" -print0 | xargs -0 rm -f)
@@ -635,6 +639,9 @@
 
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libc_malloc*)
 
+# Clean up old location of soft OMX plugins
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libstagefright_soft*)
+
 # Move odm build.prop to /odm/etc/.
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/odm/build.prop)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/odm/build.prop)
@@ -655,6 +662,22 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/product/generic*/*/product)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/product/generic*/*/system_ext)
 
+# Move GSI-specific files from /system to /system/system_ext
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/init.gsi.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/config/)
+
+# Move fuzz targets from /data/fuzz/* to /data/fuzz/<arch>/* for device, and
+# /fuzz/* to /fuzz/<arch>/* on host.
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/fuzz/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/data/fuzz/*)
+$(call add-clean-step, rm -rf $(HOST_OUT)/fuzz/*)
+$(call add-clean-step, rm -rf $(SOONG_OUT_DIR)/host/*/fuzz/*)
+
+# Change file layout of system_other
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system_other)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/apex)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 99b86ee..1b6c532 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -502,6 +502,7 @@
 	$(hide) echo ro.vendor.product.cpu.abilist64="$(TARGET_CPU_ABI_LIST_64_BIT)">>$@
 	$(hide) echo ro.product.board="$(TARGET_BOOTLOADER_BOARD_NAME)">>$@
 	$(hide) echo ro.board.platform="$(TARGET_BOARD_PLATFORM)">>$@
+	$(hide) echo ro.hwui.use_vulkan="$(TARGET_USES_VULKAN)">>$@
 ifdef TARGET_SCREEN_DENSITY
 	$(hide) echo ro.sf.lcd_density="$(TARGET_SCREEN_DENSITY)">>$@
 endif
@@ -596,16 +597,32 @@
 INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/build.prop
 ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET)
 
+ifdef TARGET_SYSTEM_EXT_PROP
+system_ext_prop_files := $(TARGET_SYSTEM_EXT_PROP)
+else
+system_ext_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/system_ext.prop)
+endif
+
 FINAL_SYSTEM_EXT_PROPERTIES += \
     $(call collapse-pairs, $(PRODUCT_SYSTEM_EXT_PROPERTIES))
 FINAL_SYSTEM_EXT_PROPERTIES := $(call uniq-pairs-by-first-component, \
     $(FINAL_SYSTEM_EXT_PROPERTIES),=)
 
-$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS)
+$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS) $(system_ext_prop_files)
 	@echo Target system_ext buildinfo: $@
 	@mkdir -p $(dir $@)
 	$(hide) echo > $@
 	$(hide) $(call generate-common-build-props,system_ext,$@)
+	$(hide) $(foreach file,$(system_ext_prop_files), \
+	    if [ -f "$(file)" ]; then \
+	        echo Target system_ext properties from: "$(file)"; \
+	        echo "" >> $@; \
+	        echo "#" >> $@; \
+	        echo "# from $(file)" >> $@; \
+	        echo "#" >> $@; \
+	        cat $(file) >> $@; \
+	        echo "# end of $(file)" >> $@; \
+	    fi;)
 	$(hide) echo "#" >> $@; \
 	        echo "# ADDITIONAL SYSTEM_EXT BUILD PROPERTIES" >> $@; \
 	        echo "#" >> $@;
@@ -710,12 +727,10 @@
 	(for MODULE in $$(PRIVATE_LOAD_MODULES); do basename $$$$MODULE >> $$@; done)
 endef
 
-# Until support for a vendor-boot/vendor-ramdisk is added, store vendor ramdisk
-# kernel modules on the generic ramdisk as a stopgap.
-ifneq ($(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),)
+ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
+  # If there is no vendor boot partition, store vendor ramdisk kernel modules in the
+  # boot ramdisk.
   BOARD_GENERIC_RAMDISK_KERNEL_MODULES += $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES)
-endif
-ifneq ($(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),)
   BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD += $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD)
 endif
 
@@ -726,13 +741,13 @@
   BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_GENERIC_RAMDISK_KERNEL_MODULES)
 endif
 
-ifdef BOARD_GENERIC_RAMDISK_KERNEL_MODULES
+ifneq ($(strip $(BOARD_GENERIC_RAMDISK_KERNEL_MODULES)),)
   ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
     BOARD_RECOVERY_KERNEL_MODULES += $(BOARD_GENERIC_RAMDISK_KERNEL_MODULES)
   endif
 endif
 
-ifdef BOARD_RECOVERY_KERNEL_MODULES
+ifneq ($(strip $(BOARD_RECOVERY_KERNEL_MODULES)),)
   ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
     ifdef BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD
       ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,ramdisk_modules),$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD),modules.load,$(TARGET_RECOVERY_ROOT_OUT)))
@@ -741,20 +756,27 @@
   ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery),$(BOARD_RECOVERY_KERNEL_MODULES_LOAD),modules.load.recovery))
 endif
 
+ifneq ($(strip $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES)),)
+  ifeq ($(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),)
+    BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES)
+  endif
+  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),$(TARGET_VENDOR_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),modules.load))
+endif
+
 ifneq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
-  ifdef BOARD_GENERIC_RAMDISK_KERNEL_MODULES
+  ifneq ($(strip $(BOARD_GENERIC_RAMDISK_KERNEL_MODULES)),)
     ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES),$(TARGET_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_ramdisk),$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD),modules.load))
   endif
 endif
 
-ifdef BOARD_VENDOR_KERNEL_MODULES
+ifneq ($(strip $(BOARD_VENDOR_KERNEL_MODULES)),)
   ifeq ($(BOARD_VENDOR_KERNEL_MODULES_LOAD),)
     BOARD_VENDOR_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_KERNEL_MODULES)
   endif
   ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor,$(call intermediates-dir-for,PACKAGING,depmod_vendor),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),modules.load))
 endif
 
-ifdef BOARD_ODM_KERNEL_MODULES
+ifneq ($(strip $(BOARD_ODM_KERNEL_MODULES)),)
   ifeq ($(BOARD_RECOVERY_KERNEL_MODULES_LOAD),)
     BOARD_ODM_KERNEL_MODULES_LOAD := $(BOARD_ODM_KERNEL_MODULES)
   endif
@@ -848,6 +870,10 @@
 $(call dist-for-goals,droidcore,$(WALL_WERROR))
 
 # -----------------------------------------------------------------
+# C/C++ flag information for modules
+$(call dist-for-goals,droidcore,$(SOONG_MODULES_CFLAG_ARTIFACTS))
+
+# -----------------------------------------------------------------
 # Modules missing profile files
 PGO_PROFILE_MISSING := $(PRODUCT_OUT)/pgo_profile_file_missing.txt
 $(PGO_PROFILE_MISSING):
@@ -1010,24 +1036,18 @@
 	$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
 	--kernel $(INSTALLED_KERNEL_TARGET)
 
-ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
-  INTERNAL_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
-endif
-
 ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
 INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
 endif
 
+ifndef BUILDING_VENDOR_BOOT_IMAGE
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+  INTERNAL_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
+endif
+endif
+
 INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
 
-ifdef BOARD_KERNEL_BASE
-  INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
-endif
-
-ifdef BOARD_KERNEL_PAGESIZE
-  INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
-endif
-
 ifeq ($(PRODUCT_SUPPORTS_VERITY),true)
 ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
 VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
@@ -1036,8 +1056,22 @@
 endif
 
 INTERNAL_KERNEL_CMDLINE := $(strip $(INTERNAL_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
+
+ifndef BUILDING_VENDOR_BOOT_IMAGE
+ifdef BOARD_KERNEL_BASE
+  INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
+endif
+ifdef BOARD_KERNEL_PAGESIZE
+  INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
+endif
 ifdef INTERNAL_KERNEL_CMDLINE
-INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
+  INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
+endif
+else
+# building vendor boot image, dtb/base/pagesize go there
+ifdef GENERIC_KERNEL_CMDLINE
+  INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(GENERIC_KERNEL_CMDLINE)"
+endif
 endif
 
 INTERNAL_MKBOOTIMG_VERSION_ARGS := \
@@ -1134,6 +1168,55 @@
 endif # TARGET_NO_KERNEL
 
 # -----------------------------------------------------------------
+# vendor boot image
+ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
+
+ifeq ($(PRODUCT_SUPPORTS_VERITY),true)
+  $(error vboot 1.0 does not support vendor_boot partition)
+endif
+
+INTERNAL_VENDOR_RAMDISK_FILES := $(filter $(TARGET_VENDOR_RAMDISK_OUT)/%, \
+    $(ALL_GENERATED_SOURCES) \
+    $(ALL_DEFAULT_INSTALLED_MODULES))
+
+INTERNAL_VENDOR_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor-boot)/vendor-ramdisk.cpio.gz
+$(INTERNAL_VENDOR_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_RAMDISK_FILES) | $(MINIGZIP)
+	$(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) | $(MINIGZIP) > $@
+
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+  INTERNAL_VENDOR_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
+endif
+ifdef BOARD_KERNEL_BASE
+  INTERNAL_VENDOR_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
+endif
+ifdef BOARD_KERNEL_PAGESIZE
+  INTERNAL_VENDOR_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
+endif
+ifdef INTERNAL_KERNEL_CMDLINE
+  INTERNAL_VENDOR_BOOTIMAGE_ARGS += --vendor_cmdline "$(INTERNAL_KERNEL_CMDLINE)"
+endif
+
+INSTALLED_VENDOR_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/vendor_boot.img
+$(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_VENDOR_RAMDISK_TARGET) $(INSTALLED_DTBIMAGE_TARGET)
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(INSTALLED_VENDOR_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_VENDOR_BOOTIMAGE_KEY_PATH)
+	$(call pretty,"Target vendor_boot image: $@")
+	$(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_RAMDISK_TARGET) --vendor_boot $@
+	$(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
+	$(AVBTOOL) add_hash_footer \
+           --image $@ \
+	   --partition_size $(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):
+	$(call pretty,"Target vendor_boot image: $@")
+	$(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_RAMDISK_TARGET) --vendor_boot $@
+	$(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
+endif
+endif # BUILDING_VENDOR_BOOT_IMAGE
+
+# -----------------------------------------------------------------
 # NOTICE files
 #
 # We are required to publish the licenses for all code under BSD, GPL and
@@ -1654,8 +1737,10 @@
 recovery_sepolicy := \
     $(TARGET_RECOVERY_ROOT_OUT)/sepolicy \
     $(TARGET_RECOVERY_ROOT_OUT)/plat_file_contexts \
-    $(TARGET_RECOVERY_ROOT_OUT)/vendor_file_contexts \
     $(TARGET_RECOVERY_ROOT_OUT)/plat_property_contexts \
+    $(TARGET_RECOVERY_ROOT_OUT)/system_ext_file_contexts \
+    $(TARGET_RECOVERY_ROOT_OUT)/system_ext_property_contexts \
+    $(TARGET_RECOVERY_ROOT_OUT)/vendor_file_contexts \
     $(TARGET_RECOVERY_ROOT_OUT)/vendor_property_contexts \
     $(TARGET_RECOVERY_ROOT_OUT)/odm_file_contexts \
     $(TARGET_RECOVERY_ROOT_OUT)/odm_property_contexts \
@@ -1839,7 +1924,8 @@
 ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_USES_RECOVERY_AS_BOOT) \
   $(BOARD_BUILD_SYSTEM_ROOT_IMAGE) $(BOARD_INCLUDE_RECOVERY_DTBO) $(BOARD_INCLUDE_RECOVERY_ACPIO)))
 # Named '.dat' so we don't attempt to use imgdiff for patching it.
-RECOVERY_RESOURCE_ZIP := $(TARGET_OUT)/etc/recovery-resource.dat
+RECOVERY_RESOURCE_ZIP := $(TARGET_OUT_VENDOR)/etc/recovery-resource.dat
+ALL_DEFAULT_INSTALLED_MODULES += $(RECOVERY_RESOURCE_ZIP)
 else
 RECOVERY_RESOURCE_ZIP :=
 endif
@@ -1893,11 +1979,16 @@
 	$(hide) cat $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET) >> $@
 	$(call append-recovery-ui-properties,$(PRIVATE_RECOVERY_UI_PROPERTIES),$@)
 
-INTERNAL_RECOVERYIMAGE_ARGS := \
-	$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
-	--kernel $(recovery_kernel) \
-	--ramdisk $(recovery_ramdisk)
-
+ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
+  INTERNAL_RECOVERYIMAGE_ARGS := \
+      --kernel $(recovery_kernel) --ramdisk $(recovery_ramdisk)
+ifdef GENERIC_KERNEL_CMDLINE
+  INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(GENERIC_KERNEL_CMDLINE)"
+endif
+else # INSTALLED_VENDOR_BOOTIMAGE_TARGET not defined
+  INTERNAL_RECOVERYIMAGE_ARGS := \
+      $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
+      --kernel $(recovery_kernel) --ramdisk $(recovery_ramdisk)
 # Assumes this has already been stripped
 ifdef INTERNAL_KERNEL_CMDLINE
   INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
@@ -1914,13 +2005,14 @@
 else
   INTERNAL_RECOVERYIMAGE_ARGS += --recovery_dtbo $(BOARD_PREBUILT_DTBOIMAGE)
 endif
-endif
+endif # BOARD_INCLUDE_RECOVERY_DTBO
 ifdef BOARD_INCLUDE_RECOVERY_ACPIO
   INTERNAL_RECOVERYIMAGE_ARGS += --recovery_acpio $(BOARD_RECOVERY_ACPIO)
 endif
 ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
   INTERNAL_RECOVERYIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
 endif
+endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET not defined
 
 # $(1): output file
 define build-recoveryimage-target
@@ -2062,6 +2154,7 @@
 $(error MTD device is no longer supported and thus BOARD_NAND_SPARE_SIZE is deprecated.)
 endif
 
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
 # -----------------------------------------------------------------
 # the debug ramdisk, which is the original ramdisk plus additional
 # files: force_debuggable, adb_debug.prop and userdebug sepolicy.
@@ -2158,41 +2251,116 @@
 # Using a test key to sign boot-debug.img to continue booting with the mismatched
 # public key, if the device is unlocked.
 ifneq ($(BOARD_AVB_BOOT_KEY_PATH),)
-BOARD_AVB_DEBUG_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
-$(INSTALLED_DEBUG_BOOTIMAGE_TARGET): PRIVATE_AVB_DEBUG_BOOT_SIGNING_ARGS := \
-  --algorithm SHA256_RSA2048 --key $(BOARD_AVB_DEBUG_BOOT_KEY_PATH)
-$(INSTALLED_DEBUG_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_DEBUG_BOOT_KEY_PATH)
+$(INSTALLED_DEBUG_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_BOOT_TEST_KEY_PATH)
 endif
 
+BOARD_AVB_BOOT_TEST_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
+INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS := --algorithm SHA256_RSA2048 --key $(BOARD_AVB_BOOT_TEST_KEY_PATH)
+# $(1): the bootimage to sign
+define test-key-sign-bootimage
+$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE)))
+$(AVBTOOL) add_hash_footer \
+  --image $(1) \
+  --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
+  --partition_name boot $(INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS) \
+  $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+$(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+endef
+
 # Depends on original boot.img and ramdisk-debug.img, to build the new boot-debug.img
 $(INSTALLED_DEBUG_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_DEBUG_RAMDISK_TARGET)
 	$(call pretty,"Target boot debug image: $@")
 	$(MKBOOTIMG) $(INTERNAL_DEBUG_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
-	$(if $(BOARD_AVB_BOOT_KEY_PATH),\
-	  $(call assert-max-image-size,$@,$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))); \
-	  $(AVBTOOL) add_hash_footer \
-	    --image $@ \
-	    --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
-	    --partition_name boot $(PRIVATE_AVB_DEBUG_BOOT_SIGNING_ARGS) \
-	    $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS), \
-	  $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE)))
+	$(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$@))
 
 .PHONY: bootimage_debug-nodeps
 bootimage_debug-nodeps: $(MKBOOTIMG)
 	echo "make $@: ignoring dependencies"
 	$(MKBOOTIMG) $(INTERNAL_DEBUG_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_DEBUG_BOOTIMAGE_TARGET)
-	$(if $(BOARD_AVB_BOOT_KEY_PATH),\
-	  $(call assert-max-image-size,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))); \
-	  $(AVBTOOL) add_hash_footer \
-	    --image $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) \
-	    --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
-	    --partition_name boot $(PRIVATE_AVB_DEBUG_BOOT_SIGNING_ARGS) \
-	    $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS), \
-	  $(call assert-max-image-size,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE)))
+	$(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET)))
 
 endif # TARGET_NO_KERNEL
 
 # -----------------------------------------------------------------
+# The test harness ramdisk, which is based off debug_ramdisk, plus a
+# few additional test-harness-specific properties in adb_debug.prop.
+
+ifdef BUILDING_RAMDISK_IMAGE
+BUILT_TEST_HARNESS_RAMDISK_TARGET := $(PRODUCT_OUT)/ramdisk-test-harness.img
+INSTALLED_TEST_HARNESS_RAMDISK_TARGET := $(BUILT_TEST_HARNESS_RAMDISK_TARGET)
+
+# rsync the content from ramdisk-debug.img to ramdisk-test-harness.img, then
+# appends a few test harness specific properties into the adb_debug.prop.
+TEST_HARNESS_RAMDISK_SYNC_DIR := $(PRODUCT_OUT)/debug_ramdisk
+TEST_HARNESS_RAMDISK_ROOT_DIR := $(PRODUCT_OUT)/test_harness_ramdisk
+
+# The following TARGET_TEST_HARNESS_RAMDISK_OUT will be $(PRODUCT_OUT)/test_harness_ramdisk/first_stage_ramdisk,
+# if BOARD_USES_RECOVERY_AS_BOOT is true. Otherwise, it will be $(PRODUCT_OUT)/test_harness_ramdisk.
+TEST_HARNESS_PROP_TARGET := $(TARGET_TEST_HARNESS_RAMDISK_OUT)/adb_debug.prop
+ADDITIONAL_TEST_HARNESS_PROPERTIES := ro.audio.silent=1
+ADDITIONAL_TEST_HARNESS_PROPERTIES += ro.test_harness=1
+
+# $(1): a list of key=value pairs for additional property assignments
+# $(2): the target .prop file to append the properties from $(1)
+define append-test-harness-props
+  echo "#" >> $(2); \
+  echo "# ADDITIONAL TEST HARNESS_PROPERTIES" >> $(2); \
+  echo "#" >> $(2);
+  $(foreach line,$(1), echo "$(line)" >> $(2);)
+endef
+
+$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET): $(INSTALLED_DEBUG_RAMDISK_TARGET)
+$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_TEST_HARNESS_RAMDISK_FILES) | $(MINIGZIP)
+	$(call pretty,"Target test harness ram disk: $@")
+	rsync -a $(TEST_HARNESS_RAMDISK_SYNC_DIR)/ $(TEST_HARNESS_RAMDISK_ROOT_DIR)
+	$(call append-test-harness-props,$(ADDITIONAL_TEST_HARNESS_PROPERTIES),$(TEST_HARNESS_PROP_TARGET))
+	$(MKBOOTFS) -d $(TARGET_OUT) $(TEST_HARNESS_RAMDISK_ROOT_DIR) | $(MINIGZIP) > $@
+
+.PHONY: ramdisk_test_harness-nodeps
+ramdisk_test_harness-nodeps: $(MKBOOTFS) | $(MINIGZIP)
+	echo "make $@: ignoring dependencies"
+	rsync -a $(TEST_HARNESS_RAMDISK_SYNC_DIR)/ $(TEST_HARNESS_RAMDISK_ROOT_DIR)
+	$(call append-test-harness-props,$(ADDITIONAL_TEST_HARNESS_PROPERTIES),$(TEST_HARNESS_PROP_TARGET))
+	$(MKBOOTFS) -d $(TARGET_OUT) $(TEST_HARNESS_RAMDISK_ROOT_DIR) | $(MINIGZIP) > $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
+
+endif # BUILDING_RAMDISK_IMAGE
+
+# -----------------------------------------------------------------
+# the boot-test-harness.img, which is the kernel plus ramdisk-test-harness.img
+#
+# Note: it's intentional to skip signing for boot-test-harness.img, because it
+# can only be used if the device is unlocked with verification error.
+ifneq ($(strip $(TARGET_NO_KERNEL)),true)
+
+INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot-test-harness.img
+
+# Replace ramdisk-debug.img in $(MKBOOTIMG) ARGS with ramdisk-test-harness.img to build boot-test-harness.img
+INTERNAL_TEST_HARNESS_BOOTIMAGE_ARGS := $(subst $(INSTALLED_DEBUG_RAMDISK_TARGET),$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET),$(INTERNAL_DEBUG_BOOTIMAGE_ARGS))
+
+# If boot.img is chained but boot-test-harness.img is not signed, libavb in bootloader
+# will fail to find valid AVB metadata from the end of /boot, thus stop booting.
+# Using a test key to sign boot-test-harness.img to continue booting with the mismatched
+# public key, if the device is unlocked.
+ifneq ($(BOARD_AVB_BOOT_KEY_PATH),)
+$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_BOOT_TEST_KEY_PATH)
+endif
+
+# Build the new boot-test-harness.img, based on boot-debug.img and ramdisk-test-harness.img.
+$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
+	$(call pretty,"Target boot test harness image: $@")
+	$(MKBOOTIMG) $(INTERNAL_TEST_HARNESS_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
+	$(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$@))
+
+.PHONY: bootimage_test_harness-nodeps
+bootimage_test_harness-nodeps: $(MKBOOTIMG)
+	echo "make $@: ignoring dependencies"
+	$(MKBOOTIMG) $(INTERNAL_TEST_HARNESS_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET)
+	$(if $(BOARD_AVB_BOOT_KEY_PATH),$(call test-key-sign-bootimage,$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET)))
+
+endif # TARGET_NO_KERNEL
+endif # BOARD_BUILD_SYSTEM_ROOT_IMAGE is not true
+
+# -----------------------------------------------------------------
 # system image
 #
 # Remove overridden packages from $(ALL_PDK_FUSION_FILES)
@@ -2203,8 +2371,7 @@
 INTERNAL_SYSTEMIMAGE_FILES := $(sort $(filter $(TARGET_OUT)/%, \
     $(ALL_GENERATED_SOURCES) \
     $(ALL_DEFAULT_INSTALLED_MODULES) \
-    $(PDK_FUSION_SYSIMG_FILES) \
-    $(RECOVERY_RESOURCE_ZIP)) \
+    $(PDK_FUSION_SYSIMG_FILES)) \
     $(PDK_FUSION_SYMLINK_STAMP))
 
 FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)
@@ -2698,12 +2865,19 @@
 # -- Kernel version and configurations.
 ifeq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),true)
 
+intermediates := $(call intermediates-dir-for,ETC,$(notdir $(BUILT_ASSEMBLED_VENDOR_MANIFEST)))
+BUILT_KERNEL_CONFIGS_FILE := $(intermediates)/kernel_configs.txt
+BUILT_KERNEL_VERSION_FILE := $(intermediates)/kernel_version.txt
+
 # BOARD_KERNEL_CONFIG_FILE and BOARD_KERNEL_VERSION can be used to override the values extracted
 # from INSTALLED_KERNEL_TARGET.
 ifdef BOARD_KERNEL_CONFIG_FILE
 ifdef BOARD_KERNEL_VERSION
-$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BOARD_KERNEL_CONFIG_FILE)
-$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $(BOARD_KERNEL_VERSION):$(BOARD_KERNEL_CONFIG_FILE)
+$(BUILT_KERNEL_CONFIGS_FILE): $(BOARD_KERNEL_CONFIG_FILE)
+	cp $< $@
+$(BUILT_KERNEL_VERSION_FILE):
+	echo $(BOARD_KERNEL_VERSION) > $@
+
 my_board_extracted_kernel := true
 endif # BOARD_KERNEL_VERSION
 endif # BOARD_KERNEL_CONFIG_FILE
@@ -2718,7 +2892,6 @@
     BOARD_KERNEL_VERSION manually; or (3) unsetting PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS \
     manually.)
 else
-intermediates := $(call intermediates-dir-for,ETC,$(notdir $(BUILT_ASSEMBLED_VENDOR_MANIFEST)))
 
 # Tools for decompression that is not in PATH.
 # Check $(EXTRACT_KERNEL) for decompression algorithms supported by the script.
@@ -2726,29 +2899,25 @@
 my_decompress_tools := \
     lz4:$(HOST_OUT_EXECUTABLES)/lz4 \
 
-my_kernel_configs := $(intermediates)/kernel_configs.txt
-my_kernel_version := $(intermediates)/kernel_version.txt
-$(my_kernel_configs): .KATI_IMPLICIT_OUTPUTS := $(my_kernel_version)
-$(my_kernel_configs): PRIVATE_KERNEL_VERSION_FILE := $(my_kernel_version)
-$(my_kernel_configs): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
-$(my_kernel_configs): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
-$(my_kernel_configs): $(EXTRACT_KERNEL) $(INSTALLED_KERNEL_TARGET)
+$(BUILT_KERNEL_CONFIGS_FILE): .KATI_IMPLICIT_OUTPUTS := $(BUILT_KERNEL_VERSION_FILE)
+$(BUILT_KERNEL_CONFIGS_FILE): PRIVATE_DECOMPRESS_TOOLS := $(my_decompress_tools)
+$(BUILT_KERNEL_CONFIGS_FILE): $(foreach pair,$(my_decompress_tools),$(call word-colon,2,$(pair)))
+$(BUILT_KERNEL_CONFIGS_FILE): $(EXTRACT_KERNEL) $(INSTALLED_KERNEL_TARGET)
 	$< --tools $(PRIVATE_DECOMPRESS_TOOLS) --input $(INSTALLED_KERNEL_TARGET) \
 	  --output-configs $@ \
-	  --output-version $(PRIVATE_KERNEL_VERSION_FILE)
-
-$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(my_kernel_configs) $(my_kernel_version)
-$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $$(cat $(my_kernel_version)):$(my_kernel_configs)
+	  --output-version $(BUILT_KERNEL_VERSION_FILE)
 
 intermediates :=
-my_kernel_configs :=
-my_kernel_version :=
 my_decompress_tools :=
 
 endif # my_board_extracted_kernel
 my_board_extracted_kernel :=
 
 endif # INSTALLED_KERNEL_TARGET
+
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST): $(BUILT_KERNEL_CONFIGS_FILE) $(BUILT_KERNEL_VERSION_FILE)
+$(BUILT_ASSEMBLED_VENDOR_MANIFEST): PRIVATE_FLAGS += --kernel $$(cat $(BUILT_KERNEL_VERSION_FILE)):$(BUILT_KERNEL_CONFIGS_FILE)
+
 endif # PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS
 
 $(BUILT_ASSEMBLED_VENDOR_MANIFEST):
@@ -3160,6 +3329,7 @@
 endif
 
 BOOT_FOOTER_ARGS := BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS
+VENDOR_BOOT_FOOTER_ARGS := BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS
 DTBO_FOOTER_ARGS := BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS
 SYSTEM_FOOTER_ARGS := BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS
 VENDOR_FOOTER_ARGS := BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS
@@ -3218,6 +3388,10 @@
 $(eval $(call check-and-set-avb-args,boot))
 endif
 
+ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
+$(eval $(call check-and-set-avb-args,vendor_boot))
+endif
+
 $(eval $(call check-and-set-avb-args,system))
 
 ifdef INSTALLED_VENDORIMAGE_TARGET
@@ -3293,6 +3467,9 @@
   $(if $(BOARD_AVB_BOOT_KEY_PATH),\
     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_BOOT_KEY_PATH) \
       --output $(1)/boot.avbpubkey)
+  $(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),\
+    $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_BOOT_KEY_PATH) \
+      --output $(1)/vendor_boot.avbpubkey)
   $(if $(BOARD_AVB_SYSTEM_KEY_PATH),\
     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_KEY_PATH) \
       --output $(1)/system.avbpubkey)
@@ -3380,6 +3557,7 @@
 $(INSTALLED_VBMETAIMAGE_TARGET): \
 	    $(AVBTOOL) \
 	    $(INSTALLED_BOOTIMAGE_TARGET) \
+	    $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
 	    $(INSTALLED_SYSTEMIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
 	    $(INSTALLED_PRODUCTIMAGE_TARGET) \
@@ -3598,7 +3776,7 @@
 ifeq ($(build_otatools_package),true)
 
 INTERNAL_OTATOOLS_MODULES := \
-  aapt \
+  aapt2 \
   add_img_to_target_files \
   append2simg \
   avbtool \
@@ -3614,6 +3792,7 @@
   care_map_generator \
   check_ota_package_signature \
   check_target_files_signatures \
+  check_target_files_vintf \
   checkvintf \
   delta_generator \
   e2fsck \
@@ -3635,7 +3814,6 @@
   mkbootfs \
   mkbootimg \
   mke2fs \
-  mke2fs.conf \
   mkf2fsuserimg.sh \
   mksquashfs \
   mksquashfsimage.sh \
@@ -3705,13 +3883,13 @@
 $(BUILT_OTATOOLS_PACKAGE): PRIVATE_OTATOOLS_PACKAGE_FILES := $(INTERNAL_OTATOOLS_PACKAGE_FILES)
 $(BUILT_OTATOOLS_PACKAGE): PRIVATE_OTATOOLS_RELEASETOOLS := $(INTERNAL_OTATOOLS_RELEASETOOLS)
 $(BUILT_OTATOOLS_PACKAGE): $(INTERNAL_OTATOOLS_PACKAGE_FILES) $(INTERNAL_OTATOOLS_RELEASETOOLS)
-$(BUILT_OTATOOLS_PACKAGE): $(SOONG_ZIP)
+$(BUILT_OTATOOLS_PACKAGE): $(SOONG_ZIP) $(ZIP2ZIP)
 	@echo "Package OTA tools: $@"
 	rm -rf $@ $(PRIVATE_ZIP_ROOT)
 	mkdir -p $(dir $@)
 	$(call copy-files-with-structure,$(PRIVATE_OTATOOLS_PACKAGE_FILES),$(HOST_OUT)/,$(PRIVATE_ZIP_ROOT))
 	$(call copy-files-with-structure,$(PRIVATE_OTATOOLS_RELEASETOOLS),build/make/tools/,$(PRIVATE_ZIP_ROOT))
-	cp $(SOONG_ZIP) $(PRIVATE_ZIP_ROOT)/bin/
+	cp $(SOONG_ZIP) $(ZIP2ZIP) $(PRIVATE_ZIP_ROOT)/bin/
 	$(SOONG_ZIP) -o $@ -C $(PRIVATE_ZIP_ROOT) -D $(PRIVATE_ZIP_ROOT)
 
 .PHONY: otatools-package
@@ -3746,6 +3924,10 @@
 ifeq ($(INSTALLED_BOOTIMAGE_TARGET),)
 	$(hide) echo "no_boot=true" >> $@
 endif
+ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
+	echo "vendor_boot=true" >> $@
+	echo "vendor_boot_size=$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE)" >> $@
+endif
 ifeq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
 	$(hide) echo "no_recovery=true" >> $@
 endif
@@ -3787,6 +3969,9 @@
 ifeq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
 	$(hide) echo "full_recovery_image=true" >> $@
 endif
+ifdef BOARD_USES_VENDORIMAGE
+	$(hide) echo "board_uses_vendorimage=true" >> $@
+endif
 ifeq ($(BOARD_AVB_ENABLE),true)
 	$(hide) echo "avb_enable=true" >> $@
 	$(hide) echo "avb_vbmeta_key_path=$(BOARD_AVB_KEY_PATH)" >> $@
@@ -3798,6 +3983,12 @@
 	$(hide) echo "avb_boot_algorithm=$(BOARD_AVB_BOOT_ALGORITHM)" >> $@
 	$(hide) echo "avb_boot_rollback_index_location=$(BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION)" >> $@
 endif # BOARD_AVB_BOOT_KEY_PATH
+	echo "avb_vendor_boot_add_hash_footer_args=$(BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS)" >> $@
+ifdef BOARD_AVB_VENDOR_BOOT_KEY_PATH
+	echo "avb_vendor_boot_key_path=$(BOARD_AVB_VENDOR_BOOT_KEY_PATH)" >> $@
+	echo "avb_vendor_boot_algorithm=$(BOARD_AVB_VENDOR_BOOT_ALGORITHM)" >> $@
+	echo "avb_vendor_boot_rollback_index_location=$(BOARD_AVB_VENDOR_BOOT_ROLLBACK_INDEX_LOCATION)" >> $@
+endif # BOARD_AVB_VENDOR_BOOT_KEY_PATH
 	$(hide) echo "avb_recovery_add_hash_footer_args=$(BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS)" >> $@
 ifdef BOARD_AVB_RECOVERY_KEY_PATH
 	$(hide) echo "avb_recovery_key_path=$(BOARD_AVB_RECOVERY_KEY_PATH)" >> $@
@@ -3846,6 +4037,13 @@
 endif # BOARD_AVB_ENABLE
 endif # BOARD_PREBUILT_DTBOIMAGE
 	$(call dump-dynamic-partitions-info,$@)
+	@# VINTF checks
+ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
+	$(hide) echo "vintf_enforce=true" >> $@
+endif
+ifdef ODM_MANIFEST_SKUS
+	$(hide) echo "vintf_odm_manifest_skus=$(ODM_MANIFEST_SKUS)" >> $@
+endif
 
 .PHONY: misc_info
 misc_info: $(INSTALLED_MISC_INFO_TARGET)
@@ -3913,6 +4111,18 @@
     $(BUILT_TARGET_FILES_PACKAGE): $(TARGET_OUT_OEM)/$(OSRELEASED_DIRECTORY)/product_version
     $(BUILT_TARGET_FILES_PACKAGE): $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)/system_version
   endif
+
+  # Not checking in board_config.mk, since AB_OTA_PARTITIONS may be updated in Android.mk (e.g. to
+  # additionally include radio or bootloader partitions).
+  ifeq ($(AB_OTA_PARTITIONS),)
+    $(error AB_OTA_PARTITIONS must be defined when using AB_OTA_UPDATER)
+  endif
+endif
+
+ifneq ($(AB_OTA_PARTITIONS),)
+  ifneq ($(AB_OTA_UPDATER),true)
+    $(error AB_OTA_UPDATER must be true when defining AB_OTA_PARTITIONS)
+  endif
 endif
 
 # Run fs_config while creating the target files package
@@ -3969,6 +4179,7 @@
 $(BUILT_TARGET_FILES_PACKAGE): \
 	    $(INSTALLED_RAMDISK_TARGET) \
 	    $(INSTALLED_BOOTIMAGE_TARGET) \
+	    $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
 	    $(INSTALLED_RADIOIMAGE_TARGET) \
 	    $(INSTALLED_RECOVERYIMAGE_TARGET) \
 	    $(INSTALLED_USERDATAIMAGE_TARGET) \
@@ -4005,6 +4216,8 @@
 	    $(BUILT_ASSEMBLED_VENDOR_MANIFEST) \
 	    $(BUILT_SYSTEM_MATRIX) \
 	    $(BUILT_VENDOR_MATRIX) \
+	    $(BUILT_KERNEL_CONFIGS_FILE) \
+	    $(BUILT_KERNEL_VERSION_FILE) \
 	    | $(ACP)
 	@echo "Package target files: $@"
 	$(call create-system-vendor-symlink)
@@ -4019,33 +4232,37 @@
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_RECOVERY_ROOT_OUT),$(zip_root)/$(PRIVATE_RECOVERY_OUT)/RAMDISK)
 ifdef INSTALLED_KERNEL_TARGET
-	$(hide) cp $(INSTALLED_KERNEL_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/kernel
+	cp $(INSTALLED_KERNEL_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/kernel
 endif
+ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
+	echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
+else # INSTALLED_VENDOR_BOOTIMAGE_TARGET not defined
 ifdef INSTALLED_2NDBOOTLOADER_TARGET
-	$(hide) cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
+	cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
 endif
 ifdef BOARD_INCLUDE_RECOVERY_DTBO
 ifdef BOARD_PREBUILT_RECOVERY_DTBOIMAGE
-	$(hide) cp $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_dtbo
+	cp $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_dtbo
 else
-	$(hide) cp $(BOARD_PREBUILT_DTBOIMAGE) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_dtbo
+	cp $(BOARD_PREBUILT_DTBOIMAGE) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_dtbo
 endif
-endif
+endif # BOARD_INCLUDE_RECOVERY_DTBO
 ifdef BOARD_INCLUDE_RECOVERY_ACPIO
-	$(hide) cp $(BOARD_RECOVERY_ACPIO) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_acpio
+	cp $(BOARD_RECOVERY_ACPIO) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_acpio
 endif
 ifdef INSTALLED_DTBIMAGE_TARGET
-	$(hide) cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/dtb
+	cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/dtb
 endif
 ifdef INTERNAL_KERNEL_CMDLINE
-	$(hide) echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
+	echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
 endif
 ifdef BOARD_KERNEL_BASE
-	$(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/base
+	echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/base
 endif
 ifdef BOARD_KERNEL_PAGESIZE
-	$(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/pagesize
+	echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/pagesize
 endif
+endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET not defined
 endif # INSTALLED_RECOVERYIMAGE_TARGET defined or BOARD_USES_RECOVERY_AS_BOOT is true
 	@# Components of the boot image
 	$(hide) mkdir -p $(zip_root)/BOOT
@@ -4061,25 +4278,42 @@
 ifdef INSTALLED_KERNEL_TARGET
 	$(hide) cp $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/kernel
 endif
+ifndef INSTALLED_VENDOR_BOOTIMAGE_TARGET
 ifdef INSTALLED_2NDBOOTLOADER_TARGET
-	$(hide) cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
+	cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
 endif
 ifdef INSTALLED_DTBIMAGE_TARGET
-	$(hide) cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/BOOT/dtb
+	cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/BOOT/dtb
 endif
-ifdef INTERNAL_KERNEL_CMDLINE
-	$(hide) echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
-endif
+	echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
 ifdef BOARD_KERNEL_BASE
-	$(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base
+	echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base
 endif
 ifdef BOARD_KERNEL_PAGESIZE
-	$(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/BOOT/pagesize
+	echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/BOOT/pagesize
 endif
-endif # BOARD_USES_RECOVERY_AS_BOOT
+else # INSTALLED_VENDOR_BOOTIMAGE_TARGET defined
+	echo "$(GENERIC_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
+endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET defined
+endif # BOARD_USES_RECOVERY_AS_BOOT not true
 	$(hide) $(foreach t,$(INSTALLED_RADIOIMAGE_TARGET),\
 	            mkdir -p $(zip_root)/RADIO; \
 	            cp $(t) $(zip_root)/RADIO/$(notdir $(t));)
+ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
+	mkdir -p $(zip_root)/VENDOR_BOOT
+	$(call package_files-copy-root, \
+	    $(TARGET_VENDOR_RAMDISK_OUT),$(zip_root)/VENDOR_BOOT/RAMDISK)
+ifdef INSTALLED_DTBIMAGE_TARGET
+	cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/VENDOR_BOOT/dtb
+endif
+ifdef BOARD_KERNEL_BASE
+	echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/VENDOR_BOOT/base
+endif
+ifdef BOARD_KERNEL_PAGESIZE
+	echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/VENDOR_BOOT/pagesize
+endif
+	echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/VENDOR_BOOT/vendor_cmdline
+endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET
 ifdef BUILDING_SYSTEM_IMAGE
 	@# Contents of the system image
 	$(hide) $(call package_files-copy-root, \
@@ -4156,10 +4390,8 @@
 	  $(zip_root)/META/$(notdir $(PRODUCT_ODM_BASE_FS_PATH))
 endif
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
-ifdef BUILDING_SYSTEM_IMAGE
 	$(hide) PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	    $(MAKE_RECOVERY_PATCH) $(zip_root) $(zip_root)
-endif # BUILDING_SYSTEM_IMAGE
 endif
 ifeq ($(AB_OTA_UPDATER),true)
 	@# When using the A/B updater, include the updater config files in the zip.
@@ -4232,6 +4464,9 @@
 	@# BOOT/RAMDISK exists and contains the ramdisk for recovery if using BOARD_USES_RECOVERY_AS_BOOT.
 	$(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt
 endif
+ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
+	$(call fs_config,$(zip_root)/VENDOR_BOOT/RAMDISK,) > $(zip_root)/META/vendor_boot_filesystem_config.txt
+endif
 ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
 	@# BOOT/RAMDISK also exists and contains the first stage ramdisk if not using BOARD_BUILD_SYSTEM_ROOT_IMAGE.
 	$(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt
@@ -4253,6 +4488,12 @@
 ifdef BUILT_VENDOR_MATRIX
 	$(hide) cp $(BUILT_VENDOR_MATRIX) $(zip_root)/META/vendor_matrix.xml
 endif
+ifdef BUILT_KERNEL_CONFIGS_FILE
+	$(hide) cp $(BUILT_KERNEL_CONFIGS_FILE) $(zip_root)/META/kernel_configs.txt
+endif
+ifdef BUILT_KERNEL_VERSION_FILE
+	$(hide) cp $(BUILT_KERNEL_VERSION_FILE) $(zip_root)/META/kernel_version.txt
+endif
 ifneq ($(BOARD_SUPER_PARTITION_GROUPS),)
 	$(hide) echo "super_partition_groups=$(BOARD_SUPER_PARTITION_GROUPS)" > $(zip_root)/META/dynamic_partitions_info.txt
 	@# Remove 'vendor' from the group partition list if the image is not available. This should only
@@ -4265,9 +4506,11 @@
 	    $(if $(_group_partition_list), \
 	        echo "$(group)_partition_list=$(_group_partition_list)" >> $(zip_root)/META/dynamic_partitions_info.txt;))
 endif # BOARD_SUPER_PARTITION_GROUPS
-	@# TODO(b/134525174): Remove `-r` after addressing the issue with recovery patch generation.
-	$(hide) PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \
-	    $(ADD_IMG_TO_TARGET_FILES) -a -r -v -p $(HOST_OUT) $(zip_root)
+ifeq ($(PRODUCT_VIRTUAL_AB_OTA),true)
+	echo "virtual_ab=true" >> $(zip_root)/META/dynamic_partitions_info.txt
+endif # PRODUCT_VIRTUAL_AB_OTA
+	PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \
+	    $(ADD_IMG_TO_TARGET_FILES) -a -v -p $(HOST_OUT) $(zip_root)
 ifeq ($(BUILD_QEMU_IMAGES),true)
 	$(hide) AVBTOOL=$(AVBTOOL) $(MK_VBMETA_BOOT_KERNEL_CMDLINE_SH) $(zip_root)/IMAGES/vbmeta.img \
 	    $(zip_root)/IMAGES/system.img $(zip_root)/IMAGES/VerifiedBootParams.textproto
@@ -4475,25 +4718,28 @@
 
 #------------------------------------------------------------------
 # A zip of Proguard obfuscation dictionary files.
-# Only for apps_only build.
 #
-ifdef TARGET_BUILD_APPS
 PROGUARD_DICT_ZIP := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict-$(FILE_NAME_TAG).zip
-# the dependency will be set up later in build/make/core/main.mk.
-$(PROGUARD_DICT_ZIP) :
+# For apps_only build we'll establish the dependency later in build/make/core/main.mk.
+ifndef TARGET_BUILD_APPS
+$(PROGUARD_DICT_ZIP): \
+    $(INSTALLED_SYSTEMIMAGE_TARGET) \
+    $(INSTALLED_RAMDISK_TARGET) \
+    $(INSTALLED_BOOTIMAGE_TARGET) \
+    $(INSTALLED_USERDATAIMAGE_TARGET) \
+    $(INSTALLED_VENDORIMAGE_TARGET) \
+    $(INSTALLED_PRODUCTIMAGE_TARGET) \
+    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
+    $(INSTALLED_ODMIMAGE_TARGET) \
+    $(updater_dep)
+endif
+$(PROGUARD_DICT_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,proguard)/filelist
+$(PROGUARD_DICT_ZIP): $(SOONG_ZIP)
 	@echo "Packaging Proguard obfuscation dictionary files."
-	$(hide) dict_files=`find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary`; \
-	    if [ -n "$$dict_files" ]; then \
-	      unobfuscated_jars=$${dict_files//proguard_dictionary/classes.jar}; \
-	      zip -qX $@ $$dict_files $$unobfuscated_jars; \
-	    else \
-	      touch $(dir $@)/zipdummy; \
-	      (cd $(dir $@) && zip -q $(notdir $@) zipdummy); \
-	      zip -qd $@ zipdummy; \
-	      rm $(dir $@)/zipdummy; \
-	    fi
-
-endif # TARGET_BUILD_APPS
+	mkdir -p $(dir $@) $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS $(dir $(PRIVATE_LIST_FILE))
+	find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary | \
+	    sed -e 's/\(.*\)\/proguard_dictionary/\0\n\1\/classes.jar/' > $(PRIVATE_LIST_FILE)
+	$(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(OUT_DIR)/.. -l $(PRIVATE_LIST_FILE)
 
 
 ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
@@ -4627,35 +4873,12 @@
 
 INTERNAL_UPDATE_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
 
-$(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(ZIP2ZIP)
-
-ifeq (true,$(BOARD_SUPER_IMAGE_IN_UPDATE_PACKAGE))
-$(INTERNAL_UPDATE_PACKAGE_TARGET): $(INTERNAL_SUPERIMAGE_DIST_TARGET)
-	@echo "Package: $@"
-	# Filter out super_empty and images in BOARD_SUPER_PARTITION_PARTITION_LIST.
-	# Filter out system_other for launch DAP devices because it is in super image.
-	# Include OTA/super_*.img for retrofit devices and super.img for non-retrofit
-	# devices.
-	$(hide) $(ZIP2ZIP) -i $(BUILT_TARGET_FILES_PACKAGE) -o $@ \
-	  -x IMAGES/super_empty.img \
-	  $(foreach partition,$(BOARD_SUPER_PARTITION_PARTITION_LIST), \
-	    -x IMAGES/$(partition).img) \
-	  $(if $(filter system, $(BOARD_SUPER_PARTITION_PARTITION_LIST)), \
-	    $(if $(filter true, $(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS)),, \
-	      -x IMAGES/system_other.img)) \
-	  $(if $(filter true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS)), \
-	    $(foreach device,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES), \
-	      OTA/super_$(device).img:super_$(device).img)) \
-	  IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto \
-	  OTA/android-info.txt:android-info.txt "IMAGES/*.img:."
-	$(if $(INTERNAL_SUPERIMAGE_DIST_TARGET), zip -q -j -u $@ $(INTERNAL_SUPERIMAGE_DIST_TARGET))
-else
-$(INTERNAL_UPDATE_PACKAGE_TARGET):
-	@echo "Package: $@"
-	$(hide) $(ZIP2ZIP) -i $(BUILT_TARGET_FILES_PACKAGE) -o $@ \
-	  IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto \
-	  OTA/android-info.txt:android-info.txt "IMAGES/*.img:."
-endif # BOARD_SUPER_IMAGE_IN_UPDATE_PACKAGE
+$(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(IMG_FROM_TARGET_FILES)
+	$(call pretty,"Package: $@")
+	PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$(dir $(ZIP2ZIP)):$$PATH \
+	    $(IMG_FROM_TARGET_FILES) \
+	        --additional IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto \
+	        $(BUILT_TARGET_FILES_PACKAGE) $@
 
 .PHONY: updatepackage
 updatepackage: $(INTERNAL_UPDATE_PACKAGE_TARGET)
@@ -4943,3 +5166,17 @@
 ifneq ($(sdk_repo_goal),)
 include $(TOPDIR)development/build/tools/sdk_repo.mk
 endif
+
+# -----------------------------------------------------------------
+# The rule to build all fuzz targets, and package them.
+# Note: The packages are created in Soong, and in a perfect world,
+# we'd be able to create the phony rule there. But, if we want to
+# have dist goals for the fuzz target, we need to have the PHONY
+# target defined in make. MakeVarsContext.DistForGoal doesn't take
+# into account that a PHONY rule create by Soong won't be available
+# during make, and such will fail with `writing to readonly
+# directory`, because kati will see 'fuzz' as being a file, not a
+# phony target.
+.PHONY: fuzz
+fuzz: $(SOONG_FUZZ_PACKAGING_ARCH_MODULES)
+$(call dist-for-goals,fuzz,$(SOONG_FUZZ_PACKAGING_ARCH_MODULES))
diff --git a/core/aux_config.mk b/core/aux_config.mk
index a508a2d..10d2536 100644
--- a/core/aux_config.mk
+++ b/core/aux_config.mk
@@ -32,7 +32,7 @@
 
 # setup AUX globals
 AUX_SHLIB_SUFFIX := .so
-AUX_GLOBAL_ARFLAGS := cqsD
+AUX_GLOBAL_ARFLAGS := crsPD
 AUX_STATIC_LIB_SUFFIX := .a
 
 # Load ever-lasting "indexed" version of AUX variant environment; it is treated as READ-ONLY from this
@@ -149,6 +149,8 @@
 variant_sfx :=_aux_variant_config.mk
 os_sfx :=_aux_os_config.mk
 
+ifdef AUX_OS_VARIANT_LIST
+
 config_roots := $(wildcard device vendor)
 all_configs :=
 ifdef config_roots
@@ -180,4 +182,6 @@
 )
 endif
 
+endif # AUX_OS_VARIANT_LIST
+
 INSTALLED_AUX_TARGETS :=
diff --git a/core/base_rules.mk b/core/base_rules.mk
index e3f8a70..32c5807 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -115,12 +115,6 @@
 ifeq ($(my_host_cross),true)
   my_module_tags :=
 endif
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-ifdef LOCAL_2ND_ARCH_VAR_PREFIX
-# Don't pull in modules by tags if this is for translation TARGET_2ND_ARCH.
-  my_module_tags :=
-endif
-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
@@ -204,17 +198,7 @@
 my_32_64_bit_suffix := $(if $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)IS_64_BIT),64,32)
 
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-# When in TARGET_TRANSLATE_2ND_ARCH both TARGET_ARCH and TARGET_2ND_ARCH are 32-bit,
-# to avoid path conflict we force using LOCAL_MODULE_PATH_64 for the first arch.
-ifdef LOCAL_2ND_ARCH_VAR_PREFIX
-my_multilib_module_path := $(LOCAL_MODULE_PATH_32)
-else  # ! LOCAL_2ND_ARCH_VAR_PREFIX
-my_multilib_module_path := $(LOCAL_MODULE_PATH_64)
-endif  # ! LOCAL_2ND_ARCH_VAR_PREFIX
-else  # ! TARGET_TRANSLATE_2ND_ARCH
 my_multilib_module_path := $(strip $(LOCAL_MODULE_PATH_$(my_32_64_bit_suffix)))
-endif # ! TARGET_TRANSLATE_2ND_ARCH
 ifdef my_multilib_module_path
 my_module_path := $(my_multilib_module_path)
 else
@@ -568,7 +552,7 @@
 # Source to relative dst file paths for reuse in LOCAL_COMPATIBILITY_SUITE.
 my_test_data_file_pairs :=
 
-ifneq ($(filter NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+ifneq ($(strip $(filter NATIVE_TESTS,$(LOCAL_MODULE_CLASS)) $(LOCAL_IS_FUZZ_TARGET)),)
 ifneq ($(strip $(LOCAL_TEST_DATA)),)
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 
@@ -716,6 +700,18 @@
   endif
 endif
 
+
+ifeq ($(use_testcase_folder),true)
+ifneq ($(my_test_data_file_pairs),)
+$(foreach pair, $(my_test_data_file_pairs), \
+  $(eval parts := $(subst :,$(space),$(pair))) \
+  $(eval src_path := $(word 1,$(parts))) \
+  $(eval file := $(word 2,$(parts))) \
+  $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+    $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
+      $(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data))))))
+endif
+else
 ifneq ($(my_test_data_file_pairs),)
 $(foreach pair, $(my_test_data_file_pairs), \
   $(eval parts := $(subst :,$(space),$(pair))) \
@@ -725,6 +721,7 @@
     $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
       $(src_path):$(call append-path,$(dir),$(file))))))
 endif
+endif
 
 
 
@@ -748,7 +745,7 @@
 ## Register with ALL_MODULES
 ###########################################################
 
-ifeq ($(filter $(my_register_name),$(ALL_MODULES)),)
+ifndef ALL_MODULES.$(my_register_name).PATH
     # These keys are no longer used, they've been replaced by keys that specify
     # target/host/host_cross (REQUIRED_FROM_TARGET / REQUIRED_FROM_HOST) and similar.
     #
@@ -878,18 +875,23 @@
 ##########################################################
 # Track module-level dependencies.
 # Use $(LOCAL_MODULE) instead of $(my_register_name) to ignore module's bitness.
+ifneq (,$(filter deps-license,$(MAKECMDGOALS)))
 ALL_DEPS.MODULES := $(ALL_DEPS.MODULES) $(LOCAL_MODULE)
 ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(sort \
   $(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) \
   $(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))
 
 ALL_DEPS.$(LOCAL_MODULE).LICENSE := $(sort $(ALL_DEPS.$(LOCAL_MODULE).LICENSE) $(license_files))
+endif
 
 ###########################################################
 ## Take care of my_module_tags
@@ -899,14 +901,14 @@
 ALL_MODULE_TAGS := $(sort $(ALL_MODULE_TAGS) $(my_module_tags))
 
 # Add this module name to the tag list of each specified tag.
-$(foreach tag,$(my_module_tags),\
+$(foreach tag,$(filter-out optional,$(my_module_tags)),\
     $(eval ALL_MODULE_NAME_TAGS.$(tag) := $$(ALL_MODULE_NAME_TAGS.$(tag)) $(my_register_name)))
 
 ###########################################################
 ## umbrella targets used to verify builds
 ###########################################################
 j_or_n :=
-ifneq (,$(filter EXECUTABLES SHARED_LIBRARIES STATIC_LIBRARIES HEADER_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)))
+ifneq (,$(filter EXECUTABLES SHARED_LIBRARIES STATIC_LIBRARIES HEADER_LIBRARIES NATIVE_TESTS RLIB_LIBRARIES DYLIB_LIBRARIES PROC_MACRO_LIBRARIES,$(LOCAL_MODULE_CLASS)))
 j_or_n := native
 else
 ifneq (,$(filter JAVA_LIBRARIES APPS,$(LOCAL_MODULE_CLASS)))
diff --git a/core/board_config.mk b/core/board_config.mk
index a6aef87..9032aaf 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -86,6 +86,7 @@
 
 _build_broken_var_list := \
   BUILD_BROKEN_DUP_RULES \
+  BUILD_BROKEN_PREBUILT_ELF_FILES \
   BUILD_BROKEN_USES_NETWORK \
 
 _build_broken_var_list += \
@@ -262,6 +263,7 @@
 # Now we can substitute with the real value of TARGET_COPY_OUT_DEBUG_RAMDISK
 ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
 TARGET_COPY_OUT_DEBUG_RAMDISK := debug_ramdisk/first_stage_ramdisk
+TARGET_COPY_OUT_TEST_HARNESS_RAMDISK := test_harness_ramdisk/first_stage_ramdisk
 endif
 
 ###########################################
@@ -336,6 +338,20 @@
 endif
 .KATI_READONLY := BUILDING_RECOVERY_IMAGE
 
+# Are we building a vendor boot image
+BUILDING_VENDOR_BOOT_IMAGE :=
+ifdef BOARD_BOOT_HEADER_VERSION
+  ifneq ($(call math_gt_or_eq,$(BOARD_BOOT_HEADER_VERSION),3),)
+    BUILDING_VENDOR_BOOT_IMAGE := true
+    ifdef BUILDING_RECOVERY_IMAGE
+      ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+        $(error Boot header version >=3 requires recovery as boot)
+      endif
+    endif
+  endif
+endif
+.KATI_READONLY := BUILDING_VENDOR_BOOT_IMAGE
+
 # Are we building a ramdisk image
 BUILDING_RAMDISK_IMAGE := true
 ifeq ($(PRODUCT_BUILD_RAMDISK_IMAGE),)
@@ -569,8 +585,16 @@
 # APEXes are by default flattened, i.e. non-updatable.
 # It can be unflattened (and updatable) by inheriting from
 # updatable_apex.mk
-ifeq (,$(TARGET_FLATTEN_APEX))
-TARGET_FLATTEN_APEX := true
+#
+# APEX flattening can also be forcibly enabled (resp. disabled) by
+# setting OVERRIDE_TARGET_FLATTEN_APEX to true (resp. false), e.g. by
+# setting the OVERRIDE_TARGET_FLATTEN_APEX environment variable.
+ifdef OVERRIDE_TARGET_FLATTEN_APEX
+  TARGET_FLATTEN_APEX := $(OVERRIDE_TARGET_FLATTEN_APEX)
+else
+  ifeq (,$(TARGET_FLATTEN_APEX))
+    TARGET_FLATTEN_APEX := true
+  endif
 endif
 
 ifeq (,$(TARGET_BUILD_APPS))
diff --git a/core/build_id.mk b/core/build_id.mk
index bac2f48..2329288 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -18,4 +18,4 @@
 # (like "CRB01").  It must be a single word, and is
 # capitalized by convention.
 
-BUILD_ID=PI
+BUILD_ID=QT
diff --git a/core/cc_prebuilt_internal.mk b/core/cc_prebuilt_internal.mk
index a8930d5..6313019 100644
--- a/core/cc_prebuilt_internal.mk
+++ b/core/cc_prebuilt_internal.mk
@@ -180,15 +180,8 @@
 endif
 endif
 
-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),$(built_module)))
-else ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),)
-$(built_module) : $(my_prebuilt_src_file)
-	$(transform-prebuilt-to-target-strip-comments)
-else
 $(built_module) : $(my_prebuilt_src_file)
 	$(transform-prebuilt-to-target)
-endif
 ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
 	$(hide) chmod +x $@
 endif
diff --git a/core/check_elf_file.mk b/core/check_elf_file.mk
index 0faaadd..7a5de67 100644
--- a/core/check_elf_file.mk
+++ b/core/check_elf_file.mk
@@ -38,12 +38,18 @@
 	    $<
 	$(hide) touch $@
 
-ifneq ($(PRODUCT_CHECK_ELF_FILES)$(CHECK_ELF_FILES),)
 ifneq ($(strip $(LOCAL_CHECK_ELF_FILES)),false)
+ifneq ($(strip $(BUILD_BROKEN_PREBUILT_ELF_FILES)),true)
+# TODO(b/141176116): Remove the PRODUCT_CHECK_ELF_FILES condition below and
+# cover `make droid` targets after everything goes well with `make checkbuild`
+# targets.
+ifneq ($(PRODUCT_CHECK_ELF_FILES)$(CHECK_ELF_FILES),)
 $(LOCAL_BUILT_MODULE): $(check_elf_files_stamp)
-check-elf-files: $(check_elf_files_stamp)
-endif  # LOCAL_CHECK_ELF_FILES
 endif  # PRODUCT_CHECK_ELF_FILES or CHECK_ELF_FILES
 
+check-elf-files: $(check_elf_files_stamp)
+endif  # BUILD_BROKEN_PREBUILT_ELF_FILES
+endif  # LOCAL_CHECK_ELF_FILES
+
 endif  # SHARED_LIBRARIES, EXECUTABLES, NATIVE_TESTS
 endif  # !LOCAL_IS_HOST_MODULE
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 2e24eb9..24cca5a 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -80,6 +80,7 @@
 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:=
@@ -114,12 +115,14 @@
 LOCAL_HOST_PREFIX:=
 LOCAL_HOST_REQUIRED_MODULES:=
 LOCAL_INIT_RC:=
+LOCAL_INJECT_BSSL_HASH:=
 LOCAL_INSTALLED_MODULE:=
 LOCAL_INSTALLED_MODULE_STEM:=
 LOCAL_INSTRUMENTATION_FOR:=
 LOCAL_INTERMEDIATE_SOURCE_DIR:=
 LOCAL_INTERMEDIATE_SOURCES:=
 LOCAL_INTERMEDIATE_TARGETS:=
+LOCAL_IS_FUZZ_TARGET:=
 LOCAL_IS_HOST_MODULE:=
 LOCAL_IS_RUNTIME_RESOURCE_OVERLAY:=
 LOCAL_JACK_CLASSPATH:=
@@ -214,6 +217,7 @@
 LOCAL_PRESUBMIT_DISABLED:=
 LOCAL_PRIVATE_PLATFORM_APIS:=
 LOCAL_PRIVILEGED_MODULE:=
+LOCAL_PROC_MACRO_LIBRARIES:=
 # '',full,custom,disabled,obfuscation,optimization
 LOCAL_PRODUCT_MODULE:=
 # TODO(b/135957588) Remove LOCAL_PRODUCT_SERVICES_MODULE
@@ -241,6 +245,7 @@
 LOCAL_REQUIRED_MODULES:=
 LOCAL_RES_LIBRARIES:=
 LOCAL_RESOURCE_DIR:=
+LOCAL_RLIB_LIBRARIES:=
 LOCAL_RMTYPEDEFS:=
 LOCAL_RRO_THEME:=
 LOCAL_RTTI_FLAG:=
diff --git a/core/combo/HOST_darwin-x86_64.mk b/core/combo/HOST_darwin-x86_64.mk
index 07f8d9f..dac3bbf 100644
--- a/core/combo/HOST_darwin-x86_64.mk
+++ b/core/combo/HOST_darwin-x86_64.mk
@@ -59,8 +59,3 @@
         $(PRIVATE_LDFLAGS) \
         $(PRIVATE_LDLIBS)
 endef
-
-# $(1): The file to check
-define get-file-size
-stat -f "%z" $(1)
-endef
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index deed943..3f4ec0a 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -23,8 +23,3 @@
 
 ############################################################
 ## Macros after this line are shared by the 64-bit config.
-
-# $(1): The file to check
-define get-file-size
-stat -c "%s" "$(1)" | tr -d '\n'
-endef
diff --git a/core/combo/select.mk b/core/combo/select.mk
index eab4c72..33c8e6d 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -28,7 +28,7 @@
 
 # Set reasonable defaults for the various variables
 
-$(combo_var_prefix)GLOBAL_ARFLAGS := cqsD -format=gnu
+$(combo_var_prefix)GLOBAL_ARFLAGS := crsPD -format=gnu
 
 $(combo_var_prefix)STATIC_LIB_SUFFIX := .a
 
diff --git a/core/config.mk b/core/config.mk
index ca8f523..49b9329 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -119,6 +119,7 @@
   ARCH_X86_HAVE_SSSE3 \
 )
 $(KATI_obsolete_var PRODUCT_IOT)
+$(KATI_obsolete_var MD5SUM)
 
 # Used to force goals to build.  Only use for conditionally defined goals.
 .PHONY: FORCE
@@ -506,22 +507,12 @@
 # Tools that are prebuilts for TARGET_BUILD_APPS
 #
 ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
-  AIDL := $(HOST_OUT_EXECUTABLES)/aidl
   AAPT := $(HOST_OUT_EXECUTABLES)/aapt
-  AAPT2 := $(HOST_OUT_EXECUTABLES)/aapt2
   MAINDEXCLASSES := $(HOST_OUT_EXECUTABLES)/mainDexClasses
-  SIGNAPK_JAR := $(HOST_OUT_JAVA_LIBRARIES)/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)
-  SIGNAPK_JNI_LIBRARY_PATH := $(HOST_OUT_SHARED_LIBRARIES)
-  ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign
 
 else # TARGET_BUILD_APPS || TARGET_BUILD_PDK
-  AIDL := $(prebuilt_build_tools_bin)/aidl
   AAPT := $(prebuilt_sdk_tools_bin)/aapt
-  AAPT2 := $(prebuilt_sdk_tools_bin)/aapt2
   MAINDEXCLASSES := $(prebuilt_sdk_tools)/mainDexClasses
-  SIGNAPK_JAR := $(prebuilt_sdk_tools)/lib/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)
-  SIGNAPK_JNI_LIBRARY_PATH := $(prebuilt_sdk_tools)/$(HOST_OS)/lib64
-  ZIPALIGN := $(prebuilt_build_tools_bin)/zipalign
 endif # TARGET_BUILD_APPS || TARGET_BUILD_PDK
 
 ifeq (,$(TARGET_BUILD_APPS))
@@ -542,12 +533,11 @@
 FILESLIST := $(SOONG_HOST_OUT_EXECUTABLES)/fileslist
 FILESLIST_UTIL :=$= build/make/tools/fileslist_util.py
 HOST_INIT_VERIFIER := $(HOST_OUT_EXECUTABLES)/host_init_verifier
-SOONG_JAVAC_WRAPPER := $(SOONG_HOST_OUT_EXECUTABLES)/soong_javac_wrapper
-SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
-MERGE_ZIPS := $(SOONG_HOST_OUT_EXECUTABLES)/merge_zips
 XMLLINT := $(SOONG_HOST_OUT_EXECUTABLES)/xmllint
-ZIP2ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/zip2zip
-ZIPTIME := $(prebuilt_build_tools_bin)/ziptime
+
+# SOONG_ZIP is exported by Soong, but needs to be defined early for
+# $OUT/dexpreopt.global.  It will be verified against the Soong version.
+SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
 
 # ---------------------------------------------------------------
 # Generic tools.
@@ -608,6 +598,7 @@
 ADD_IMG_TO_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/add_img_to_target_files$(HOST_EXECUTABLE_SUFFIX)
 BUILD_IMAGE := $(HOST_OUT_EXECUTABLES)/build_image$(HOST_EXECUTABLE_SUFFIX)
 BUILD_SUPER_IMAGE := $(HOST_OUT_EXECUTABLES)/build_super_image$(HOST_EXECUTABLE_SUFFIX)
+IMG_FROM_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/img_from_target_files$(HOST_EXECUTABLE_SUFFIX)
 MAKE_RECOVERY_PATCH := $(HOST_OUT_EXECUTABLES)/make_recovery_patch$(HOST_EXECUTABLE_SUFFIX)
 OTA_FROM_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/ota_from_target_files$(HOST_EXECUTABLE_SUFFIX)
 SPARSE_IMG := $(HOST_OUT_EXECUTABLES)/sparse_img$(HOST_EXECUTABLE_SUFFIX)
@@ -647,13 +638,6 @@
 # Path to tools.jar
 HOST_JDK_TOOLS_JAR := $(ANDROID_JAVA8_HOME)/lib/tools.jar
 
-# It's called md5 on Mac OS and md5sum on Linux
-ifeq ($(HOST_OS),darwin)
-MD5SUM:=md5 -q
-else
-MD5SUM:=md5sum
-endif
-
 APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK) --no-banner --compatible-output=yes
 
 # Boolean variable determining if the whitelist for compatible properties is enabled
@@ -807,7 +791,7 @@
 # is made which breaks compatibility with the previous platform sepolicy version,
 # not just on every increase in PLATFORM_SDK_VERSION.  The minor version should
 # be reset to 0 on every bump of the PLATFORM_SDK_VERSION.
-sepolicy_major_vers := 28
+sepolicy_major_vers := 29
 sepolicy_minor_vers := 0
 
 ifneq ($(sepolicy_major_vers), $(PLATFORM_SDK_VERSION))
@@ -1187,8 +1171,10 @@
     systemotherimage-nodeps \
     ramdisk-nodeps \
     ramdisk_debug-nodeps \
+    ramdisk_test_harness-nodeps \
     bootimage-nodeps \
     bootimage_debug-nodeps \
+    bootimage_test_harness-nodeps \
     recoveryimage-nodeps \
     vbmetaimage-nodeps \
     product-graph dump-products
diff --git a/core/cxx_stl_setup.mk b/core/cxx_stl_setup.mk
index 55c4975..95b1090 100644
--- a/core/cxx_stl_setup.mk
+++ b/core/cxx_stl_setup.mk
@@ -33,12 +33,6 @@
     endif
 endif
 
-# Yes, this is actually what the clang driver does.
-linux_dynamic_gcclibs := -lgcc_s -lgcc -lc -lgcc_s -lgcc
-linux_static_gcclibs := -Wl,--start-group -lgcc -lgcc_eh -lc -Wl,--end-group
-darwin_dynamic_gcclibs := -lc -lSystem
-darwin_static_gcclibs := NO_STATIC_HOST_BINARIES_ON_DARWIN
-
 my_link_type := dynamic
 ifdef LOCAL_IS_HOST_MODULE
     ifneq (,$(BUILD_HOST_static))
@@ -55,8 +49,6 @@
 
 my_cxx_ldlibs :=
 ifneq ($(filter $(my_cxx_stl),libc++ libc++_static),)
-    my_cflags += -D_USING_LIBCXX
-
     ifeq ($($(my_prefix)OS),darwin)
         # libc++'s headers are annotated with availability macros that indicate
         # which version of Mac OS was the first to ship with a libc++ feature
@@ -81,8 +73,7 @@
 
     ifdef LOCAL_IS_HOST_MODULE
         my_cppflags += -nostdinc++
-        my_ldflags += -nodefaultlibs
-        my_cxx_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
+        my_ldflags += -nostdlib++
     else
         my_static_libraries += libc++demangle
         ifeq (arm,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
@@ -101,8 +92,7 @@
 else ifeq ($(my_cxx_stl),none)
     ifdef LOCAL_IS_HOST_MODULE
         my_cppflags += -nostdinc++
-        my_ldflags += -nodefaultlibs
-        my_cxx_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
+        my_ldflags += -nostdlib++
     endif
 else
     $(error $(LOCAL_PATH): $(LOCAL_MODULE): $(my_cxx_stl) is not a supported STL.)
diff --git a/core/definitions.mk b/core/definitions.mk
index a93979a..7450d4f 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2270,7 +2270,7 @@
 # $(1): the package file we are signing.
 define sign-package-arg
 $(hide) mv $(1) $(1).unsigned
-$(hide) $(JAVA) -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(SIGNAPK_JAR) \
+$(hide) $(JAVA) -Djava.library.path=$$(dirname $(SIGNAPK_JNI_LIBRARY_PATH)) -jar $(SIGNAPK_JAR) \
     $(PRIVATE_CERTIFICATE) $(PRIVATE_PRIVATE_KEY) \
     $(PRIVATE_ADDITIONAL_CERTIFICATES) $(1).unsigned $(1).signed
 $(hide) mv $(1).signed $(1)
@@ -2302,7 +2302,7 @@
 ifeq ($(HOST_OS),linux)
 # Runs appcompat and store logs in $(PRODUCT_OUT)/appcompat
 define extract-package
-$(AAPT2) dump $@ | awk -F ' |=' '/^Package/{print $$3}' >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log &&
+$(AAPT2) dump resources $@ | awk -F ' |=' '/^Package/{print $$3}' >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log &&
 endef
 define appcompat-header
 $(hide) \
@@ -2419,6 +2419,16 @@
 $(if $(filter-out $(2), $(LOCAL_INSTALLED_MODULE)), $(1):$(2))
 endef
 
+# Create copy pair for $(1) $(2)
+# If $(2) is substring of $(3) do nothing.
+# $(1): source path
+# $(2): destination path
+# $(3): filter-out target
+# The format of copy pair is src:dst
+define filter-copy-pair
+$(if $(findstring $(2), $(3)),,$(1):$(2))
+endef
+
 # Copies many files.
 # $(1): The files to copy.  Each entry is a ':' separated src:dst pair
 # $(2): An optional directory to prepend to the destination
@@ -2678,9 +2688,9 @@
 ###########################################################
 
 # $(1): The file to check
-ifndef get-file-size
-$(error HOST_OS must define get-file-size)
-endif
+define get-file-size
+stat -c "%s" "$(1)" | tr -d '\n'
+endef
 
 # $(1): The file(s) to check (often $@)
 # $(2): The partition size.
@@ -2847,7 +2857,9 @@
 # Can be passed a subdirectory to use for the common testcase directory.
 define compatibility_suite_dirs
   $(strip \
-    $(COMPATIBILITY_TESTCASES_OUT_$(1)) \
+    $(if $(COMPATIBILITY_TESTCASES_OUT_INCLUDE_MODULE_FOLDER_$(1)),\
+      $(COMPATIBILITY_TESTCASES_OUT_$(1))/$(LOCAL_MODULE)$(2),\
+      $(COMPATIBILITY_TESTCASES_OUT_$(1))) \
     $($(my_prefix)OUT_TESTCASES)/$(LOCAL_MODULE)$(2))
 endef
 
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index b856bf4..69eaea1 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -99,7 +99,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, RuntimeApexJars,                    $(RUNTIME_APEX_JARS))
+  $(call add_json_list, ArtApexJars,                        $(ART_APEX_JARS))
   $(call add_json_list, ProductUpdatableBootModules,        $(PRODUCT_UPDATABLE_BOOT_MODULES))
   $(call add_json_list, ProductUpdatableBootLocations,      $(PRODUCT_UPDATABLE_BOOT_LOCATIONS))
   $(call add_json_list, SystemServerJars,                   $(PRODUCT_SYSTEM_SERVER_JARS))
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 85f2f3b..79d5f8c 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -21,10 +21,8 @@
 	mkdir -p $(dir $@)/$(TARGET_ARCH)
 	ln -sfn ../$(notdir $@) $(dir $@)/$(TARGET_ARCH)
 ifdef TARGET_2ND_ARCH
-  ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
 	mkdir -p $(dir $@)/$(TARGET_2ND_ARCH)
 	ln -sfn ../$(notdir $@) $(dir $@)/$(TARGET_2ND_ARCH)
-  endif
 endif
 
 my_dexpreopt_image_extra_deps := $(firstword $(my_installed))
@@ -33,10 +31,8 @@
 include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
 
 ifdef TARGET_2ND_ARCH
-  ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-    my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
-    include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
-  endif
+  my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
+  include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
 endif
 
 my_2nd_arch_prefix :=
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index 0accdc0..27ff2c9 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -39,6 +39,17 @@
 include $(BUILD_SYSTEM)/binary.mk
 ###################################
 
+ifdef LOCAL_INJECT_BSSL_HASH
+inject_module := $(intermediates)/INJECT_BSSL_HASH/$(notdir $(my_installed_module_stem))
+LOCAL_INTERMEDIATE_TARGETS += $(inject_module)
+$(inject_module): $(SOONG_HOST_OUT)/bin/bssl_inject_hash
+$(inject_module): $(linked_module)
+	@echo "target inject BSSL hash: $(PRIVATE_MODULE) ($@)"
+	$(SOONG_HOST_OUT)/bin/bssl_inject_hash -in-object $< -o $@
+else
+inject_module := $(linked_module)
+endif
+
 ###########################################################
 ## Store a copy with symbols for symbolic debugging
 ###########################################################
@@ -47,7 +58,7 @@
 else
 my_unstripped_path := $(LOCAL_UNSTRIPPED_PATH)
 endif
-symbolic_input := $(linked_module)
+symbolic_input := $(inject_module)
 symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
 $(symbolic_output) : $(symbolic_input)
 	@echo "target Symbolic: $(PRIVATE_MODULE) ($@)"
@@ -59,7 +70,7 @@
 
 ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
 my_breakpad_path := $(TARGET_OUT_BREAKPAD)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path))
-breakpad_input := $(linked_module)
+breakpad_input := $(inject_module)
 breakpad_output := $(my_breakpad_path)/$(my_installed_module_stem).sym
 $(breakpad_output) : $(breakpad_input) | $(BREAKPAD_DUMP_SYMS) $(PRIVATE_READELF)
 	@echo "target breakpad: $(PRIVATE_MODULE) ($@)"
@@ -133,6 +144,7 @@
 
 $(cleantarget): PRIVATE_CLEAN_FILES += \
     $(linked_module) \
+    $(inject_module) \
     $(breakpad_output) \
     $(symbolic_output) \
     $(strip_output)
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 92c5cca..0c58cd6 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -228,6 +228,7 @@
 TARGET_COPY_OUT_OEM := oem
 TARGET_COPY_OUT_RAMDISK := ramdisk
 TARGET_COPY_OUT_DEBUG_RAMDISK := debug_ramdisk
+TARGET_COPY_OUT_TEST_HARNESS_RAMDISK := test_harness_ramdisk
 TARGET_COPY_OUT_ROOT := root
 TARGET_COPY_OUT_RECOVERY := recovery
 # The directory used for optional partitions depend on the BoardConfig, so
@@ -238,6 +239,7 @@
 _system_ext_path_placeholder := ||SYSTEM_EXT-PATH-PH||
 _odm_path_placeholder := ||ODM-PATH-PH||
 TARGET_COPY_OUT_VENDOR := $(_vendor_path_placeholder)
+TARGET_COPY_OUT_VENDOR_RAMDISK := vendor-ramdisk
 TARGET_COPY_OUT_PRODUCT := $(_product_path_placeholder)
 # TODO(b/135957588) TARGET_COPY_OUT_PRODUCT_SERVICES will copy the target to
 # product
@@ -253,10 +255,10 @@
 #################################################################
 # Set up minimal BOOTCLASSPATH list of jars to build/execute
 # java code with dalvikvm/art.
-# Jars present in the runtime apex. These should match exactly the list of
-# Java libraries in the runtime apex build rule.
-RUNTIME_APEX_JARS := core-oj core-libart core-icu4j okhttp bouncycastle apache-xml
-TARGET_CORE_JARS := $(RUNTIME_APEX_JARS) conscrypt
+# Jars present in the ART apex. These should match exactly the list of
+# Java libraries in the ART apex build rule.
+ART_APEX_JARS := core-oj core-libart core-icu4j okhttp bouncycastle apache-xml
+TARGET_CORE_JARS := $(ART_APEX_JARS) conscrypt
 ifeq ($(EMMA_INSTRUMENT),true)
   ifneq ($(EMMA_INSTRUMENT_STATIC),true)
     # For instrumented build, if Jacoco is not being included statically
@@ -328,6 +330,7 @@
 
 HOST_OUT_EXECUTABLES := $(HOST_OUT)/bin
 HOST_OUT_SHARED_LIBRARIES := $(HOST_OUT)/lib64
+HOST_OUT_DYLIB_LIBRARIES := $(HOST_OUT)/lib64
 HOST_OUT_RENDERSCRIPT_BITCODE := $(HOST_OUT_SHARED_LIBRARIES)
 HOST_OUT_JAVA_LIBRARIES := $(HOST_OUT)/framework
 HOST_OUT_SDK_ADDON := $(HOST_OUT)/sdk_addon
@@ -499,12 +502,7 @@
 .KATI_READONLY := TARGET_OUT_SYSTEM_OTHER
 
 # Out for TARGET_2ND_ARCH
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-# With this you can reference the arm binary translation library with libfoo_arm in PRODUCT_PACKAGES.
-TARGET_2ND_ARCH_MODULE_SUFFIX := _$(TARGET_2ND_ARCH)
-else
 TARGET_2ND_ARCH_MODULE_SUFFIX := $(HOST_2ND_ARCH_MODULE_SUFFIX)
-endif
 .KATI_READONLY := TARGET_2ND_ARCH_MODULE_SUFFIX
 
 ifneq ($(filter address,$(SANITIZE_TARGET)),)
@@ -512,11 +510,7 @@
 else
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj_$(TARGET_2ND_ARCH)
 endif
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
-else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib
-endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_RENDERSCRIPT_BITCODE := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_EXECUTABLES := $(TARGET_OUT_EXECUTABLES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_APPS := $(TARGET_OUT_APPS)
@@ -581,17 +575,10 @@
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_EXECUTABLES := $(TARGET_OUT_DATA_EXECUTABLES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_SHARED_LIBRARIES := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_APPS := $(TARGET_OUT_DATA_APPS)
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest/$(TARGET_2ND_ARCH)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest/$(TARGET_2ND_ARCH)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest/$(TARGET_2ND_ARCH)$(TARGET_VENDOR_TEST_SUFFIX)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest/$(TARGET_2ND_ARCH)$(TARGET_VENDOR_TEST_SUFFIX)
-else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest$(TARGET_VENDOR_TEST_SUFFIX)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_METRIC_TESTS := $(TARGET_OUT_DATA)/benchmarktest$(TARGET_VENDOR_TEST_SUFFIX)
-endif
 .KATI_READONLY := \
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_EXECUTABLES \
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_SHARED_LIBRARIES \
@@ -643,11 +630,7 @@
   TARGET_OUT_VENDOR_ETC
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR_EXECUTABLES)
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
-else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib
-endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_RENDERSCRIPT_BITCODE := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR_APPS)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_APPS_PRIVILEGED := $(TARGET_OUT_VENDOR_APPS_PRIVILEGED)
@@ -677,11 +660,7 @@
   TARGET_OUT_OEM_ETC
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_EXECUTABLES := $(TARGET_OUT_OEM_EXECUTABLES)
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib/$(TARGET_2ND_ARCH)
-else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib
-endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_APPS := $(TARGET_OUT_OEM_APPS)
 .KATI_READONLY := \
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_EXECUTABLES \
@@ -727,11 +706,7 @@
   TARGET_OUT_ODM_ETC
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_EXECUTABLES := $(TARGET_OUT_ODM_EXECUTABLES)
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_SHARED_LIBRARIES := $(target_out_odm_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
-else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_SHARED_LIBRARIES := $(target_out_odm_shared_libraries_base)/lib
-endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_RENDERSCRIPT_BITCODE := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_SHARED_LIBRARIES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS := $(TARGET_OUT_ODM_APPS)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS_PRIVILEGED := $(TARGET_OUT_ODM_APPS_PRIVILEGED)
@@ -777,11 +752,7 @@
   TARGET_OUT_PRODUCT_ETC
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_EXECUTABLES := $(TARGET_OUT_PRODUCT_EXECUTABLES)
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SHARED_LIBRARIES := $(target_out_product_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
-else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SHARED_LIBRARIES := $(target_out_product_shared_libraries_base)/lib
-endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_APPS := $(TARGET_OUT_PRODUCT_APPS)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_APPS_PRIVILEGED := $(TARGET_OUT_PRODUCT_APPS_PRIVILEGED)
 .KATI_READONLY := \
@@ -824,11 +795,7 @@
   TARGET_OUT_SYSTEM_EXT_ETC
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_EXECUTABLES := $(TARGET_OUT_SYSTEM_EXT_EXECUTABLES)
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_SHARED_LIBRARIES := $(target_out_system_ext_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
-else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_SHARED_LIBRARIES := $(target_out_system_ext_shared_libraries_base)/lib
-endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_APPS := $(TARGET_OUT_SYSTEM_EXT_APPS)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_APPS_PRIVILEGED := $(TARGET_OUT_SYSTEM_EXT_APPS_PRIVILEGED)
 .KATI_READONLY := \
@@ -859,6 +826,9 @@
 TARGET_RAMDISK_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_RAMDISK)
 TARGET_RAMDISK_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)
 TARGET_DEBUG_RAMDISK_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_DEBUG_RAMDISK)
+TARGET_TEST_HARNESS_RAMDISK_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_TEST_HARNESS_RAMDISK)
+
+TARGET_VENDOR_RAMDISK_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR_RAMDISK)
 
 TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT)
 TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin
@@ -895,7 +865,7 @@
   TARGET_INSTALLER_SYSTEM_OUT
 
 COMMON_MODULE_CLASSES := TARGET-NOTICE_FILES HOST-NOTICE_FILES HOST-JAVA_LIBRARIES
-PER_ARCH_MODULE_CLASSES := SHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP RENDERSCRIPT_BITCODE NATIVE_TESTS HEADER_LIBRARIES
+PER_ARCH_MODULE_CLASSES := SHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP RENDERSCRIPT_BITCODE NATIVE_TESTS HEADER_LIBRARIES RLIB_LIBRARIES DYLIB_LIBRARIES
 .KATI_READONLY := COMMON_MODULE_CLASSES PER_ARCH_MODULE_CLASSES
 
 ifeq ($(CALLED_FROM_SETUP),true)
diff --git a/core/executable.mk b/core/executable.mk
index e71ff33..c8d9272 100644
--- a/core/executable.mk
+++ b/core/executable.mk
@@ -20,15 +20,6 @@
 ifneq (true,$(my_skip_this_target))
 $(call record-module-type,EXECUTABLE)
 
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-# If a native test explicity specifies to build only for the translation arch,
-# we'll still need LOCAL_MULTILIB=both and let module_arch_supported.mk choose
-# to build only for TARGET_2ND_ARCH.
-ifneq (1,$(words $(LOCAL_MODULE_TARGET_ARCH)))
-LOCAL_MULTILIB := first
-endif
-endif
-
 my_prefix := TARGET_
 include $(BUILD_SYSTEM)/multilib.mk
 
diff --git a/core/fuzz_test.mk b/core/fuzz_test.mk
index f5bdef0..4a0fcfa2 100644
--- a/core/fuzz_test.mk
+++ b/core/fuzz_test.mk
@@ -64,14 +64,8 @@
 $(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH_64 when building test $(LOCAL_MODULE))
 endif
 
-LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/fuzzers/$(LOCAL_MODULE)
-LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/fuzzers/$(LOCAL_MODULE)
-
-ifndef LOCAL_MULTILIB
-ifndef LOCAL_32_BIT_ONLY
-LOCAL_MULTILIB := both
-endif
-endif
+LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/fuzzers/$(my_fuzzer)/$(LOCAL_MODULE)
+LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/fuzzers/$(my_fuzzer)/$(LOCAL_MODULE)
 
 ifndef LOCAL_STRIP_MODULE
 LOCAL_STRIP_MODULE := keep_symbols
diff --git a/core/instrumentation_test_config_template.xml b/core/instrumentation_test_config_template.xml
index afaa561..18ea676 100644
--- a/core/instrumentation_test_config_template.xml
+++ b/core/instrumentation_test_config_template.xml
@@ -22,8 +22,6 @@
         <option name="test-file-name" value="{MODULE}.apk" />
     </target_preparer>
 
-    {EXTRA_CONFIGS}
-
     <test class="com.android.tradefed.testtype.{TEST_TYPE}" >
         <option name="package" value="{PACKAGE}" />
         <option name="runner" value="{RUNNER}" />
diff --git a/core/java_common.mk b/core/java_common.mk
index a23d92d..dfe75f3 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -86,6 +86,8 @@
   $(proto_java_srcjar): $(HOST_OUT_EXECUTABLES)/protoc-gen-javamicro
 else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nano)
   $(proto_java_srcjar): PRIVATE_PROTO_JAVA_OUTPUT_OPTION := --javanano_out
+  $(proto_java_srcjar): PRIVATE_PROTOC_FLAGS += --plugin=$(HOST_OUT_EXECUTABLES)/protoc-gen-javanano
+  $(proto_java_srcjar): $(HOST_OUT_EXECUTABLES)/protoc-gen-javanano
 else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),stream)
   $(proto_java_srcjar): PRIVATE_PROTO_JAVA_OUTPUT_OPTION := --javastream_out
   $(proto_java_srcjar): PRIVATE_PROTOC_FLAGS += --plugin=$(HOST_OUT_EXECUTABLES)/protoc-gen-javastream
diff --git a/core/main.mk b/core/main.mk
index f99f16d..e9d4390 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -44,11 +44,7 @@
 .KATI_READONLY := BUILD_NUMBER_FILE
 $(KATI_obsolete_var BUILD_NUMBER,See https://android.googlesource.com/platform/build/+/master/Changes.md#BUILD_NUMBER)
 
-ifeq ($(HOST_OS),darwin)
-DATE_FROM_FILE := date -r $(BUILD_DATETIME_FROM_FILE)
-else
 DATE_FROM_FILE := date -d @$(BUILD_DATETIME_FROM_FILE)
-endif
 .KATI_READONLY := DATE_FROM_FILE
 
 # Pick a reasonable string to use to identify files.
@@ -79,6 +75,8 @@
 -include test/suite_harness/tools/cts-instant-tradefed/build/config.mk
 # MTS-specific config.
 -include test/mts/tools/build/config.mk
+# VTS-Core-specific config.
+-include test/vts/tools/vts-core-tradefed/build/config.mk
 
 # Clean rules
 .PHONY: clean-dex-files
@@ -195,17 +193,7 @@
 # The pdk (Platform Development Kit) build
 include build/make/core/pdk_config.mk
 
-#
 # -----------------------------------------------------------------
-# Enable dynamic linker warnings for userdebug, eng and non-REL builds
-ifneq ($(TARGET_BUILD_VARIANT),user)
-  ADDITIONAL_BUILD_PROPERTIES += ro.bionic.ld.warning=1
-else
-# Enable it for user builds as long as they are not final.
-ifneq ($(PLATFORM_VERSION_CODENAME),REL)
-  ADDITIONAL_BUILD_PROPERTIES += ro.bionic.ld.warning=1
-endif
-endif
 
 ADDITIONAL_BUILD_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE}
 
@@ -494,7 +482,6 @@
 #
 # Resolve the required module name to 32-bit or 64-bit variant.
 # Get a list of corresponding 32-bit module names, if one exists.
-ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
 define get-32-bit-modules
 $(sort $(foreach m,$(1),\
   $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\
@@ -508,15 +495,6 @@
     $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX), \
     $(m))))
 endef
-else  # TARGET_TRANSLATE_2ND_ARCH
-# For binary translation config, by default only install the first arch.
-define get-32-bit-modules
-endef
-
-define get-32-bit-modules-if-we-can
-$(strip $(1))
-endef
-endif  # TARGET_TRANSLATE_2ND_ARCH
 
 # TODO: we can probably check to see if these modules are actually host
 # modules
@@ -1365,7 +1343,9 @@
     $(eval whitelist_patterns := $(call resolve-product-relative-paths,$(whitelist))) \
     $(eval files := $(call product-installed-files, $(makefile))) \
     $(eval offending_files := $(filter-out $(path_patterns) $(whitelist_patterns) $(static_whitelist_patterns),$(files))) \
-    $(call maybe-print-list-and-error,$(offending_files),$(makefile) produces files outside its artifact path requirement.) \
+    $(call maybe-print-list-and-error,$(offending_files),\
+      $(makefile) produces files outside its artifact path requirement. \
+      Allowed paths are $(subst $(space),$(comma)$(space),$(addsuffix *,$(requirements)))) \
     $(eval unused_whitelist := $(filter-out $(files),$(whitelist_patterns))) \
     $(call maybe-print-list-and-error,$(unused_whitelist),$(makefile) includes redundant whitelist entries in its artifact path requirement.) \
     $(eval ### Optionally verify that nothing else produces files inside this artifact path requirement.) \
@@ -1498,7 +1478,7 @@
 # -------------------------------------------------------------------
 
 .PHONY: checkbuild
-checkbuild: $(modules_to_check) droid_targets
+checkbuild: $(modules_to_check) droid_targets check-elf-files
 
 ifeq (true,$(ANDROID_BUILD_EVERYTHING_BY_DEFAULT))
 droid: checkbuild
@@ -1510,6 +1490,9 @@
 .PHONY: ramdisk_debug
 ramdisk_debug: $(INSTALLED_DEBUG_RAMDISK_TARGET)
 
+.PHONY: ramdisk_test_harness
+ramdisk_test_harness: $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
+
 .PHONY: userdataimage
 userdataimage: $(INSTALLED_USERDATAIMAGE_TARGET)
 
@@ -1526,6 +1509,9 @@
 .PHONY: vendorimage
 vendorimage: $(INSTALLED_VENDORIMAGE_TARGET)
 
+.PHONY: vendorbootimage
+vendorbootimage: $(INSTALLED_VENDOR_BOOTIMAGE_TARGET)
+
 .PHONY: productimage
 productimage: $(INSTALLED_PRODUCTIMAGE_TARGET)
 
@@ -1547,6 +1533,9 @@
 .PHONY: bootimage_debug
 bootimage_debug: $(INSTALLED_DEBUG_BOOTIMAGE_TARGET)
 
+.PHONY: bootimage_test_harness
+bootimage_test_harness: $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET)
+
 .PHONY: vbmetaimage
 vbmetaimage: $(INSTALLED_VBMETAIMAGE_TARGET)
 
@@ -1568,6 +1557,7 @@
     $(INSTALLED_CACHEIMAGE_TARGET) \
     $(INSTALLED_BPTIMAGE_TARGET) \
     $(INSTALLED_VENDORIMAGE_TARGET) \
+    $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
     $(INSTALLED_ODMIMAGE_TARGET) \
     $(INSTALLED_SUPERIMAGE_EMPTY_TARGET) \
     $(INSTALLED_PRODUCTIMAGE_TARGET) \
@@ -1663,6 +1653,7 @@
     $(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET) \
     $(BUILT_OTATOOLS_PACKAGE) \
     $(SYMBOLS_ZIP) \
+    $(PROGUARD_DICT_ZIP) \
     $(COVERAGE_ZIP) \
     $(APPCOMPAT_ZIP) \
     $(INSTALLED_FILES_FILE) \
@@ -1712,6 +1703,10 @@
       $(INSTALLED_DEBUG_RAMDISK_TARGET) \
       $(INSTALLED_DEBUG_BOOTIMAGE_TARGET) \
     )
+    $(call dist-for-goals, bootimage_test_harness, \
+      $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET) \
+      $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET) \
+    )
   endif
 
   ifeq ($(EMMA_INSTRUMENT),true)
diff --git a/core/misc_prebuilt_internal.mk b/core/misc_prebuilt_internal.mk
index cc2683c..a52b9e5 100644
--- a/core/misc_prebuilt_internal.mk
+++ b/core/misc_prebuilt_internal.mk
@@ -25,7 +25,14 @@
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
+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)
+endif
 
-built_module := $(LOCAL_BUILT_MODULE)
\ No newline at end of file
+built_module := $(LOCAL_BUILT_MODULE)
diff --git a/core/notice_files.mk b/core/notice_files.mk
index 6df570e..680a0b1 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -55,7 +55,7 @@
   module_installed_filename := $(patsubst $(PRODUCT_OUT)/%,%,$(LOCAL_INSTALLED_MODULE))
 else
   # This module isn't installable
-  ifneq ($(filter STATIC_LIBRARIES HEADER_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
+  ifneq ($(filter  STATIC_LIBRARIES RLIB_LIBRARIES PROC_MACRO_LIBRARIES HEADER_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
     # Stick the static libraries with the dynamic libraries.
     # We can't use xxx_OUT_STATIC_LIBRARIES because it points into
     # device-obj or host-obj.
diff --git a/core/package.mk b/core/package.mk
index 854e009..6bde485 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -7,14 +7,6 @@
 my_prefix := TARGET_
 include $(BUILD_SYSTEM)/multilib.mk
 
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-  ifeq ($(TARGET_SUPPORTS_64_BIT_APPS),true)
-    my_module_multilib := first
-  else ifneq ($(my_module_multilib),64)
-    my_module_multilib := first
-  endif
-endif
-
 ifeq ($(TARGET_SUPPORTS_32_BIT_APPS)|$(TARGET_SUPPORTS_64_BIT_APPS),true|true)
   # packages default to building for either architecture,
   # the preferred if its supported, otherwise the non-preferred.
diff --git a/core/package_internal.mk b/core/package_internal.mk
index b80ccb3..eb3c67d 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -99,7 +99,7 @@
 
 # Determine whether auto-RRO is enabled for this package.
 enforce_rro_enabled :=
-ifeq ($(PRODUCT_ENFORCE_RRO_TARGETS),*)
+ifneq (,$(filter *, $(PRODUCT_ENFORCE_RRO_TARGETS)))
   # * means all system APKs, so enable conditionally based on module path.
 
   # Note that base_rules.mk has not yet been included, so it's likely that only
@@ -455,7 +455,7 @@
 certificate := $(LOCAL_CERTIFICATE).x509.pem
 additional_certificates := $(foreach c,$(LOCAL_ADDITIONAL_CERTIFICATES), $(c).x509.pem $(c).pk8)
 
-$(LOCAL_BUILT_MODULE): $(private_key) $(certificate) $(SIGNAPK_JAR)
+$(LOCAL_BUILT_MODULE): $(private_key) $(certificate) $(SIGNAPK_JAR) $(SIGNAPK_JNI_LIBRARY_PATH)
 $(LOCAL_BUILT_MODULE): PRIVATE_PRIVATE_KEY := $(private_key)
 $(LOCAL_BUILT_MODULE): PRIVATE_CERTIFICATE := $(certificate)
 
diff --git a/core/prebuilt.mk b/core/prebuilt.mk
index 9d284fb..4512cd9 100644
--- a/core/prebuilt.mk
+++ b/core/prebuilt.mk
@@ -12,13 +12,6 @@
   LOCAL_HOST_PREFIX :=
 else
   my_prefix := TARGET_
-
-  ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-    # Only support prebuilt shared and static libraries for translated arch
-    ifeq ($(filter SHARED_LIBRARIES STATIC_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
-      LOCAL_MULTILIB := first
-    endif
-  endif
 endif
 
 include $(BUILD_SYSTEM)/multilib.mk
diff --git a/core/proguard_basic_keeps.flags b/core/proguard_basic_keeps.flags
index a0f577d..28ec2d0 100644
--- a/core/proguard_basic_keeps.flags
+++ b/core/proguard_basic_keeps.flags
@@ -72,3 +72,7 @@
 
 # Less spammy.
 -dontnote
+
+# The lite proto runtime uses reflection to access fields based on the names in
+# the schema, keep all the fields.
+-keepclassmembers class * extends com.google.protobuf.MessageLite { <fields>; }
diff --git a/core/rbe.mk b/core/rbe.mk
index fb39d51..231859b 100644
--- a/core/rbe.mk
+++ b/core/rbe.mk
@@ -21,7 +21,7 @@
   else
     rbe_dir := $(HOME)/rbe
   endif
-  RBE_WRAPPER := $(rbe_dir)/rewrapper --labels=type=compile,lang=cpp,compiler=clang
+  RBE_WRAPPER := $(rbe_dir)/rewrapper --labels=type=compile,lang=cpp,compiler=clang --env_var_whitelist=PWD
 
   # Append rewrapper to existing *_WRAPPER variables so it's possible to
   # use both ccache and rewrapper.
diff --git a/core/sdk_check.mk b/core/sdk_check.mk
index 49ea2a8..c09fc7c 100644
--- a/core/sdk_check.mk
+++ b/core/sdk_check.mk
@@ -8,6 +8,11 @@
 
 whitelisted_modules := framework-res__auto_generated_rro
 
+
+ifeq (,$(JAVA_SDK_ENFORCEMENT_ERROR))
+  JAVA_SDK_ENFORCEMENT_ERROR := APPS
+endif
+
 ifeq ($(LOCAL_SDK_VERSION)$(LOCAL_PRIVATE_PLATFORM_APIS),)
   ifeq (,$(filter $(LOCAL_MODULE),$(whitelisted_modules)))
     ifneq ($(JAVA_SDK_ENFORCEMENT_WARNING)$(JAVA_SDK_ENFORCEMENT_ERROR),)
diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk
index 34dd3e8..9e3f0d3 100644
--- a/core/soong_cc_prebuilt.mk
+++ b/core/soong_cc_prebuilt.mk
@@ -31,20 +31,6 @@
   $(call pretty-error,Unsupported LOCAL_MODULE_$(my_prefix)ARCH=$(LOCAL_MODULE_$(my_prefix)ARCH))
 endif
 
-skip_module :=
-ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-  ifndef LOCAL_IS_HOST_MODULE
-    ifdef LOCAL_2ND_ARCH_VAR_PREFIX
-      # Only support shared and static libraries and tests for translated arch
-      ifeq ($(filter SHARED_LIBRARIES STATIC_LIBRARIES HEADER_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
-        skip_module := true
-      endif
-    endif
-  endif
-endif
-
-ifndef skip_module
-
 # Don't install static libraries by default.
 ifndef LOCAL_UNINSTALLABLE_MODULE
   ifeq (STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS))
@@ -150,7 +136,7 @@
 
 ifndef LOCAL_IS_HOST_MODULE
   ifdef LOCAL_SOONG_UNSTRIPPED_BINARY
-    ifneq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+    ifneq ($(LOCAL_UNINSTALLABLE_MODULE),true)
       my_symbol_path := $(if $(LOCAL_SOONG_SYMBOL_PATH),$(LOCAL_SOONG_SYMBOL_PATH),$(my_module_path))
       # Store a copy with symbols for symbolic debugging
       my_unstripped_path := $(TARGET_OUT_UNSTRIPPED)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
@@ -233,7 +219,3 @@
 
 $(notice_target): | $(installed_static_library_notice_file_targets)
 $(LOCAL_INSTALLED_MODULE): | $(notice_target)
-
-endif # !skip_module
-
-skip_module :=
diff --git a/core/soong_rust_prebuilt.mk b/core/soong_rust_prebuilt.mk
new file mode 100644
index 0000000..23d18c4
--- /dev/null
+++ b/core/soong_rust_prebuilt.mk
@@ -0,0 +1,108 @@
+# Native prebuilt coming from Soong.
+# Extra inputs:
+# LOCAL_SOONG_UNSTRIPPED_BINARY
+
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+  $(call pretty-error,soong_rust_prebuilt.mk may only be used from Soong)
+endif
+
+ifdef LOCAL_IS_HOST_MODULE
+  ifneq ($(HOST_OS),$(LOCAL_MODULE_HOST_OS))
+    my_prefix := HOST_CROSS_
+    LOCAL_HOST_PREFIX := $(my_prefix)
+  else
+    my_prefix := HOST_
+    LOCAL_HOST_PREFIX :=
+  endif
+else
+  my_prefix := TARGET_
+endif
+
+ifeq ($($(my_prefix)ARCH),$(LOCAL_MODULE_$(my_prefix)ARCH))
+  # primary arch
+  LOCAL_2ND_ARCH_VAR_PREFIX :=
+else ifeq ($($(my_prefix)2ND_ARCH),$(LOCAL_MODULE_$(my_prefix)ARCH))
+  # secondary arch
+  LOCAL_2ND_ARCH_VAR_PREFIX := $($(my_prefix)2ND_ARCH_VAR_PREFIX)
+else
+  $(call pretty-error,Unsupported LOCAL_MODULE_$(my_prefix)ARCH=$(LOCAL_MODULE_$(my_prefix)ARCH))
+endif
+
+# Don't install rlib/proc_macro libraries.
+ifndef LOCAL_UNINSTALLABLE_MODULE
+  ifneq ($(filter RLIB_LIBRARIES PROC_MACRO_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
+    LOCAL_UNINSTALLABLE_MODULE := true
+  endif
+endif
+
+
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
+# The real dependency will be added after all Android.mks are loaded and the install paths
+# of the shared libraries are determined.
+ifdef LOCAL_INSTALLED_MODULE
+  ifdef LOCAL_SHARED_LIBRARIES
+    my_shared_libraries := $(LOCAL_SHARED_LIBRARIES)
+    $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)DEPENDENCIES_ON_SHARED_LIBRARIES += \
+      $(my_register_name):$(LOCAL_INSTALLED_MODULE):$(subst $(space),$(comma),$(my_shared_libraries))
+  endif
+  ifdef LOCAL_DYLIB_LIBRARIES
+    my_dylibs := $(LOCAL_DYLIB_LIBRARIES)
+    # Treat these as shared library dependencies for installation purposes.
+    $(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)DEPENDENCIES_ON_SHARED_LIBRARIES += \
+      $(my_register_name):$(LOCAL_INSTALLED_MODULE):$(subst $(space),$(comma),$(my_dylibs))
+  endif
+endif
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE)
+	$(transform-prebuilt-to-target)
+ifneq ($(filter EXECUTABLES,$(LOCAL_MODULE_CLASS)),)
+	$(hide) chmod +x $@
+endif
+
+ifndef LOCAL_IS_HOST_MODULE
+  ifdef LOCAL_SOONG_UNSTRIPPED_BINARY
+    my_symbol_path := $(if $(LOCAL_SOONG_SYMBOL_PATH),$(LOCAL_SOONG_SYMBOL_PATH),$(my_module_path))
+    # Store a copy with symbols for symbolic debugging
+    my_unstripped_path := $(TARGET_OUT_UNSTRIPPED)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
+    # drop /root as /root is mounted as /
+    my_unstripped_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/root/%,$(TARGET_OUT_UNSTRIPPED)/%, $(my_unstripped_path))
+    symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
+    $(eval $(call copy-one-file,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
+    $(call add-dependency,$(LOCAL_BUILT_MODULE),$(symbolic_output))
+  endif
+endif
+
+# A product may be configured to strip everything in some build variants.
+# We do the stripping as a post-install command so that LOCAL_BUILT_MODULE
+# is still with the symbols and we don't need to clean it (and relink) when
+# you switch build variant.
+ifneq ($(filter $(STRIP_EVERYTHING_BUILD_VARIANTS),$(TARGET_BUILD_VARIANT)),)
+$(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := \
+  $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_STRIP) --strip-all $(LOCAL_INSTALLED_MODULE)
+endif
+
+$(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), \
+      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))
+
+$(notice_target): | $(installed_static_library_notice_file_targets)
+$(LOCAL_INSTALLED_MODULE): | $(notice_target)
diff --git a/core/tasks/check_boot_jars/package_whitelist.txt b/core/tasks/check_boot_jars/package_whitelist.txt
index 3b63843..8d9878f 100644
--- a/core/tasks/check_boot_jars/package_whitelist.txt
+++ b/core/tasks/check_boot_jars/package_whitelist.txt
@@ -243,3 +243,4 @@
 ###################################################
 # Packages used for Android in Chrome OS
 org\.chromium\.arc
+org\.chromium\.arc\..*
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 33c3a83..f3b4368 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -14,7 +14,6 @@
 
 test_suite_name := cts
 test_suite_tradefed := cts-tradefed
-# TODO: Fix the following two lines after harness is moved to its own repo
 test_suite_dynamic_config := test/suite_harness/tools/cts-tradefed/DynamicConfig.xml
 test_suite_readme := test/suite_harness/tools/cts-tradefed/README
 
diff --git a/core/tasks/cts_instant.mk b/core/tasks/cts_instant.mk
deleted file mode 100644
index 18f1db3..0000000
--- a/core/tasks/cts_instant.mk
+++ /dev/null
@@ -1,25 +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.
-
-test_suite_name := cts_instant
-test_suite_tradefed := cts-instant-tradefed
-test_suite_dynamic_config := test/suite_harness/tools/cts-instant-tradefed/DynamicConfig.xml
-test_suite_readme := test/suite_harness/tools/cts-instant-tradefed/README
-
-include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
-
-.PHONY: cts_instant
-cts_instant: $(compatibility_zip)
-$(call dist-for-goals, cts_instant, $(compatibility_zip))
-
diff --git a/core/tasks/vndk.mk b/core/tasks/vndk.mk
index b487f53..3c4d942 100644
--- a/core/tasks/vndk.mk
+++ b/core/tasks/vndk.mk
@@ -48,7 +48,6 @@
 vndk_snapshot_top := $(call intermediates-dir-for,PACKAGING,vndk-snapshot)
 vndk_snapshot_out := $(vndk_snapshot_top)/vndk-snapshot
 vndk_snapshot_soong_dir := $(call intermediates-dir-for,PACKAGING,vndk-snapshot-soong)
-vndk_snapshot_configs_out := $(vndk_snapshot_top)/configs
 
 #######################################
 # vndk_snapshot_zip
@@ -105,7 +104,6 @@
 vndk_snapshot_out :=
 vndk_snapshot_soong_dir :=
 vndk_snapshot_soong_files :=
-vndk_snapshot_configs_out :=
 vndk_snapshot_variant :=
 
 else # BOARD_VNDK_RUNTIME_DISABLE is set to 'true'
diff --git a/core/tasks/vts-core-tests.mk b/core/tasks/vts-core-tests.mk
index fb1e1c6..95b729a 100644
--- a/core/tasks/vts-core-tests.mk
+++ b/core/tasks/vts-core-tests.mk
@@ -44,6 +44,13 @@
 	  $(PRIVATE_vts_core_list)
 
 vts-core: $(vts-core-zip)
-$(call dist-for-goals, vts-core, $(vts-core-zip) $(vts-core-list-zip) $(vts-core-configs-zip))
+
+test_suite_name := vts-core
+test_suite_tradefed := vts-core-tradefed
+test_suite_readme := test/vts/tools/vts-core-tradefed/README
+include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
+vts-core: $(compatibility_zip)
+
+$(call dist-for-goals, vts-core, $(vts-core-zip) $(vts-core-list-zip) $(vts-core-configs-zip) $(compatibility_zip))
 
 tests: vts-core
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index f949b05..30890c0 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -84,12 +84,10 @@
 # generate the range of allowed SDK versions, so it must have an entry for every
 # unreleased API level targetable by this branch, not just those that are valid
 # lunch targets for this branch.
-PLATFORM_VERSION.QP1A := Q
 PLATFORM_VERSION.RP1A := R
 
 # These are the current development codenames, if the build is not a final
 # release build.  If this is a final release build, it is simply "REL".
-PLATFORM_VERSION_CODENAME.QP1A := Q
 PLATFORM_VERSION_CODENAME.RP1A := R
 
 ifndef PLATFORM_VERSION
@@ -114,7 +112,7 @@
   # When you increment the PLATFORM_SDK_VERSION please ensure you also
   # clear out the following text file of all older PLATFORM_VERSION's:
   # cts/tests/tests/os/assets/platform_versions.txt
-  PLATFORM_SDK_VERSION := 28
+  PLATFORM_SDK_VERSION := 29
 endif
 .KATI_READONLY := PLATFORM_SDK_VERSION
 
@@ -252,17 +250,13 @@
     #  It must be of the form "YYYY-MM-DD" on production devices.
     #  It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
     #  If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
-      PLATFORM_SECURITY_PATCH := 2019-08-01
+      PLATFORM_SECURITY_PATCH := 2019-09-05
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH
 
 ifndef PLATFORM_SECURITY_PATCH_TIMESTAMP
   # Used to indicate the matching timestamp for the security patch string in PLATFORM_SECURITY_PATCH.
-  ifneq (,$(findstring Darwin,$(UNAME)))
-    PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -jf '%Y-%m-%d %T %Z' '$(PLATFORM_SECURITY_PATCH) 00:00:00 GMT' +%s)
-  else
-    PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -d 'TZ="GMT" $(PLATFORM_SECURITY_PATCH)' +%s)
-  endif
+  PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -d 'TZ="GMT" $(PLATFORM_SECURITY_PATCH)' +%s)
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH_TIMESTAMP
 
@@ -291,11 +285,7 @@
   BUILD_DATETIME := $(shell date +%s)
 endif
 
-ifneq (,$(findstring Darwin,$(UNAME)))
-DATE := date -r $(BUILD_DATETIME)
-else
 DATE := date -d @$(BUILD_DATETIME)
-endif
 .KATI_READONLY := DATE
 
 # Everything should be using BUILD_DATETIME_FROM_FILE instead.
diff --git a/envsetup.sh b/envsetup.sh
index 40f7705..f0c6b9b 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -33,9 +33,7 @@
 - refreshmod: Refresh list of modules for allmod/gomod.
 
 Environment options:
-- SANITIZE_HOST: Set to 'true' to use ASAN for all host modules. Note that
-                 ASAN_OPTIONS=detect_leaks=0 will be set by default until the
-                 build is leak-check clean.
+- SANITIZE_HOST: Set to 'address' to use ASAN for all host modules.
 - ANDROID_QUIET_BUILD: set to 'true' to display only the essential messages.
 
 Look at the source to view more functions. The complete list is:
@@ -333,7 +331,6 @@
     export ANDROID_BUILD_TOP=$(gettop)
     # With this environment variable new GCC can apply colors to warnings/errors
     export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
-    export ASAN_OPTIONS=detect_leaks=0
 }
 
 function set_sequence_number()
@@ -527,7 +524,7 @@
             export TARGET_BUILD_VARIANT=$default_value
         elif (echo -n $ANSWER | grep -q -e "^[0-9][0-9]*$") ; then
             if [ "$ANSWER" -le "${#VARIANT_CHOICES[@]}" ] ; then
-                export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[$(($ANSWER-1))]}
+                export TARGET_BUILD_VARIANT=${VARIANT_CHOICES[@]:$(($ANSWER-1)):1}
             fi
         else
             if check_variant $ANSWER
@@ -575,6 +572,7 @@
 function print_lunch_menu()
 {
     local uname=$(uname)
+    local choices=$(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES)
     echo
     echo "You're building on" $uname
     echo
@@ -582,7 +580,7 @@
 
     local i=1
     local choice
-    for choice in $(TARGET_BUILD_APPS= get_build_var COMMON_LUNCH_CHOICES)
+    for choice in $(echo $choices)
     do
         echo "     $i. $choice"
         i=$(($i+1))
@@ -1297,10 +1295,10 @@
                 echo "Invalid choice"
                 continue
             fi
-            pathname=${lines[$(($choice-1))]}
+            pathname=${lines[@]:$(($choice-1)):1}
         done
     else
-        pathname=${lines[0]}
+        pathname=${lines[@]:0:1}
     fi
     \cd $T/$pathname
 }
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index ac21918..d11f9d2 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -7,6 +7,9 @@
 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
 
@@ -35,9 +38,25 @@
   # 3G + header
   BOARD_SUPER_PARTITION_SIZE := 3229614080
   BOARD_SUPER_PARTITION_GROUPS := emulator_dynamic_partitions
-  BOARD_EMULATOR_DYNAMIC_PARTITIONS_PARTITION_LIST := \
-      system \
-      vendor
+
+  ifeq ($(QEMU_USE_SYSTEM_EXT_PARTITIONS),true)
+    BOARD_EMULATOR_DYNAMIC_PARTITIONS_PARTITION_LIST := \
+        system \
+        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
+  else
+    TARGET_COPY_OUT_PRODUCT := system/product
+    TARGET_COPY_OUT_SYSTEM_EXT := system/system_ext
+    BOARD_EMULATOR_DYNAMIC_PARTITIONS_PARTITION_LIST := \
+        system \
+        vendor
+  endif
 
   # 3G
   BOARD_EMULATOR_DYNAMIC_PARTITIONS_SIZE := 3221225472
@@ -55,6 +74,12 @@
   BOARD_VENDORIMAGE_PARTITION_SIZE := 146800640
 endif
 
+# 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
 DEVICE_MATRIX_FILE   := device/generic/goldfish/compatibility_matrix.xml
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index e4dd032..61aa67c 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -33,17 +33,11 @@
 #   updating the last seen rollback index in the tamper-evident storage.
 BOARD_AVB_ROLLBACK_INDEX := 0
 
-# 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
-
 # GSI specific System Properties
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-TARGET_SYSTEM_PROP := build/make/target/board/gsi_system.prop
+TARGET_SYSTEM_EXT_PROP := build/make/target/board/gsi_system_ext.prop
 else
-TARGET_SYSTEM_PROP := build/make/target/board/gsi_system_user.prop
+TARGET_SYSTEM_EXT_PROP := build/make/target/board/gsi_system_ext_user.prop
 endif
 
 # Set this to create /cache mount point for non-A/B devices that mounts /cache.
@@ -56,7 +50,3 @@
 
 # Disable 64 bit mediadrmserver
 TARGET_ENABLE_MEDIADRM_64 :=
-
-# Ordinary (non-flattened) APEX may require kernel changes. For maximum compatibility,
-# use flattened APEX for GSI
-TARGET_FLATTEN_APEX := true
diff --git a/target/board/BoardConfigMainlineCommon.mk b/target/board/BoardConfigMainlineCommon.mk
index 70cfe39..52ba814 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -13,6 +13,10 @@
 TARGET_COPY_OUT_VENDOR := vendor
 TARGET_COPY_OUT_PRODUCT := product
 
+# Creates metadata partition mount point under root for
+# the devices with metadata parition
+BOARD_USES_METADATA_PARTITION := true
+
 BOARD_VNDK_VERSION := current
 
 # Required flag for non-64 bit devices from P.
@@ -45,6 +49,3 @@
 
 # Generate an APEX image for experiment b/119800099.
 DEXPREOPT_GENERATE_APEX_IMAGE := true
-
-# Mainline devices support apex
-TARGET_FLATTEN_APEX := false
diff --git a/target/board/generic/system.prop b/target/board/generic/system_ext.prop
similarity index 100%
rename from target/board/generic/system.prop
rename to target/board/generic/system_ext.prop
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index ecc547f..f5caf70 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -67,7 +67,7 @@
 
 # TODO(b/36764215): remove this setting when the generic system image
 # no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64_ab/sepolicy
+BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64/sepolicy
 
 # Wifi.
 BOARD_WLAN_DEVICE           := emulator
diff --git a/target/board/generic_arm64_ab/sepolicy/OWNERS b/target/board/generic_arm64/sepolicy/OWNERS
similarity index 100%
rename from target/board/generic_arm64_ab/sepolicy/OWNERS
rename to target/board/generic_arm64/sepolicy/OWNERS
diff --git a/target/board/generic_arm64_ab/sepolicy/file.te b/target/board/generic_arm64/sepolicy/file.te
similarity index 100%
rename from target/board/generic_arm64_ab/sepolicy/file.te
rename to target/board/generic_arm64/sepolicy/file.te
diff --git a/target/board/generic_arm64_ab/sepolicy/file_contexts b/target/board/generic_arm64/sepolicy/file_contexts
similarity index 100%
rename from target/board/generic_arm64_ab/sepolicy/file_contexts
rename to target/board/generic_arm64/sepolicy/file_contexts
diff --git a/target/board/generic_arm64/system.prop b/target/board/generic_arm64/system_ext.prop
similarity index 100%
rename from target/board/generic_arm64/system.prop
rename to target/board/generic_arm64/system_ext.prop
diff --git a/target/board/generic_arm64_ab/BoardConfig.mk b/target/board/generic_arm64_ab/BoardConfig.mk
deleted file mode 100644
index 28140ce..0000000
--- a/target/board/generic_arm64_ab/BoardConfig.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm64
-TARGET_ARCH_VARIANT := armv8-a
-TARGET_CPU_ABI := arm64-v8a
-TARGET_CPU_ABI2 :=
-TARGET_CPU_VARIANT := generic
-
-TARGET_2ND_ARCH := arm
-TARGET_2ND_ARCH_VARIANT := armv8-a
-TARGET_2ND_CPU_ABI := armeabi-v7a
-TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_CPU_VARIANT := generic
-
-# TODO(jiyong) These might be SoC specific.
-BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
-
-# TODO(b/36764215): remove this setting when the generic system image
-# no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64_ab/sepolicy
diff --git a/target/board/generic_arm_ab/BoardConfig.mk b/target/board/generic_arm_ab/BoardConfig.mk
deleted file mode 100644
index bcb4cc5..0000000
--- a/target/board/generic_arm_ab/BoardConfig.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_ARCH := arm
-TARGET_ARCH_VARIANT := armv7-a-neon
-TARGET_CPU_ABI := armeabi-v7a
-TARGET_CPU_ABI2 := armeabi
-TARGET_CPU_VARIANT := generic
-
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
-
-# TODO(jiyong) These might be SoC specific.
-BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/lib/dsp:/dsp
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/image:/firmware/image
-BOARD_ROOT_EXTRA_SYMLINKS += /vendor/firmware_mnt/verinfo:/firmware/verinfo
-
-# TODO(b/36764215): remove this setting when the generic system image
-# no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64_ab/sepolicy
diff --git a/target/board/generic_x86/system.prop b/target/board/generic_x86/system_ext.prop
similarity index 100%
rename from target/board/generic_x86/system.prop
rename to target/board/generic_x86/system_ext.prop
diff --git a/target/board/generic_x86_64/system.prop b/target/board/generic_x86_64/system_ext.prop
similarity index 100%
rename from target/board/generic_x86_64/system.prop
rename to target/board/generic_x86_64/system_ext.prop
diff --git a/target/board/generic_x86_64_arm64/BoardConfig.mk b/target/board/generic_x86_64_arm64/BoardConfig.mk
new file mode 100755
index 0000000..f528294
--- /dev/null
+++ b/target/board/generic_x86_64_arm64/BoardConfig.mk
@@ -0,0 +1,59 @@
+# 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.
+#
+
+# 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/generic_x86_64_arm64/README.txt b/target/board/generic_x86_64_arm64/README.txt
new file mode 100644
index 0000000..48ee319
--- /dev/null
+++ b/target/board/generic_x86_64_arm64/README.txt
@@ -0,0 +1,10 @@
+The "generic_x86_64" product defines a non-hardware-specific IA target
+without a kernel or bootloader.
+
+It can be used to build the entire user-level system, and
+will work with the IA version of the emulator,
+
+It is not a product "base class"; no other products inherit
+from it or use it in any way.
+
+Third party arm64 to x86_64 translator has to be installed as well
diff --git a/target/board/generic_x86_64_ab/BoardConfig.mk b/target/board/generic_x86_64_arm64/device.mk
old mode 100644
new mode 100755
similarity index 66%
copy from target/board/generic_x86_64_ab/BoardConfig.mk
copy to target/board/generic_x86_64_arm64/device.mk
index 1dd5e48..fa1eb67
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ b/target/board/generic_x86_64_arm64/device.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2017 The Android Open-Source Project
+# 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.
@@ -13,13 +13,3 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-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
diff --git a/target/board/generic_x86_64/system.prop b/target/board/generic_x86_64_arm64/system_ext.prop
similarity index 100%
copy from target/board/generic_x86_64/system.prop
copy to target/board/generic_x86_64_arm64/system_ext.prop
diff --git a/target/board/generic_x86_ab/BoardConfig.mk b/target/board/generic_x86_ab/BoardConfig.mk
deleted file mode 100644
index 53acffd..0000000
--- a/target/board/generic_x86_ab/BoardConfig.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-TARGET_CPU_ABI := x86
-TARGET_ARCH := x86
-TARGET_ARCH_VARIANT := x86
-
-# Legacy GSI keeps 32 bits binder for 32 bits CPU Arch
-TARGET_USES_64_BIT_BINDER := false
diff --git a/target/board/generic_x86_arm/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
index 6fae411..f6589b0 100644
--- a/target/board/generic_x86_arm/BoardConfig.mk
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -18,21 +18,23 @@
 TARGET_ARCH := x86
 TARGET_ARCH_VARIANT := x86
 
-TARGET_2ND_ARCH := arm
-TARGET_2ND_CPU_ABI := armeabi-v7a
-TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_ARCH_VARIANT := armv7-a-neon
-TARGET_2ND_CPU_VARIANT := generic
-
-TARGET_CPU_ABI_LIST := x86 armeabi-v7a armeabi
-TARGET_TRANSLATE_2ND_ARCH := true
+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
 
-
-include build/make/target/board/BoardConfigGsiCommon.mk
+#
+# 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 accomodate ASAN and CTS
 BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
 
diff --git a/target/board/generic_x86_arm/device.mk b/target/board/generic_x86_arm/device.mk
index 0a32415..fa1eb67 100644
--- a/target/board/generic_x86_arm/device.mk
+++ b/target/board/generic_x86_arm/device.mk
@@ -13,12 +13,3 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-# NFC:
-#   Provide default libnfc-nci.conf file for devices that does not have one in
-#   vendor/etc because aosp system image (of aosp_$arch products) is going to
-#   be used as GSI.
-#   May need to remove the following for newly launched devices in P since this
-#   NFC configuration file should be in vendor/etc, instead of system/etc
-PRODUCT_COPY_FILES += \
-    device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf
diff --git a/target/board/generic_x86_arm/system.prop b/target/board/generic_x86_arm/system_ext.prop
similarity index 100%
rename from target/board/generic_x86_arm/system.prop
rename to target/board/generic_x86_arm/system_ext.prop
diff --git a/target/board/generic_x86_64_ab/BoardConfig.mk b/target/board/go_defaults.prop
similarity index 66%
rename from target/board/generic_x86_64_ab/BoardConfig.mk
rename to target/board/go_defaults.prop
index 1dd5e48..93071cd 100644
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ b/target/board/go_defaults.prop
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2017 The Android Open-Source Project
+# Copyright (C) 2017 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.
@@ -13,13 +13,3 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-include build/make/target/board/BoardConfigGsiCommon.mk
-
-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
diff --git a/target/board/generic_x86_64_ab/BoardConfig.mk b/target/board/go_defaults_512.prop
similarity index 66%
copy from target/board/generic_x86_64_ab/BoardConfig.mk
copy to target/board/go_defaults_512.prop
index 1dd5e48..a8eea9c 100644
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ b/target/board/go_defaults_512.prop
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2017 The Android Open-Source Project
+# Copyright (C) 2017 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.
@@ -14,12 +14,10 @@
 # limitations under the License.
 #
 
-include build/make/target/board/BoardConfigGsiCommon.mk
+# 512MB specific properties.
 
-TARGET_CPU_ABI := x86_64
-TARGET_ARCH := x86_64
-TARGET_ARCH_VARIANT := x86_64
+# lmkd can kill more now.
+ro.lmk.medium=700
 
-TARGET_2ND_CPU_ABI := x86
-TARGET_2ND_ARCH := x86
-TARGET_2ND_ARCH_VARIANT := x86_64
+# madvise random in ART to reduce page cache thrashing.
+dalvik.vm.madvise-random=true
diff --git a/target/board/go_defaults_common.prop b/target/board/go_defaults_common.prop
new file mode 100644
index 0000000..d4989e0
--- /dev/null
+++ b/target/board/go_defaults_common.prop
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2017 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.
+#
+
+# Sets Android Go recommended default values for propreties.
+
+# Set lowram options
+ro.lmk.critical_upgrade=true
+ro.lmk.upgrade_pressure=40
+ro.lmk.downgrade_pressure=60
+ro.lmk.kill_heaviest_task=false
+ro.statsd.enable=true
+
+# set threshold to filter unused apps
+pm.dexopt.downgrade_after_inactive_days=10
+
+# set the compiler filter for shared apks to quicken.
+# Rationale: speed has a lot of dex code expansion, it uses more ram and space
+# compared to quicken. Using quicken for shared APKs on Go devices may save RAM.
+# Note that this is a trade-off: here we trade clean pages for dirty pages,
+# extra cpu and battery. That's because the quicken files will be jit-ed in all
+# the processes that load of shared apk and the code cache is not shared.
+# Some notable apps that will be affected by this are gms and chrome.
+# b/65591595.
+pm.dexopt.shared=quicken
+
+# Default heap sizes. Allow up to 256m for large heaps to make sure a single app
+# doesn't take all of the RAM.
+dalvik.vm.heapgrowthlimit=128m
+dalvik.vm.heapsize=256m
diff --git a/target/board/gsi_arm64/BoardConfig.mk b/target/board/gsi_arm64/BoardConfig.mk
index 571d623..db6f3f0 100644
--- a/target/board/gsi_arm64/BoardConfig.mk
+++ b/target/board/gsi_arm64/BoardConfig.mk
@@ -34,4 +34,4 @@
 
 # TODO(b/36764215): remove this setting when the generic system image
 # no longer has QCOM-specific directories under /.
-BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64_ab/sepolicy
+BOARD_SEPOLICY_DIRS += build/make/target/board/generic_arm64/sepolicy
diff --git a/target/board/gsi_system.prop b/target/board/gsi_system_ext.prop
similarity index 100%
rename from target/board/gsi_system.prop
rename to target/board/gsi_system_ext.prop
diff --git a/target/board/gsi_system_user.prop b/target/board/gsi_system_ext_user.prop
similarity index 100%
rename from target/board/gsi_system_user.prop
rename to target/board/gsi_system_ext_user.prop
diff --git a/target/board/mainline_arm64/BoardConfig.mk b/target/board/mainline_arm64/BoardConfig.mk
index 70505f4..7cb2609 100644
--- a/target/board/mainline_arm64/BoardConfig.mk
+++ b/target/board/mainline_arm64/BoardConfig.mk
@@ -32,5 +32,11 @@
 AB_OTA_UPDATER := true
 AB_OTA_PARTITIONS := system
 
-BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
 BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
+
+# Mainline devices support apex
+# TODO: move this to BoardConfigMainlineCommon. Currently, GSI wants flattened
+#       apexes, but emulator wants .apex files, preventing this.
+TARGET_FLATTEN_APEX := false
diff --git a/target/board/mainline_x86/BoardConfig.mk b/target/board/mainline_x86/BoardConfig.mk
new file mode 100644
index 0000000..a20d17c
--- /dev/null
+++ b/target/board/mainline_x86/BoardConfig.mk
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+TARGET_ARCH := x86
+TARGET_ARCH_VARIANT := x86
+TARGET_CPU_ABI := x86
+
+include build/make/target/board/BoardConfigMainlineCommon.mk
+
+TARGET_NO_KERNEL := true
+
+# Build generic A/B format system-only OTA.
+AB_OTA_UPDATER := true
+AB_OTA_PARTITIONS := system
+
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
+
+# Mainline devices support apex
+# TODO: move this to product makefile and use updatable_apex.mk
+TARGET_FLATTEN_APEX := false
diff --git a/target/board/mainline_x86_arm/BoardConfig.mk b/target/board/mainline_x86_arm/BoardConfig.mk
new file mode 100644
index 0000000..6b282c2
--- /dev/null
+++ b/target/board/mainline_x86_arm/BoardConfig.mk
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+TARGET_ARCH := x86
+TARGET_ARCH_VARIANT := x86
+TARGET_CPU_ABI := 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
+
+include build/make/target/board/BoardConfigMainlineCommon.mk
+
+TARGET_NO_KERNEL := true
+
+# Build generic A/B format system-only OTA.
+AB_OTA_UPDATER := true
+AB_OTA_PARTITIONS := system
+
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
+
+# Mainline devices support apex
+# TODO: move this to product makefile and use updatable_apex.mk
+TARGET_FLATTEN_APEX := false
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index cfb8930..ca4ed2c 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -43,13 +43,9 @@
 
 else
 PRODUCT_MAKEFILES := \
-    $(LOCAL_DIR)/aosp_arm64_ab.mk \
     $(LOCAL_DIR)/aosp_arm64.mk \
-    $(LOCAL_DIR)/aosp_arm_ab.mk \
     $(LOCAL_DIR)/aosp_arm.mk \
-    $(LOCAL_DIR)/aosp_x86_64_ab.mk \
     $(LOCAL_DIR)/aosp_x86_64.mk \
-    $(LOCAL_DIR)/aosp_x86_ab.mk \
     $(LOCAL_DIR)/aosp_x86_arm.mk \
     $(LOCAL_DIR)/aosp_x86.mk \
     $(LOCAL_DIR)/full.mk \
@@ -59,6 +55,8 @@
     $(LOCAL_DIR)/gsi_arm64.mk \
     $(LOCAL_DIR)/mainline_arm64.mk \
     $(LOCAL_DIR)/mainline_system_arm64.mk \
+    $(LOCAL_DIR)/mainline_system_x86.mk \
+    $(LOCAL_DIR)/mainline_system_x86_arm.mk \
     $(LOCAL_DIR)/sdk_arm64.mk \
     $(LOCAL_DIR)/sdk.mk \
     $(LOCAL_DIR)/sdk_phone_arm64.mk \
diff --git a/target/product/aosp_arm64_ab.mk b/target/product/aosp_arm64_ab.mk
deleted file mode 100644
index f707a39..0000000
--- a/target/product/aosp_arm64_ab.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# Copyright (C) 2017 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_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_arm64_ab-userdebug is a Legacy GSI for the devices with:
-# - ARM 64 bits user space
-# - 64 bits binder interface
-# - system-as-root
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_arm64_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    root/init.zygote32_64.rc \
-    root/init.zygote64_32.rc \
-
-# Copy different zygote settings for vendor.img to select by setting property
-# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
-#   1. 64-bit primary, 32-bit secondary OR
-#   2. 32-bit primary, 64-bit secondary
-# init.zygote64_32.rc is in the core_64_bit.mk below
-PRODUCT_COPY_FILES += \
-    system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
-
-PRODUCT_NAME := aosp_arm64_ab
-PRODUCT_DEVICE := generic_arm64_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM64
diff --git a/target/product/aosp_arm_ab.mk b/target/product/aosp_arm_ab.mk
deleted file mode 100644
index e760932..0000000
--- a/target/product/aosp_arm_ab.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2017 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_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_arm_ab-userdebug is a Legacy GSI for the devices with:
-# - ARM 32 bits user space
-# - 32 bits binder interface
-# - system-as-root
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_arm_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-PRODUCT_NAME := aosp_arm_ab
-PRODUCT_DEVICE := generic_arm_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on ARM32
diff --git a/target/product/aosp_product.mk b/target/product/aosp_product.mk
index fa56779..aefad82 100644
--- a/target/product/aosp_product.mk
+++ b/target/product/aosp_product.mk
@@ -21,27 +21,11 @@
 # Default AOSP sounds
 $(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
 
-# TODO(b/133643923): Clean up the mainline whitelist
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    system/app/messaging/messaging.apk \
-    system/app/messaging/oat/% \
-    system/app/WAPPushManager/WAPPushManager.apk \
-    system/app/WAPPushManager/oat/% \
-    system/bin/healthd \
-    system/etc/init/healthd.rc \
-    system/etc/seccomp_policy/crash_dump.%.policy \
-    system/etc/seccomp_policy/mediacodec.policy \
-    system/etc/vintf/manifest/manifest_healthd.xml \
-    system/lib/libframesequence.so \
-    system/lib/libgiftranscode.so \
-    system/lib64/libframesequence.so \
-    system/lib64/libgiftranscode.so \
-
-
 # Additional settings used in all AOSP builds
 PRODUCT_PRODUCT_PROPERTIES += \
     ro.config.ringtone=Ring_Synth_04.ogg \
     ro.config.notification_sound=pixiedust.ogg \
+    ro.com.android.dataroaming=true \
 
 # More AOSP packages
 PRODUCT_PACKAGES += \
diff --git a/target/product/aosp_x86_64_ab.mk b/target/product/aosp_x86_64_ab.mk
deleted file mode 100644
index dfb7b49..0000000
--- a/target/product/aosp_x86_64_ab.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# Copyright (C) 2017 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_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_x86_64_ab-userdebug is a Legacy GSI for the devices with:
-# - x86 64 bits user space
-# - 64 bits binder interface
-# - system-as-root
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_x86_64_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    root/init.zygote32_64.rc \
-    root/init.zygote64_32.rc \
-
-# Copy different zygote settings for vendor.img to select by setting property
-# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
-#   1. 64-bit primary, 32-bit secondary OR
-#   2. 32-bit primary, 64-bit secondary
-# init.zygote64_32.rc is in the core_64_bit.mk below
-PRODUCT_COPY_FILES += \
-    system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
-
-PRODUCT_NAME := aosp_x86_64_ab
-PRODUCT_DEVICE := generic_x86_64_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86_64
diff --git a/target/product/aosp_x86_ab.mk b/target/product/aosp_x86_ab.mk
deleted file mode 100644
index d07351c..0000000
--- a/target/product/aosp_x86_ab.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2017 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_PROPERTY_OVERRIDES cannot be used here because sysprops will be at
-# /vendor/[build|default].prop when build split is on. In order to have sysprops
-# on the generic system image, place them in build/make/target/board/
-# gsi_system.prop.
-
-# aosp_x86_ab-userdebug is a Legacy GSI for the devices with:
-# - x86 32 bits user space
-# - 32 bits binder interface
-# - system-as-root
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/legacy_gsi_common.mk)
-
-# Enable mainline checking for excat this product name
-ifeq (aosp_x86_ab,$(TARGET_PRODUCT))
-PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
-endif
-
-PRODUCT_NAME := aosp_x86_ab
-PRODUCT_DEVICE := generic_x86_ab
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on x86
diff --git a/target/product/aosp_x86_arm.mk b/target/product/aosp_x86_arm.mk
index 70aa64e..c0f8f8a 100644
--- a/target/product/aosp_x86_arm.mk
+++ b/target/product/aosp_x86_arm.mk
@@ -16,27 +16,35 @@
 
 PRODUCT_USE_DYNAMIC_PARTITIONS := true
 
-# aosp_x86 with arm libraries needed by binary translation.
+#
+# All components inherited here go to system image
+#
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
 
-# The system image of aosp_x86-userdebug is a GSI for the devices with:
-# - x86 32 bits user space
-# - 64 bits binder interface
-# - system-as-root
-# - VNDK enforcement
-# - compatible property override enabled
+# Enable mainline checking
+ifeq (aosp_x86_arm,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
 
--include device/generic/goldfish/x86-vendor.mk
+# TODO (b/138382074): remove following setting after enable product/system_ext
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    system/product/% \
+    system/system_ext/%
 
-include $(SRC_TARGET_DIR)/product/full_x86.mk
+#
+# All components inherited here go to product image
+#
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk)
 
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
+#
+# All components inherited here go to vendor image
+#
+$(call inherit-product-if-exists, device/generic/goldfish/x86-vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_arm/device.mk)
 
-# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
-
-# Support addtional P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
 
 PRODUCT_NAME := aosp_x86_arm
 PRODUCT_DEVICE := generic_x86_arm
+PRODUCT_BRAND := Android
+PRODUCT_MODEL := AOSP on IA Emulator
diff --git a/target/product/base_product.mk b/target/product/base_product.mk
index 749d2c2..2ed550c 100644
--- a/target/product/base_product.mk
+++ b/target/product/base_product.mk
@@ -17,7 +17,6 @@
 # Base modules and settings for the product partition.
 PRODUCT_PACKAGES += \
     group_product \
-    healthd \
     ModuleMetadata \
     passwd_product \
     product_compatibility_matrix.xml \
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 60646c3..f49218a 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -19,9 +19,6 @@
     abb \
     adbd \
     am \
-    android.hardware.neuralnetworks@1.0 \
-    android.hardware.neuralnetworks@1.1 \
-    android.hardware.neuralnetworks@1.2 \
     android.hidl.allocator@1.0-service \
     android.hidl.base-V1.0-java \
     android.hidl.manager-V1.0-java \
@@ -32,11 +29,9 @@
     android.test.mock \
     android.test.runner \
     apexd \
-    applypatch \
     appops \
     app_process \
     appwidget \
-    ashmemd \
     atrace \
     audioserver \
     BackupRestoreConfirmation \
@@ -53,9 +48,12 @@
     cgroups.json \
     charger \
     cmd \
+    com.android.apex.cts.shim.v1_prebuilt \
     com.android.conscrypt \
     com.android.i18n \
     com.android.location.provider \
+    com.android.media \
+    com.android.media.swcodec \
     com.android.resolv \
     com.android.neuralnetworks \
     com.android.tzdata \
@@ -65,13 +63,14 @@
     CtsShimPrebuilt \
     CtsShimPrivPrebuilt \
     debuggerd\
-    DefaultContainerService \
+    device_config \
     dmctl \
     dnsmasq \
     DownloadProvider \
     dpm \
     dumpstate \
     dumpsys \
+    DynamicSystemInstallationService \
     e2fsck \
     ExtServices \
     ExtShared \
@@ -84,6 +83,7 @@
     fs_config_dirs_system \
     group_system \
     gsid \
+    gsi_tool \
     heapprofd \
     heapprofd_client \
     gatekeeperd \
@@ -91,6 +91,8 @@
     hid \
     hwservicemanager \
     idmap \
+    idmap2 \
+    idmap2d \
     ime \
     ims-common \
     incident \
@@ -111,17 +113,13 @@
     ld.config.txt \
     ld.mc \
     libaaudio \
+    libamidi \
     libandroid \
     libandroidfw \
     libandroid_runtime \
     libandroid_servers \
     libartpalette-system \
-    libashmemd_client \
     libaudioeffect_jni \
-    libaudioflinger \
-    libaudiopolicymanager \
-    libaudiopolicyservice \
-    libaudioutils \
     libbinder \
     libbinder_ndk \
     libc.bootstrap \
@@ -154,11 +152,11 @@
     libmedia \
     libmedia_jni \
     libmediandk \
-    libmediaplayerservice \
     libmtp \
     libnetd_client \
     libnetlink \
     libnetutils \
+    libneuralnetworks_packageinfo \
     libOpenMAXAL \
     libOpenSLES \
     libpdfium \
@@ -168,17 +166,14 @@
     libradio_metadata \
     librtp_jni \
     libsensorservice \
+    libsfplugin_ccodec \
     libskia \
     libsonic \
     libsonivox \
     libsoundpool \
-    libsoundtrigger \
-    libsoundtriggerservice \
     libspeexresampler \
     libsqlite \
     libstagefright \
-    libstagefright_amrnb_common \
-    libstagefright_enc_common \
     libstagefright_foundation \
     libstagefright_omx \
     libstdc++ \
@@ -187,13 +182,13 @@
     libui \
     libusbhost \
     libutils \
-    libvorbisidec \
     libvulkan \
     libwifi-service \
     libwilhelm \
     linker \
     linkerconfig \
     lmkd \
+    LocalTransport \
     locksettings \
     logcat \
     logd \
@@ -201,6 +196,7 @@
     lshal \
     mdnsd \
     media \
+    mediacodec.policy \
     mediadrmserver \
     mediaextractor \
     mediametrics \
@@ -215,8 +211,10 @@
     NetworkStack \
     org.apache.http.legacy \
     otacerts \
+    PackageInstaller \
     passwd_system \
     perfetto \
+    PermissionController \
     ping \
     ping6 \
     platform.xml \
@@ -245,6 +243,7 @@
     Shell \
     shell_and_utilities_system \
     sm \
+    snapshotctl \
     statsd \
     storaged \
     surfaceflinger \
@@ -253,7 +252,6 @@
     tc \
     telecom \
     telephony-common \
-    thermalserviced \
     tombstoned \
     traced \
     traced_probes \
@@ -266,8 +264,6 @@
     viewcompiler \
     voip-common \
     vold \
-    vndkcore.libraries.txt \
-    vndkprivate.libraries.txt \
     WallpaperBackup \
     watchdogd \
     wificond \
@@ -292,6 +288,7 @@
     flags_health_check \
     icu-data_host_i18n_apex \
     icu_tzdata.dat_host_tzdata_apex \
+    idmap2 \
     incident_report \
     ld.mc \
     lpdump \
@@ -325,10 +322,12 @@
     ext \
     telephony-common \
     voip-common \
-    ims-common
-PRODUCT_UPDATABLE_BOOT_MODULES := conscrypt
+    ims-common \
+    updatable-media
+PRODUCT_UPDATABLE_BOOT_MODULES := conscrypt updatable-media
 PRODUCT_UPDATABLE_BOOT_LOCATIONS := \
-    /apex/com.android.conscrypt/javalib/conscrypt.jar
+    /apex/com.android.conscrypt/javalib/conscrypt.jar \
+    /apex/com.android.media/javalib/updatable-media.jar
 
 
 PRODUCT_COPY_FILES += \
@@ -357,8 +356,10 @@
     adb_keys \
     arping \
     gdbserver \
+    idlcli \
     init-debug.rc \
     iotop \
+    iperf3 \
     iw \
     logpersist.start \
     logtagd.rc \
@@ -383,7 +384,9 @@
     WallpaperBackup
 
 # Packages included only for eng/userdebug builds, when building with SANITIZE_TARGET=address
-PRODUCT_PACKAGES_DEBUG_ASAN :=
+PRODUCT_PACKAGES_DEBUG_ASAN := \
+    fuzz \
+    honggfuzz
 
 PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE := \
     libdumpcoverage
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index e3c600f..1657e71 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -40,9 +40,10 @@
 
 # Base modules and settings for the vendor partition.
 PRODUCT_PACKAGES += \
-    android.hardware.cas@1.0-service \
+    android.hardware.cas@1.1-service \
     android.hardware.configstore@1.1-service \
     android.hardware.media.omx@1.0-service \
+    boringssl_self_test_vendor \
     dumpsys_vendor \
     fs_config_files_nonsystem \
     fs_config_dirs_nonsystem \
@@ -51,7 +52,6 @@
     group_system_ext \
     group_vendor \
     init_vendor \
-    libashmemd_hidl_client \
     libbundlewrapper \
     libclearkeycasplugin \
     libdownmix \
@@ -75,3 +75,8 @@
 # VINTF data for vendor image
 PRODUCT_PACKAGES += \
     device_compatibility_matrix.xml \
+
+# Packages to update the recovery partition, which will be installed on
+# /vendor. TODO(b/141648565): Don't install these unless they're needed.
+PRODUCT_PACKAGES += \
+    applypatch
diff --git a/target/product/emulator.mk b/target/product/emulator.mk
index f6e1011..7ff01cd 100644
--- a/target/product/emulator.mk
+++ b/target/product/emulator.mk
@@ -53,14 +53,16 @@
 #config.disable_location=true
 
 # Enable Perfetto traced
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+# There is a stable property API for this prop so we can move it to /product.
+# https://android-review.googlesource.com/c/platform/system/libsysprop/+/952375
+PRODUCT_PRODUCT_PROPERTIES += \
     persist.traced.enable=1
 
 # enable Google-specific location features,
 # like NetworkLocationProvider and LocationCollector
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+PRODUCT_SYSTEM_EXT_PROPERTIES += \
     ro.com.google.locationfeatures=1
 
 # disable setupwizard
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+PRODUCT_SYSTEM_EXT_PROPERTIES += \
     ro.setupwizard.mode=DISABLED
diff --git a/target/product/emulator_vendor.mk b/target/product/emulator_vendor.mk
index 727987c..e67124e 100644
--- a/target/product/emulator_vendor.mk
+++ b/target/product/emulator_vendor.mk
@@ -58,14 +58,16 @@
 #config.disable_location=true
 
 # Enable Perfetto traced
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+# There is a stable property API for this prop so we can move it to /product.
+# https://android-review.googlesource.com/c/platform/system/libsysprop/+/952375
+PRODUCT_PRODUCT_PROPERTIES += \
     persist.traced.enable=1
 
 # enable Google-specific location features,
 # like NetworkLocationProvider and LocationCollector
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+PRODUCT_SYSTEM_EXT_PROPERTIES += \
     ro.com.google.locationfeatures=1
 
 # disable setupwizard
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+PRODUCT_SYSTEM_EXT_PROPERTIES += \
     ro.setupwizard.mode=DISABLED
diff --git a/target/product/go_defaults.mk b/target/product/go_defaults.mk
index cb9383f..b717486 100644
--- a/target/product/go_defaults.mk
+++ b/target/product/go_defaults.mk
@@ -17,3 +17,6 @@
 # Inherit common Android Go defaults.
 $(call inherit-product, build/make/target/product/go_defaults_common.mk)
 
+# Add the system properties.
+TARGET_SYSTEM_PROP += \
+    build/make/target/board/go_defaults.prop
diff --git a/target/product/go_defaults_512.mk b/target/product/go_defaults_512.mk
index 985912f..70d067e 100644
--- a/target/product/go_defaults_512.mk
+++ b/target/product/go_defaults_512.mk
@@ -17,12 +17,6 @@
 # Inherit common Android Go defaults.
 $(call inherit-product, build/make/target/product/go_defaults_common.mk)
 
-# 512MB specific properties.
-
-# lmkd can kill more now.
-PRODUCT_PROPERTY_OVERRIDES += \
-     ro.lmk.medium=700 \
-
-# madvise random in ART to reduce page cache thrashing.
-PRODUCT_PROPERTY_OVERRIDES += \
-     dalvik.vm.madvise-random=true
+# Add the system properties.
+TARGET_SYSTEM_PROP += \
+    build/make/target/board/go_defaults_512.prop
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index 7042f6d..d4655f1 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -14,21 +14,13 @@
 # limitations under the License.
 #
 
-# Sets Android Go recommended default values for propreties.
+# Sets Android Go recommended default product options..
 
-# Set lowram options
+
+# Set lowram options and enable traced by default
 PRODUCT_PROPERTY_OVERRIDES += \
      ro.config.low_ram=true \
-     ro.lmk.critical_upgrade=true \
-     ro.lmk.upgrade_pressure=40 \
-     ro.lmk.downgrade_pressure=60 \
-     ro.lmk.kill_heaviest_task=false \
-     ro.statsd.enable=false
-
-# set threshold to filter unused apps
-PRODUCT_PROPERTY_OVERRIDES += \
-     pm.dexopt.downgrade_after_inactive_days=10
-
+     persist.traced.enable=1 \
 
 # Speed profile services and wifi-service to reduce RAM and storage.
 PRODUCT_SYSTEM_SERVER_COMPILER_FILTER := speed-profile
@@ -42,27 +34,12 @@
 PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE := true
 PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := frameworks/base/config/boot-image-profile.txt
 
-# set the compiler filter for shared apks to quicken.
-# Rationale: speed has a lot of dex code expansion, it uses more ram and space
-# compared to quicken. Using quicken for shared APKs on Go devices may save RAM.
-# Note that this is a trade-off: here we trade clean pages for dirty pages,
-# extra cpu and battery. That's because the quicken files will be jit-ed in all
-# the processes that load of shared apk and the code cache is not shared.
-# Some notable apps that will be affected by this are gms and chrome.
-# b/65591595.
-PRODUCT_PROPERTY_OVERRIDES += \
-     pm.dexopt.shared=quicken
-
-# Default heap sizes. Allow up to 256m for large heaps to make sure a single app
-# doesn't take all of the RAM.
-PRODUCT_PROPERTY_OVERRIDES += dalvik.vm.heapgrowthlimit=128m
-PRODUCT_PROPERTY_OVERRIDES += dalvik.vm.heapsize=256m
-
 # Do not generate libartd.
 PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD := false
 
 # Do not spin up a separate process for the network stack on go devices, use an in-process APK.
 PRODUCT_PACKAGES += InProcessNetworkStack
+PRODUCT_PACKAGES += CellBroadcastAppPlatform
 
 # Strip the local variable table and the local variable type table to reduce
 # the size of the system image. This has no bearing on stack traces, but will
@@ -73,3 +50,14 @@
 ifneq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
   PRODUCT_DISABLE_SCUDO := true
 endif
+
+# Add the system properties.
+TARGET_SYSTEM_PROP += \
+    build/make/target/board/go_defaults_common.prop
+
+# use the go specific handheld_core_hardware.xml from frameworks
+PRODUCT_COPY_FILES += \
+    frameworks/native/data/etc/go_handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml
+
+# Dedupe VNDK libraries with identical core variants.
+TARGET_VNDK_USE_CORE_VARIANT := true
diff --git a/target/product/gsi/29.txt b/target/product/gsi/29.txt
new file mode 100644
index 0000000..14faba5
--- /dev/null
+++ b/target/product/gsi/29.txt
@@ -0,0 +1,273 @@
+LLNDK: libEGL.so
+LLNDK: libGLESv1_CM.so
+LLNDK: libGLESv2.so
+LLNDK: libGLESv3.so
+LLNDK: libRS.so
+LLNDK: libandroid_net.so
+LLNDK: libc.so
+LLNDK: libcgrouprc.so
+LLNDK: libdl.so
+LLNDK: libft2.so
+LLNDK: liblog.so
+LLNDK: libm.so
+LLNDK: libmediandk.so
+LLNDK: libnativewindow.so
+LLNDK: libneuralnetworks.so
+LLNDK: libsync.so
+LLNDK: libvndksupport.so
+LLNDK: libvulkan.so
+VNDK-SP: android.hardware.graphics.common@1.0.so
+VNDK-SP: android.hardware.graphics.common@1.1.so
+VNDK-SP: android.hardware.graphics.common@1.2.so
+VNDK-SP: android.hardware.graphics.mapper@2.0.so
+VNDK-SP: android.hardware.graphics.mapper@2.1.so
+VNDK-SP: android.hardware.graphics.mapper@3.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.so
+VNDK-SP: android.hidl.memory@1.0-impl.so
+VNDK-SP: android.hidl.safe_union@1.0.so
+VNDK-SP: libRSCpuRef.so
+VNDK-SP: libRSDriver.so
+VNDK-SP: libRS_internal.so
+VNDK-SP: libbacktrace.so
+VNDK-SP: libbase.so
+VNDK-SP: libbcinfo.so
+VNDK-SP: libbinderthreadstate.so
+VNDK-SP: libblas.so
+VNDK-SP: libc++.so
+VNDK-SP: libcompiler_rt.so
+VNDK-SP: libcutils.so
+VNDK-SP: libhardware.so
+VNDK-SP: libhidlbase.so
+VNDK-SP: libhidlmemory.so
+VNDK-SP: libhidltransport.so
+VNDK-SP: libhwbinder.so
+VNDK-SP: libhwbinder_noltopgo.so
+VNDK-SP: libion.so
+VNDK-SP: libjsoncpp.so
+VNDK-SP: liblzma.so
+VNDK-SP: libprocessgroup.so
+VNDK-SP: libunwindstack.so
+VNDK-SP: libutils.so
+VNDK-SP: libutilscallstack.so
+VNDK-SP: libz.so
+VNDK-core: android.frameworks.cameraservice.common@2.0.so
+VNDK-core: android.frameworks.cameraservice.device@2.0.so
+VNDK-core: android.frameworks.cameraservice.service@2.0.so
+VNDK-core: android.frameworks.displayservice@1.0.so
+VNDK-core: android.frameworks.schedulerservice@1.0.so
+VNDK-core: android.frameworks.sensorservice@1.0.so
+VNDK-core: android.frameworks.stats@1.0.so
+VNDK-core: android.frameworks.vr.composer@1.0.so
+VNDK-core: android.hardware.atrace@1.0.so
+VNDK-core: android.hardware.audio.common@2.0.so
+VNDK-core: android.hardware.audio.common@4.0.so
+VNDK-core: android.hardware.audio.common@5.0.so
+VNDK-core: android.hardware.audio.effect@2.0.so
+VNDK-core: android.hardware.audio.effect@4.0.so
+VNDK-core: android.hardware.audio.effect@5.0.so
+VNDK-core: android.hardware.audio@2.0.so
+VNDK-core: android.hardware.audio@4.0.so
+VNDK-core: android.hardware.audio@5.0.so
+VNDK-core: android.hardware.authsecret@1.0.so
+VNDK-core: android.hardware.automotive.audiocontrol@1.0.so
+VNDK-core: android.hardware.automotive.evs@1.0.so
+VNDK-core: android.hardware.automotive.vehicle@2.0.so
+VNDK-core: android.hardware.biometrics.face@1.0.so
+VNDK-core: android.hardware.biometrics.fingerprint@2.1.so
+VNDK-core: android.hardware.bluetooth.a2dp@1.0.so
+VNDK-core: android.hardware.bluetooth.audio@2.0.so
+VNDK-core: android.hardware.bluetooth@1.0.so
+VNDK-core: android.hardware.boot@1.0.so
+VNDK-core: android.hardware.broadcastradio@1.0.so
+VNDK-core: android.hardware.broadcastradio@1.1.so
+VNDK-core: android.hardware.broadcastradio@2.0.so
+VNDK-core: android.hardware.camera.common@1.0.so
+VNDK-core: android.hardware.camera.device@1.0.so
+VNDK-core: android.hardware.camera.device@3.2.so
+VNDK-core: android.hardware.camera.device@3.3.so
+VNDK-core: android.hardware.camera.device@3.4.so
+VNDK-core: android.hardware.camera.device@3.5.so
+VNDK-core: android.hardware.camera.metadata@3.2.so
+VNDK-core: android.hardware.camera.metadata@3.3.so
+VNDK-core: android.hardware.camera.metadata@3.4.so
+VNDK-core: android.hardware.camera.provider@2.4.so
+VNDK-core: android.hardware.camera.provider@2.5.so
+VNDK-core: android.hardware.cas.native@1.0.so
+VNDK-core: android.hardware.cas@1.0.so
+VNDK-core: android.hardware.cas@1.1.so
+VNDK-core: android.hardware.configstore-utils.so
+VNDK-core: android.hardware.configstore@1.0.so
+VNDK-core: android.hardware.configstore@1.1.so
+VNDK-core: android.hardware.confirmationui-support-lib.so
+VNDK-core: android.hardware.confirmationui@1.0.so
+VNDK-core: android.hardware.contexthub@1.0.so
+VNDK-core: android.hardware.drm@1.0.so
+VNDK-core: android.hardware.drm@1.1.so
+VNDK-core: android.hardware.drm@1.2.so
+VNDK-core: android.hardware.dumpstate@1.0.so
+VNDK-core: android.hardware.fastboot@1.0.so
+VNDK-core: android.hardware.gatekeeper@1.0.so
+VNDK-core: android.hardware.gnss.measurement_corrections@1.0.so
+VNDK-core: android.hardware.gnss.visibility_control@1.0.so
+VNDK-core: android.hardware.gnss@1.0.so
+VNDK-core: android.hardware.gnss@1.1.so
+VNDK-core: android.hardware.gnss@2.0.so
+VNDK-core: android.hardware.graphics.allocator@2.0.so
+VNDK-core: android.hardware.graphics.allocator@3.0.so
+VNDK-core: android.hardware.graphics.bufferqueue@1.0.so
+VNDK-core: android.hardware.graphics.bufferqueue@2.0.so
+VNDK-core: android.hardware.graphics.composer@2.1.so
+VNDK-core: android.hardware.graphics.composer@2.2.so
+VNDK-core: android.hardware.graphics.composer@2.3.so
+VNDK-core: android.hardware.health.storage@1.0.so
+VNDK-core: android.hardware.health@1.0.so
+VNDK-core: android.hardware.health@2.0.so
+VNDK-core: android.hardware.input.classifier@1.0.so
+VNDK-core: android.hardware.input.common@1.0.so
+VNDK-core: android.hardware.ir@1.0.so
+VNDK-core: android.hardware.keymaster@3.0.so
+VNDK-core: android.hardware.keymaster@4.0.so
+VNDK-core: android.hardware.light@2.0.so
+VNDK-core: android.hardware.media.bufferpool@1.0.so
+VNDK-core: android.hardware.media.bufferpool@2.0.so
+VNDK-core: android.hardware.media.c2@1.0.so
+VNDK-core: android.hardware.media.omx@1.0.so
+VNDK-core: android.hardware.media@1.0.so
+VNDK-core: android.hardware.memtrack@1.0.so
+VNDK-core: android.hardware.neuralnetworks@1.0.so
+VNDK-core: android.hardware.neuralnetworks@1.1.so
+VNDK-core: android.hardware.neuralnetworks@1.2.so
+VNDK-core: android.hardware.nfc@1.0.so
+VNDK-core: android.hardware.nfc@1.1.so
+VNDK-core: android.hardware.nfc@1.2.so
+VNDK-core: android.hardware.oemlock@1.0.so
+VNDK-core: android.hardware.power.stats@1.0.so
+VNDK-core: android.hardware.power@1.0.so
+VNDK-core: android.hardware.power@1.1.so
+VNDK-core: android.hardware.power@1.2.so
+VNDK-core: android.hardware.power@1.3.so
+VNDK-core: android.hardware.radio.config@1.0.so
+VNDK-core: android.hardware.radio.config@1.1.so
+VNDK-core: android.hardware.radio.config@1.2.so
+VNDK-core: android.hardware.radio.deprecated@1.0.so
+VNDK-core: android.hardware.radio@1.0.so
+VNDK-core: android.hardware.radio@1.1.so
+VNDK-core: android.hardware.radio@1.2.so
+VNDK-core: android.hardware.radio@1.3.so
+VNDK-core: android.hardware.radio@1.4.so
+VNDK-core: android.hardware.secure_element@1.0.so
+VNDK-core: android.hardware.secure_element@1.1.so
+VNDK-core: android.hardware.sensors@1.0.so
+VNDK-core: android.hardware.sensors@2.0.so
+VNDK-core: android.hardware.soundtrigger@2.0.so
+VNDK-core: android.hardware.soundtrigger@2.0-core.so
+VNDK-core: android.hardware.soundtrigger@2.1.so
+VNDK-core: android.hardware.soundtrigger@2.2.so
+VNDK-core: android.hardware.tetheroffload.config@1.0.so
+VNDK-core: android.hardware.tetheroffload.control@1.0.so
+VNDK-core: android.hardware.thermal@1.0.so
+VNDK-core: android.hardware.thermal@1.1.so
+VNDK-core: android.hardware.thermal@2.0.so
+VNDK-core: android.hardware.tv.cec@1.0.so
+VNDK-core: android.hardware.tv.cec@2.0.so
+VNDK-core: android.hardware.tv.input@1.0.so
+VNDK-core: android.hardware.usb.gadget@1.0.so
+VNDK-core: android.hardware.usb@1.0.so
+VNDK-core: android.hardware.usb@1.1.so
+VNDK-core: android.hardware.usb@1.2.so
+VNDK-core: android.hardware.vibrator@1.0.so
+VNDK-core: android.hardware.vibrator@1.1.so
+VNDK-core: android.hardware.vibrator@1.2.so
+VNDK-core: android.hardware.vibrator@1.3.so
+VNDK-core: android.hardware.vr@1.0.so
+VNDK-core: android.hardware.weaver@1.0.so
+VNDK-core: android.hardware.wifi.hostapd@1.0.so
+VNDK-core: android.hardware.wifi.hostapd@1.1.so
+VNDK-core: android.hardware.wifi.offload@1.0.so
+VNDK-core: android.hardware.wifi.supplicant@1.0.so
+VNDK-core: android.hardware.wifi.supplicant@1.1.so
+VNDK-core: android.hardware.wifi.supplicant@1.2.so
+VNDK-core: android.hardware.wifi@1.0.so
+VNDK-core: android.hardware.wifi@1.1.so
+VNDK-core: android.hardware.wifi@1.2.so
+VNDK-core: android.hardware.wifi@1.3.so
+VNDK-core: android.hidl.allocator@1.0.so
+VNDK-core: android.hidl.memory.block@1.0.so
+VNDK-core: android.hidl.token@1.0.so
+VNDK-core: android.hidl.token@1.0-utils.so
+VNDK-core: android.system.net.netd@1.0.so
+VNDK-core: android.system.net.netd@1.1.so
+VNDK-core: android.system.suspend@1.0.so
+VNDK-core: android.system.wifi.keystore@1.0.so
+VNDK-core: libadf.so
+VNDK-core: libaudioroute.so
+VNDK-core: libaudioutils.so
+VNDK-core: libbinder.so
+VNDK-core: libcamera_metadata.so
+VNDK-core: libcap.so
+VNDK-core: libcn-cbor.so
+VNDK-core: libcodec2.so
+VNDK-core: libcrypto.so
+VNDK-core: libcrypto_utils.so
+VNDK-core: libcurl.so
+VNDK-core: libdiskconfig.so
+VNDK-core: libdumpstateutil.so
+VNDK-core: libevent.so
+VNDK-core: libexif.so
+VNDK-core: libexpat.so
+VNDK-core: libfmq.so
+VNDK-core: libgatekeeper.so
+VNDK-core: libgui.so
+VNDK-core: libhardware_legacy.so
+VNDK-core: libhidlallocatorutils.so
+VNDK-core: libhidlcache.so
+VNDK-core: libjpeg.so
+VNDK-core: libkeymaster_messages.so
+VNDK-core: libkeymaster_portable.so
+VNDK-core: libldacBT_abr.so
+VNDK-core: libldacBT_enc.so
+VNDK-core: liblz4.so
+VNDK-core: libmedia_helper.so
+VNDK-core: libmedia_omx.so
+VNDK-core: libmemtrack.so
+VNDK-core: libminijail.so
+VNDK-core: libmkbootimg_abi_check.so
+VNDK-core: libnetutils.so
+VNDK-core: libnl.so
+VNDK-core: libpcre2.so
+VNDK-core: libpiex.so
+VNDK-core: libpng.so
+VNDK-core: libpower.so
+VNDK-core: libprocinfo.so
+VNDK-core: libprotobuf-cpp-full.so
+VNDK-core: libprotobuf-cpp-lite.so
+VNDK-core: libpuresoftkeymasterdevice.so
+VNDK-core: libradio_metadata.so
+VNDK-core: libselinux.so
+VNDK-core: libsoftkeymasterdevice.so
+VNDK-core: libspeexresampler.so
+VNDK-core: libsqlite.so
+VNDK-core: libssl.so
+VNDK-core: libstagefright_bufferpool@2.0.so
+VNDK-core: libstagefright_bufferqueue_helper.so
+VNDK-core: libstagefright_foundation.so
+VNDK-core: libstagefright_omx.so
+VNDK-core: libstagefright_omx_utils.so
+VNDK-core: libstagefright_xmlparser.so
+VNDK-core: libsysutils.so
+VNDK-core: libtinyalsa.so
+VNDK-core: libtinyxml2.so
+VNDK-core: libui.so
+VNDK-core: libusbhost.so
+VNDK-core: libwifi-system-iface.so
+VNDK-core: libxml2.so
+VNDK-core: libyuv.so
+VNDK-core: libziparchive.so
+VNDK-private: libbacktrace.so
+VNDK-private: libbinderthreadstate.so
+VNDK-private: libblas.so
+VNDK-private: libcompiler_rt.so
+VNDK-private: libft2.so
+VNDK-private: libgui.so
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index c93e4ca..2b288e6 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -144,12 +144,15 @@
 LOCAL_MODULE := vndk_package
 # Filter LLNDK libs moved to APEX to avoid pulling them into /system/LIB
 LOCAL_REQUIRED_MODULES := \
-    $(filter-out $(LLNDK_MOVED_TO_APEX_LIBRARIES),$(LLNDK_LIBRARIES)))
+    $(filter-out $(LLNDK_MOVED_TO_APEX_LIBRARIES),$(LLNDK_LIBRARIES))
 
 ifneq ($(TARGET_SKIP_CURRENT_VNDK),true)
 LOCAL_REQUIRED_MODULES += \
     llndk.libraries.txt \
     vndksp.libraries.txt \
+    vndkcore.libraries.txt \
+    vndkprivate.libraries.txt \
+    vndkcorevariant.libraries.txt \
     $(addsuffix .vendor,$(VNDK_CORE_LIBRARIES)) \
     $(addsuffix .vendor,$(VNDK_SAMEPROCESS_LIBRARIES))
 endif
@@ -169,3 +172,38 @@
 include $(BUILD_PHONY_PACKAGE)
 
 endif # BOARD_VNDK_VERSION is set
+
+#####################################################################
+# skip_mount.cfg, read by init to skip mounting some partitions when GSI is used.
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := gsi_skip_mount.cfg
+LOCAL_MODULE_STEM := skip_mount.cfg
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SYSTEM_EXT_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := init/config
+
+# Adds a symlink under /system/etc/init/config pointing to /system/system_ext/etc/init/config
+# because first-stage init in Android 10.0 will read the skip_mount.cfg from /system/etc/* after
+# chroot /system.
+# TODO: remove this symlink when no need to support new GSI on Android 10.
+# The actual file needs to be under /system/system_ext because it's GSI-specific and does not
+# belong to core CSI.
+LOCAL_POST_INSTALL_CMD := \
+    mkdir -p $(TARGET_OUT)/etc/init; \
+    ln -sf /system/system_ext/etc/init/config $(TARGET_OUT)/etc/init/config
+
+include $(BUILD_PREBUILT)
+
+#####################################################################
+# init.gsi.rc, GSI-specific init script.
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := init.gsi.rc
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SYSTEM_EXT_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := init
+
+include $(BUILD_PREBUILT)
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 89e61d0..6649f28 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -19,8 +19,10 @@
 LLNDK: libvulkan.so
 VNDK-SP: android.hardware.graphics.common@1.0.so
 VNDK-SP: android.hardware.graphics.common@1.1.so
+VNDK-SP: android.hardware.graphics.common@1.2.so
 VNDK-SP: android.hardware.graphics.mapper@2.0.so
 VNDK-SP: android.hardware.graphics.mapper@2.1.so
+VNDK-SP: android.hardware.graphics.mapper@3.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.so
@@ -40,9 +42,6 @@
 VNDK-SP: libhardware.so
 VNDK-SP: libhidlbase.so
 VNDK-SP: libhidlmemory.so
-VNDK-SP: libhidltransport.so
-VNDK-SP: libhwbinder.so
-VNDK-SP: libhwbinder_noltopgo.so
 VNDK-SP: libion.so
 VNDK-SP: libjsoncpp.so
 VNDK-SP: liblzma.so
@@ -51,16 +50,16 @@
 VNDK-SP: libutils.so
 VNDK-SP: libutilscallstack.so
 VNDK-SP: libz.so
+VNDK-core: android.frameworks.cameraservice.common@2.0.so
+VNDK-core: android.frameworks.cameraservice.device@2.0.so
+VNDK-core: android.frameworks.cameraservice.service@2.0.so
 VNDK-core: android.frameworks.displayservice@1.0.so
 VNDK-core: android.frameworks.schedulerservice@1.0.so
 VNDK-core: android.frameworks.sensorservice@1.0.so
-VNDK-core: android.frameworks.vr.composer@1.0.so
+VNDK-core: android.frameworks.stats@1.0.so
 VNDK-core: android.hardware.atrace@1.0.so
-VNDK-core: android.hardware.audio.common-util.so
 VNDK-core: android.hardware.audio.common@2.0.so
-VNDK-core: android.hardware.audio.common@2.0-util.so
 VNDK-core: android.hardware.audio.common@4.0.so
-VNDK-core: android.hardware.audio.common@4.0-util.so
 VNDK-core: android.hardware.audio.common@5.0.so
 VNDK-core: android.hardware.audio.effect@2.0.so
 VNDK-core: android.hardware.audio.effect@4.0.so
@@ -72,6 +71,7 @@
 VNDK-core: android.hardware.automotive.audiocontrol@1.0.so
 VNDK-core: android.hardware.automotive.evs@1.0.so
 VNDK-core: android.hardware.automotive.vehicle@2.0.so
+VNDK-core: android.hardware.biometrics.face@1.0.so
 VNDK-core: android.hardware.biometrics.fingerprint@2.1.so
 VNDK-core: android.hardware.bluetooth.a2dp@1.0.so
 VNDK-core: android.hardware.bluetooth.audio@2.0.so
@@ -86,11 +86,15 @@
 VNDK-core: android.hardware.camera.device@3.2.so
 VNDK-core: android.hardware.camera.device@3.3.so
 VNDK-core: android.hardware.camera.device@3.4.so
+VNDK-core: android.hardware.camera.device@3.5.so
 VNDK-core: android.hardware.camera.metadata@3.2.so
 VNDK-core: android.hardware.camera.metadata@3.3.so
+VNDK-core: android.hardware.camera.metadata@3.4.so
 VNDK-core: android.hardware.camera.provider@2.4.so
+VNDK-core: android.hardware.camera.provider@2.5.so
 VNDK-core: android.hardware.cas.native@1.0.so
 VNDK-core: android.hardware.cas@1.0.so
+VNDK-core: android.hardware.cas@1.1.so
 VNDK-core: android.hardware.configstore-utils.so
 VNDK-core: android.hardware.configstore@1.0.so
 VNDK-core: android.hardware.configstore@1.1.so
@@ -99,23 +103,34 @@
 VNDK-core: android.hardware.contexthub@1.0.so
 VNDK-core: android.hardware.drm@1.0.so
 VNDK-core: android.hardware.drm@1.1.so
+VNDK-core: android.hardware.drm@1.2.so
 VNDK-core: android.hardware.dumpstate@1.0.so
 VNDK-core: android.hardware.fastboot@1.0.so
 VNDK-core: android.hardware.gatekeeper@1.0.so
+VNDK-core: android.hardware.gnss.measurement_corrections@1.0.so
+VNDK-core: android.hardware.gnss.visibility_control@1.0.so
 VNDK-core: android.hardware.gnss@1.0.so
 VNDK-core: android.hardware.gnss@1.1.so
+VNDK-core: android.hardware.gnss@2.0.so
 VNDK-core: android.hardware.graphics.allocator@2.0.so
+VNDK-core: android.hardware.graphics.allocator@3.0.so
 VNDK-core: android.hardware.graphics.bufferqueue@1.0.so
+VNDK-core: android.hardware.graphics.bufferqueue@2.0.so
 VNDK-core: android.hardware.graphics.composer@2.1.so
 VNDK-core: android.hardware.graphics.composer@2.2.so
+VNDK-core: android.hardware.graphics.composer@2.3.so
 VNDK-core: android.hardware.health.storage@1.0.so
 VNDK-core: android.hardware.health@1.0.so
 VNDK-core: android.hardware.health@2.0.so
+VNDK-core: android.hardware.input.classifier@1.0.so
+VNDK-core: android.hardware.input.common@1.0.so
 VNDK-core: android.hardware.ir@1.0.so
 VNDK-core: android.hardware.keymaster@3.0.so
 VNDK-core: android.hardware.keymaster@4.0.so
 VNDK-core: android.hardware.light@2.0.so
 VNDK-core: android.hardware.media.bufferpool@1.0.so
+VNDK-core: android.hardware.media.bufferpool@2.0.so
+VNDK-core: android.hardware.media.c2@1.0.so
 VNDK-core: android.hardware.media.omx@1.0.so
 VNDK-core: android.hardware.media@1.0.so
 VNDK-core: android.hardware.memtrack@1.0.so
@@ -143,35 +158,44 @@
 VNDK-core: android.hardware.secure_element@1.0.so
 VNDK-core: android.hardware.secure_element@1.1.so
 VNDK-core: android.hardware.sensors@1.0.so
+VNDK-core: android.hardware.sensors@2.0.so
 VNDK-core: android.hardware.soundtrigger@2.0.so
 VNDK-core: android.hardware.soundtrigger@2.0-core.so
 VNDK-core: android.hardware.soundtrigger@2.1.so
+VNDK-core: android.hardware.soundtrigger@2.2.so
 VNDK-core: android.hardware.tetheroffload.config@1.0.so
 VNDK-core: android.hardware.tetheroffload.control@1.0.so
 VNDK-core: android.hardware.thermal@1.0.so
 VNDK-core: android.hardware.thermal@1.1.so
+VNDK-core: android.hardware.thermal@2.0.so
 VNDK-core: android.hardware.tv.cec@1.0.so
+VNDK-core: android.hardware.tv.cec@2.0.so
 VNDK-core: android.hardware.tv.input@1.0.so
+VNDK-core: android.hardware.tv.tuner@1.0.so
 VNDK-core: android.hardware.usb.gadget@1.0.so
 VNDK-core: android.hardware.usb@1.0.so
 VNDK-core: android.hardware.usb@1.1.so
+VNDK-core: android.hardware.usb@1.2.so
 VNDK-core: android.hardware.vibrator@1.0.so
 VNDK-core: android.hardware.vibrator@1.1.so
 VNDK-core: android.hardware.vibrator@1.2.so
+VNDK-core: android.hardware.vibrator@1.3.so
 VNDK-core: android.hardware.vr@1.0.so
 VNDK-core: android.hardware.weaver@1.0.so
 VNDK-core: android.hardware.wifi.hostapd@1.0.so
+VNDK-core: android.hardware.wifi.hostapd@1.1.so
 VNDK-core: android.hardware.wifi.offload@1.0.so
 VNDK-core: android.hardware.wifi.supplicant@1.0.so
 VNDK-core: android.hardware.wifi.supplicant@1.1.so
+VNDK-core: android.hardware.wifi.supplicant@1.2.so
 VNDK-core: android.hardware.wifi@1.0.so
 VNDK-core: android.hardware.wifi@1.1.so
 VNDK-core: android.hardware.wifi@1.2.so
+VNDK-core: android.hardware.wifi@1.3.so
 VNDK-core: android.hidl.allocator@1.0.so
 VNDK-core: android.hidl.memory.block@1.0.so
 VNDK-core: android.hidl.token@1.0.so
 VNDK-core: android.hidl.token@1.0-utils.so
-VNDK-core: android.system.ashmem@1.0.so
 VNDK-core: android.system.net.netd@1.0.so
 VNDK-core: android.system.net.netd@1.1.so
 VNDK-core: android.system.suspend@1.0.so
@@ -183,6 +207,7 @@
 VNDK-core: libcamera_metadata.so
 VNDK-core: libcap.so
 VNDK-core: libcn-cbor.so
+VNDK-core: libcodec2.so
 VNDK-core: libcrypto.so
 VNDK-core: libcrypto_utils.so
 VNDK-core: libcurl.so
@@ -209,7 +234,6 @@
 VNDK-core: libmkbootimg_abi_check.so
 VNDK-core: libnetutils.so
 VNDK-core: libnl.so
-VNDK-core: libopus.so
 VNDK-core: libpcre2.so
 VNDK-core: libpiex.so
 VNDK-core: libpng.so
@@ -224,41 +248,17 @@
 VNDK-core: libspeexresampler.so
 VNDK-core: libsqlite.so
 VNDK-core: libssl.so
-VNDK-core: libstagefright_amrnb_common.so
+VNDK-core: libstagefright_bufferpool@2.0.so
 VNDK-core: libstagefright_bufferqueue_helper.so
-VNDK-core: libstagefright_enc_common.so
-VNDK-core: libstagefright_flacdec.so
 VNDK-core: libstagefright_foundation.so
 VNDK-core: libstagefright_omx.so
 VNDK-core: libstagefright_omx_utils.so
-VNDK-core: libstagefright_soft_aacdec.so
-VNDK-core: libstagefright_soft_aacenc.so
-VNDK-core: libstagefright_soft_amrdec.so
-VNDK-core: libstagefright_soft_amrnbenc.so
-VNDK-core: libstagefright_soft_amrwbenc.so
-VNDK-core: libstagefright_soft_avcdec.so
-VNDK-core: libstagefright_soft_avcenc.so
-VNDK-core: libstagefright_soft_flacdec.so
-VNDK-core: libstagefright_soft_flacenc.so
-VNDK-core: libstagefright_soft_g711dec.so
-VNDK-core: libstagefright_soft_gsmdec.so
-VNDK-core: libstagefright_soft_hevcdec.so
-VNDK-core: libstagefright_soft_mp3dec.so
-VNDK-core: libstagefright_soft_mpeg2dec.so
-VNDK-core: libstagefright_soft_mpeg4dec.so
-VNDK-core: libstagefright_soft_mpeg4enc.so
-VNDK-core: libstagefright_soft_opusdec.so
-VNDK-core: libstagefright_soft_rawdec.so
-VNDK-core: libstagefright_soft_vorbisdec.so
-VNDK-core: libstagefright_soft_vpxdec.so
-VNDK-core: libstagefright_soft_vpxenc.so
 VNDK-core: libstagefright_xmlparser.so
 VNDK-core: libsysutils.so
 VNDK-core: libtinyalsa.so
 VNDK-core: libtinyxml2.so
 VNDK-core: libui.so
 VNDK-core: libusbhost.so
-VNDK-core: libvorbisidec.so
 VNDK-core: libwifi-system-iface.so
 VNDK-core: libxml2.so
 VNDK-core: libyuv.so
diff --git a/target/product/gsi/skip_mount.cfg b/target/product/gsi/gsi_skip_mount.cfg
similarity index 100%
rename from target/product/gsi/skip_mount.cfg
rename to target/product/gsi/gsi_skip_mount.cfg
diff --git a/target/product/gsi_common.mk b/target/product/gsi_common.mk
deleted file mode 100644
index 1b5cd55..0000000
--- a/target/product/gsi_common.mk
+++ /dev/null
@@ -1,96 +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.
-#
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
-
-# GSI includes all AOSP product packages and placed under /system/product
-$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_product.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_product.mk)
-
-# Default AOSP sounds
-$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
-
-# GSI doesn't support apex for now.
-# Properties set in product take precedence over those in vendor.
-PRODUCT_PRODUCT_PROPERTIES += \
-    ro.apex.updatable=false
-
-# Additional settings used in all AOSP builds
-PRODUCT_PRODUCT_PROPERTIES += \
-    ro.config.ringtone=Ring_Synth_04.ogg \
-    ro.config.notification_sound=pixiedust.ogg \
-
-# The mainline checking whitelist, should be clean up
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    system/app/messaging/messaging.apk \
-    system/app/WAPPushManager/WAPPushManager.apk \
-    system/bin/healthd \
-    system/etc/init/healthd.rc \
-    system/etc/seccomp_policy/crash_dump.%.policy \
-    system/etc/seccomp_policy/mediacodec.policy \
-    system/etc/vintf/manifest/manifest_healthd.xml \
-    system/lib/libframesequence.so \
-    system/lib/libgiftranscode.so \
-    system/lib64/libframesequence.so \
-    system/lib64/libgiftranscode.so \
-
-# Some GSI builds enable dexpreopt, whitelist these preopt files
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += %.odex %.vdex %.art
-
-# Exclude GSI specific files
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    system/etc/init/config/skip_mount.cfg \
-    system/etc/init/init.gsi.rc \
-
-# Exclude all files under system/product and system/system_ext
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    system/product/% \
-    system/system_ext/%
-
-
-# Split selinux policy
-PRODUCT_FULL_TREBLE_OVERRIDE := true
-
-# Enable dynamic partition size
-PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
-
-# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
-
-# GSI specific tasks on boot
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
-    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
-
-# Support addtional P vendor interface
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
-
-# More AOSP packages
-PRODUCT_PACKAGES += \
-    messaging \
-    PhotoTable \
-    WAPPushManager \
-    WallpaperPicker \
-
-# Telephony:
-#   Provide a APN configuration to GSI product
-PRODUCT_COPY_FILES += \
-    device/sample/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml
-
-# NFC:
-#   Provide a libnfc-nci.conf to GSI product
-PRODUCT_COPY_FILES += \
-    device/generic/common/nfc/libnfc-nci.conf:$(TARGET_COPY_OUT_PRODUCT)/etc/libnfc-nci.conf
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 4c471db..cab3916 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -24,11 +24,6 @@
 # - etc.
 #
 
-# Exclude GSI specific files
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    system/etc/init/config/skip_mount.cfg \
-    system/etc/init/init.gsi.rc \
-
 # Exclude all files under system/product and system/system_ext
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     system/product/% \
@@ -50,12 +45,12 @@
 PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
 
 # GSI specific tasks on boot
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/skip_mount.cfg:system/etc/init/config/skip_mount.cfg \
-    build/make/target/product/gsi/init.gsi.rc:system/etc/init/init.gsi.rc \
+PRODUCT_PACKAGES += \
+    gsi_skip_mount.cfg \
+    init.gsi.rc
 
-# Support addtional P VNDK packages
-PRODUCT_EXTRA_VNDK_VERSIONS := 28
+# Support addtional P and Q VNDK packages
+PRODUCT_EXTRA_VNDK_VERSIONS := 28 29
 
 # The 64 bits GSI build targets inhiert core_64_bit.mk to enable 64 bits and
 # include the init.zygote64_32.rc.
diff --git a/target/product/handheld_product.mk b/target/product/handheld_product.mk
index 758fa9b..54dcaf2 100644
--- a/target/product/handheld_product.mk
+++ b/target/product/handheld_product.mk
@@ -27,7 +27,6 @@
     Camera2 \
     Contacts \
     DeskClock \
-    Email \
     Gallery2 \
     LatinIME \
     Launcher3QuickStep \
@@ -40,3 +39,7 @@
     StorageManager \
     SystemUI \
     WallpaperCropper \
+    frameworks-base-overlays
+
+PRODUCT_PACKAGES_DEBUG += \
+    frameworks-base-overlays-debug
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index a4dd6d7..6463a54 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -24,6 +24,7 @@
 $(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts.mk)
 $(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk)
 $(call inherit-product-if-exists, external/google-fonts/cutive-mono/fonts.mk)
+$(call inherit-product-if-exists, external/google-fonts/source-sans-pro/fonts.mk)
 $(call inherit-product-if-exists, external/noto-fonts/fonts.mk)
 $(call inherit-product-if-exists, external/roboto-fonts/fonts.mk)
 $(call inherit-product-if-exists, external/hyphenation-patterns/patterns.mk)
@@ -56,6 +57,7 @@
     MtpDocumentsProvider \
     MusicFX \
     NfcNci \
+    OsuLogin \
     PacProcessor \
     PrintRecommendationService \
     PrintSpooler \
diff --git a/target/product/handheld_vendor.mk b/target/product/handheld_vendor.mk
index ca7760a..cb7cf74 100644
--- a/target/product/handheld_vendor.mk
+++ b/target/product/handheld_vendor.mk
@@ -23,10 +23,7 @@
 # /vendor packages
 PRODUCT_PACKAGES += \
     audio.primary.default \
-    DisplayCutoutEmulationCornerOverlay \
-    DisplayCutoutEmulationDoubleOverlay \
-    DisplayCutoutEmulationTallOverlay \
     local_time.default \
     power.default \
-    SysuiDarkThemeOverlay \
     vibrator.default \
+
diff --git a/target/product/legacy_gsi_common.mk b/target/product/legacy_gsi_common.mk
deleted file mode 100644
index fdae6eb..0000000
--- a/target/product/legacy_gsi_common.mk
+++ /dev/null
@@ -1,37 +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.
-#
-
-include $(SRC_TARGET_DIR)/product/gsi_common.mk
-
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
-    system/etc/init/init.legacy-gsi.rc \
-    system/etc/init/gsi/init.vndk-27.rc \
-    system/etc/ld.config.vndk_lite.txt \
-
-# Legacy GSI support addtional O-MR1 interface
-PRODUCT_EXTRA_VNDK_VERSIONS += 27
-
-# Support for the O-MR1 devices
-PRODUCT_COPY_FILES += \
-    build/make/target/product/gsi/init.legacy-gsi.rc:system/etc/init/init.legacy-gsi.rc \
-    build/make/target/product/gsi/init.vndk-27.rc:system/etc/init/gsi/init.vndk-27.rc
-
-# Name space configuration file for non-enforcing VNDK
-PRODUCT_PACKAGES += \
-    ld.config.vndk_lite.txt
-
-# Legacy GSI relax the compatible property checking
-PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := false
diff --git a/target/product/mainline_arm64.mk b/target/product/mainline_arm64.mk
index a32bb16..6d998d6 100644
--- a/target/product/mainline_arm64.mk
+++ b/target/product/mainline_arm64.mk
@@ -28,8 +28,6 @@
 PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
   root/init.zygote64_32.rc \
-  system/etc/seccomp_policy/crash_dump.arm.policy \
-  system/etc/seccomp_policy/mediacodec.policy \
 
 # Modules that should probably be moved to /product
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index 8bcc212..b8f2838 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -18,8 +18,6 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
-# Enable updating of APEXes
-#$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
 # Add adb keys to debuggable AOSP builds (if they exist)
 $(call inherit-product-if-exists, vendor/google/security/adb/vendor_key.mk)
 
@@ -73,6 +71,8 @@
     android.hardware.radio@1.0 \
     android.hardware.radio@1.1 \
     android.hardware.radio@1.2 \
+    android.hardware.radio@1.3 \
+    android.hardware.radio@1.4 \
     android.hardware.radio.config@1.0 \
     android.hardware.radio.deprecated@1.0 \
     android.hardware.secure_element@1.0 \
@@ -85,6 +85,11 @@
     libnl \
     libprotobuf-cpp-full \
 
+# Camera service uses 'libdepthphoto' for adding dynamic depth
+# metadata inside depth jpegs.
+PRODUCT_PACKAGES += \
+    libdepthphoto \
+
 PRODUCT_PACKAGES_DEBUG += \
     avbctl \
     bootctl \
@@ -100,6 +105,8 @@
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
 
+PRODUCT_ENFORCE_RRO_TARGETS := *
+
 PRODUCT_NAME := mainline_system
 PRODUCT_BRAND := generic
 
diff --git a/target/product/mainline_system_arm64.mk b/target/product/mainline_system_arm64.mk
index b9ac1e3..4031371 100644
--- a/target/product/mainline_system_arm64.mk
+++ b/target/product/mainline_system_arm64.mk
@@ -14,16 +14,24 @@
 # limitations under the License.
 #
 
+#
+# 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/mainline_system.mk)
 $(call enforce-product-packages-exist,)
 
+# Enable mainline checking
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+  root/init.zygote64_32.rc \
+
 PRODUCT_BUILD_CACHE_IMAGE := false
 PRODUCT_BUILD_ODM_IMAGE := false
 PRODUCT_BUILD_PRODUCT_IMAGE  := false
-PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false
 PRODUCT_BUILD_RAMDISK_IMAGE := false
 PRODUCT_BUILD_SYSTEM_IMAGE := true
+PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false
 PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false
 PRODUCT_BUILD_USERDATA_IMAGE := false
 PRODUCT_BUILD_VENDOR_IMAGE := false
diff --git a/target/product/mainline_system_x86.mk b/target/product/mainline_system_x86.mk
new file mode 100644
index 0000000..ac33068
--- /dev/null
+++ b/target/product/mainline_system_x86.mk
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+#
+# All components inherited here go to system image
+#
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
+$(call enforce-product-packages-exist,)
+
+# Enable mainline checking
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true
+
+PRODUCT_BUILD_CACHE_IMAGE := false
+PRODUCT_BUILD_ODM_IMAGE := false
+PRODUCT_BUILD_PRODUCT_IMAGE  := false
+PRODUCT_BUILD_RAMDISK_IMAGE := false
+PRODUCT_BUILD_SYSTEM_IMAGE := true
+PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false
+PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false
+PRODUCT_BUILD_USERDATA_IMAGE := false
+PRODUCT_BUILD_VENDOR_IMAGE := false
+
+PRODUCT_NAME := mainline_system_x86
+PRODUCT_DEVICE := mainline_x86
+PRODUCT_BRAND := generic
+PRODUCT_SHIPPING_API_LEVEL := 28
+PRODUCT_RESTRICT_VENDOR_FILES := all
diff --git a/target/product/mainline_system_x86_arm.mk b/target/product/mainline_system_x86_arm.mk
new file mode 100644
index 0000000..0ed86cc
--- /dev/null
+++ b/target/product/mainline_system_x86_arm.mk
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+#
+# All components inherited here go to system image
+#
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
+$(call enforce-product-packages-exist,)
+
+# Enable mainline checking
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := true
+
+PRODUCT_BUILD_CACHE_IMAGE := false
+PRODUCT_BUILD_ODM_IMAGE := false
+PRODUCT_BUILD_PRODUCT_IMAGE  := false
+PRODUCT_BUILD_RAMDISK_IMAGE := false
+PRODUCT_BUILD_SYSTEM_IMAGE := true
+PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false
+PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false
+PRODUCT_BUILD_USERDATA_IMAGE := false
+PRODUCT_BUILD_VENDOR_IMAGE := false
+
+PRODUCT_NAME := mainline_system_x86_arm
+PRODUCT_DEVICE := mainline_x86_arm
+PRODUCT_BRAND := generic
+PRODUCT_SHIPPING_API_LEVEL := 28
+PRODUCT_RESTRICT_VENDOR_FILES := all
diff --git a/target/product/media_system.mk b/target/product/media_system.mk
index 2ba7005..5c0902d 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -31,31 +31,9 @@
     fsck.f2fs \
     HTMLViewer \
     libfilterpack_imageproc \
-    libstagefright_soft_aacdec \
-    libstagefright_soft_aacenc \
-    libstagefright_soft_amrdec \
-    libstagefright_soft_amrnbenc \
-    libstagefright_soft_amrwbenc \
-    libstagefright_soft_avcdec \
-    libstagefright_soft_avcenc \
-    libstagefright_soft_flacdec \
-    libstagefright_soft_flacenc \
-    libstagefright_soft_g711dec \
-    libstagefright_soft_gsmdec \
-    libstagefright_soft_hevcdec \
-    libstagefright_soft_mp3dec \
-    libstagefright_soft_mpeg2dec \
-    libstagefright_soft_mpeg4dec \
-    libstagefright_soft_mpeg4enc \
-    libstagefright_soft_opusdec \
-    libstagefright_soft_rawdec \
-    libstagefright_soft_vorbisdec \
-    libstagefright_soft_vpxdec \
-    libstagefright_soft_vpxenc \
     libwebviewchromium_loader \
     libwebviewchromium_plat_support \
     make_f2fs \
-    PackageInstaller \
     requestsync \
     StatementService \
     vndk_snapshot_package \
diff --git a/target/product/profile_boot_common.mk b/target/product/profile_boot_common.mk
index fc19954..a40b3e9 100644
--- a/target/product/profile_boot_common.mk
+++ b/target/product/profile_boot_common.mk
@@ -20,29 +20,11 @@
 # Ideally we would just generate an empty boot.art but we don't have the build
 # support to separate the image from the compile code.
 PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := build/make/target/product/empty-profile
-PRODUCT_DEX_PREOPT_BOOT_FLAGS := --count-hotness-in-compiled-code
 DEX_PREOPT_DEFAULT := nostripping
 
-# Disable uncompressing priv apps so that there is enough space to build the system partition.
-DONT_UNCOMPRESS_PRIV_APPS_DEXS := true
-
-# Use an empty preloaded-classes list.
-PRODUCT_COPY_FILES += \
-    build/make/target/product/empty-preloaded-classes:system/etc/preloaded-classes
-
 # Boot image property overrides.
 PRODUCT_PROPERTY_OVERRIDES += \
-    dalvik.vm.jitinitialsize=32m \
-    dalvik.vm.jitmaxsize=32m \
-    dalvik.vm.usejitprofiles=true \
-    dalvik.vm.hot-startup-method-samples=256 \
     dalvik.vm.profilesystemserver=true \
-    dalvik.vm.profilebootimage=true
-
-# Use speed compiler filter since system server doesn't have JIT.
-PRODUCT_DEX_PREOPT_BOOT_FLAGS += --compiler-filter=speed
-# System server is speed compiled and doesn't have a separate preopt flag,
-# so we enable hotness in compiled code for everything.
-PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := --count-hotness-in-compiled-code
+    dalvik.vm.profilebootclasspath=true
 
 PRODUCT_DIST_BOOT_AND_SYSTEM_JARS := true
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index 5db32f2..581a72b 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -33,9 +33,12 @@
 PRODUCT_PACKAGES += \
     ext \
 
-# Android Runtime APEX module.
+# Runtime (Bionic) APEX module.
 PRODUCT_PACKAGES += com.android.runtime
-PRODUCT_HOST_PACKAGES += com.android.runtime
+
+# ART APEX module.
+PRODUCT_PACKAGES += com.android.art
+PRODUCT_HOST_PACKAGES += com.android.art
 
 # Certificates.
 PRODUCT_PACKAGES += \
diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk
index 96f0bfd..ad72633 100644
--- a/target/product/sdk_phone_arm64.mk
+++ b/target/product/sdk_phone_arm64.mk
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+QEMU_USE_SYSTEM_EXT_PARTITIONS := true
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_arm64.mk)
 
diff --git a/target/product/sdk_phone_armv7.mk b/target/product/sdk_phone_armv7.mk
index 04d8d6a..77b8b50 100644
--- a/target/product/sdk_phone_armv7.mk
+++ b/target/product/sdk_phone_armv7.mk
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+QEMU_USE_SYSTEM_EXT_PARTITIONS := true
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_arm.mk)
 
diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk
index b34e5b6..efb3c6e 100644
--- a/target/product/sdk_phone_x86.mk
+++ b/target/product/sdk_phone_x86.mk
@@ -13,6 +13,30 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+QEMU_USE_SYSTEM_EXT_PARTITIONS := true
+PRODUCT_USE_DYNAMIC_PARTITIONS := true
+
+#
+# All components inherited here go to system image
+#
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
+
+# Enable mainline checking for excat this product name
+ifeq (sdk_phone_x86,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
+
+#
+# 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-vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86.mk)
 
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
index 37c078e..267796f 100644
--- a/target/product/sdk_phone_x86_64.mk
+++ b/target/product/sdk_phone_x86_64.mk
@@ -13,8 +13,34 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+QEMU_USE_SYSTEM_EXT_PARTITIONS := true
+PRODUCT_USE_DYNAMIC_PARTITIONS := true
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86_64.mk)
+#
+# 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/mainline_system.mk)
+
+# Enable mainline checking for excat this product name
+ifeq (sdk_phone_x86_64,$(TARGET_PRODUCT))
+PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := relaxed
+endif
+
+PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
+    root/init.zygote64_32.rc \
+
+#
+# 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/generic_x86_64/device.mk)
 
 # Define the host tools and libs that are parts of the SDK.
 -include sdk/build/product_sdk.mk
diff --git a/target/product/security/Android.mk b/target/product/security/Android.mk
index a0b2d6d..3631cfd 100644
--- a/target/product/security/Android.mk
+++ b/target/product/security/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 
 #######################################
-# verity_key
+# verity_key (installed to /, i.e. part of system.img)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := verity_key
@@ -9,9 +9,29 @@
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
 
+# For devices using a separate ramdisk, we need a copy there to establish the chain of trust.
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+LOCAL_REQUIRED_MODULES := verity_key_ramdisk
+endif
+
 include $(BUILD_PREBUILT)
 
 #######################################
+# verity_key (installed to ramdisk)
+#
+# Enabling the target when using system-as-root would cause build failure, as TARGET_RAMDISK_OUT
+# points to the same location as TARGET_ROOT_OUT.
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+  include $(CLEAR_VARS)
+  LOCAL_MODULE := verity_key_ramdisk
+  LOCAL_MODULE_CLASS := ETC
+  LOCAL_SRC_FILES := verity_key
+  LOCAL_MODULE_STEM := verity_key
+  LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)
+  include $(BUILD_PREBUILT)
+endif
+
+#######################################
 # adb key, if configured via PRODUCT_ADB_KEYS
 ifdef PRODUCT_ADB_KEYS
   ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
diff --git a/target/product/telephony_system.mk b/target/product/telephony_system.mk
index 584cf1e..4da9bdf 100644
--- a/target/product/telephony_system.mk
+++ b/target/product/telephony_system.mk
@@ -21,6 +21,6 @@
     ONS \
     CarrierDefaultApp \
     CallLogBackup \
-    CellBroadcastReceiver \
+    CellBroadcastAppPlatform \
 
 PRODUCT_COPY_FILES := \
diff --git a/target/product/updatable_apex.mk b/target/product/updatable_apex.mk
index 038f66e..bdaf545 100644
--- a/target/product/updatable_apex.mk
+++ b/target/product/updatable_apex.mk
@@ -16,6 +16,7 @@
 
 # Inherit this when the target needs to support updating APEXes
 
-PRODUCT_PROPERTY_OVERRIDES := ro.apex.updatable=true
-PRODUCT_PACKAGES := com.android.apex.cts.shim.v1_prebuilt
-TARGET_FLATTEN_APEX := false
+ifneq ($(OVERRIDE_TARGET_FLATTEN_APEX),true)
+  PRODUCT_PROPERTY_OVERRIDES := ro.apex.updatable=true
+  TARGET_FLATTEN_APEX := false
+endif
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
index e68c27f..51a8583 100644
--- a/tools/auto_gen_test_config_test.py
+++ b/tools/auto_gen_test_config_test.py
@@ -34,7 +34,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.android.my.tests.x">
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.my.tests" />
 </manifest>
 """
@@ -72,7 +72,7 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.my.tests.x" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
 """
diff --git a/tools/extract_kernel.py b/tools/extract_kernel.py
index 42561cf..8ca11d1 100755
--- a/tools/extract_kernel.py
+++ b/tools/extract_kernel.py
@@ -100,19 +100,25 @@
   return o
 
 
-def try_decompress(cmd, search_bytes, input_bytes):
-  idx = input_bytes.find(search_bytes)
-  if idx < 0:
-    return None
-
-  idx = 0
+def try_decompress_bytes(cmd, input_bytes):
   sp = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
-  o, _ = sp.communicate(input=input_bytes[idx:])
+  o, _ = sp.communicate(input=input_bytes)
   # ignore errors
   return o
 
 
+def try_decompress(cmd, search_bytes, input_bytes):
+  idx = 0
+  while True:
+    idx = input_bytes.find(search_bytes, idx)
+    if idx < 0:
+      raise StopIteration()
+
+    yield try_decompress_bytes(cmd, input_bytes[idx:])
+    idx += 1
+
+
 def decompress_dump(func, input_bytes):
   """
   Run func(input_bytes) first; and if that fails (returns value evaluates to
@@ -122,15 +128,15 @@
   if o:
     return o
   for cmd, search_bytes in COMPRESSION_ALGO:
-    decompressed = try_decompress(cmd, search_bytes, input_bytes)
-    if decompressed:
-      o = func(decompressed)
-      if o:
-        return o
+    for decompressed in try_decompress(cmd, search_bytes, input_bytes):
+      if decompressed:
+        o = decompress_dump(func, decompressed)
+        if o:
+          return o
     # Force decompress the whole file even if header doesn't match
-    decompressed = try_decompress(cmd, b"", input_bytes)
+    decompressed = try_decompress_bytes(cmd, input_bytes)
     if decompressed:
-      o = func(decompressed)
+      o = decompress_dump(func, decompressed)
       if o:
         return o
 
diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py
index 2956b11..1405fd3 100755
--- a/tools/fs_config/fs_config_generator.py
+++ b/tools/fs_config/fs_config_generator.py
@@ -1066,6 +1066,8 @@
         path = fs_config.path
 
         if self._partition == 'system':
+            if not self._all_partitions:
+                return True
             for skip_partition in self._all_partitions.split(','):
                 if path.startswith(skip_partition) or path.startswith(
                         'system/' + skip_partition):
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 0302856..6cde77e 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -73,6 +73,22 @@
         "releasetools_build_super_image",
         "releasetools_common",
     ],
+    required: [
+        "zip2zip",
+    ],
+}
+
+python_defaults {
+    name: "releasetools_check_target_files_vintf_defaults",
+    srcs: [
+        "check_target_files_vintf.py",
+    ],
+    libs: [
+        "releasetools_common",
+    ],
+    required: [
+        "checkvintf",
+    ],
 }
 
 python_defaults {
@@ -83,11 +99,13 @@
         "target_files_diff.py",
     ],
     libs: [
+        "releasetools_check_target_files_vintf",
         "releasetools_common",
         "releasetools_verity_utils",
     ],
     required: [
         "brillo_update_payload",
+        "checkvintf",
     ],
 }
 
@@ -143,6 +161,14 @@
 }
 
 python_library_host {
+    name: "releasetools_check_target_files_vintf",
+    defaults: [
+        "releasetools_library_defaults",
+        "releasetools_check_target_files_vintf_defaults",
+    ],
+}
+
+python_library_host {
     name: "releasetools_common",
     defaults: ["releasetools_library_defaults"],
     srcs: [
@@ -155,7 +181,7 @@
     // Only the tools that are referenced directly are listed as required modules. For example,
     // `avbtool` is not here, as the script always uses the one from info_dict['avb_avbtool'].
     required: [
-        "aapt",
+        "aapt2",
         "boot_signer",
         "brotli",
         "bsdiff",
@@ -266,6 +292,14 @@
 }
 
 python_binary_host {
+    name: "check_target_files_vintf",
+    defaults: [
+        "releasetools_binary_defaults",
+        "releasetools_check_target_files_vintf_defaults"
+    ],
+}
+
+python_binary_host {
     name: "img_from_target_files",
     defaults: [
         "releasetools_binary_defaults",
@@ -305,10 +339,14 @@
     libs: [
         "releasetools_add_img_to_target_files",
         "releasetools_build_super_image",
+        "releasetools_check_target_files_vintf",
         "releasetools_common",
         "releasetools_img_from_target_files",
         "releasetools_ota_from_target_files",
     ],
+    required: [
+        "checkvintf",
+    ],
 }
 
 python_binary_host {
@@ -396,13 +434,14 @@
         "releasetools_apex_utils",
         "releasetools_build_image",
         "releasetools_build_super_image",
+        "releasetools_check_target_files_vintf",
         "releasetools_common",
         "releasetools_img_from_target_files",
         "releasetools_ota_from_target_files",
         "releasetools_verity_utils",
     ],
     data: [
-        "testdata/*",
+        "testdata/**/*",
     ],
     required: [
         "otatools",
diff --git a/tools/releasetools/OWNERS b/tools/releasetools/OWNERS
index 766adb4..a8295d4 100644
--- a/tools/releasetools/OWNERS
+++ b/tools/releasetools/OWNERS
@@ -1,2 +1,3 @@
-tbao@google.com
+nhdo@google.com
 xunchang@google.com
+zhaojiac@google.com
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 23ae29f..8249915 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -165,9 +165,12 @@
       else:
         common.ZipWrite(output_zip, output_file, arc_name)
 
-  if (OPTIONS.rebuild_recovery and recovery_img is not None and
-      boot_img is not None):
-    logger.info("Building new recovery patch")
+  board_uses_vendorimage = OPTIONS.info_dict.get(
+      "board_uses_vendorimage") == "true"
+
+  if (OPTIONS.rebuild_recovery and not board_uses_vendorimage and
+      recovery_img is not None and boot_img is not None):
+    logger.info("Building new recovery patch on system at system/vendor")
     common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
                              boot_img, info_dict=OPTIONS.info_dict)
 
@@ -190,7 +193,7 @@
   CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system_other", img)
 
 
-def AddVendor(output_zip):
+def AddVendor(output_zip, recovery_img=None, boot_img=None):
   """Turn the contents of VENDOR into a vendor image and store in it
   output_zip."""
 
@@ -199,6 +202,27 @@
     logger.info("vendor.img already exists; no need to rebuild...")
     return img.name
 
+  def output_sink(fn, data):
+    ofile = open(os.path.join(OPTIONS.input_tmp, "VENDOR", fn), "w")
+    ofile.write(data)
+    ofile.close()
+
+    if output_zip:
+      arc_name = "VENDOR/" + fn
+      if arc_name in output_zip.namelist():
+        OPTIONS.replace_updated_files_list.append(arc_name)
+      else:
+        common.ZipWrite(output_zip, ofile.name, arc_name)
+
+  board_uses_vendorimage = OPTIONS.info_dict.get(
+      "board_uses_vendorimage") == "true"
+
+  if (OPTIONS.rebuild_recovery and board_uses_vendorimage and
+      recovery_img is not None and boot_img is not None):
+    logger.info("Building new recovery patch on vendor")
+    common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
+                             boot_img, info_dict=OPTIONS.info_dict)
+
   block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.map")
   CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "vendor", img,
               block_list=block_list)
@@ -293,11 +317,6 @@
   logger.info("creating %s.img...", what)
 
   image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
-  fstab = info_dict["fstab"]
-  mount_point = "/" + what
-  if fstab and mount_point in fstab:
-    image_props["fs_type"] = fstab[mount_point].fs_type
-
   image_props["timestamp"] = FIXED_FILE_TIMESTAMP
 
   if what == "system":
@@ -318,13 +337,8 @@
 
   # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
   # build fingerprint).
-  uuid_seed = what + "-"
-  if "build.prop" in info_dict:
-    build_prop = info_dict["build.prop"]
-    if "ro.build.fingerprint" in build_prop:
-      uuid_seed += build_prop["ro.build.fingerprint"]
-    elif "ro.build.thumbprint" in build_prop:
-      uuid_seed += build_prop["ro.build.thumbprint"]
+  build_info = common.BuildInfo(info_dict)
+  uuid_seed = what + "-" + build_info.fingerprint
   image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
   hash_seed = "hash_seed-" + uuid_seed
   image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
@@ -382,9 +396,6 @@
   else:
     user_dir = common.MakeTempDir()
 
-  fstab = OPTIONS.info_dict["fstab"]
-  if fstab:
-    image_props["fs_type"] = fstab["/data"].fs_type
   build_image.BuildImage(user_dir, image_props, img.name)
 
   common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict)
@@ -471,10 +482,6 @@
   image_props["timestamp"] = FIXED_FILE_TIMESTAMP
 
   user_dir = common.MakeTempDir()
-
-  fstab = OPTIONS.info_dict["fstab"]
-  if fstab:
-    image_props["fs_type"] = fstab["/cache"].fs_type
   build_image.BuildImage(user_dir, image_props, img.name)
 
   common.CheckSize(img.name, "cache.img", OPTIONS.info_dict)
@@ -673,6 +680,7 @@
 
   has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
   has_boot = OPTIONS.info_dict.get("no_boot") != "true"
+  has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true"
 
   # {vendor,odm,product,system_ext}.img are unlike system.img or
   # system_other.img. Because it could be built from source, or dropped into
@@ -715,7 +723,7 @@
 
   # A map between partition names and their paths, which could be used when
   # generating AVB vbmeta image.
-  partitions = dict()
+  partitions = {}
 
   def banner(s):
     logger.info("\n\n++++ %s  ++++\n\n", s)
@@ -734,6 +742,19 @@
         if output_zip:
           boot_image.AddToZip(output_zip)
 
+  if has_vendor_boot:
+    banner("vendor_boot")
+    vendor_boot_image = common.GetVendorBootImage(
+        "IMAGES/vendor_boot.img", "vendor_boot.img", OPTIONS.input_tmp,
+        "VENDOR_BOOT")
+    if vendor_boot_image:
+      partitions['vendor_boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
+                                               "vendor_boot.img")
+      if not os.path.exists(partitions['vendor_boot']):
+        vendor_boot_image.WriteToDir(OPTIONS.input_tmp)
+        if output_zip:
+          vendor_boot_image.AddToZip(output_zip)
+
   recovery_image = None
   if has_recovery:
     banner("recovery")
@@ -767,7 +788,8 @@
 
   if has_vendor:
     banner("vendor")
-    partitions['vendor'] = AddVendor(output_zip)
+    partitions['vendor'] = AddVendor(
+        output_zip, recovery_img=recovery_image, boot_img=boot_image)
 
   if has_product:
     banner("product")
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index 6eaa12f..ee3c463 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -42,7 +42,7 @@
 
 
 def SignApexPayload(avbtool, payload_file, payload_key_path, payload_key_name,
-                    algorithm, salt, signing_args=None):
+                    algorithm, salt, no_hashtree, signing_args=None):
   """Signs a given payload_file with the payload key."""
   # Add the new footer. Old footer, if any, will be replaced by avbtool.
   cmd = [avbtool, 'add_hashtree_footer',
@@ -52,6 +52,8 @@
          '--prop', 'apex.key:{}'.format(payload_key_name),
          '--image', payload_file,
          '--salt', salt]
+  if no_hashtree:
+    cmd.append('--no_hashtree')
   if signing_args:
     cmd.extend(shlex.split(signing_args))
 
@@ -64,13 +66,15 @@
 
   # Verify the signed payload image with specified public key.
   logger.info('Verifying %s', payload_file)
-  VerifyApexPayload(avbtool, payload_file, payload_key_path)
+  VerifyApexPayload(avbtool, payload_file, payload_key_path, no_hashtree)
 
 
-def VerifyApexPayload(avbtool, payload_file, payload_key):
+def VerifyApexPayload(avbtool, payload_file, payload_key, no_hashtree=False):
   """Verifies the APEX payload signature with the given key."""
   cmd = [avbtool, 'verify_image', '--image', payload_file,
          '--key', payload_key]
+  if no_hashtree:
+    cmd.append('--accept_zeroed_hashtree')
   try:
     common.RunAndCheckOutput(cmd)
   except common.ExternalError as e:
@@ -91,7 +95,7 @@
 
   Returns:
     A dict that contains payload property-value pairs. The dict should at least
-    contain Algorithm, Salt and apex.key.
+    contain Algorithm, Salt, Tree Size and apex.key.
   """
   if not os.path.exists(payload_path):
     raise ApexInfoError('Failed to find image: {}'.format(payload_path))
@@ -104,11 +108,11 @@
         'Failed to get APEX payload info for {}:\n{}'.format(
             payload_path, e))
 
-  # Extract the Algorithm / Salt / Prop info from payload (i.e. an image signed
-  # with avbtool). For example,
+  # Extract the Algorithm / Salt / Prop info / Tree size from payload (i.e. an
+  # image signed with avbtool). For example,
   # Algorithm:                SHA256_RSA4096
   PAYLOAD_INFO_PATTERN = (
-      r'^\s*(?P<key>Algorithm|Salt|Prop)\:\s*(?P<value>.*?)$')
+      r'^\s*(?P<key>Algorithm|Salt|Prop|Tree Size)\:\s*(?P<value>.*?)$')
   payload_info_matcher = re.compile(PAYLOAD_INFO_PATTERN)
 
   payload_info = {}
@@ -151,7 +155,7 @@
 
 
 def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
-             codename_to_api_level_map, signing_args=None):
+             codename_to_api_level_map, no_hashtree, signing_args=None):
   """Signs the current APEX with the given payload/container keys.
 
   Args:
@@ -160,6 +164,7 @@
     container_key: The path to container signing key (w/o extension).
     container_pw: The matching password of the container_key, or None.
     codename_to_api_level_map: A dict that maps from codename to API level.
+    no_hashtree: Don't include hashtree in the signed APEX.
     signing_args: Additional args to be passed to the payload signer.
 
   Returns:
@@ -177,6 +182,7 @@
   payload_dir = common.MakeTempDir(prefix='apex-payload-')
   with zipfile.ZipFile(apex_file) as apex_fd:
     payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)
+    zip_items = apex_fd.namelist()
 
   payload_info = ParseApexPayloadInfo(avbtool, payload_file)
   SignApexPayload(
@@ -186,13 +192,15 @@
       payload_info['apex.key'],
       payload_info['Algorithm'],
       payload_info['Salt'],
+      no_hashtree,
       signing_args)
 
   # 1b. Update the embedded payload public key.
   payload_public_key = common.ExtractAvbPublicKey(avbtool, payload_key)
 
   common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
-  common.ZipDelete(apex_file, APEX_PUBKEY)
+  if APEX_PUBKEY in zip_items:
+    common.ZipDelete(apex_file, APEX_PUBKEY)
   apex_zip = zipfile.ZipFile(apex_file, 'a')
   common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
   common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
diff --git a/tools/releasetools/build_super_image.py b/tools/releasetools/build_super_image.py
index 045ad55..f63453d 100755
--- a/tools/releasetools/build_super_image.py
+++ b/tools/releasetools/build_super_image.py
@@ -80,10 +80,12 @@
   block_devices = shlex.split(info_dict.get("super_block_devices", "").strip())
   groups = shlex.split(info_dict.get("super_partition_groups", "").strip())
 
-  if ab_update:
+  if ab_update and retrofit:
     cmd += ["--metadata-slots", "2"]
+  elif ab_update:
+    cmd += ["--metadata-slots", "3"]
   else:
-    cmd += ["--metadata-slots", "1"]
+    cmd += ["--metadata-slots", "2"]
 
   if ab_update and retrofit:
     cmd.append("--auto-slot-suffixing")
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index 60200a3..8c1bb9a 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -213,7 +213,7 @@
     self.certs = frozenset(out)
 
   def ReadManifest(self, full_filename):
-    p = common.Run(["aapt", "dump", "xmltree", full_filename,
+    p = common.Run(["aapt2", "dump", "xmltree", full_filename, "--file",
                     "AndroidManifest.xml"],
                    stdout=subprocess.PIPE)
     manifest, err = p.communicate()
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
new file mode 100755
index 0000000..543147c
--- /dev/null
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""
+Check VINTF compatibility from a target files package.
+
+Usage: check_target_files_vintf target_files
+
+target_files can be a ZIP file or an extracted target files directory.
+"""
+
+import logging
+import subprocess
+import sys
+import os
+import zipfile
+
+import common
+
+logger = logging.getLogger(__name__)
+
+OPTIONS = common.OPTIONS
+
+# Keys are paths that VINTF searches. Must keep in sync with libvintf's search
+# paths (VintfObject.cpp).
+# These paths are stored in different directories in target files package, so
+# we have to search for the correct path and tell checkvintf to remap them.
+DIR_SEARCH_PATHS = {
+    '/system': ('SYSTEM',),
+    '/vendor': ('VENDOR', 'SYSTEM/vendor'),
+    '/product': ('PRODUCT', 'SYSTEM/product'),
+    '/odm': ('ODM', 'VENDOR/odm'),
+}
+
+UNZIP_PATTERN = ['META/*', '*/build.prop']
+
+
+def GetDirmap(input_tmp):
+  dirmap = {}
+  for device_path, target_files_rel_paths in DIR_SEARCH_PATHS.items():
+    for target_files_rel_path in target_files_rel_paths:
+      target_files_path = os.path.join(input_tmp, target_files_rel_path)
+      if os.path.isdir(target_files_path):
+        dirmap[device_path] = target_files_path
+        break
+    if device_path not in dirmap:
+      raise ValueError("Can't determine path for device path " + device_path +
+                       ". Searched the following:" +
+                       ("\n".join(target_files_rel_paths)))
+  return dirmap
+
+
+def GetArgsForSkus(info_dict):
+  skus = info_dict.get('vintf_odm_manifest_skus', '').strip().split()
+  if not skus:
+    logger.info("ODM_MANIFEST_SKUS is not defined. Check once without SKUs.")
+    skus = ['']
+  return [['--property', 'ro.boot.product.hardware.sku=' + sku]
+          for sku in skus]
+
+
+def GetArgsForShippingApiLevel(info_dict):
+  shipping_api_level = info_dict['vendor.build.prop'].get(
+      'ro.product.first_api_level')
+  if not shipping_api_level:
+    logger.warning('Cannot determine ro.product.first_api_level')
+    return []
+  return ['--property', 'ro.product.first_api_level=' + shipping_api_level]
+
+
+def GetArgsForKernel(input_tmp):
+  version_path = os.path.join(input_tmp, 'META/kernel_version.txt')
+  config_path = os.path.join(input_tmp, 'META/kernel_configs.txt')
+
+  if not os.path.isfile(version_path) or not os.path.isfile(config_path):
+    logger.info('Skipping kernel config checks because ' +
+                'PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is not set')
+    return []
+
+  with open(version_path) as f:
+    version = f.read().strip()
+
+  return ['--kernel', '{}:{}'.format(version, config_path)]
+
+
+def CheckVintfFromExtractedTargetFiles(input_tmp, info_dict=None):
+  """
+  Checks VINTF metadata of an extracted target files directory.
+
+  Args:
+    inp: path to the directory that contains the extracted target files archive.
+    info_dict: The build-time info dict. If None, it will be loaded from inp.
+
+  Returns:
+    True if VINTF check is skipped or compatible, False if incompatible. Raise
+    a RuntimeError if any error occurs.
+  """
+
+  if info_dict is None:
+    info_dict = common.LoadInfoDict(input_tmp)
+
+  if info_dict.get('vintf_enforce') != 'true':
+    logger.warning('PRODUCT_ENFORCE_VINTF_MANIFEST is not set, skipping checks')
+    return True
+
+  dirmap = GetDirmap(input_tmp)
+  args_for_skus = GetArgsForSkus(info_dict)
+  shipping_api_level_args = GetArgsForShippingApiLevel(info_dict)
+  kernel_args = GetArgsForKernel(input_tmp)
+
+  common_command = [
+      'checkvintf',
+      '--check-compat',
+  ]
+  for device_path, real_path in dirmap.items():
+    common_command += ['--dirmap', '{}:{}'.format(device_path, real_path)]
+  common_command += kernel_args
+  common_command += shipping_api_level_args
+
+  success = True
+  for sku_args in args_for_skus:
+    command = common_command + sku_args
+    proc = common.Run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    out, err = proc.communicate()
+    if proc.returncode == 0:
+      logger.info("Command `%s` returns 'compatible'", ' '.join(command))
+    elif out.strip() == "INCOMPATIBLE":
+      logger.info("Command `%s` returns 'incompatible'", ' '.join(command))
+      success = False
+    else:
+      raise common.ExternalError(
+          "Failed to run command '{}' (exit code {}):\nstdout:{}\nstderr:{}"
+          .format(' '.join(command), proc.returncode, out, err))
+    logger.info("stdout: %s", out)
+    logger.info("stderr: %s", err)
+
+  return success
+
+
+def GetVintfFileList():
+  """
+  Returns a list of VINTF metadata files that should be read from a target files
+  package before executing checkvintf.
+  """
+  def PathToPatterns(path):
+    if path[-1] == '/':
+      path += '*'
+    for device_path, target_files_rel_paths in DIR_SEARCH_PATHS.items():
+      if path.startswith(device_path):
+        suffix = path[len(device_path):]
+        return [rel_path + suffix for rel_path in target_files_rel_paths]
+    raise RuntimeError('Unrecognized path from checkvintf --dump-file-list: ' +
+                       path)
+
+  out = common.RunAndCheckOutput(['checkvintf', '--dump-file-list'])
+  paths = out.strip().split('\n')
+  paths = sum((PathToPatterns(path) for path in paths if path), [])
+  return paths
+
+
+def CheckVintfFromTargetFiles(inp, info_dict=None):
+  """
+  Checks VINTF metadata of a target files zip.
+
+  Args:
+    inp: path to the target files archive.
+    info_dict: The build-time info dict. If None, it will be loaded from inp.
+
+  Returns:
+    True if VINTF check is skipped or compatible, False if incompatible. Raise
+    a RuntimeError if any error occurs.
+  """
+  input_tmp = common.UnzipTemp(inp, GetVintfFileList() + UNZIP_PATTERN)
+  return CheckVintfFromExtractedTargetFiles(input_tmp, info_dict)
+
+
+def CheckVintf(inp, info_dict=None):
+  """
+  Checks VINTF metadata of a target files zip or extracted target files
+  directory.
+
+  Args:
+    inp: path to the (possibly extracted) target files archive.
+    info_dict: The build-time info dict. If None, it will be loaded from inp.
+
+  Returns:
+    True if VINTF check is skipped or compatible, False if incompatible. Raise
+    a RuntimeError if any error occurs.
+  """
+  if os.path.isdir(inp):
+    logger.info('Checking VINTF compatibility extracted target files...')
+    return CheckVintfFromExtractedTargetFiles(inp, info_dict)
+
+  if zipfile.is_zipfile(inp):
+    logger.info('Checking VINTF compatibility target files...')
+    return CheckVintfFromTargetFiles(inp, info_dict)
+
+  raise ValueError('{} is not a valid directory or zip file'.format(inp))
+
+
+def main(argv):
+  args = common.ParseOptions(argv, __doc__)
+  if len(args) != 1:
+    common.Usage(__doc__)
+    sys.exit(1)
+  common.InitLogging()
+  if not CheckVintf(args[0]):
+    sys.exit(1)
+
+
+if __name__ == '__main__':
+  try:
+    common.CloseInheritedPipes()
+    main(sys.argv[1:])
+  except common.ExternalError:
+    logger.exception('\n   ERROR:\n')
+    sys.exit(1)
+  finally:
+    common.Cleanup()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 2401e46..d73628f 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -100,7 +100,7 @@
 # that system_other is not in the list because we don't want to include its
 # descriptor into vbmeta.img.
 AVB_PARTITIONS = ('boot', 'dtbo', 'odm', 'product', 'recovery', 'system',
-                  'system_ext', 'vendor')
+                  'system_ext', 'vendor', 'vendor_boot')
 
 # Chained VBMeta partitions.
 AVB_VBMETA_PARTITIONS = ('vbmeta_system', 'vbmeta_vendor')
@@ -284,6 +284,225 @@
       pass
 
 
+class BuildInfo(object):
+  """A class that holds the information for a given build.
+
+  This class wraps up the property querying for a given source or target build.
+  It abstracts away the logic of handling OEM-specific properties, and caches
+  the commonly used properties such as fingerprint.
+
+  There are two types of info dicts: a) build-time info dict, which is generated
+  at build time (i.e. included in a target_files zip); b) OEM info dict that is
+  specified at package generation time (via command line argument
+  '--oem_settings'). If a build doesn't use OEM-specific properties (i.e. not
+  having "oem_fingerprint_properties" in build-time info dict), all the queries
+  would be answered based on build-time info dict only. Otherwise if using
+  OEM-specific properties, some of them will be calculated from two info dicts.
+
+  Users can query properties similarly as using a dict() (e.g. info['fstab']),
+  or to query build properties via GetBuildProp() or GetVendorBuildProp().
+
+  Attributes:
+    info_dict: The build-time info dict.
+    is_ab: Whether it's a build that uses A/B OTA.
+    oem_dicts: A list of OEM dicts.
+    oem_props: A list of OEM properties that should be read from OEM dicts; None
+        if the build doesn't use any OEM-specific property.
+    fingerprint: The fingerprint of the build, which would be calculated based
+        on OEM properties if applicable.
+    device: The device name, which could come from OEM dicts if applicable.
+  """
+
+  _RO_PRODUCT_RESOLVE_PROPS = ["ro.product.brand", "ro.product.device",
+                               "ro.product.manufacturer", "ro.product.model",
+                               "ro.product.name"]
+  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "odm", "vendor",
+                                            "system_ext", "system"]
+
+  def __init__(self, info_dict, oem_dicts=None):
+    """Initializes a BuildInfo instance with the given dicts.
+
+    Note that it only wraps up the given dicts, without making copies.
+
+    Arguments:
+      info_dict: The build-time info dict.
+      oem_dicts: A list of OEM dicts (which is parsed from --oem_settings). Note
+          that it always uses the first dict to calculate the fingerprint or the
+          device name. The rest would be used for asserting OEM properties only
+          (e.g. one package can be installed on one of these devices).
+
+    Raises:
+      ValueError: On invalid inputs.
+    """
+    self.info_dict = info_dict
+    self.oem_dicts = oem_dicts
+
+    self._is_ab = info_dict.get("ab_update") == "true"
+    self._oem_props = info_dict.get("oem_fingerprint_properties")
+
+    if self._oem_props:
+      assert oem_dicts, "OEM source required for this build"
+
+    # These two should be computed only after setting self._oem_props.
+    self._device = self.GetOemProperty("ro.product.device")
+    self._fingerprint = self.CalculateFingerprint()
+
+    # Sanity check the build fingerprint.
+    if (' ' in self._fingerprint or
+        any(ord(ch) > 127 for ch in self._fingerprint)):
+      raise ValueError(
+          'Invalid build fingerprint: "{}". See the requirement in Android CDD '
+          '3.2.2. Build Parameters.'.format(self._fingerprint))
+
+  @property
+  def is_ab(self):
+    return self._is_ab
+
+  @property
+  def device(self):
+    return self._device
+
+  @property
+  def fingerprint(self):
+    return self._fingerprint
+
+  @property
+  def vendor_fingerprint(self):
+    return self._fingerprint_of("vendor")
+
+  @property
+  def product_fingerprint(self):
+    return self._fingerprint_of("product")
+
+  @property
+  def odm_fingerprint(self):
+    return self._fingerprint_of("odm")
+
+  def _fingerprint_of(self, partition):
+    if partition + ".build.prop" not in self.info_dict:
+      return None
+    build_prop = self.info_dict[partition + ".build.prop"]
+    if "ro." + partition + ".build.fingerprint" in build_prop:
+      return build_prop["ro." + partition + ".build.fingerprint"]
+    if "ro." + partition + ".build.thumbprint" in build_prop:
+      return build_prop["ro." + partition + ".build.thumbprint"]
+    return None
+
+  @property
+  def oem_props(self):
+    return self._oem_props
+
+  def __getitem__(self, key):
+    return self.info_dict[key]
+
+  def __setitem__(self, key, value):
+    self.info_dict[key] = value
+
+  def get(self, key, default=None):
+    return self.info_dict.get(key, default)
+
+  def items(self):
+    return self.info_dict.items()
+
+  def GetBuildProp(self, prop):
+    """Returns the inquired build property."""
+    if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS:
+      return self._ResolveRoProductBuildProp(prop)
+
+    try:
+      return self.info_dict.get("build.prop", {})[prop]
+    except KeyError:
+      raise ExternalError("couldn't find %s in build.prop" % (prop,))
+
+  def _ResolveRoProductBuildProp(self, prop):
+    """Resolves the inquired ro.product.* build property"""
+    prop_val = self.info_dict.get("build.prop", {}).get(prop)
+    if prop_val:
+      return prop_val
+
+    source_order_val = self.info_dict.get("build.prop", {}).get(
+        "ro.product.property_source_order")
+    if source_order_val:
+      source_order = source_order_val.split(",")
+    else:
+      source_order = BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
+
+    # Check that all sources in ro.product.property_source_order are valid
+    if any([x not in BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
+            for x in source_order]):
+      raise ExternalError(
+          "Invalid ro.product.property_source_order '{}'".format(source_order))
+
+    for source in source_order:
+      source_prop = prop.replace(
+          "ro.product", "ro.product.{}".format(source), 1)
+      prop_val = self.info_dict.get(
+          "{}.build.prop".format(source), {}).get(source_prop)
+      if prop_val:
+        return prop_val
+
+    raise ExternalError("couldn't resolve {}".format(prop))
+
+  def GetVendorBuildProp(self, prop):
+    """Returns the inquired vendor build property."""
+    try:
+      return self.info_dict.get("vendor.build.prop", {})[prop]
+    except KeyError:
+      raise ExternalError(
+          "couldn't find %s in vendor.build.prop" % (prop,))
+
+  def GetOemProperty(self, key):
+    if self.oem_props is not None and key in self.oem_props:
+      return self.oem_dicts[0][key]
+    return self.GetBuildProp(key)
+
+  def CalculateFingerprint(self):
+    if self.oem_props is None:
+      try:
+        return self.GetBuildProp("ro.build.fingerprint")
+      except ExternalError:
+        return "{}/{}/{}:{}/{}/{}:{}/{}".format(
+            self.GetBuildProp("ro.product.brand"),
+            self.GetBuildProp("ro.product.name"),
+            self.GetBuildProp("ro.product.device"),
+            self.GetBuildProp("ro.build.version.release"),
+            self.GetBuildProp("ro.build.id"),
+            self.GetBuildProp("ro.build.version.incremental"),
+            self.GetBuildProp("ro.build.type"),
+            self.GetBuildProp("ro.build.tags"))
+    return "%s/%s/%s:%s" % (
+        self.GetOemProperty("ro.product.brand"),
+        self.GetOemProperty("ro.product.name"),
+        self.GetOemProperty("ro.product.device"),
+        self.GetBuildProp("ro.build.thumbprint"))
+
+  def WriteMountOemScript(self, script):
+    assert self.oem_props is not None
+    recovery_mount_options = self.info_dict.get("recovery_mount_options")
+    script.Mount("/oem", recovery_mount_options)
+
+  def WriteDeviceAssertions(self, script, oem_no_mount):
+    # Read the property directly if not using OEM properties.
+    if not self.oem_props:
+      script.AssertDevice(self.device)
+      return
+
+    # Otherwise assert OEM properties.
+    if not self.oem_dicts:
+      raise ExternalError(
+          "No OEM file provided to answer expected assertions")
+
+    for prop in self.oem_props.split():
+      values = []
+      for oem_dict in self.oem_dicts:
+        if prop in oem_dict:
+          values.append(oem_dict[prop])
+      if not values:
+        raise ExternalError(
+            "The OEM file is missing the property %s" % (prop,))
+      script.AssertOemProperty(prop, values, oem_no_mount)
+
+
 def LoadInfoDict(input_file, repacking=False):
   """Loads the key/value pairs from the given input target_files.
 
@@ -393,37 +612,8 @@
   makeint("boot_size")
   makeint("fstab_version")
 
-  # We changed recovery.fstab path in Q, from ../RAMDISK/etc/recovery.fstab to
-  # ../RAMDISK/system/etc/recovery.fstab. LoadInfoDict() has to handle both
-  # cases, since it may load the info_dict from an old build (e.g. when
-  # generating incremental OTAs from that build).
-  system_root_image = d.get("system_root_image") == "true"
-  if d.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"
-    d["fstab"] = LoadRecoveryFSTab(
-        read_helper, d["fstab_version"], recovery_fstab_path, system_root_image)
-
-  elif d.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"
-    d["fstab"] = LoadRecoveryFSTab(
-        read_helper, d["fstab_version"], recovery_fstab_path, system_root_image)
-
-  else:
-    d["fstab"] = None
+  # Load recovery fstab if applicable.
+  d["fstab"] = _FindAndLoadRecoveryFstab(d, input_file, read_helper)
 
   # Tries to load the build props for all partitions with care_map, including
   # system and vendor.
@@ -438,18 +628,11 @@
           read_helper, "{}/etc/build.prop".format(partition.upper()))
   d["build.prop"] = d["system.build.prop"]
 
-  # Set up the salt (based on fingerprint or thumbprint) that will be used when
-  # adding AVB footer.
+  # Set up the salt (based on fingerprint) that will be used when adding AVB
+  # hash / hashtree footers.
   if d.get("avb_enable") == "true":
-    fp = None
-    if "build.prop" in d:
-      build_prop = d["build.prop"]
-      if "ro.build.fingerprint" in build_prop:
-        fp = build_prop["ro.build.fingerprint"]
-      elif "ro.build.thumbprint" in build_prop:
-        fp = build_prop["ro.build.thumbprint"]
-    if fp:
-      d["avb_salt"] = sha256(fp).hexdigest()
+    build_info = BuildInfo(d)
+    d["avb_salt"] = sha256(build_info.fingerprint).hexdigest()
 
   return d
 
@@ -549,6 +732,47 @@
   return d
 
 
+def _FindAndLoadRecoveryFstab(info_dict, input_file, read_helper):
+  """Finds the path to recovery fstab and loads its contents."""
+  # recovery fstab is only meaningful when installing an update via recovery
+  # (i.e. non-A/B OTA). Skip loading fstab if device used A/B OTA.
+  if info_dict.get('ab_update') == 'true':
+    return None
+
+  # We changed recovery.fstab path in Q, from ../RAMDISK/etc/recovery.fstab to
+  # ../RAMDISK/system/etc/recovery.fstab. This function has to handle both
+  # cases, since it may load the info_dict from an old build (e.g. when
+  # generating incremental OTAs from that build).
+  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'
+    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'
+    return LoadRecoveryFSTab(
+        read_helper, info_dict['fstab_version'], recovery_fstab_path,
+        system_root_image)
+
+  return None
+
+
 def DumpInfoDict(d):
   for k, v in sorted(d.items()):
     logger.info("%-25s = (%s) %s", k, type(v).__name__, v)
@@ -616,6 +840,10 @@
   """Append signing arguments for avbtool."""
   # e.g., "--key path/to/signing_key --algorithm SHA256_RSA4096"
   key_path = OPTIONS.info_dict.get("avb_" + partition + "_key_path")
+  if key_path and not os.path.exists(key_path) and OPTIONS.search_path:
+    new_key_path = os.path.join(OPTIONS.search_path, key_path)
+    if os.path.exists(new_key_path):
+      key_path = new_key_path
   algorithm = OPTIONS.info_dict.get("avb_" + partition + "_algorithm")
   if key_path and algorithm:
     cmd.extend(["--key", key_path, "--algorithm", algorithm])
@@ -625,7 +853,7 @@
     cmd.extend(["--salt", avb_salt])
 
 
-def GetAvbPartitionArg(partition, image, info_dict = None):
+def GetAvbPartitionArg(partition, image, info_dict=None):
   """Returns the VBMeta arguments for partition.
 
   It sets up the VBMeta argument by including the partition descriptor from the
@@ -648,8 +876,7 @@
   if key_path:
     chained_partition_arg = GetAvbChainedPartitionArg(partition, info_dict)
     return ["--chain_partition", chained_partition_arg]
-  else:
-    return ["--include_descriptors_from_image", image]
+  return ["--include_descriptors_from_image", image]
 
 
 def GetAvbChainedPartitionArg(partition, info_dict, key=None):
@@ -668,6 +895,10 @@
   """
   if key is None:
     key = info_dict["avb_" + partition + "_key_path"]
+  if key and not os.path.exists(key) and OPTIONS.search_path:
+    new_key_path = os.path.join(OPTIONS.search_path, key)
+    if os.path.exists(new_key_path):
+      key = new_key_path
   pubkey_path = ExtractAvbPublicKey(info_dict["avb_avbtool"], key)
   rollback_index_location = info_dict[
       "avb_" + partition + "_rollback_index_location"]
@@ -733,6 +964,25 @@
   RunAndCheckOutput(cmd)
 
 
+def _MakeRamdisk(sourcedir, fs_config_file=None):
+  ramdisk_img = tempfile.NamedTemporaryFile()
+
+  if fs_config_file is not None and os.access(fs_config_file, os.F_OK):
+    cmd = ["mkbootfs", "-f", fs_config_file,
+           os.path.join(sourcedir, "RAMDISK")]
+  else:
+    cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
+  p1 = Run(cmd, stdout=subprocess.PIPE)
+  p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
+
+  p2.wait()
+  p1.wait()
+  assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (sourcedir,)
+  assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (sourcedir,)
+
+  return ramdisk_img
+
+
 def _BuildBootableImage(sourcedir, fs_config_file, info_dict=None,
                         has_ramdisk=False, two_step_image=False):
   """Build a bootable image from the specified sourcedir.
@@ -746,24 +996,6 @@
   for building the requested image.
   """
 
-  def make_ramdisk():
-    ramdisk_img = tempfile.NamedTemporaryFile()
-
-    if os.access(fs_config_file, os.F_OK):
-      cmd = ["mkbootfs", "-f", fs_config_file,
-             os.path.join(sourcedir, "RAMDISK")]
-    else:
-      cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
-    p1 = Run(cmd, stdout=subprocess.PIPE)
-    p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
-
-    p2.wait()
-    p1.wait()
-    assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (sourcedir,)
-    assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (sourcedir,)
-
-    return ramdisk_img
-
   if not os.access(os.path.join(sourcedir, "kernel"), os.F_OK):
     return None
 
@@ -776,7 +1008,7 @@
   img = tempfile.NamedTemporaryFile()
 
   if has_ramdisk:
-    ramdisk_img = make_ramdisk()
+    ramdisk_img = _MakeRamdisk(sourcedir, fs_config_file)
 
   # use MKBOOTIMG from environ, or "mkbootimg" if empty or not set
   mkbootimg = os.getenv('MKBOOTIMG') or "mkbootimg"
@@ -938,6 +1170,105 @@
   return None
 
 
+def _BuildVendorBootImage(sourcedir, info_dict=None):
+  """Build a vendor boot image from the specified sourcedir.
+
+  Take a ramdisk, dtb, and vendor_cmdline from the input (in 'sourcedir'), and
+  turn them into a vendor boot image.
+
+  Return the image data, or None if sourcedir does not appear to contains files
+  for building the requested image.
+  """
+
+  if info_dict is None:
+    info_dict = OPTIONS.info_dict
+
+  img = tempfile.NamedTemporaryFile()
+
+  ramdisk_img = _MakeRamdisk(sourcedir)
+
+  # use MKBOOTIMG from environ, or "mkbootimg" if empty or not set
+  mkbootimg = os.getenv('MKBOOTIMG') or "mkbootimg"
+
+  cmd = [mkbootimg]
+
+  fn = os.path.join(sourcedir, "dtb")
+  if os.access(fn, os.F_OK):
+    cmd.append("--dtb")
+    cmd.append(fn)
+
+  fn = os.path.join(sourcedir, "vendor_cmdline")
+  if os.access(fn, os.F_OK):
+    cmd.append("--vendor_cmdline")
+    cmd.append(open(fn).read().rstrip("\n"))
+
+  fn = os.path.join(sourcedir, "base")
+  if os.access(fn, os.F_OK):
+    cmd.append("--base")
+    cmd.append(open(fn).read().rstrip("\n"))
+
+  fn = os.path.join(sourcedir, "pagesize")
+  if os.access(fn, os.F_OK):
+    cmd.append("--pagesize")
+    cmd.append(open(fn).read().rstrip("\n"))
+
+  args = info_dict.get("mkbootimg_args")
+  if args and args.strip():
+    cmd.extend(shlex.split(args))
+
+  args = info_dict.get("mkbootimg_version_args")
+  if args and args.strip():
+    cmd.extend(shlex.split(args))
+
+  cmd.extend(["--vendor_ramdisk", ramdisk_img.name])
+  cmd.extend(["--vendor_boot", img.name])
+
+  RunAndCheckOutput(cmd)
+
+  # AVB: if enabled, calculate and add hash.
+  if info_dict.get("avb_enable") == "true":
+    avbtool = info_dict["avb_avbtool"]
+    part_size = info_dict["vendor_boot_size"]
+    cmd = [avbtool, "add_hash_footer", "--image", img.name,
+           "--partition_size", str(part_size), "--partition_name vendor_boot"]
+    AppendAVBSigningArgs(cmd, "vendor_boot")
+    args = info_dict.get("avb_vendor_boot_add_hash_footer_args")
+    if args and args.strip():
+      cmd.extend(shlex.split(args))
+    RunAndCheckOutput(cmd)
+
+  img.seek(os.SEEK_SET, 0)
+  data = img.read()
+
+  ramdisk_img.close()
+  img.close()
+
+  return data
+
+
+def GetVendorBootImage(name, prebuilt_name, unpack_dir, tree_subdir,
+                       info_dict=None):
+  """Return a File object with the desired vendor boot image.
+
+  Look for it under 'unpack_dir'/IMAGES, otherwise construct it from
+  the source files in 'unpack_dir'/'tree_subdir'."""
+
+  prebuilt_path = os.path.join(unpack_dir, "IMAGES", prebuilt_name)
+  if os.path.exists(prebuilt_path):
+    logger.info("using prebuilt %s from IMAGES...", prebuilt_name)
+    return File.FromLocalFile(name, prebuilt_path)
+
+  logger.info("building image from target_files %s...", tree_subdir)
+
+  if info_dict is None:
+    info_dict = OPTIONS.info_dict
+
+  data = _BuildVendorBootImage(os.path.join(unpack_dir, tree_subdir), info_dict)
+  if data:
+    return File(name, data)
+  return None
+
+
 def Gunzip(in_filename, out_filename):
   """Gunzips the given gzip compressed file to a given output file."""
   with gzip.open(in_filename, "rb") as in_file, \
@@ -1192,7 +1523,7 @@
 def GetMinSdkVersion(apk_name):
   """Gets the minSdkVersion declared in the APK.
 
-  It calls 'aapt' to query the embedded minSdkVersion from the given APK file.
+  It calls 'aapt2' to query the embedded minSdkVersion from the given APK file.
   This can be both a decimal number (API Level) or a codename.
 
   Args:
@@ -1205,12 +1536,12 @@
     ExternalError: On failing to obtain the min SDK version.
   """
   proc = Run(
-      ["aapt", "dump", "badging", apk_name], stdout=subprocess.PIPE,
+      ["aapt2", "dump", "badging", apk_name], stdout=subprocess.PIPE,
       stderr=subprocess.PIPE)
   stdoutdata, stderrdata = proc.communicate()
   if proc.returncode != 0:
     raise ExternalError(
-        "Failed to obtain minSdkVersion: aapt return code {}:\n{}\n{}".format(
+        "Failed to obtain minSdkVersion: aapt2 return code {}:\n{}\n{}".format(
             proc.returncode, stdoutdata, stderrdata))
 
   for line in stdoutdata.split("\n"):
@@ -1218,7 +1549,7 @@
     m = re.match(r'sdkVersion:\'([^\']*)\'', line)
     if m:
       return m.group(1)
-  raise ExternalError("No minSdkVersion returned by aapt")
+  raise ExternalError("No minSdkVersion returned by aapt2")
 
 
 def GetMinSdkVersionInt(apk_name, codename_to_api_level_map):
@@ -2427,13 +2758,25 @@
     info_dict = OPTIONS.info_dict
 
   full_recovery_image = info_dict.get("full_recovery_image") == "true"
+  board_uses_vendorimage = info_dict.get("board_uses_vendorimage") == "true"
+
+  if board_uses_vendorimage:
+    # In this case, the output sink is rooted at VENDOR
+    recovery_img_path = "etc/recovery.img"
+    recovery_resource_dat_path = "VENDOR/etc/recovery-resource.dat"
+    sh_dir = "bin"
+  else:
+    # In this case the output sink is rooted at SYSTEM
+    recovery_img_path = "vendor/etc/recovery.img"
+    recovery_resource_dat_path = "SYSTEM/vendor/etc/recovery-resource.dat"
+    sh_dir = "vendor/bin"
 
   if full_recovery_image:
-    output_sink("etc/recovery.img", recovery_img.data)
+    output_sink(recovery_img_path, recovery_img.data)
 
   else:
     system_root_image = info_dict.get("system_root_image") == "true"
-    path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat")
+    path = os.path.join(input_dir, recovery_resource_dat_path)
     # With system-root-image, boot and recovery images will have mismatching
     # entries (only recovery has the ramdisk entry) (Bug: 72731506). Use bsdiff
     # to handle such a case.
@@ -2446,7 +2789,7 @@
       if os.path.exists(path):
         diff_program.append("-b")
         diff_program.append(path)
-        bonus_args = "--bonus /system/etc/recovery-resource.dat"
+        bonus_args = "--bonus /vendor/etc/recovery-resource.dat"
       else:
         bonus_args = ""
 
@@ -2463,10 +2806,16 @@
     return
 
   if full_recovery_image:
-    sh = """#!/system/bin/sh
+
+    # Note that we use /vendor to refer to the recovery resources. This will
+    # work for a separate vendor partition mounted at /vendor or a
+    # /system/vendor subdirectory on the system partition, for which init will
+    # create a symlink from /vendor to /system/vendor.
+
+    sh = """#!/vendor/bin/sh
 if ! applypatch --check %(type)s:%(device)s:%(size)d:%(sha1)s; then
   applypatch \\
-          --flash /system/etc/recovery.img \\
+          --flash /vendor/etc/recovery.img \\
           --target %(type)s:%(device)s:%(size)d:%(sha1)s && \\
       log -t recovery "Installing new recovery image: succeeded" || \\
       log -t recovery "Installing new recovery image: failed"
@@ -2478,10 +2827,10 @@
        'sha1': recovery_img.sha1,
        'size': recovery_img.size}
   else:
-    sh = """#!/system/bin/sh
+    sh = """#!/vendor/bin/sh
 if ! applypatch --check %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then
   applypatch %(bonus_args)s \\
-          --patch /system/recovery-from-boot.p \\
+          --patch /vendor/recovery-from-boot.p \\
           --source %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s \\
           --target %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s && \\
       log -t recovery "Installing new recovery image: succeeded" || \\
@@ -2499,9 +2848,9 @@
        'recovery_device': recovery_device,
        'bonus_args': bonus_args}
 
-  # The install script location moved from /system/etc to /system/bin
-  # in the L release.
-  sh_location = "bin/install-recovery.sh"
+  # The install script location moved from /system/etc to /system/bin in the L
+  # release. In the R release it is in VENDOR/bin or SYSTEM/vendor/bin.
+  sh_location = os.path.join(sh_dir, "install-recovery.sh")
 
   logger.info("putting script in %s", sh_location)
 
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index 4b94ad8..ab38d0d 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -27,6 +27,14 @@
       Include only the bootable images (eg 'boot' and 'recovery') in
       the output.
 
+  --additional <filespec>
+      Include an additional entry into the generated zip file. The filespec is
+      in a format that's accepted by zip2zip (e.g.
+      'OTA/android-info.txt:android-info.txt', to copy `OTA/android-info.txt`
+      from input_file into output_file as `android-info.txt`. Refer to the
+      `filespec` arg in zip2zip's help message). The option can be repeated to
+      include multiple entries.
+
 """
 
 from __future__ import print_function
@@ -40,103 +48,129 @@
 from build_super_image import BuildSuperImage
 
 if sys.hexversion < 0x02070000:
-  print("Python 2.7 or newer is required.", file=sys.stderr)
+  print('Python 2.7 or newer is required.', file=sys.stderr)
   sys.exit(1)
 
 logger = logging.getLogger(__name__)
 
 OPTIONS = common.OPTIONS
 
+OPTIONS.additional_entries = []
+OPTIONS.bootable_only = False
+OPTIONS.put_super = None
+OPTIONS.dynamic_partition_list = None
+OPTIONS.super_device_list = None
+OPTIONS.retrofit_dap = None
+OPTIONS.build_super = None
+OPTIONS.sparse_userimages = None
+
 
 def LoadOptions(input_file):
   """Loads information from input_file to OPTIONS.
 
   Args:
-    input_file: Path to the root dir of an extracted target_files zip.
+    input_file: Path to the input target_files zip file.
   """
-  info = OPTIONS.info_dict = common.LoadInfoDict(input_file)
+  with zipfile.ZipFile(input_file) as input_zip:
+    info = OPTIONS.info_dict = common.LoadInfoDict(input_zip)
 
-  OPTIONS.put_super = info.get("super_image_in_update_package") == "true"
-  OPTIONS.dynamic_partition_list = info.get("dynamic_partition_list",
-                                            "").strip().split()
-  OPTIONS.super_device_list = info.get("super_block_devices",
-                                       "").strip().split()
-  OPTIONS.retrofit_dap = info.get("dynamic_partition_retrofit") == "true"
-  OPTIONS.build_super = info.get("build_super_partition") == "true"
-  OPTIONS.sparse_userimages = bool(info.get("extfs_sparse_flag"))
+  OPTIONS.put_super = info.get('super_image_in_update_package') == 'true'
+  OPTIONS.dynamic_partition_list = info.get('dynamic_partition_list',
+                                            '').strip().split()
+  OPTIONS.super_device_list = info.get('super_block_devices',
+                                       '').strip().split()
+  OPTIONS.retrofit_dap = info.get('dynamic_partition_retrofit') == 'true'
+  OPTIONS.build_super = info.get('build_super_partition') == 'true'
+  OPTIONS.sparse_userimages = bool(info.get('extfs_sparse_flag'))
 
 
-def CopyInfo(input_tmp, output_zip):
-  """Copies the android-info.txt file from the input to the output."""
-  common.ZipWrite(
-      output_zip, os.path.join(input_tmp, "OTA", "android-info.txt"),
-      "android-info.txt")
-
-
-def CopyUserImages(input_tmp, output_zip):
-  """Copies user images from the unzipped input and write to output_zip.
+def CopyZipEntries(input_file, output_file, entries):
+  """Copies ZIP entries between input and output files.
 
   Args:
-    input_tmp: path to the unzipped input.
-    output_zip: a ZipFile instance to write images to.
+    input_file: Path to the input target_files zip.
+    output_file: Output filename.
+    entries: A list of entries to copy, in a format that's accepted by zip2zip
+        (e.g. 'OTA/android-info.txt:android-info.txt', which copies
+        `OTA/android-info.txt` from input_file into output_file as
+        `android-info.txt`. Refer to the `filespec` arg in zip2zip's help
+        message).
   """
-  dynamic_images = [p + ".img" for p in OPTIONS.dynamic_partition_list]
+  logger.info('Writing %d entries to archive...', len(entries))
+  cmd = ['zip2zip', '-i', input_file, '-o', output_file]
+  cmd.extend(entries)
+  common.RunAndCheckOutput(cmd)
+
+
+def EntriesForUserImages(input_file):
+  """Returns the user images entries to be copied.
+
+  Args:
+    input_file: Path to the input target_files zip file.
+  """
+  dynamic_images = [p + '.img' for p in OPTIONS.dynamic_partition_list]
 
   # Filter out system_other for launch DAP devices because it is in super image.
-  if not OPTIONS.retrofit_dap and "system" in OPTIONS.dynamic_partition_list:
-    dynamic_images.append("system_other.img")
+  if not OPTIONS.retrofit_dap and 'system' in OPTIONS.dynamic_partition_list:
+    dynamic_images.append('system_other.img')
 
-  images_path = os.path.join(input_tmp, "IMAGES")
-  # A target-files zip must contain the images since Lollipop.
-  assert os.path.exists(images_path)
-  for image in sorted(os.listdir(images_path)):
-    if OPTIONS.bootable_only and image not in ("boot.img", "recovery.img"):
+  entries = [
+      'OTA/android-info.txt:android-info.txt',
+  ]
+  with zipfile.ZipFile(input_file) as input_zip:
+    namelist = input_zip.namelist()
+
+  for image_path in [name for name in namelist if name.startswith('IMAGES/')]:
+    image = os.path.basename(image_path)
+    if OPTIONS.bootable_only and image not in ('boot.img', 'recovery.img'):
       continue
-    if not image.endswith(".img"):
+    if not image.endswith('.img'):
       continue
+    # Filter out super_empty and the images that are already in super partition.
     if OPTIONS.put_super:
-      if image == "super_empty.img":
+      if image == 'super_empty.img':
         continue
       if image in dynamic_images:
         continue
-    logger.info("writing %s to archive...", os.path.join("IMAGES", image))
-    common.ZipWrite(output_zip, os.path.join(images_path, image), image)
+    entries.append('{}:{}'.format(image_path, image))
+  return entries
 
 
-def WriteSuperImages(input_tmp, output_zip):
-  """Writes super images from the unzipped input into output_zip.
+def EntriesForSplitSuperImages(input_file):
+  """Returns the entries for split super images.
 
-  This is only done if super_image_in_update_package is set to "true".
-
-  - For retrofit dynamic partition devices, copy split super images from target
-    files package.
-  - For devices launched with dynamic partitions, build super image from target
-    files package.
+  This is only done for retrofit dynamic partition devices.
 
   Args:
-    input_tmp: path to the unzipped input.
-    output_zip: a ZipFile instance to write images to.
+    input_file: Path to the input target_files zip file.
   """
-  if not OPTIONS.build_super or not OPTIONS.put_super:
-    return
+  with zipfile.ZipFile(input_file) as input_zip:
+    namelist = input_zip.namelist()
+  entries = []
+  for device in OPTIONS.super_device_list:
+    image = 'OTA/super_{}.img'.format(device)
+    assert image in namelist, 'Failed to find {}'.format(image)
+    entries.append('{}:{}'.format(image, os.path.basename(image)))
+  return entries
 
-  if OPTIONS.retrofit_dap:
-    # retrofit devices already have split super images under OTA/
-    images_path = os.path.join(input_tmp, "OTA")
-    for device in OPTIONS.super_device_list:
-      image = "super_%s.img" % device
-      image_path = os.path.join(images_path, image)
-      assert os.path.exists(image_path)
-      logger.info("writing %s to archive...", os.path.join("OTA", image))
-      common.ZipWrite(output_zip, image_path, image)
-  else:
-    # super image for non-retrofit devices aren't in target files package,
-    # so build it.
-    super_file = common.MakeTempFile("super_", ".img")
-    logger.info("building super image %s...", super_file)
-    BuildSuperImage(input_tmp, super_file)
-    logger.info("writing super.img to archive...")
-    common.ZipWrite(output_zip, super_file, "super.img")
+
+def RebuildAndWriteSuperImages(input_file, output_file):
+  """Builds and writes super images to the output file."""
+  logger.info('Building super image...')
+
+  # We need files under IMAGES/, OTA/, META/ for img_from_target_files.py.
+  # However, common.LoadInfoDict() may read additional files under BOOT/,
+  # RECOVERY/ and ROOT/. So unzip everything from the target_files.zip.
+  input_tmp = common.UnzipTemp(input_file)
+
+  super_file = common.MakeTempFile('super_', '.img')
+  BuildSuperImage(input_tmp, super_file)
+
+  logger.info('Writing super.img to archive...')
+  with zipfile.ZipFile(
+      output_file, 'a', compression=zipfile.ZIP_DEFLATED,
+      allowZip64=not OPTIONS.sparse_userimages) as output_zip:
+    common.ZipWrite(output_zip, super_file, 'super.img')
 
 
 def ImgFromTargetFiles(input_file, output_file):
@@ -150,47 +184,51 @@
     ValueError: On invalid input.
   """
   if not zipfile.is_zipfile(input_file):
-    raise ValueError("%s is not a valid zipfile" % input_file)
+    raise ValueError('%s is not a valid zipfile' % input_file)
 
-  logger.info("Building image zip from target files zip.")
+  logger.info('Building image zip from target files zip.')
 
-  # We need files under IMAGES/, OTA/, META/ for img_from_target_files.py.
-  # However, common.LoadInfoDict() may read additional files under BOOT/,
-  # RECOVERY/ and ROOT/. So unzip everything from the target_files.zip.
-  input_tmp = common.UnzipTemp(input_file)
+  LoadOptions(input_file)
 
-  LoadOptions(input_tmp)
-  output_zip = zipfile.ZipFile(
-      output_file, "w", compression=zipfile.ZIP_DEFLATED,
-      allowZip64=not OPTIONS.sparse_userimages)
+  # Entries to be copied into the output file.
+  entries = EntriesForUserImages(input_file)
 
-  try:
-    CopyInfo(input_tmp, output_zip)
-    CopyUserImages(input_tmp, output_zip)
-    WriteSuperImages(input_tmp, output_zip)
-  finally:
-    logger.info("cleaning up...")
-    common.ZipClose(output_zip)
+  # Only for devices that retrofit dynamic partitions there're split super
+  # images available in the target_files.zip.
+  rebuild_super = False
+  if OPTIONS.build_super and OPTIONS.put_super:
+    if OPTIONS.retrofit_dap:
+      entries += EntriesForSplitSuperImages(input_file)
+    else:
+      rebuild_super = True
+
+  # Any additional entries provided by caller.
+  entries += OPTIONS.additional_entries
+
+  CopyZipEntries(input_file, output_file, entries)
+
+  if rebuild_super:
+    RebuildAndWriteSuperImages(input_file, output_file)
 
 
 def main(argv):
-  # This allows modifying the value from inner function.
-  bootable_only_array = [False]
 
-  def option_handler(o, _):
-    if o in ("-z", "--bootable_zip"):
-      bootable_only_array[0] = True
+  def option_handler(o, a):
+    if o in ('-z', '--bootable_zip'):
+      OPTIONS.bootable_only = True
+    elif o == '--additional':
+      OPTIONS.additional_entries.append(a)
     else:
       return False
     return True
 
   args = common.ParseOptions(argv, __doc__,
-                             extra_opts="z",
-                             extra_long_opts=["bootable_zip"],
+                             extra_opts='z',
+                             extra_long_opts=[
+                                 'additional=',
+                                 'bootable_zip',
+                             ],
                              extra_option_handler=option_handler)
-
-  OPTIONS.bootable_only = bootable_only_array[0]
-
   if len(args) != 2:
     common.Usage(__doc__)
     sys.exit(1)
@@ -199,7 +237,7 @@
 
   ImgFromTargetFiles(args[0], args[1])
 
-  logger.info("done.")
+  logger.info('done.')
 
 
 if __name__ == '__main__':
@@ -207,7 +245,7 @@
     common.CloseInheritedPipes()
     main(sys.argv[1:])
   except common.ExternalError as e:
-    logger.exception("\n   ERROR:\n")
+    logger.exception('\n   ERROR:\n')
     sys.exit(1)
   finally:
     common.Cleanup()
diff --git a/tools/releasetools/make_recovery_patch.py b/tools/releasetools/make_recovery_patch.py
index 725b355..1497d69 100644
--- a/tools/releasetools/make_recovery_patch.py
+++ b/tools/releasetools/make_recovery_patch.py
@@ -47,8 +47,17 @@
   if not recovery_img or not boot_img:
     sys.exit(0)
 
+  board_uses_vendorimage = OPTIONS.info_dict.get(
+      "board_uses_vendorimage") == "true"
+
+  if board_uses_vendorimage:
+    target_files_dir = "VENDOR"
+  else:
+    target_files_dir = "SYSTEM"
+
   def output_sink(fn, data):
-    with open(os.path.join(output_dir, "SYSTEM", *fn.split("/")), "wb") as f:
+    with open(os.path.join(output_dir, target_files_dir,
+                           *fn.split("/")), "wb") as f:
       f.write(data)
 
   common.MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img)
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index b7ed645..544f996 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -68,8 +68,7 @@
       files package and saves it at this path.
 
   --rebuild_recovery
-      Rebuild the recovery patch used by non-A/B devices and write it to the
-      system image.
+      Deprecated; does nothing.
 
   --keep-tmp
       Keep tempoary files for debugging purposes.
@@ -87,6 +86,7 @@
 
 import add_img_to_target_files
 import build_super_image
+import check_target_files_vintf
 import common
 import img_from_target_files
 import ota_from_target_files
@@ -105,6 +105,7 @@
 OPTIONS.output_ota = None
 OPTIONS.output_img = None
 OPTIONS.output_super_empty = None
+# TODO(b/132730255): Remove this option.
 OPTIONS.rebuild_recovery = False
 OPTIONS.keep_tmp = False
 
@@ -117,8 +118,6 @@
     'META/apkcerts.txt',
     'META/filesystem_config.txt',
     'META/root_filesystem_config.txt',
-    'META/system_manifest.xml',
-    'META/system_matrix.xml',
     'META/update_engine_config.txt',
     'PRODUCT/*',
     'ROOT/*',
@@ -163,8 +162,6 @@
     'META/otakeys.txt',
     'META/releasetools.py',
     'META/vendor_filesystem_config.txt',
-    'META/vendor_manifest.xml',
-    'META/vendor_matrix.xml',
     'BOOT/*',
     'DATA/*',
     'ODM/*',
@@ -375,32 +372,6 @@
   write_sorted_data(data=output_ab_partitions, path=output_ab_partitions_txt)
 
 
-def append_recovery_to_filesystem_config(output_target_files_temp_dir):
-  """Performs special processing for META/filesystem_config.txt.
-
-  This function appends recovery information to META/filesystem_config.txt so
-  that recovery patch regeneration will succeed.
-
-  Args:
-    output_target_files_temp_dir: The name of a directory that will be used to
-      create the output target files package after all the special cases are
-      processed. We find filesystem_config.txt here.
-  """
-
-  filesystem_config_txt = os.path.join(output_target_files_temp_dir, 'META',
-                                       'filesystem_config.txt')
-
-  with open(filesystem_config_txt, 'a') as f:
-    # TODO(bpeckham) this data is hard coded. It should be generated
-    # programmatically.
-    f.write('system/bin/install-recovery.sh 0 0 750 '
-            'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
-    f.write('system/recovery-from-boot.p 0 0 644 '
-            'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
-    f.write('system/etc/recovery.img 0 0 440 '
-            'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
-
-
 def process_misc_info_txt(framework_target_files_temp_dir,
                           vendor_target_files_temp_dir,
                           output_target_files_temp_dir,
@@ -597,7 +568,7 @@
 def process_special_cases(framework_target_files_temp_dir,
                           vendor_target_files_temp_dir,
                           output_target_files_temp_dir,
-                          framework_misc_info_keys, rebuild_recovery):
+                          framework_misc_info_keys):
   """Performs special-case processing for certain target files items.
 
   Certain files in the output target files package require special-case
@@ -614,8 +585,6 @@
     framework_misc_info_keys: A list of keys to obtain from the framework
       instance of META/misc_info.txt. The remaining keys from the vendor
       instance.
-    rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
-      devices and write it to the system image.
   """
 
   if 'ab_update' in framework_misc_info_keys:
@@ -624,10 +593,6 @@
         vendor_target_files_temp_dir=vendor_target_files_temp_dir,
         output_target_files_temp_dir=output_target_files_temp_dir)
 
-  if rebuild_recovery:
-    append_recovery_to_filesystem_config(
-        output_target_files_temp_dir=output_target_files_temp_dir)
-
   copy_file_contexts(
       framework_target_files_dir=framework_target_files_temp_dir,
       vendor_target_files_dir=vendor_target_files_temp_dir,
@@ -760,8 +725,7 @@
       framework_target_files_temp_dir=framework_target_files_temp_dir,
       vendor_target_files_temp_dir=vendor_target_files_temp_dir,
       output_target_files_temp_dir=output_target_files_temp_dir,
-      framework_misc_info_keys=framework_misc_info_keys,
-      rebuild_recovery=rebuild_recovery)
+      framework_misc_info_keys=framework_misc_info_keys)
 
   return output_target_files_temp_dir
 
@@ -782,6 +746,7 @@
 
   add_img_args = ['--verbose']
   add_img_args.append('--add_missing')
+  # TODO(b/132730255): Remove this if statement.
   if rebuild_recovery:
     add_img_args.append('--rebuild_recovery')
   add_img_args.append(target_files_dir)
@@ -910,15 +875,13 @@
       vendor_target_files, vendor_item_list, framework_misc_info_keys,
       rebuild_recovery)
 
+  if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
+    raise RuntimeError("Incompatible VINTF metadata")
+
   generate_images(output_target_files_temp_dir, rebuild_recovery)
 
   generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
 
-  if output_img:
-    # Create the IMG package from the merged target files (before zipping, in
-    # order to avoid an unnecessary unzip and copy).
-    img_from_target_files.main([output_target_files_temp_dir, output_img])
-
   # Finally, create the output target files zip archive and/or copy the
   # output items to the output target files directory.
 
@@ -932,6 +895,11 @@
                                            output_target_files_temp_dir,
                                            temp_dir)
 
+  # Create the IMG package from the merged target files package.
+
+  if output_img:
+    img_from_target_files.main([output_zip, output_img])
+
   # Create the OTA package from the merged target files package.
 
   if output_ota:
@@ -1016,7 +984,7 @@
       OPTIONS.output_img = a
     elif o == '--output-super-empty':
       OPTIONS.output_super_empty = a
-    elif o == '--rebuild_recovery':
+    elif o == '--rebuild_recovery': # TODO(b/132730255): Warn
       OPTIONS.rebuild_recovery = True
     elif o == '--keep-tmp':
       OPTIONS.keep_tmp = True
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index c6c859c..1e7bb3a 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -72,7 +72,7 @@
       --skip_postinstall is implied.
 
   --skip_compatibility_check
-      Skip adding the compatibility package to the generated OTA package.
+      Skip checking compatibility of the input target files package.
 
   --output_metadata_path
       Write a copy of the metadata to a separate file. Therefore, users can
@@ -139,6 +139,9 @@
 
 A/B OTA specific options
 
+  --disable_fec_computation
+      Disable the on device FEC data computation for incremental updates.
+
   --include_secondary
       Additionally include the payload for secondary slot images (default:
       False). Only meaningful when generating A/B OTAs.
@@ -189,9 +192,9 @@
 import shutil
 import struct
 import sys
-import tempfile
 import zipfile
 
+import check_target_files_vintf
 import common
 import edify_generator
 import verity_utils
@@ -235,6 +238,7 @@
 OPTIONS.retrofit_dynamic_partitions = False
 OPTIONS.skip_compatibility_check = False
 OPTIONS.output_metadata_path = None
+OPTIONS.disable_fec_computation = False
 
 
 METADATA_NAME = 'META-INF/com/android/metadata'
@@ -247,214 +251,11 @@
                                 'PRODUCT/*', 'SYSTEM_EXT/*', 'ODM/*']
 RETROFIT_DAP_UNZIP_PATTERN = ['OTA/super_*.img', AB_PARTITIONS]
 
-
-class BuildInfo(object):
-  """A class that holds the information for a given build.
-
-  This class wraps up the property querying for a given source or target build.
-  It abstracts away the logic of handling OEM-specific properties, and caches
-  the commonly used properties such as fingerprint.
-
-  There are two types of info dicts: a) build-time info dict, which is generated
-  at build time (i.e. included in a target_files zip); b) OEM info dict that is
-  specified at package generation time (via command line argument
-  '--oem_settings'). If a build doesn't use OEM-specific properties (i.e. not
-  having "oem_fingerprint_properties" in build-time info dict), all the queries
-  would be answered based on build-time info dict only. Otherwise if using
-  OEM-specific properties, some of them will be calculated from two info dicts.
-
-  Users can query properties similarly as using a dict() (e.g. info['fstab']),
-  or to query build properties via GetBuildProp() or GetVendorBuildProp().
-
-  Attributes:
-    info_dict: The build-time info dict.
-    is_ab: Whether it's a build that uses A/B OTA.
-    oem_dicts: A list of OEM dicts.
-    oem_props: A list of OEM properties that should be read from OEM dicts; None
-        if the build doesn't use any OEM-specific property.
-    fingerprint: The fingerprint of the build, which would be calculated based
-        on OEM properties if applicable.
-    device: The device name, which could come from OEM dicts if applicable.
-  """
-
-  _RO_PRODUCT_RESOLVE_PROPS = ["ro.product.brand", "ro.product.device",
-                               "ro.product.manufacturer", "ro.product.model",
-                               "ro.product.name"]
-  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "odm", "vendor",
-                                            "system_ext", "system"]
-
-  def __init__(self, info_dict, oem_dicts):
-    """Initializes a BuildInfo instance with the given dicts.
-
-    Note that it only wraps up the given dicts, without making copies.
-
-    Arguments:
-      info_dict: The build-time info dict.
-      oem_dicts: A list of OEM dicts (which is parsed from --oem_settings). Note
-          that it always uses the first dict to calculate the fingerprint or the
-          device name. The rest would be used for asserting OEM properties only
-          (e.g. one package can be installed on one of these devices).
-    """
-    self.info_dict = info_dict
-    self.oem_dicts = oem_dicts
-
-    self._is_ab = info_dict.get("ab_update") == "true"
-    self._oem_props = info_dict.get("oem_fingerprint_properties")
-
-    if self._oem_props:
-      assert oem_dicts, "OEM source required for this build"
-
-    # These two should be computed only after setting self._oem_props.
-    self._device = self.GetOemProperty("ro.product.device")
-    self._fingerprint = self.CalculateFingerprint()
-
-  @property
-  def is_ab(self):
-    return self._is_ab
-
-  @property
-  def device(self):
-    return self._device
-
-  @property
-  def fingerprint(self):
-    return self._fingerprint
-
-  @property
-  def vendor_fingerprint(self):
-    return self._fingerprint_of("vendor")
-
-  @property
-  def product_fingerprint(self):
-    return self._fingerprint_of("product")
-
-  @property
-  def odm_fingerprint(self):
-    return self._fingerprint_of("odm")
-
-  def _fingerprint_of(self, partition):
-    if partition + ".build.prop" not in self.info_dict:
-      return None
-    build_prop = self.info_dict[partition + ".build.prop"]
-    if "ro." + partition + ".build.fingerprint" in build_prop:
-      return build_prop["ro." + partition + ".build.fingerprint"]
-    if "ro." + partition + ".build.thumbprint" in build_prop:
-      return build_prop["ro." + partition + ".build.thumbprint"]
-    return None
-
-  @property
-  def oem_props(self):
-    return self._oem_props
-
-  def __getitem__(self, key):
-    return self.info_dict[key]
-
-  def __setitem__(self, key, value):
-    self.info_dict[key] = value
-
-  def get(self, key, default=None):
-    return self.info_dict.get(key, default)
-
-  def items(self):
-    return self.info_dict.items()
-
-  def GetBuildProp(self, prop):
-    """Returns the inquired build property."""
-    if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS:
-      return self._ResolveRoProductBuildProp(prop)
-
-    try:
-      return self.info_dict.get("build.prop", {})[prop]
-    except KeyError:
-      raise common.ExternalError("couldn't find %s in build.prop" % (prop,))
-
-  def _ResolveRoProductBuildProp(self, prop):
-    """Resolves the inquired ro.product.* build property"""
-    prop_val = self.info_dict.get("build.prop", {}).get(prop)
-    if prop_val:
-      return prop_val
-
-    source_order_val = self.info_dict.get("build.prop", {}).get(
-        "ro.product.property_source_order")
-    if source_order_val:
-      source_order = source_order_val.split(",")
-    else:
-      source_order = BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
-
-    # Check that all sources in ro.product.property_source_order are valid
-    if any([x not in BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
-            for x in source_order]):
-      raise common.ExternalError(
-          "Invalid ro.product.property_source_order '{}'".format(source_order))
-
-    for source in source_order:
-      source_prop = prop.replace(
-          "ro.product", "ro.product.{}".format(source), 1)
-      prop_val = self.info_dict.get(
-          "{}.build.prop".format(source), {}).get(source_prop)
-      if prop_val:
-        return prop_val
-
-    raise common.ExternalError("couldn't resolve {}".format(prop))
-
-  def GetVendorBuildProp(self, prop):
-    """Returns the inquired vendor build property."""
-    try:
-      return self.info_dict.get("vendor.build.prop", {})[prop]
-    except KeyError:
-      raise common.ExternalError(
-          "couldn't find %s in vendor.build.prop" % (prop,))
-
-  def GetOemProperty(self, key):
-    if self.oem_props is not None and key in self.oem_props:
-      return self.oem_dicts[0][key]
-    return self.GetBuildProp(key)
-
-  def CalculateFingerprint(self):
-    if self.oem_props is None:
-      try:
-        return self.GetBuildProp("ro.build.fingerprint")
-      except common.ExternalError:
-        return "{}/{}/{}:{}/{}/{}:{}/{}".format(
-            self.GetBuildProp("ro.product.brand"),
-            self.GetBuildProp("ro.product.name"),
-            self.GetBuildProp("ro.product.device"),
-            self.GetBuildProp("ro.build.version.release"),
-            self.GetBuildProp("ro.build.id"),
-            self.GetBuildProp("ro.build.version.incremental"),
-            self.GetBuildProp("ro.build.type"),
-            self.GetBuildProp("ro.build.tags"))
-    return "%s/%s/%s:%s" % (
-        self.GetOemProperty("ro.product.brand"),
-        self.GetOemProperty("ro.product.name"),
-        self.GetOemProperty("ro.product.device"),
-        self.GetBuildProp("ro.build.thumbprint"))
-
-  def WriteMountOemScript(self, script):
-    assert self.oem_props is not None
-    recovery_mount_options = self.info_dict.get("recovery_mount_options")
-    script.Mount("/oem", recovery_mount_options)
-
-  def WriteDeviceAssertions(self, script, oem_no_mount):
-    # Read the property directly if not using OEM properties.
-    if not self.oem_props:
-      script.AssertDevice(self.device)
-      return
-
-    # Otherwise assert OEM properties.
-    if not self.oem_dicts:
-      raise common.ExternalError(
-          "No OEM file provided to answer expected assertions")
-
-    for prop in self.oem_props.split():
-      values = []
-      for oem_dict in self.oem_dicts:
-        if prop in oem_dict:
-          values.append(oem_dict[prop])
-      if not values:
-        raise common.ExternalError(
-            "The OEM file is missing the property %s" % (prop,))
-      script.AssertOemProperty(prop, values, oem_no_mount)
+# Images to be excluded from secondary payload. We essentially only keep
+# 'system_other' and bootloader partitions.
+SECONDARY_PAYLOAD_SKIPPED_IMAGES = [
+    'boot', 'dtbo', 'modem', 'odm', 'product', 'radio', 'recovery',
+    'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor']
 
 
 class PayloadSigner(object):
@@ -571,6 +372,8 @@
            "--target_image", target_file]
     if source_file is not None:
       cmd.extend(["--source_image", source_file])
+      if OPTIONS.disable_fec_computation:
+        cmd.extend(["--disable_fec_computation", "true"])
     cmd.extend(additional_args)
     self._Run(cmd)
 
@@ -709,10 +512,19 @@
     script.WriteRawImage("/boot", "recovery.img")
 
 
-def HasRecoveryPatch(target_files_zip):
+def HasRecoveryPatch(target_files_zip, info_dict):
+  board_uses_vendorimage = info_dict.get("board_uses_vendorimage") == "true"
+
+  if board_uses_vendorimage:
+    target_files_dir = "VENDOR"
+  else:
+    target_files_dir = "SYSTEM/vendor"
+
+  patch = "%s/recovery-from-boot.p" % target_files_dir
+  img = "%s/etc/recovery.img" %target_files_dir
+
   namelist = [name for name in target_files_zip.namelist()]
-  return ("SYSTEM/recovery-from-boot.p" in namelist or
-          "SYSTEM/etc/recovery.img" in namelist)
+  return (patch in namelist or img in namelist)
 
 
 def HasPartition(target_files_zip, partition):
@@ -723,20 +535,15 @@
     return False
 
 
-def HasVendorPartition(target_files_zip):
-  return HasPartition(target_files_zip, "vendor")
+def HasTrebleEnabled(target_files, target_info):
+  def HasVendorPartition(target_files):
+    if os.path.isdir(target_files):
+      return os.path.isdir(os.path.join(target_files, "VENDOR"))
+    if zipfile.is_zipfile(target_files):
+      return HasPartition(zipfile.ZipFile(target_files), "vendor")
+    raise ValueError("Unknown target_files argument")
 
-
-def HasProductPartition(target_files_zip):
-  return HasPartition(target_files_zip, "product")
-
-
-def HasOdmPartition(target_files_zip):
-  return HasPartition(target_files_zip, "odm")
-
-
-def HasTrebleEnabled(target_files_zip, target_info):
-  return (HasVendorPartition(target_files_zip) and
+  return (HasVendorPartition(target_files) and
           target_info.GetBuildProp("ro.treble.enabled") == "true")
 
 
@@ -761,74 +568,23 @@
         source_info.GetBuildProp("ro.build.thumbprint"))
 
 
-def AddCompatibilityArchiveIfTrebleEnabled(target_zip, output_zip, target_info,
-                                           source_info=None):
-  """Adds compatibility info into the output zip if it's Treble-enabled target.
+def CheckVintfIfTrebleEnabled(target_files, target_info):
+  """Checks compatibility info of the input target files.
 
-  Metadata used for on-device compatibility verification is retrieved from
-  target_zip then added to compatibility.zip which is added to the output_zip
-  archive.
+  Metadata used for compatibility verification is retrieved from target_zip.
 
-  Compatibility archive should only be included for devices that have enabled
+  Compatibility should only be checked for devices that have enabled
   Treble support.
 
   Args:
-    target_zip: Zip file containing the source files to be included for OTA.
-    output_zip: Zip file that will be sent for OTA.
+    target_files: Path to zip file containing the source files to be included
+        for OTA. Can also be the path to extracted directory.
     target_info: The BuildInfo instance that holds the target build info.
-    source_info: The BuildInfo instance that holds the source build info, if
-        generating an incremental OTA; None otherwise.
   """
 
-  def AddCompatibilityArchive(framework_updated, device_updated):
-    """Adds compatibility info based on update status of both sides of Treble
-    boundary.
-
-    Args:
-      framework_updated: If True, the system / product image will be updated
-          and therefore their metadata should be included.
-      device_updated: If True, the vendor / odm image will be updated and
-          therefore their metadata should be included.
-    """
-    # Determine what metadata we need. Files are names relative to META/.
-    compatibility_files = []
-    device_metadata = ("vendor_manifest.xml", "vendor_matrix.xml")
-    framework_metadata = ("system_manifest.xml", "system_matrix.xml")
-    if device_updated:
-      compatibility_files += device_metadata
-    if framework_updated:
-      compatibility_files += framework_metadata
-
-    # Create new archive.
-    compatibility_archive = tempfile.NamedTemporaryFile()
-    compatibility_archive_zip = zipfile.ZipFile(
-        compatibility_archive, "w", compression=zipfile.ZIP_DEFLATED)
-
-    # Add metadata.
-    for file_name in compatibility_files:
-      target_file_name = "META/" + file_name
-
-      if target_file_name in target_zip.namelist():
-        data = target_zip.read(target_file_name)
-        common.ZipWriteStr(compatibility_archive_zip, file_name, data)
-
-    # Ensure files are written before we copy into output_zip.
-    compatibility_archive_zip.close()
-
-    # Only add the archive if we have any compatibility info.
-    if compatibility_archive_zip.namelist():
-      common.ZipWrite(output_zip, compatibility_archive.name,
-                      arcname="compatibility.zip",
-                      compress_type=zipfile.ZIP_STORED)
-
-  def FingerprintChanged(source_fp, target_fp):
-    if source_fp is None or target_fp is None:
-      return True
-    return source_fp != target_fp
-
   # Will only proceed if the target has enabled the Treble support (as well as
   # having a /vendor partition).
-  if not HasTrebleEnabled(target_zip, target_info):
+  if not HasTrebleEnabled(target_files, target_info):
     return
 
   # Skip adding the compatibility package as a workaround for b/114240221. The
@@ -836,28 +592,8 @@
   if OPTIONS.skip_compatibility_check:
     return
 
-  # Full OTA carries the info for system/vendor/product/odm
-  if source_info is None:
-    AddCompatibilityArchive(True, True)
-    return
-
-  source_fp = source_info.fingerprint
-  target_fp = target_info.fingerprint
-  system_updated = source_fp != target_fp
-
-  # other build fingerprints could be possibly blacklisted at build time. For
-  # such a case, we consider those images being changed.
-  vendor_updated = FingerprintChanged(source_info.vendor_fingerprint,
-                                      target_info.vendor_fingerprint)
-  product_updated = HasProductPartition(target_zip) and \
-                    FingerprintChanged(source_info.product_fingerprint,
-                                       target_info.product_fingerprint)
-  odm_updated = HasOdmPartition(target_zip) and \
-                FingerprintChanged(source_info.odm_fingerprint,
-                                   target_info.odm_fingerprint)
-
-  AddCompatibilityArchive(system_updated or product_updated,
-                          vendor_updated or odm_updated)
+  if not check_target_files_vintf.CheckVintf(target_files, target_info):
+    raise RuntimeError("VINTF compatibility check failed")
 
 
 def GetBlockDifferences(target_zip, source_zip, target_info, source_info,
@@ -949,7 +685,7 @@
 
 
 def WriteFullOTAPackage(input_zip, output_file):
-  target_info = BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
+  target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
 
   # We don't know what version it will be installed on top of. We expect the API
   # just won't change very often. Similarly for fstab, it might have changed in
@@ -979,7 +715,7 @@
       metadata=metadata,
       info_dict=OPTIONS.info_dict)
 
-  assert HasRecoveryPatch(input_zip)
+  assert HasRecoveryPatch(input_zip, info_dict=OPTIONS.info_dict)
 
   # Assertions (e.g. downgrade check, device properties check).
   ts = target_info.GetBuildProp("ro.build.date.utc")
@@ -1068,7 +804,7 @@
                              progress=progress_dict.get(block_diff.partition),
                              write_verify_script=OPTIONS.verify)
 
-  AddCompatibilityArchiveIfTrebleEnabled(input_zip, output_zip, target_info)
+  CheckVintfIfTrebleEnabled(OPTIONS.input_tmp, target_info)
 
   boot_img = common.GetBootableImage(
       "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
@@ -1175,8 +911,8 @@
   Returns:
     A dict to be written into package metadata entry.
   """
-  assert isinstance(target_info, BuildInfo)
-  assert source_info is None or isinstance(source_info, BuildInfo)
+  assert isinstance(target_info, common.BuildInfo)
+  assert source_info is None or isinstance(source_info, common.BuildInfo)
 
   metadata = {
       'post-build' : target_info.fingerprint,
@@ -1589,8 +1325,8 @@
 
 
 def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
-  target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
-  source_info = BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
+  target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
+  source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
 
   target_api_version = target_info["recovery_api_version"]
   source_api_version = source_info["recovery_api_version"]
@@ -1643,8 +1379,7 @@
                                         source_info=source_info,
                                         device_specific=device_specific)
 
-  AddCompatibilityArchiveIfTrebleEnabled(
-      target_zip, output_zip, target_info, source_info)
+  CheckVintfIfTrebleEnabled(OPTIONS.target_tmp, target_info)
 
   # Assertions (e.g. device properties check).
   target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount)
@@ -1863,6 +1598,43 @@
   Returns:
     The filename of the target-files.zip for generating secondary payload.
   """
+
+  def GetInfoForSecondaryImages(info_file):
+    """Updates info file for secondary payload generation.
+
+    Scan each line in the info file, and remove the unwanted partitions from
+    the dynamic partition list in the related properties. e.g.
+    "super_google_dynamic_partitions_partition_list=system vendor product"
+    will become "super_google_dynamic_partitions_partition_list=system".
+
+    Args:
+      info_file: The input info file. e.g. misc_info.txt.
+
+    Returns:
+      A string of the updated info content.
+    """
+
+    output_list = []
+    with open(info_file) as f:
+      lines = f.read().splitlines()
+
+    # The suffix in partition_list variables that follows the name of the
+    # partition group.
+    LIST_SUFFIX = 'partition_list'
+    for line in lines:
+      if line.startswith('#') or '=' not in line:
+        output_list.append(line)
+        continue
+      key, value = line.strip().split('=', 1)
+      if key == 'dynamic_partition_list' or key.endswith(LIST_SUFFIX):
+        partitions = value.split()
+        partitions = [partition for partition in partitions if partition
+                      not in SECONDARY_PAYLOAD_SKIPPED_IMAGES]
+        output_list.append('{}={}'.format(key, ' '.join(partitions)))
+      else:
+        output_list.append(line)
+    return '\n'.join(output_list)
+
   target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
   target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
 
@@ -1880,12 +1652,33 @@
                            'IMAGES/system.map'):
       pass
 
+    # Copy images that are not in SECONDARY_PAYLOAD_SKIPPED_IMAGES.
+    elif info.filename.startswith(('IMAGES/', 'RADIO/')):
+      image_name = os.path.basename(info.filename)
+      if image_name not in ['{}.img'.format(partition) for partition in
+                            SECONDARY_PAYLOAD_SKIPPED_IMAGES]:
+        common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+
     # Skip copying the postinstall config if requested.
     elif skip_postinstall and info.filename == POSTINSTALL_CONFIG:
       pass
 
-    elif info.filename.startswith(('META/', 'IMAGES/', 'RADIO/')):
-      common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+    elif info.filename.startswith('META/'):
+      # Remove the unnecessary partitions for secondary images from the
+      # ab_partitions file.
+      if info.filename == AB_PARTITIONS:
+        with open(unzipped_file) as f:
+          partition_list = f.read().splitlines()
+        partition_list = [partition for partition in partition_list if partition
+                          and partition not in SECONDARY_PAYLOAD_SKIPPED_IMAGES]
+        common.ZipWriteStr(target_zip, info.filename, '\n'.join(partition_list))
+      # Remove the unnecessary partitions from the dynamic partitions list.
+      elif (info.filename == 'META/misc_info.txt' or
+            info.filename == DYNAMIC_PARTITION_INFO):
+        modified_info = GetInfoForSecondaryImages(unzipped_file)
+        common.ZipWriteStr(target_zip, info.filename, modified_info)
+      else:
+        common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
 
   common.ZipClose(target_zip)
 
@@ -2012,10 +1805,10 @@
                                compression=zipfile.ZIP_DEFLATED)
 
   if source_file is not None:
-    target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
-    source_info = BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
+    target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
+    source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
   else:
-    target_info = BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
+    target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
     source_info = None
 
   # Metadata to comply with Android OTA package format.
@@ -2079,11 +1872,10 @@
     else:
       logger.warning("Cannot find care map file in target_file package")
 
-  AddCompatibilityArchiveIfTrebleEnabled(
-      target_zip, output_zip, target_info, source_info)
-
   common.ZipClose(target_zip)
 
+  CheckVintfIfTrebleEnabled(target_file, target_info)
+
   # We haven't written the metadata entry yet, which will be handled in
   # FinalizeMetadata().
   common.ZipClose(output_zip)
@@ -2225,6 +2017,8 @@
       OPTIONS.skip_compatibility_check = True
     elif o == "--output_metadata_path":
       OPTIONS.output_metadata_path = a
+    elif o == "--disable_fec_computation":
+      OPTIONS.disable_fec_computation = True
     else:
       return False
     return True
@@ -2259,6 +2053,7 @@
                                  "retrofit_dynamic_partitions",
                                  "skip_compatibility_check",
                                  "output_metadata_path=",
+                                 "disable_fec_computation",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
diff --git a/tools/releasetools/sign_apex.py b/tools/releasetools/sign_apex.py
index 2516e15..f2daa46 100755
--- a/tools/releasetools/sign_apex.py
+++ b/tools/releasetools/sign_apex.py
@@ -56,6 +56,7 @@
       container_key=container_key,
       container_pw=None,
       codename_to_api_level_map=None,
+      no_hashtree=False,
       signing_args=signing_args)
 
 
@@ -103,7 +104,8 @@
       args[0],
       options['payload_key'],
       options['container_key'],
-      options.get('payload_extra_args'))
+      no_hashtree=False,
+      signing_args=options.get('payload_extra_args'))
   shutil.copyfile(signed_apex, args[1])
   logger.info("done.")
 
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 3119afa..710147b 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -479,7 +479,8 @@
             container_key,
             key_passwords[container_key],
             codename_to_api_level_map,
-            OPTIONS.avb_extra_args.get('apex'))
+            no_hashtree=True,
+            signing_args=OPTIONS.avb_extra_args.get('apex'))
         common.ZipWrite(output_tf_zip, signed_apex, filename)
 
       else:
@@ -602,11 +603,16 @@
     ReplaceVerityPrivateKey(misc_info, OPTIONS.replace_verity_private_key[1])
 
   if OPTIONS.replace_verity_public_key:
-    dest = "ROOT/verity_key" if system_root_image else "BOOT/RAMDISK/verity_key"
-    # We are replacing the one in boot image only, since the one under
-    # recovery won't ever be needed.
+    # Replace the one in root dir in system.img.
     ReplaceVerityPublicKey(
-        output_tf_zip, dest, OPTIONS.replace_verity_public_key[1])
+        output_tf_zip, 'ROOT/verity_key', OPTIONS.replace_verity_public_key[1])
+
+    if not system_root_image:
+      # Additionally replace the copy in ramdisk if not using system-as-root.
+      ReplaceVerityPublicKey(
+          output_tf_zip,
+          'BOOT/RAMDISK/verity_key',
+          OPTIONS.replace_verity_public_key[1])
 
   # Replace the keyid string in BOOT/cmdline.
   if OPTIONS.replace_verity_keyid:
diff --git a/tools/releasetools/sparse_img.py b/tools/releasetools/sparse_img.py
index 3367896..a249081 100644
--- a/tools/releasetools/sparse_img.py
+++ b/tools/releasetools/sparse_img.py
@@ -249,8 +249,9 @@
 
     with open(fn) as f:
       for line in f:
-        fn, ranges = line.split(None, 1)
-        ranges = rangelib.RangeSet.parse(ranges)
+        fn, ranges_text = line.rstrip().split(None, 1)
+        ranges = rangelib.RangeSet.parse(ranges_text)
+        ranges.extra['text_str'] = ranges_text
 
         if allow_shared_blocks:
           # Find the shared blocks that have been claimed by others. If so, tag
@@ -261,9 +262,6 @@
             if not non_shared:
               continue
 
-            # There shouldn't anything in the extra dict yet.
-            assert not ranges.extra, "Non-empty RangeSet.extra"
-
             # Put the non-shared RangeSet as the value in the block map, which
             # has a copy of the original RangeSet.
             non_shared.extra['uses_shared_blocks'] = ranges
diff --git a/tools/releasetools/test_apex_utils.py b/tools/releasetools/test_apex_utils.py
index e9c26f0..5d4cc77 100644
--- a/tools/releasetools/test_apex_utils.py
+++ b/tools/releasetools/test_apex_utils.py
@@ -44,19 +44,42 @@
     payload_file = self._GetTestPayload()
     apex_utils.SignApexPayload(
         'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
-        self.SALT)
+        self.SALT, no_hashtree=True)
     payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
     self.assertEqual('SHA256_RSA2048', payload_info['Algorithm'])
     self.assertEqual(self.SALT, payload_info['Salt'])
     self.assertEqual('testkey', payload_info['apex.key'])
+    self.assertEqual('0 bytes', payload_info['Tree Size'])
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_SignApexPayload(self):
     payload_file = self._GetTestPayload()
     apex_utils.SignApexPayload(
         'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
-        self.SALT)
+        self.SALT, no_hashtree=True)
+    apex_utils.VerifyApexPayload(
+        'avbtool', payload_file, self.payload_key, True)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_SignApexPayload_withHashtree(self):
+    payload_file = self._GetTestPayload()
+    apex_utils.SignApexPayload(
+        'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
+        self.SALT, no_hashtree=False)
     apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
+    payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
+    self.assertEqual('4096 bytes', payload_info['Tree Size'])
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_SignApexPayload_noHashtree(self):
+    payload_file = self._GetTestPayload()
+    apex_utils.SignApexPayload(
+        'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
+        self.SALT, no_hashtree=True)
+    apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key,
+                                 no_hashtree=True)
+    payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
+    self.assertEqual('0 bytes', payload_info['Tree Size'])
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_SignApexPayload_withSignerHelper(self):
@@ -70,8 +93,10 @@
         payload_file,
         self.payload_key,
         'testkey', 'SHA256_RSA2048', self.SALT,
+        True,
         payload_signer_args)
-    apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
+    apex_utils.VerifyApexPayload(
+        'avbtool', payload_file, self.payload_key, True)
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_SignApexPayload_invalidKey(self):
@@ -83,18 +108,21 @@
         os.path.join(self.testdata_dir, 'testkey.x509.pem'),
         'testkey',
         'SHA256_RSA2048',
-        self.SALT)
+        self.SALT,
+        no_hashtree=True)
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_VerifyApexPayload_wrongKey(self):
     payload_file = self._GetTestPayload()
     apex_utils.SignApexPayload(
         'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
-        self.SALT)
-    apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
+        self.SALT, True)
+    apex_utils.VerifyApexPayload(
+        'avbtool', payload_file, self.payload_key, True)
     self.assertRaises(
         apex_utils.ApexSigningError,
         apex_utils.VerifyApexPayload,
         'avbtool',
         payload_file,
-        os.path.join(self.testdata_dir, 'testkey_with_passwd.key'))
+        os.path.join(self.testdata_dir, 'testkey_with_passwd.key'),
+        no_hashtree=True)
diff --git a/tools/releasetools/test_check_target_files_vintf.py b/tools/releasetools/test_check_target_files_vintf.py
new file mode 100644
index 0000000..79f9018
--- /dev/null
+++ b/tools/releasetools/test_check_target_files_vintf.py
@@ -0,0 +1,145 @@
+#
+# 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.
+#
+
+import os.path
+
+import common
+import test_utils
+from check_target_files_vintf import CheckVintf
+
+# A skeleton target files directory structure. This is VINTF compatible.
+SKELETON_TARGET_FILE_STRUCTURE = {
+    # Empty files
+    'PRODUCT/build.prop': '',
+    'PRODUCT/etc/build.prop': '',
+    'VENDOR/etc/build.prop': '',
+    'ODM/build.prop': '',
+    'ODM/etc/build.prop': '',
+    'RECOVERY/RAMDISK/etc/recovery.fstab': '',
+    'SYSTEM/build.prop': '',
+    'SYSTEM/etc/build.prop': '',
+    'SYSTEM_EXT/build.prop': '',
+    'SYSTEM_EXT/etc/build.prop': '',
+
+    # Non-empty files
+    'SYSTEM/compatibility_matrix.xml':"""
+        <compatibility-matrix version="1.0" type="framework">
+            <sepolicy>
+                <sepolicy-version>0.0</sepolicy-version>
+                <kernel-sepolicy-version>0</kernel-sepolicy-version>
+            </sepolicy>
+        </compatibility-matrix>""",
+    'SYSTEM/manifest.xml':
+        '<manifest version="1.0" type="framework" />',
+    'VENDOR/build.prop': 'ro.product.first_api_level=29\n',
+    'VENDOR/compatibility_matrix.xml':
+        '<compatibility-matrix version="1.0" type="device" />',
+    'VENDOR/manifest.xml':
+        '<manifest version="1.0" type="device"/>',
+    'META/misc_info.txt':
+        'recovery_api_version=3\nfstab_version=2\nvintf_enforce=true\n',
+}
+
+
+def write_string_to_file(content, path, mode='w'):
+  if not os.path.isdir(os.path.dirname(path)):
+    os.makedirs(os.path.dirname(path))
+  with open(path, mode=mode) as f:
+    f.write(content)
+
+
+class CheckTargetFilesVintfTest(test_utils.ReleaseToolsTestCase):
+
+  def setUp(self):
+    self.testdata_dir = test_utils.get_testdata_dir()
+
+  def prepare_test_dir(self, test_delta_rel_path):
+    test_delta_dir = os.path.join(self.testdata_dir, test_delta_rel_path)
+    test_dir = common.MakeTempDir(prefix='check_target_files_vintf')
+
+    # Create a skeleton directory structure of target files
+    for rel_path, content in SKELETON_TARGET_FILE_STRUCTURE.items():
+      write_string_to_file(content, os.path.join(test_dir, rel_path))
+
+    # Overwrite with files from test_delta_rel_path
+    for root, _, files in os.walk(test_delta_dir):
+      rel_root = os.path.relpath(root, test_delta_dir)
+      for f in files:
+        if not f.endswith('.xml'):
+          continue
+        output_file = os.path.join(test_dir, rel_root, f)
+        with open(os.path.join(root, f)) as inp:
+          write_string_to_file(inp.read(), output_file)
+
+    return test_dir
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_CheckVintf_sanity(self):
+    msg = 'Sanity check with skeleton target files failed.'
+    test_dir = self.prepare_test_dir('does-not-exist')
+    self.assertTrue(CheckVintf(test_dir), msg=msg)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_CheckVintf_matrix_incompat(self):
+    msg = 'vintf/matrix_incompat should be incompatible because sepolicy ' \
+          'version fails to match'
+    test_dir = self.prepare_test_dir('vintf/matrix_incompat')
+    self.assertFalse(CheckVintf(test_dir), msg=msg)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_CheckVintf_kernel_compat(self):
+    msg = 'vintf/kernel with 4.14.1 kernel version should be compatible'
+    test_dir = self.prepare_test_dir('vintf/kernel')
+    write_string_to_file('', os.path.join(test_dir, 'META/kernel_configs.txt'))
+    write_string_to_file('4.14.1',
+                         os.path.join(test_dir, 'META/kernel_version.txt'))
+    self.assertTrue(CheckVintf(test_dir), msg=msg)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_CheckVintf_kernel_incompat(self):
+    msg = 'vintf/kernel with 4.14.0 kernel version should be incompatible ' \
+          'because 4.14.1 kernel version is required'
+    test_dir = self.prepare_test_dir('vintf/kernel')
+    write_string_to_file('', os.path.join(test_dir, 'META/kernel_configs.txt'))
+    write_string_to_file('4.14.0',
+                         os.path.join(test_dir, 'META/kernel_version.txt'))
+    self.assertFalse(CheckVintf(test_dir), msg=msg)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_CheckVintf_sku_compat(self):
+    msg = 'vintf/sku_compat should be compatible because ' \
+          'ODM/etc/vintf/manifest_sku.xml has the required HALs'
+    test_dir = self.prepare_test_dir('vintf/sku_compat')
+    write_string_to_file('vintf_odm_manifest_skus=sku',
+                         os.path.join(test_dir, 'META/misc_info.txt'), mode='a')
+    self.assertTrue(CheckVintf(test_dir), msg=msg)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_CheckVintf_sku_incompat(self):
+    msg = 'vintf/sku_compat should be compatible because ' \
+          'ODM/etc/vintf/manifest_sku.xml does not have the required HALs'
+    test_dir = self.prepare_test_dir('vintf/sku_incompat')
+    write_string_to_file('vintf_odm_manifest_skus=sku',
+                         os.path.join(test_dir, 'META/misc_info.txt'), mode='a')
+    self.assertFalse(CheckVintf(test_dir), msg=msg)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_CheckVintf_bad_xml(self):
+    test_dir = self.prepare_test_dir('does-not-exist')
+    write_string_to_file('not an XML',
+                         os.path.join(test_dir, 'VENDOR/manifest.xml'))
+    # Should raise an error because a file has invalid format.
+    self.assertRaises(common.ExternalError, CheckVintf, test_dir)
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index ceb023f..59b05e9 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -44,6 +44,210 @@
     yield b'\0' * (step_size - block_size)
 
 
+class BuildInfoTest(test_utils.ReleaseToolsTestCase):
+
+  TEST_INFO_DICT = {
+      'build.prop' : {
+          'ro.product.device' : 'product-device',
+          'ro.product.name' : 'product-name',
+          'ro.build.fingerprint' : 'build-fingerprint',
+          'ro.build.foo' : 'build-foo',
+      },
+      'vendor.build.prop' : {
+          'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
+      },
+      'property1' : 'value1',
+      'property2' : 4096,
+  }
+
+  TEST_INFO_DICT_USES_OEM_PROPS = {
+      'build.prop' : {
+          'ro.product.name' : 'product-name',
+          'ro.build.thumbprint' : 'build-thumbprint',
+          'ro.build.bar' : 'build-bar',
+      },
+      'vendor.build.prop' : {
+          'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
+      },
+      'property1' : 'value1',
+      'property2' : 4096,
+      'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
+  }
+
+  TEST_OEM_DICTS = [
+      {
+          'ro.product.brand' : 'brand1',
+          'ro.product.device' : 'device1',
+      },
+      {
+          'ro.product.brand' : 'brand2',
+          'ro.product.device' : 'device2',
+      },
+      {
+          'ro.product.brand' : 'brand3',
+          'ro.product.device' : 'device3',
+      },
+  ]
+
+  def test_init(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    self.assertEqual('product-device', target_info.device)
+    self.assertEqual('build-fingerprint', target_info.fingerprint)
+    self.assertFalse(target_info.is_ab)
+    self.assertIsNone(target_info.oem_props)
+
+  def test_init_with_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    self.assertEqual('device1', target_info.device)
+    self.assertEqual('brand1/product-name/device1:build-thumbprint',
+                     target_info.fingerprint)
+
+    # Swap the order in oem_dicts, which would lead to different BuildInfo.
+    oem_dicts = copy.copy(self.TEST_OEM_DICTS)
+    oem_dicts[0], oem_dicts[2] = oem_dicts[2], oem_dicts[0]
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   oem_dicts)
+    self.assertEqual('device3', target_info.device)
+    self.assertEqual('brand3/product-name/device3:build-thumbprint',
+                     target_info.fingerprint)
+
+    # Missing oem_dict should be rejected.
+    self.assertRaises(AssertionError, common.BuildInfo,
+                      self.TEST_INFO_DICT_USES_OEM_PROPS, None)
+
+  def test_init_badFingerprint(self):
+    info_dict = copy.deepcopy(self.TEST_INFO_DICT)
+    info_dict['build.prop']['ro.build.fingerprint'] = 'bad fingerprint'
+    self.assertRaises(ValueError, common.BuildInfo, info_dict, None)
+
+    info_dict['build.prop']['ro.build.fingerprint'] = 'bad\x80fingerprint'
+    self.assertRaises(ValueError, common.BuildInfo, info_dict, None)
+
+  def test___getitem__(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    self.assertEqual('value1', target_info['property1'])
+    self.assertEqual(4096, target_info['property2'])
+    self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
+
+  def test___getitem__with_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    self.assertEqual('value1', target_info['property1'])
+    self.assertEqual(4096, target_info['property2'])
+    self.assertRaises(KeyError,
+                      lambda: target_info['build.prop']['ro.build.foo'])
+
+  def test___setitem__(self):
+    target_info = common.BuildInfo(copy.deepcopy(self.TEST_INFO_DICT), None)
+    self.assertEqual('value1', target_info['property1'])
+    target_info['property1'] = 'value2'
+    self.assertEqual('value2', target_info['property1'])
+
+    self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
+    target_info['build.prop']['ro.build.foo'] = 'build-bar'
+    self.assertEqual('build-bar', target_info['build.prop']['ro.build.foo'])
+
+  def test_get(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    self.assertEqual('value1', target_info.get('property1'))
+    self.assertEqual(4096, target_info.get('property2'))
+    self.assertEqual(4096, target_info.get('property2', 1024))
+    self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
+    self.assertEqual('build-foo', target_info.get('build.prop')['ro.build.foo'])
+
+  def test_get_with_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    self.assertEqual('value1', target_info.get('property1'))
+    self.assertEqual(4096, target_info.get('property2'))
+    self.assertEqual(4096, target_info.get('property2', 1024))
+    self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
+    self.assertIsNone(target_info.get('build.prop').get('ro.build.foo'))
+    self.assertRaises(KeyError,
+                      lambda: target_info.get('build.prop')['ro.build.foo'])
+
+  def test_items(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    items = target_info.items()
+    self.assertIn(('property1', 'value1'), items)
+    self.assertIn(('property2', 4096), items)
+
+  def test_GetBuildProp(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    self.assertEqual('build-foo', target_info.GetBuildProp('ro.build.foo'))
+    self.assertRaises(common.ExternalError, target_info.GetBuildProp,
+                      'ro.build.nonexistent')
+
+  def test_GetBuildProp_with_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    self.assertEqual('build-bar', target_info.GetBuildProp('ro.build.bar'))
+    self.assertRaises(common.ExternalError, target_info.GetBuildProp,
+                      'ro.build.nonexistent')
+
+  def test_GetVendorBuildProp(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    self.assertEqual('vendor-build-fingerprint',
+                     target_info.GetVendorBuildProp(
+                         'ro.vendor.build.fingerprint'))
+    self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
+                      'ro.build.nonexistent')
+
+  def test_GetVendorBuildProp_with_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    self.assertEqual('vendor-build-fingerprint',
+                     target_info.GetVendorBuildProp(
+                         'ro.vendor.build.fingerprint'))
+    self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
+                      'ro.build.nonexistent')
+
+  def test_vendor_fingerprint(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    self.assertEqual('vendor-build-fingerprint',
+                     target_info.vendor_fingerprint)
+
+  def test_vendor_fingerprint_blacklisted(self):
+    target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
+    del target_info_dict['vendor.build.prop']['ro.vendor.build.fingerprint']
+    target_info = common.BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
+    self.assertIsNone(target_info.vendor_fingerprint)
+
+  def test_vendor_fingerprint_without_vendor_build_prop(self):
+    target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
+    del target_info_dict['vendor.build.prop']
+    target_info = common.BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
+    self.assertIsNone(target_info.vendor_fingerprint)
+
+  def test_WriteMountOemScript(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    script_writer = test_utils.MockScriptWriter()
+    target_info.WriteMountOemScript(script_writer)
+    self.assertEqual([('Mount', '/oem', None)], script_writer.lines)
+
+  def test_WriteDeviceAssertions(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
+    script_writer = test_utils.MockScriptWriter()
+    target_info.WriteDeviceAssertions(script_writer, False)
+    self.assertEqual([('AssertDevice', 'product-device')], script_writer.lines)
+
+  def test_WriteDeviceAssertions_with_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    script_writer = test_utils.MockScriptWriter()
+    target_info.WriteDeviceAssertions(script_writer, False)
+    self.assertEqual(
+        [
+            ('AssertOemProperty', 'ro.product.device',
+             ['device1', 'device2', 'device3'], False),
+            ('AssertOemProperty', 'ro.product.brand',
+             ['brand1', 'brand2', 'brand3'], False),
+        ],
+        script_writer.lines)
+
+
 class CommonZipTest(test_utils.ReleaseToolsTestCase):
 
   def _verify(self, zip_file, zip_file_name, arcname, expected_hash,
@@ -749,10 +953,12 @@
     self.assertNotIn(
         'incomplete', sparse_image.file_map['/system/file2'].extra)
 
-    # All other entries should look normal without any tags.
+    # '/system/file1' will only contain one field -- a copy of the input text.
+    self.assertEqual(1, len(sparse_image.file_map['/system/file1'].extra))
+
+    # Meta entries should not have any extra tag.
     self.assertFalse(sparse_image.file_map['__COPY'].extra)
     self.assertFalse(sparse_image.file_map['__NONZERO-0'].extra)
-    self.assertFalse(sparse_image.file_map['/system/file1'].extra)
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_GetSparseImage_incompleteRanges(self):
@@ -775,7 +981,9 @@
     with zipfile.ZipFile(target_files, 'r') as input_zip:
       sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
 
-    self.assertFalse(sparse_image.file_map['/system/file1'].extra)
+    self.assertEqual(
+        '1-5 9-10',
+        sparse_image.file_map['/system/file1'].extra['text_str'])
     self.assertTrue(sparse_image.file_map['/system/file2'].extra['incomplete'])
 
   @test_utils.SkipIfExternalToolsUnavailable()
@@ -801,7 +1009,9 @@
     with zipfile.ZipFile(target_files, 'r') as input_zip:
       sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
 
-    self.assertFalse(sparse_image.file_map['//system/file1'].extra)
+    self.assertEqual(
+        '1-5 9-10',
+        sparse_image.file_map['//system/file1'].extra['text_str'])
     self.assertTrue(sparse_image.file_map['//system/file2'].extra['incomplete'])
     self.assertTrue(
         sparse_image.file_map['/system/app/file3'].extra['incomplete'])
@@ -826,7 +1036,9 @@
     with zipfile.ZipFile(target_files, 'r') as input_zip:
       sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
 
-    self.assertFalse(sparse_image.file_map['//system/file1'].extra)
+    self.assertEqual(
+        '1-5 9-10',
+        sparse_image.file_map['//system/file1'].extra['text_str'])
     self.assertTrue(sparse_image.file_map['//init.rc'].extra['incomplete'])
 
   @test_utils.SkipIfExternalToolsUnavailable()
@@ -1224,24 +1436,6 @@
                                                         self._info)
 
 
-class MockScriptWriter(object):
-  """A class that mocks edify_generator.EdifyGenerator."""
-
-  def __init__(self, enable_comments=False):
-    self.lines = []
-    self.enable_comments = enable_comments
-
-  def Comment(self, comment):
-    if self.enable_comments:
-      self.lines.append('# {}'.format(comment))
-
-  def AppendExtra(self, extra):
-    self.lines.append(extra)
-
-  def __str__(self):
-    return '\n'.join(self.lines)
-
-
 class MockBlockDifference(object):
 
   def __init__(self, partition, tgt, src=None):
@@ -1279,7 +1473,7 @@
                 if not line.startswith(b'#')]
 
   def setUp(self):
-    self.script = MockScriptWriter()
+    self.script = test_utils.MockScriptWriter()
     self.output_path = common.MakeTempFile(suffix='.zip')
 
   def test_full(self):
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index ee831e3..c3021a1 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -22,7 +22,7 @@
 import common
 import test_utils
 from ota_from_target_files import (
-    _LoadOemDicts, AbOtaPropertyFiles, BuildInfo, FinalizeMetadata,
+    _LoadOemDicts, AbOtaPropertyFiles, FinalizeMetadata,
     GetPackageMetadata, GetTargetFilesZipForSecondaryImages,
     GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
     Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
@@ -74,283 +74,6 @@
   return target_files
 
 
-class MockScriptWriter(object):
-  """A class that mocks edify_generator.EdifyGenerator.
-
-  It simply pushes the incoming arguments onto script stack, which is to assert
-  the calls to EdifyGenerator functions.
-  """
-
-  def __init__(self):
-    self.script = []
-
-  def Mount(self, *args):
-    self.script.append(('Mount',) + args)
-
-  def AssertDevice(self, *args):
-    self.script.append(('AssertDevice',) + args)
-
-  def AssertOemProperty(self, *args):
-    self.script.append(('AssertOemProperty',) + args)
-
-  def AssertFingerprintOrThumbprint(self, *args):
-    self.script.append(('AssertFingerprintOrThumbprint',) + args)
-
-  def AssertSomeFingerprint(self, *args):
-    self.script.append(('AssertSomeFingerprint',) + args)
-
-  def AssertSomeThumbprint(self, *args):
-    self.script.append(('AssertSomeThumbprint',) + args)
-
-
-class BuildInfoTest(test_utils.ReleaseToolsTestCase):
-
-  TEST_INFO_DICT = {
-      'build.prop' : {
-          'ro.product.device' : 'product-device',
-          'ro.product.name' : 'product-name',
-          'ro.build.fingerprint' : 'build-fingerprint',
-          'ro.build.foo' : 'build-foo',
-      },
-      'vendor.build.prop' : {
-          'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
-      },
-      'property1' : 'value1',
-      'property2' : 4096,
-  }
-
-  TEST_INFO_DICT_USES_OEM_PROPS = {
-      'build.prop' : {
-          'ro.product.name' : 'product-name',
-          'ro.build.thumbprint' : 'build-thumbprint',
-          'ro.build.bar' : 'build-bar',
-      },
-      'vendor.build.prop' : {
-          'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
-      },
-      'property1' : 'value1',
-      'property2' : 4096,
-      'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
-  }
-
-  TEST_OEM_DICTS = [
-      {
-          'ro.product.brand' : 'brand1',
-          'ro.product.device' : 'device1',
-      },
-      {
-          'ro.product.brand' : 'brand2',
-          'ro.product.device' : 'device2',
-      },
-      {
-          'ro.product.brand' : 'brand3',
-          'ro.product.device' : 'device3',
-      },
-  ]
-
-  def test_init(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    self.assertEqual('product-device', target_info.device)
-    self.assertEqual('build-fingerprint', target_info.fingerprint)
-    self.assertFalse(target_info.is_ab)
-    self.assertIsNone(target_info.oem_props)
-
-  def test_init_with_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    self.assertEqual('device1', target_info.device)
-    self.assertEqual('brand1/product-name/device1:build-thumbprint',
-                     target_info.fingerprint)
-
-    # Swap the order in oem_dicts, which would lead to different BuildInfo.
-    oem_dicts = copy.copy(self.TEST_OEM_DICTS)
-    oem_dicts[0], oem_dicts[2] = oem_dicts[2], oem_dicts[0]
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, oem_dicts)
-    self.assertEqual('device3', target_info.device)
-    self.assertEqual('brand3/product-name/device3:build-thumbprint',
-                     target_info.fingerprint)
-
-    # Missing oem_dict should be rejected.
-    self.assertRaises(AssertionError, BuildInfo,
-                      self.TEST_INFO_DICT_USES_OEM_PROPS, None)
-
-  def test___getitem__(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    self.assertEqual('value1', target_info['property1'])
-    self.assertEqual(4096, target_info['property2'])
-    self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
-
-  def test___getitem__with_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    self.assertEqual('value1', target_info['property1'])
-    self.assertEqual(4096, target_info['property2'])
-    self.assertRaises(KeyError,
-                      lambda: target_info['build.prop']['ro.build.foo'])
-
-  def test___setitem__(self):
-    target_info = BuildInfo(copy.deepcopy(self.TEST_INFO_DICT), None)
-    self.assertEqual('value1', target_info['property1'])
-    target_info['property1'] = 'value2'
-    self.assertEqual('value2', target_info['property1'])
-
-    self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
-    target_info['build.prop']['ro.build.foo'] = 'build-bar'
-    self.assertEqual('build-bar', target_info['build.prop']['ro.build.foo'])
-
-  def test_get(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    self.assertEqual('value1', target_info.get('property1'))
-    self.assertEqual(4096, target_info.get('property2'))
-    self.assertEqual(4096, target_info.get('property2', 1024))
-    self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
-    self.assertEqual('build-foo', target_info.get('build.prop')['ro.build.foo'])
-
-  def test_get_with_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    self.assertEqual('value1', target_info.get('property1'))
-    self.assertEqual(4096, target_info.get('property2'))
-    self.assertEqual(4096, target_info.get('property2', 1024))
-    self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
-    self.assertIsNone(target_info.get('build.prop').get('ro.build.foo'))
-    self.assertRaises(KeyError,
-                      lambda: target_info.get('build.prop')['ro.build.foo'])
-
-  def test_items(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    items = target_info.items()
-    self.assertIn(('property1', 'value1'), items)
-    self.assertIn(('property2', 4096), items)
-
-  def test_GetBuildProp(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    self.assertEqual('build-foo', target_info.GetBuildProp('ro.build.foo'))
-    self.assertRaises(common.ExternalError, target_info.GetBuildProp,
-                      'ro.build.nonexistent')
-
-  def test_GetBuildProp_with_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    self.assertEqual('build-bar', target_info.GetBuildProp('ro.build.bar'))
-    self.assertRaises(common.ExternalError, target_info.GetBuildProp,
-                      'ro.build.nonexistent')
-
-  def test_GetVendorBuildProp(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    self.assertEqual('vendor-build-fingerprint',
-                     target_info.GetVendorBuildProp(
-                         'ro.vendor.build.fingerprint'))
-    self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
-                      'ro.build.nonexistent')
-
-  def test_GetVendorBuildProp_with_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    self.assertEqual('vendor-build-fingerprint',
-                     target_info.GetVendorBuildProp(
-                         'ro.vendor.build.fingerprint'))
-    self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
-                      'ro.build.nonexistent')
-
-  def test_vendor_fingerprint(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    self.assertEqual('vendor-build-fingerprint',
-                     target_info.vendor_fingerprint)
-
-  def test_vendor_fingerprint_blacklisted(self):
-    target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
-    del target_info_dict['vendor.build.prop']['ro.vendor.build.fingerprint']
-    target_info = BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
-    self.assertIsNone(target_info.vendor_fingerprint)
-
-  def test_vendor_fingerprint_without_vendor_build_prop(self):
-    target_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
-    del target_info_dict['vendor.build.prop']
-    target_info = BuildInfo(target_info_dict, self.TEST_OEM_DICTS)
-    self.assertIsNone(target_info.vendor_fingerprint)
-
-  def test_WriteMountOemScript(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    script_writer = MockScriptWriter()
-    target_info.WriteMountOemScript(script_writer)
-    self.assertEqual([('Mount', '/oem', None)], script_writer.script)
-
-  def test_WriteDeviceAssertions(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    script_writer = MockScriptWriter()
-    target_info.WriteDeviceAssertions(script_writer, False)
-    self.assertEqual([('AssertDevice', 'product-device')], script_writer.script)
-
-  def test_WriteDeviceAssertions_with_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    script_writer = MockScriptWriter()
-    target_info.WriteDeviceAssertions(script_writer, False)
-    self.assertEqual(
-        [
-            ('AssertOemProperty', 'ro.product.device',
-             ['device1', 'device2', 'device3'], False),
-            ('AssertOemProperty', 'ro.product.brand',
-             ['brand1', 'brand2', 'brand3'], False),
-        ],
-        script_writer.script)
-
-  def test_WriteFingerprintAssertion_without_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    source_info_dict = copy.deepcopy(self.TEST_INFO_DICT)
-    source_info_dict['build.prop']['ro.build.fingerprint'] = (
-        'source-build-fingerprint')
-    source_info = BuildInfo(source_info_dict, None)
-
-    script_writer = MockScriptWriter()
-    WriteFingerprintAssertion(script_writer, target_info, source_info)
-    self.assertEqual(
-        [('AssertSomeFingerprint', 'source-build-fingerprint',
-          'build-fingerprint')],
-        script_writer.script)
-
-  def test_WriteFingerprintAssertion_with_source_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT, None)
-    source_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-
-    script_writer = MockScriptWriter()
-    WriteFingerprintAssertion(script_writer, target_info, source_info)
-    self.assertEqual(
-        [('AssertFingerprintOrThumbprint', 'build-fingerprint',
-          'build-thumbprint')],
-        script_writer.script)
-
-  def test_WriteFingerprintAssertion_with_target_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    source_info = BuildInfo(self.TEST_INFO_DICT, None)
-
-    script_writer = MockScriptWriter()
-    WriteFingerprintAssertion(script_writer, target_info, source_info)
-    self.assertEqual(
-        [('AssertFingerprintOrThumbprint', 'build-fingerprint',
-          'build-thumbprint')],
-        script_writer.script)
-
-  def test_WriteFingerprintAssertion_with_both_oem_props(self):
-    target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
-                            self.TEST_OEM_DICTS)
-    source_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
-    source_info_dict['build.prop']['ro.build.thumbprint'] = (
-        'source-build-thumbprint')
-    source_info = BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
-
-    script_writer = MockScriptWriter()
-    WriteFingerprintAssertion(script_writer, target_info, source_info)
-    self.assertEqual(
-        [('AssertSomeThumbprint', 'build-thumbprint',
-          'source-build-thumbprint')],
-        script_writer.script)
-
-
 class LoadOemDictsTest(test_utils.ReleaseToolsTestCase):
 
   def test_NoneDict(self):
@@ -408,6 +131,35 @@
       },
   }
 
+  TEST_INFO_DICT_USES_OEM_PROPS = {
+      'build.prop' : {
+          'ro.product.name' : 'product-name',
+          'ro.build.thumbprint' : 'build-thumbprint',
+          'ro.build.bar' : 'build-bar',
+      },
+      'vendor.build.prop' : {
+          'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
+      },
+      'property1' : 'value1',
+      'property2' : 4096,
+      'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
+  }
+
+  TEST_OEM_DICTS = [
+      {
+          'ro.product.brand' : 'brand1',
+          'ro.product.device' : 'device1',
+      },
+      {
+          'ro.product.brand' : 'brand2',
+          'ro.product.device' : 'device2',
+      },
+      {
+          'ro.product.brand' : 'brand3',
+          'ro.product.device' : 'device3',
+      },
+  ]
+
   def setUp(self):
     self.testdata_dir = test_utils.get_testdata_dir()
     self.assertTrue(os.path.exists(self.testdata_dir))
@@ -429,7 +181,7 @@
   def test_GetPackageMetadata_abOta_full(self):
     target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
     target_info_dict['ab_update'] = 'true'
-    target_info = BuildInfo(target_info_dict, None)
+    target_info = common.BuildInfo(target_info_dict, None)
     metadata = GetPackageMetadata(target_info)
     self.assertDictEqual(
         {
@@ -447,8 +199,8 @@
   def test_GetPackageMetadata_abOta_incremental(self):
     target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
     target_info_dict['ab_update'] = 'true'
-    target_info = BuildInfo(target_info_dict, None)
-    source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
+    target_info = common.BuildInfo(target_info_dict, None)
+    source_info = common.BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
     common.OPTIONS.incremental_source = ''
     metadata = GetPackageMetadata(target_info, source_info)
     self.assertDictEqual(
@@ -467,7 +219,7 @@
         metadata)
 
   def test_GetPackageMetadata_nonAbOta_full(self):
-    target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+    target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
     metadata = GetPackageMetadata(target_info)
     self.assertDictEqual(
         {
@@ -482,8 +234,8 @@
         metadata)
 
   def test_GetPackageMetadata_nonAbOta_incremental(self):
-    target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
-    source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
+    target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+    source_info = common.BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
     common.OPTIONS.incremental_source = ''
     metadata = GetPackageMetadata(target_info, source_info)
     self.assertDictEqual(
@@ -501,7 +253,7 @@
         metadata)
 
   def test_GetPackageMetadata_wipe(self):
-    target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+    target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
     common.OPTIONS.wipe_user_data = True
     metadata = GetPackageMetadata(target_info)
     self.assertDictEqual(
@@ -518,7 +270,7 @@
         metadata)
 
   def test_GetPackageMetadata_retrofitDynamicPartitions(self):
-    target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+    target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
     common.OPTIONS.retrofit_dynamic_partitions = True
     metadata = GetPackageMetadata(target_info)
     self.assertDictEqual(
@@ -547,8 +299,8 @@
     self._test_GetPackageMetadata_swapBuildTimestamps(
         target_info_dict, source_info_dict)
 
-    target_info = BuildInfo(target_info_dict, None)
-    source_info = BuildInfo(source_info_dict, None)
+    target_info = common.BuildInfo(target_info_dict, None)
+    source_info = common.BuildInfo(source_info_dict, None)
     common.OPTIONS.incremental_source = ''
     self.assertRaises(RuntimeError, GetPackageMetadata, target_info,
                       source_info)
@@ -559,8 +311,8 @@
     self._test_GetPackageMetadata_swapBuildTimestamps(
         target_info_dict, source_info_dict)
 
-    target_info = BuildInfo(target_info_dict, None)
-    source_info = BuildInfo(source_info_dict, None)
+    target_info = common.BuildInfo(target_info_dict, None)
+    source_info = common.BuildInfo(source_info_dict, None)
     common.OPTIONS.incremental_source = ''
     common.OPTIONS.downgrade = True
     common.OPTIONS.wipe_user_data = True
@@ -588,17 +340,20 @@
 
     with zipfile.ZipFile(target_file) as verify_zip:
       namelist = verify_zip.namelist()
+      ab_partitions = verify_zip.read('META/ab_partitions.txt').decode()
 
     self.assertIn('META/ab_partitions.txt', namelist)
-    self.assertIn('IMAGES/boot.img', namelist)
     self.assertIn('IMAGES/system.img', namelist)
-    self.assertIn('IMAGES/vendor.img', namelist)
     self.assertIn('RADIO/bootloader.img', namelist)
-    self.assertIn('RADIO/modem.img', namelist)
     self.assertIn(POSTINSTALL_CONFIG, namelist)
 
+    self.assertNotIn('IMAGES/boot.img', namelist)
     self.assertNotIn('IMAGES/system_other.img', namelist)
     self.assertNotIn('IMAGES/system.map', namelist)
+    self.assertNotIn('RADIO/modem.img', namelist)
+
+    expected_ab_partitions = ['system', 'bootloader']
+    self.assertEqual('\n'.join(expected_ab_partitions), ab_partitions)
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_GetTargetFilesZipForSecondaryImages_skipPostinstall(self):
@@ -610,14 +365,13 @@
       namelist = verify_zip.namelist()
 
     self.assertIn('META/ab_partitions.txt', namelist)
-    self.assertIn('IMAGES/boot.img', namelist)
     self.assertIn('IMAGES/system.img', namelist)
-    self.assertIn('IMAGES/vendor.img', namelist)
     self.assertIn('RADIO/bootloader.img', namelist)
-    self.assertIn('RADIO/modem.img', namelist)
 
+    self.assertNotIn('IMAGES/boot.img', namelist)
     self.assertNotIn('IMAGES/system_other.img', namelist)
     self.assertNotIn('IMAGES/system.map', namelist)
+    self.assertNotIn('RADIO/modem.img', namelist)
     self.assertNotIn(POSTINSTALL_CONFIG, namelist)
 
   @test_utils.SkipIfExternalToolsUnavailable()
@@ -631,17 +385,65 @@
       namelist = verify_zip.namelist()
 
     self.assertIn('META/ab_partitions.txt', namelist)
-    self.assertIn('IMAGES/boot.img', namelist)
     self.assertIn('IMAGES/system.img', namelist)
-    self.assertIn('IMAGES/vendor.img', namelist)
     self.assertIn(POSTINSTALL_CONFIG, namelist)
 
+    self.assertNotIn('IMAGES/boot.img', namelist)
     self.assertNotIn('IMAGES/system_other.img', namelist)
     self.assertNotIn('IMAGES/system.map', namelist)
     self.assertNotIn('RADIO/bootloader.img', namelist)
     self.assertNotIn('RADIO/modem.img', namelist)
 
   @test_utils.SkipIfExternalToolsUnavailable()
+  def test_GetTargetFilesZipForSecondaryImages_dynamicPartitions(self):
+    input_file = construct_target_files(secondary=True)
+    misc_info = '\n'.join([
+        'use_dynamic_partition_size=true',
+        'use_dynamic_partitions=true',
+        'dynamic_partition_list=system vendor product',
+        'super_partition_groups=google_dynamic_partitions',
+        'super_google_dynamic_partitions_group_size=4873781248',
+        'super_google_dynamic_partitions_partition_list=system vendor product',
+    ])
+    dynamic_partitions_info = '\n'.join([
+        'super_partition_groups=google_dynamic_partitions',
+        'super_google_dynamic_partitions_group_size=4873781248',
+        'super_google_dynamic_partitions_partition_list=system vendor product',
+    ])
+
+    with zipfile.ZipFile(input_file, 'a') as append_zip:
+      common.ZipWriteStr(append_zip, 'META/misc_info.txt', misc_info)
+      common.ZipWriteStr(append_zip, 'META/dynamic_partitions_info.txt',
+                         dynamic_partitions_info)
+
+    target_file = GetTargetFilesZipForSecondaryImages(input_file)
+
+    with zipfile.ZipFile(target_file) as verify_zip:
+      namelist = verify_zip.namelist()
+      updated_misc_info = verify_zip.read('META/misc_info.txt').decode()
+      updated_dynamic_partitions_info = verify_zip.read(
+          'META/dynamic_partitions_info.txt').decode()
+
+    self.assertIn('META/ab_partitions.txt', namelist)
+    self.assertIn('IMAGES/system.img', namelist)
+    self.assertIn(POSTINSTALL_CONFIG, namelist)
+    self.assertIn('META/misc_info.txt', namelist)
+    self.assertIn('META/dynamic_partitions_info.txt', namelist)
+
+    self.assertNotIn('IMAGES/boot.img', namelist)
+    self.assertNotIn('IMAGES/system_other.img', namelist)
+    self.assertNotIn('IMAGES/system.map', namelist)
+
+    # Check the vendor & product are removed from the partitions list.
+    expected_misc_info = misc_info.replace('system vendor product',
+                                           'system')
+    expected_dynamic_partitions_info = dynamic_partitions_info.replace(
+        'system vendor product', 'system')
+    self.assertEqual(expected_misc_info, updated_misc_info)
+    self.assertEqual(expected_dynamic_partitions_info,
+                     updated_dynamic_partitions_info)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_GetTargetFilesZipWithoutPostinstallConfig(self):
     input_file = construct_target_files()
     target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
@@ -723,6 +525,59 @@
     FinalizeMetadata(metadata, zip_file, output_file, needed_property_files)
     self.assertIn('ota-test-property-files', metadata)
 
+  def test_WriteFingerprintAssertion_without_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+    source_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
+    source_info_dict['build.prop']['ro.build.fingerprint'] = (
+        'source-build-fingerprint')
+    source_info = common.BuildInfo(source_info_dict, None)
+
+    script_writer = test_utils.MockScriptWriter()
+    WriteFingerprintAssertion(script_writer, target_info, source_info)
+    self.assertEqual(
+        [('AssertSomeFingerprint', 'source-build-fingerprint',
+          'build-fingerprint-target')],
+        script_writer.lines)
+
+  def test_WriteFingerprintAssertion_with_source_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+    source_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+
+    script_writer = test_utils.MockScriptWriter()
+    WriteFingerprintAssertion(script_writer, target_info, source_info)
+    self.assertEqual(
+        [('AssertFingerprintOrThumbprint', 'build-fingerprint-target',
+          'build-thumbprint')],
+        script_writer.lines)
+
+  def test_WriteFingerprintAssertion_with_target_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    source_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+
+    script_writer = test_utils.MockScriptWriter()
+    WriteFingerprintAssertion(script_writer, target_info, source_info)
+    self.assertEqual(
+        [('AssertFingerprintOrThumbprint', 'build-fingerprint-target',
+          'build-thumbprint')],
+        script_writer.lines)
+
+  def test_WriteFingerprintAssertion_with_both_oem_props(self):
+    target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+                                   self.TEST_OEM_DICTS)
+    source_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
+    source_info_dict['build.prop']['ro.build.thumbprint'] = (
+        'source-build-thumbprint')
+    source_info = common.BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
+
+    script_writer = test_utils.MockScriptWriter()
+    WriteFingerprintAssertion(script_writer, target_info, source_info)
+    self.assertEqual(
+        [('AssertSomeThumbprint', 'build-thumbprint',
+          'source-build-thumbprint')],
+        script_writer.lines)
+
 
 class TestPropertyFiles(PropertyFiles):
   """A class that extends PropertyFiles for testing purpose."""
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 70c147e..e0a635a 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -525,3 +525,26 @@
             'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
             'build/make/target/product/security/testkey'),
         }, keys_info)
+
+  def test_ReadApexKeysInfo_presignedKeys(self):
+    apex_keys = self.APEX_KEYS_TXT + (
+        'name="apex.apexd_test_different_app2.apex" '
+        'private_key="PRESIGNED" '
+        'public_key="PRESIGNED" '
+        'container_certificate="PRESIGNED" '
+        'container_private_key="PRESIGNED"')
+    target_files = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+      target_files_zip.writestr('META/apexkeys.txt', apex_keys)
+
+    with zipfile.ZipFile(target_files) as target_files_zip:
+      keys_info = ReadApexKeysInfo(target_files_zip)
+
+    self.assertEqual({
+        'apex.apexd_test.apex': (
+            'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
+            'build/make/target/product/security/testkey'),
+        'apex.apexd_test_different_app.apex': (
+            'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
+            'build/make/target/product/security/testkey'),
+        }, keys_info)
diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py
index 2445671..e999757 100755
--- a/tools/releasetools/test_utils.py
+++ b/tools/releasetools/test_utils.py
@@ -145,6 +145,47 @@
   return sparse_image
 
 
+class MockScriptWriter(object):
+  """A class that mocks edify_generator.EdifyGenerator.
+
+  It simply pushes the incoming arguments onto script stack, which is to assert
+  the calls to EdifyGenerator functions.
+  """
+
+  def __init__(self, enable_comments=False):
+    self.lines = []
+    self.enable_comments = enable_comments
+
+  def Mount(self, *args):
+    self.lines.append(('Mount',) + args)
+
+  def AssertDevice(self, *args):
+    self.lines.append(('AssertDevice',) + args)
+
+  def AssertOemProperty(self, *args):
+    self.lines.append(('AssertOemProperty',) + args)
+
+  def AssertFingerprintOrThumbprint(self, *args):
+    self.lines.append(('AssertFingerprintOrThumbprint',) + args)
+
+  def AssertSomeFingerprint(self, *args):
+    self.lines.append(('AssertSomeFingerprint',) + args)
+
+  def AssertSomeThumbprint(self, *args):
+    self.lines.append(('AssertSomeThumbprint',) + args)
+
+  def Comment(self, comment):
+    if not self.enable_comments:
+      return
+    self.lines.append('# {}'.format(comment))
+
+  def AppendExtra(self, extra):
+    self.lines.append(extra)
+
+  def __str__(self):
+    return '\n'.join(self.lines)
+
+
 class ReleaseToolsTestCase(unittest.TestCase):
   """A common base class for all the releasetools unittests."""
 
diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index 0f0d773..6504515 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -143,21 +143,52 @@
     verity_image_builder.Build(output_file)
 
   @test_utils.SkipIfExternalToolsUnavailable()
-  def test_ValidateVerifiedBootImages_systemImage(self):
+  def test_ValidateVerifiedBootImages_systemRootImage(self):
     input_tmp = common.MakeTempDir()
     os.mkdir(os.path.join(input_tmp, 'IMAGES'))
     system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
     self._generate_system_image(system_image)
 
     # Pack the verity key.
-    verity_key_mincrypt = os.path.join(
-        input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
     os.makedirs(os.path.dirname(verity_key_mincrypt))
     shutil.copyfile(
         os.path.join(self.testdata_dir, 'testkey_mincrypt'),
         verity_key_mincrypt)
 
     info_dict = {
+        'system_root_image' : 'true',
+        'verity' : 'true',
+    }
+    options = {
+        'verity_key' : os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+        'verity_key_mincrypt' : verity_key_mincrypt,
+    }
+    ValidateVerifiedBootImages(input_tmp, info_dict, options)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_ValidateVerifiedBootImages_nonSystemRootImage(self):
+    input_tmp = common.MakeTempDir()
+    os.mkdir(os.path.join(input_tmp, 'IMAGES'))
+    system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
+    self._generate_system_image(system_image)
+
+    # Pack the verity key into the root dir in system.img.
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_mincrypt))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'testkey_mincrypt'),
+        verity_key_mincrypt)
+
+    # And a copy in ramdisk.
+    verity_key_ramdisk = os.path.join(
+        input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_ramdisk))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'testkey_mincrypt'),
+        verity_key_ramdisk)
+
+    info_dict = {
         'verity' : 'true',
     }
     options = {
@@ -167,6 +198,39 @@
     ValidateVerifiedBootImages(input_tmp, info_dict, options)
 
   @test_utils.SkipIfExternalToolsUnavailable()
+  def test_ValidateVerifiedBootImages_nonSystemRootImage_mismatchingKeys(self):
+    input_tmp = common.MakeTempDir()
+    os.mkdir(os.path.join(input_tmp, 'IMAGES'))
+    system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
+    self._generate_system_image(system_image)
+
+    # Pack the verity key into the root dir in system.img.
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_mincrypt))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'testkey_mincrypt'),
+        verity_key_mincrypt)
+
+    # And an invalid copy in ramdisk.
+    verity_key_ramdisk = os.path.join(
+        input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    os.makedirs(os.path.dirname(verity_key_ramdisk))
+    shutil.copyfile(
+        os.path.join(self.testdata_dir, 'verity_mincrypt'),
+        verity_key_ramdisk)
+
+    info_dict = {
+        'verity' : 'true',
+    }
+    options = {
+        'verity_key' : os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+        'verity_key_mincrypt' : verity_key_mincrypt,
+    }
+    self.assertRaises(
+        AssertionError, ValidateVerifiedBootImages, input_tmp, info_dict,
+        options)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_ValidateFileConsistency_incompleteRange(self):
     input_tmp = common.MakeTempDir()
     os.mkdir(os.path.join(input_tmp, 'IMAGES'))
@@ -174,14 +238,14 @@
     system_root = os.path.join(input_tmp, "SYSTEM")
     os.mkdir(system_root)
 
-    # Write the test file that contain multiple blocks of zeros, and these
-    # zero blocks will be omitted by kernel. And the test files will occupy one
-    # block range each in the final system image.
+    # Write test files that contain multiple blocks of zeros, and these zero
+    # blocks will be omitted by kernel. Each test file will occupy one block in
+    # the final system image.
     with open(os.path.join(system_root, 'a'), 'w') as f:
-      f.write("aaa")
+      f.write('aaa')
       f.write('\0' * 4096 * 3)
     with open(os.path.join(system_root, 'b'), 'w') as f:
-      f.write("bbb")
+      f.write('bbb')
       f.write('\0' * 4096 * 3)
 
     raw_file_map = os.path.join(input_tmp, 'IMAGES', 'raw_system.map')
@@ -190,7 +254,7 @@
     # Parse the generated file map and update the block ranges for each file.
     file_map_list = {}
     image_ranges = RangeSet()
-    with open(raw_file_map, 'r') as f:
+    with open(raw_file_map) as f:
       for line in f.readlines():
         info = line.split()
         self.assertEqual(2, len(info))
@@ -201,7 +265,7 @@
     mock_shared_block = RangeSet("10-20").subtract(image_ranges).first(1)
     with open(os.path.join(input_tmp, 'IMAGES', 'system.map'), 'w') as f:
       for key in sorted(file_map_list.keys()):
-        line = "{} {}\n".format(
+        line = '{} {}\n'.format(
             key, file_map_list[key].union(mock_shared_block))
         f.write(line)
 
@@ -213,9 +277,55 @@
       for name in all_entries:
         input_zip.write(os.path.join(input_tmp, name), arcname=name)
 
-    input_zip = zipfile.ZipFile(input_file, 'r')
-    info_dict = {'extfs_sparse_flag': '-s'}
-
     # Expect the validation to pass and both files are skipped due to
     # 'incomplete' block range.
-    ValidateFileConsistency(input_zip, input_tmp, info_dict)
+    with zipfile.ZipFile(input_file) as input_zip:
+      info_dict = {'extfs_sparse_flag': '-s'}
+      ValidateFileConsistency(input_zip, input_tmp, info_dict)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_ValidateFileConsistency_nonMonotonicRanges(self):
+    input_tmp = common.MakeTempDir()
+    os.mkdir(os.path.join(input_tmp, 'IMAGES'))
+    system_image = os.path.join(input_tmp, 'IMAGES', 'system.img')
+    system_root = os.path.join(input_tmp, "SYSTEM")
+    os.mkdir(system_root)
+
+    # Write the test file that contain three blocks of 'a', 'b', 'c'.
+    with open(os.path.join(system_root, 'abc'), 'w') as f:
+      f.write('a' * 4096 + 'b' * 4096 + 'c' * 4096)
+    raw_file_map = os.path.join(input_tmp, 'IMAGES', 'raw_system.map')
+    self._generate_system_image(system_image, system_root, raw_file_map)
+
+    # Parse the generated file map and manipulate the block ranges of 'abc' to
+    # be 'cba'.
+    file_map_list = {}
+    with open(raw_file_map) as f:
+      for line in f.readlines():
+        info = line.split()
+        self.assertEqual(2, len(info))
+        ranges = RangeSet(info[1])
+        self.assertTrue(ranges.monotonic)
+        blocks = reversed(list(ranges.next_item()))
+        file_map_list[info[0]] = ' '.join([str(block) for block in blocks])
+
+    # Update the contents of 'abc' to be 'cba'.
+    with open(os.path.join(system_root, 'abc'), 'w') as f:
+      f.write('c' * 4096 + 'b' * 4096 + 'a' * 4096)
+
+    # Update the system.map.
+    with open(os.path.join(input_tmp, 'IMAGES', 'system.map'), 'w') as f:
+      for key in sorted(file_map_list.keys()):
+        f.write('{} {}\n'.format(key, file_map_list[key]))
+
+    # Get the target zip file.
+    input_file = common.MakeTempFile()
+    all_entries = ['SYSTEM/', 'SYSTEM/abc', 'IMAGES/',
+                   'IMAGES/system.map', 'IMAGES/system.img']
+    with zipfile.ZipFile(input_file, 'w') as input_zip:
+      for name in all_entries:
+        input_zip.write(os.path.join(input_tmp, name), arcname=name)
+
+    with zipfile.ZipFile(input_file) as input_zip:
+      info_dict = {'extfs_sparse_flag': '-s'}
+      ValidateFileConsistency(input_zip, input_tmp, info_dict)
diff --git a/tools/releasetools/testdata/vintf/kernel/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/kernel/SYSTEM/compatibility_matrix.xml
new file mode 100644
index 0000000..ed46b6b
--- /dev/null
+++ b/tools/releasetools/testdata/vintf/kernel/SYSTEM/compatibility_matrix.xml
@@ -0,0 +1,7 @@
+<compatibility-matrix version="1.0" type="framework">
+    <kernel version="4.14.1" />
+    <sepolicy>
+        <sepolicy-version>0.0</sepolicy-version>
+        <kernel-sepolicy-version>0</kernel-sepolicy-version>
+    </sepolicy>
+</compatibility-matrix>
diff --git a/tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/compatibility_matrix.xml
new file mode 100644
index 0000000..5d891fa
--- /dev/null
+++ b/tools/releasetools/testdata/vintf/matrix_incompat/SYSTEM/compatibility_matrix.xml
@@ -0,0 +1,6 @@
+<compatibility-matrix version="1.0" type="framework">
+    <sepolicy>
+        <sepolicy-version>1.0</sepolicy-version>
+        <kernel-sepolicy-version>0</kernel-sepolicy-version>
+    </sepolicy>
+</compatibility-matrix>
diff --git a/tools/releasetools/testdata/vintf/sku_compat/ODM/etc/vintf/manifest_sku.xml b/tools/releasetools/testdata/vintf/sku_compat/ODM/etc/vintf/manifest_sku.xml
new file mode 100644
index 0000000..bcd7ce4
--- /dev/null
+++ b/tools/releasetools/testdata/vintf/sku_compat/ODM/etc/vintf/manifest_sku.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>foo</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.0::IFoo/default</fqname>
+    </hal>
+</manifest>
diff --git a/tools/releasetools/testdata/vintf/sku_compat/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/sku_compat/SYSTEM/compatibility_matrix.xml
new file mode 100644
index 0000000..19a9b6a
--- /dev/null
+++ b/tools/releasetools/testdata/vintf/sku_compat/SYSTEM/compatibility_matrix.xml
@@ -0,0 +1,14 @@
+<compatibility-matrix version="1.0" type="framework">
+    <hal format="hidl" optional="false">
+        <name>foo</name>
+        <version>1.0</version>
+        <interface>
+            <name>IFoo</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <sepolicy>
+        <sepolicy-version>0.0</sepolicy-version>
+        <kernel-sepolicy-version>0</kernel-sepolicy-version>
+    </sepolicy>
+</compatibility-matrix>
diff --git a/tools/releasetools/testdata/vintf/sku_incompat/ODM/etc/vintf/manifest_sku.xml b/tools/releasetools/testdata/vintf/sku_incompat/ODM/etc/vintf/manifest_sku.xml
new file mode 100644
index 0000000..bcd7ce4
--- /dev/null
+++ b/tools/releasetools/testdata/vintf/sku_incompat/ODM/etc/vintf/manifest_sku.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>foo</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.0::IFoo/default</fqname>
+    </hal>
+</manifest>
diff --git a/tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/compatibility_matrix.xml b/tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/compatibility_matrix.xml
new file mode 100644
index 0000000..e0e0d6c
--- /dev/null
+++ b/tools/releasetools/testdata/vintf/sku_incompat/SYSTEM/compatibility_matrix.xml
@@ -0,0 +1,14 @@
+<compatibility-matrix version="1.0" type="framework">
+    <hal format="hidl" optional="false">
+        <name>foo</name>
+        <version>1.1</version>
+        <interface>
+            <name>IFoo</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <sepolicy>
+        <sepolicy-version>0.0</sepolicy-version>
+        <kernel-sepolicy-version>0</kernel-sepolicy-version>
+    </sepolicy>
+</compatibility-matrix>
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index d189499..383ef7b 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -36,20 +36,21 @@
 import os.path
 import re
 import zipfile
+from hashlib import sha1
 
 import common
+import rangelib
 
 
 def _ReadFile(file_name, unpacked_name, round_up=False):
   """Constructs and returns a File object. Rounds up its size if needed."""
-
   assert os.path.exists(unpacked_name)
   with open(unpacked_name, 'rb') as f:
     file_data = f.read()
   file_size = len(file_data)
   if round_up:
     file_size_rounded_up = common.RoundUpTo4K(file_size)
-    file_data += '\0' * (file_size_rounded_up - file_size)
+    file_data += b'\0' * (file_size_rounded_up - file_size)
   return common.File(file_name, file_data)
 
 
@@ -96,13 +97,15 @@
         logging.warning('Skipping %s that has incomplete block list', entry)
         continue
 
-      # TODO(b/79951650): Handle files with non-monotonic ranges.
+      # If the file has non-monotonic ranges, read each range in order.
       if not file_ranges.monotonic:
-        logging.warning(
-            'Skipping %s that has non-monotonic ranges: %s', entry, file_ranges)
-        continue
-
-      blocks_sha1 = image.RangeSha1(file_ranges)
+        h = sha1()
+        for file_range in file_ranges.extra['text_str'].split(' '):
+          for data in image.ReadRangeSet(rangelib.RangeSet(file_range)):
+            h.update(data)
+        blocks_sha1 = h.hexdigest()
+      else:
+        blocks_sha1 = image.RangeSha1(file_ranges)
 
       # The filename under unpacked directory, such as SYSTEM/bin/sh.
       unpacked_name = os.path.join(
@@ -138,7 +141,7 @@
   1. full recovery:
   ...
   if ! applypatch --check type:device:size:sha1; then
-    applypatch --flash /system/etc/recovery.img \\
+    applypatch --flash /vendor/etc/recovery.img \\
         type:device:size:sha1 && \\
   ...
 
@@ -146,18 +149,26 @@
   ...
   if ! applypatch --check type:recovery_device:recovery_size:recovery_sha1; then
     applypatch [--bonus bonus_args] \\
-        --patch /system/recovery-from-boot.p \\
+        --patch /vendor/recovery-from-boot.p \\
         --source type:boot_device:boot_size:boot_sha1 \\
         --target type:recovery_device:recovery_size:recovery_sha1 && \\
   ...
 
-  For full recovery, we want to calculate the SHA-1 of /system/etc/recovery.img
+  For full recovery, we want to calculate the SHA-1 of /vendor/etc/recovery.img
   and compare it against the one embedded in the script. While for recovery
   from boot, we want to check the SHA-1 for both recovery.img and boot.img
   under IMAGES/.
   """
 
-  script_path = 'SYSTEM/bin/install-recovery.sh'
+  board_uses_vendorimage = info_dict.get("board_uses_vendorimage") == "true"
+
+  if board_uses_vendorimage:
+    script_path = 'VENDOR/bin/install-recovery.sh'
+    recovery_img = 'VENDOR/etc/recovery.img'
+  else:
+    script_path = 'SYSTEM/vendor/bin/install-recovery.sh'
+    recovery_img = 'SYSTEM/vendor/etc/recovery.img'
+
   if not os.path.exists(os.path.join(input_tmp, script_path)):
     logging.info('%s does not exist in input_tmp', script_path)
     return
@@ -188,7 +199,7 @@
     # Validate the SHA-1 of the recovery image.
     recovery_sha1 = flash_partition.split(':')[3]
     ValidateFileAgainstSha1(
-        input_tmp, 'recovery.img', 'SYSTEM/etc/recovery.img', recovery_sha1)
+        input_tmp, 'recovery.img', recovery_img, recovery_sha1)
   else:
     assert len(lines) == 11, "Invalid line count: {}".format(lines)
 
@@ -276,15 +287,12 @@
   # Verify verity signed system images in Verified Boot 1.0. Note that not using
   # 'elif' here, since 'boot_signer' and 'verity' are not bundled in VB 1.0.
   if info_dict.get('verity') == 'true':
-    # First verify that the verity key that's built into the root image (as
-    # /verity_key) matches the one given via command line, if any.
-    if info_dict.get("system_root_image") == "true":
-      verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
-    else:
-      verity_key_mincrypt = os.path.join(
-          input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+    # First verify that the verity key is built into the root image (regardless
+    # of system-as-root).
+    verity_key_mincrypt = os.path.join(input_tmp, 'ROOT', 'verity_key')
     assert os.path.exists(verity_key_mincrypt), 'Missing verity_key'
 
+    # Verify /verity_key matches the one given via command line, if any.
     if options['verity_key_mincrypt'] is None:
       logging.warn(
           'Skipped checking the content of /verity_key, as the key file not '
@@ -295,6 +303,18 @@
           "Mismatching mincrypt verity key files"
       logging.info('Verified the content of /verity_key')
 
+    # For devices with a separate ramdisk (i.e. non-system-as-root), there must
+    # be a copy in ramdisk.
+    if info_dict.get("system_root_image") != "true":
+      verity_key_ramdisk = os.path.join(
+          input_tmp, 'BOOT', 'RAMDISK', 'verity_key')
+      assert os.path.exists(verity_key_ramdisk), 'Missing verity_key in ramdisk'
+
+      assert filecmp.cmp(
+          verity_key_mincrypt, verity_key_ramdisk, shallow=False), \
+              'Mismatching verity_key files in root and ramdisk'
+      logging.info('Verified the content of /verity_key in ramdisk')
+
     # Then verify the verity signed system/vendor/product images, against the
     # verity pubkey in mincrypt format.
     for image in ('system.img', 'vendor.img', 'product.img'):
diff --git a/tools/signapk/Android.bp b/tools/signapk/Android.bp
index ad9d957..c799dbf 100644
--- a/tools/signapk/Android.bp
+++ b/tools/signapk/Android.bp
@@ -24,7 +24,7 @@
         "apksig",
         "bouncycastle-unbundled",
         "bouncycastle-bcpkix-unbundled",
-        "conscrypt-nojarjar",
+        "conscrypt-unbundled",
     ],
 
     required: ["libconscrypt_openjdk_jni"],
diff --git a/tools/warn.py b/tools/warn.py
index 48feb49..5994124 100755
--- a/tools/warn.py
+++ b/tools/warn.py
@@ -159,11 +159,64 @@
   return tidy_warn_pattern(description, description + r'-.+')
 
 
+def analyzer_high(description, patterns):
+  # Important clang analyzer warnings to be fixed ASAP.
+  return {
+      'category': 'C/C++',
+      'severity': Severity.HIGH,
+      'description': description,
+      'patterns': patterns
+  }
+
+
+def analyzer_high_check(check):
+  return analyzer_high(check, [r'.*: .+\[' + check + r'\]$'])
+
+
+def analyzer_group_high(check):
+  return analyzer_high(check, [r'.*: .+\[' + check + r'.+\]$'])
+
+
+def analyzer_warn(description, patterns):
+  return {
+      'category': 'C/C++',
+      'severity': Severity.ANALYZER,
+      'description': description,
+      'patterns': patterns
+  }
+
+
+def analyzer_warn_check(check):
+  return analyzer_warn(check, [r'.*: .+\[' + check + r'\]$'])
+
+
+def analyzer_group_check(check):
+  return analyzer_warn(check, [r'.*: .+\[' + check + r'.+\]$'])
+
+
+def java_warn(severity, description, patterns):
+  return {
+      'category': 'Java',
+      'severity': severity,
+      'description': 'Java: ' + description,
+      'patterns': patterns
+  }
+
+
+def java_high(description, patterns):
+  return java_warn(Severity.HIGH, description, patterns)
+
+
+def java_medium(description, patterns):
+  return java_warn(Severity.MEDIUM, description, patterns)
+
+
+def java_low(description, patterns):
+  return java_warn(Severity.LOW, description, patterns)
+
+
 warn_patterns = [
     # pylint:disable=line-too-long,g-inconsistent-quotes
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Security warning',
-     'patterns': [r".*: warning: .+\[clang-analyzer-security.*\]"]},
     {'category': 'make', 'severity': Severity.MEDIUM,
      'description': 'make: overriding commands/ignoring old commands',
      'patterns': [r".*: warning: overriding commands for target .+",
@@ -183,7 +236,7 @@
     {'category': 'make', 'severity': Severity.MEDIUM,
      'description': 'Duplicate header copy',
      'patterns': [r".*: warning: Duplicate header copy: .+"]},
-    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Wimplicit-function-declaration',
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wimplicit-function-declaration',
      'description': 'Implicit function declaration',
      'patterns': [r".*: warning: implicit declaration of function .+",
                   r".*: warning: implicitly declaring library function"]},
@@ -195,17 +248,17 @@
      'patterns': [r".*: warning: comparison is always .+ due to limited range of data type",
                   r".*: warning: comparison of unsigned .*expression .+ is always true",
                   r".*: warning: comparison of unsigned .*expression .+ is always false"]},
-    {'category': 'C/C++', 'severity': Severity.HIGH,
-     'description': 'Potential leak of memory, bad free, use after free',
-     'patterns': [r".*: warning: Potential leak of memory",
-                  r".*: warning: Potential memory leak",
-                  r".*: warning: Memory allocated by alloca\(\) should not be deallocated",
-                  r".*: warning: Memory allocated by .+ should be deallocated by .+ not .+",
-                  r".*: warning: 'delete' applied to a pointer that was allocated",
-                  r".*: warning: Use of memory after it is freed",
-                  r".*: warning: Argument to .+ is the address of .+ variable",
-                  r".*: warning: Argument to free\(\) is offset by .+ of memory allocated by",
-                  r".*: warning: Attempt to .+ released memory"]},
+    # {'category': 'C/C++', 'severity': Severity.HIGH,
+    #  'description': 'Potential leak of memory, bad free, use after free',
+    #  'patterns': [r".*: warning: Potential leak of memory",
+    #               r".*: warning: Potential memory leak",
+    #               r".*: warning: Memory allocated by alloca\(\) should not be deallocated",
+    #               r".*: warning: Memory allocated by .+ should be deallocated by .+ not .+",
+    #               r".*: warning: 'delete' applied to a pointer that was allocated",
+    #               r".*: warning: Use of memory after it is freed",
+    #               r".*: warning: Argument to .+ is the address of .+ variable",
+    #               r".*: warning: Argument to free\(\) is offset by .+ of memory allocated by",
+    #               r".*: warning: Attempt to .+ released memory"]},
     {'category': 'C/C++', 'severity': Severity.HIGH,
      'description': 'Use transient memory for control value',
      'patterns': [r".*: warning: .+Using such transient memory for the control value is .*dangerous."]},
@@ -213,10 +266,10 @@
      'description': 'Return address of stack memory',
      'patterns': [r".*: warning: Address of stack memory .+ returned to caller",
                   r".*: warning: Address of stack memory .+ will be a dangling reference"]},
-    {'category': 'C/C++', 'severity': Severity.HIGH,
-     'description': 'Problem with vfork',
-     'patterns': [r".*: warning: This .+ is prohibited after a successful vfork",
-                  r".*: warning: Call to function '.+' is insecure "]},
+    # {'category': 'C/C++', 'severity': Severity.HIGH,
+    #  'description': 'Problem with vfork',
+    #  'patterns': [r".*: warning: This .+ is prohibited after a successful vfork",
+    #               r".*: warning: Call to function '.+' is insecure "]},
     {'category': 'C/C++', 'severity': Severity.HIGH, 'option': 'infinite-recursion',
      'description': 'Infinite recursion',
      'patterns': [r".*: warning: all paths through this function will call itself"]},
@@ -271,6 +324,9 @@
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wdate-time',
      'description': 'Expansion of data or time macro',
      'patterns': [r".*: warning: expansion of date or time macro is not reproducible"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wexpansion-to-defined',
+     'description': 'Macro expansion has undefined behavior',
+     'patterns': [r".*: warning: macro expansion .* has undefined behavior"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wformat',
      'description': 'Format string does not match arguments',
      'patterns': [r".*: warning: format '.+' expects type '.+', but argument [0-9]+ has type '.+'",
@@ -398,16 +454,16 @@
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wimplicit int',
      'description': 'No type or storage class (will default to int)',
      'patterns': [r".*: warning: data definition has no type or storage class"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Null pointer',
-     'patterns': [r".*: warning: Dereference of null pointer",
-                  r".*: warning: Called .+ pointer is null",
-                  r".*: warning: Forming reference to null pointer",
-                  r".*: warning: Returning null reference",
-                  r".*: warning: Null pointer passed as an argument to a 'nonnull' parameter",
-                  r".*: warning: .+ results in a null pointer dereference",
-                  r".*: warning: Access to .+ results in a dereference of a null pointer",
-                  r".*: warning: Null pointer argument in"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'Null pointer',
+    #  'patterns': [r".*: warning: Dereference of null pointer",
+    #               r".*: warning: Called .+ pointer is null",
+    #               r".*: warning: Forming reference to null pointer",
+    #               r".*: warning: Returning null reference",
+    #               r".*: warning: Null pointer passed as an argument to a 'nonnull' parameter",
+    #               r".*: warning: .+ results in a null pointer dereference",
+    #               r".*: warning: Access to .+ results in a dereference of a null pointer",
+    #               r".*: warning: Null pointer argument in"]},
     {'category': 'cont.', 'severity': Severity.SKIP,
      'description': 'skip, parameter name (without types) in function declaration',
      'patterns': [r".*: warning: parameter names \(without types\) in function declaration"]},
@@ -422,8 +478,8 @@
      'description': 'Cast to pointer from integer of different size',
      'patterns': [r".*: warning: cast to pointer from integer of different size"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Symbol redefined',
-     'patterns': [r".*: warning: "".+"" redefined"]},
+     'description': 'Macro redefined',
+     'patterns': [r".*: warning: '.+' macro redefined"]},
     {'category': 'cont.', 'severity': Severity.SKIP,
      'description': 'skip, ... location of the previous definition',
      'patterns': [r".*: warning: this is the location of the previous definition"]},
@@ -463,1700 +519,704 @@
     {'category': 'cont.', 'severity': Severity.SKIP,
      'description': 'skip, previous declaration ... was here',
      'patterns': [r".*: warning: previous declaration of '.+' was here"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wswitch-enum',
+    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Wswitch-enum',
      'description': 'Enum value not handled in switch',
      'patterns': [r".*: warning: .*enumeration value.* not handled in switch.+Wswitch"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wuser-defined-warnings',
      'description': 'User defined warnings',
      'patterns': [r".*: warning: .* \[-Wuser-defined-warnings\]$"]},
-    {'category': 'java', 'severity': Severity.MEDIUM, 'option': '-encoding',
-     'description': 'Java: Non-ascii characters used, but ascii encoding specified',
-     'patterns': [r".*: warning: unmappable character for encoding ascii"]},
-    {'category': 'java', 'severity': Severity.MEDIUM,
-     'description': 'Java: Non-varargs call of varargs method with inexact argument type for last parameter',
-     'patterns': [r".*: warning: non-varargs call of varargs method with inexact argument type for last parameter"]},
-    {'category': 'java', 'severity': Severity.MEDIUM,
-     'description': 'Java: Unchecked method invocation',
-     'patterns': [r".*: warning: \[unchecked\] unchecked method invocation: .+ in class .+"]},
-    {'category': 'java', 'severity': Severity.MEDIUM,
-     'description': 'Java: Unchecked conversion',
-     'patterns': [r".*: warning: \[unchecked\] unchecked conversion"]},
-    {'category': 'java', 'severity': Severity.MEDIUM,
-     'description': '_ used as an identifier',
-     'patterns': [r".*: warning: '_' used as an identifier"]},
-    {'category': 'java', 'severity': Severity.HIGH,
-     'description': 'Use of internal proprietary API',
-     'patterns': [r".*: warning: .* is internal proprietary API and may be removed"]},
+
+    # Java warnings
+    java_medium('Non-ascii characters used, but ascii encoding specified',
+                [r".*: warning: unmappable character for encoding ascii"]),
+    java_medium('Non-varargs call of varargs method with inexact argument type for last parameter',
+                [r".*: warning: non-varargs call of varargs method with inexact argument type for last parameter"]),
+    java_medium('Unchecked method invocation',
+                [r".*: warning: \[unchecked\] unchecked method invocation: .+ in class .+"]),
+    java_medium('Unchecked conversion',
+                [r".*: warning: \[unchecked\] unchecked conversion"]),
+    java_medium('_ used as an identifier',
+                [r".*: warning: '_' used as an identifier"]),
+    java_medium('hidden superclass',
+                [r".*: warning: .* stripped of .* superclass .* \[HiddenSuperclass\]"]),
+    java_high('Use of internal proprietary API',
+              [r".*: warning: .* is internal proprietary API and may be removed"]),
 
     # Warnings from Javac
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description': 'Java: Use of deprecated member',
-     'patterns': [r'.*: warning: \[deprecation\] .+']},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description': 'Java: Unchecked conversion',
-     'patterns': [r'.*: warning: \[unchecked\] .+']},
+    java_medium('Use of deprecated member',
+                [r'.*: warning: \[deprecation\] .+']),
+    java_medium('Unchecked conversion',
+                [r'.*: warning: \[unchecked\] .+']),
 
     # Begin warnings generated by Error Prone
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Use parameter comments to document ambiguous literals',
-     'patterns': [r".*: warning: \[BooleanParameter\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: This class\'s name looks like a Type Parameter.',
-     'patterns': [r".*: warning: \[ClassNamedLikeTypeParameter\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Field name is CONSTANT_CASE, but field is not static and final',
-     'patterns': [r".*: warning: \[ConstantField\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: @Multibinds is a more efficient and declarative mechanism for ensuring that a set multibinding is present in the graph.',
-     'patterns': [r".*: warning: \[EmptySetMultibindingContributions\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Prefer assertThrows to ExpectedException',
-     'patterns': [r".*: warning: \[ExpectedExceptionRefactoring\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: This field is only assigned during initialization; consider making it final',
-     'patterns': [r".*: warning: \[FieldCanBeFinal\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Fields that can be null should be annotated @Nullable',
-     'patterns': [r".*: warning: \[FieldMissingNullable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Refactors uses of the JSR 305 @Immutable to Error Prone\'s annotation',
-     'patterns': [r".*: warning: \[ImmutableRefactoring\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         u'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.',
-     'patterns': [r".*: warning: \[LambdaFunctionalInterface\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: A private method that does not reference the enclosing instance can be static',
-     'patterns': [r".*: warning: \[MethodCanBeStatic\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: C-style array declarations should not be used',
-     'patterns': [r".*: warning: \[MixedArrayDimensions\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Variable declarations should declare only one variable',
-     'patterns': [r".*: warning: \[MultiVariableDeclaration\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Source files should not contain multiple top-level class declarations',
-     'patterns': [r".*: warning: \[MultipleTopLevelClasses\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Avoid having multiple unary operators acting on the same variable in a method call',
-     'patterns': [r".*: warning: \[MultipleUnaryOperatorsInMethodCall\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Package names should match the directory they are declared in',
-     'patterns': [r".*: warning: \[PackageLocation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Non-standard parameter comment; prefer `/* paramName= */ arg`',
-     'patterns': [r".*: warning: \[ParameterComment\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Method parameters that aren\'t checked for null shouldn\'t be annotated @Nullable',
-     'patterns': [r".*: warning: \[ParameterNotNullable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Add a private constructor to modules that will not be instantiated by Dagger.',
-     'patterns': [r".*: warning: \[PrivateConstructorForNoninstantiableModule\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Utility classes (only static members) are not designed to be instantiated and should be made noninstantiable with a default constructor.',
-     'patterns': [r".*: warning: \[PrivateConstructorForUtilityClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Unused imports',
-     'patterns': [r".*: warning: \[RemoveUnusedImports\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Methods that can return null should be annotated @Nullable',
-     'patterns': [r".*: warning: \[ReturnMissingNullable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Scopes on modules have no function and will soon be an error.',
-     'patterns': [r".*: warning: \[ScopeOnModule\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: The default case of a switch should appear at the end of the last statement group',
-     'patterns': [r".*: warning: \[SwitchDefault\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Prefer assertThrows to @Test(expected=...)',
-     'patterns': [r".*: warning: \[TestExceptionRefactoring\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Unchecked exceptions do not need to be declared in the method signature.',
-     'patterns': [r".*: warning: \[ThrowsUncheckedException\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Prefer assertThrows to try/fail',
-     'patterns': [r".*: warning: \[TryFailRefactoring\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Type parameters must be a single letter with an optional numeric suffix, or an UpperCamelCase name followed by the letter \'T\'.',
-     'patterns': [r".*: warning: \[TypeParameterNaming\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Constructors and methods with the same name should appear sequentially with no other code in between. Please re-order or re-name methods.',
-     'patterns': [r".*: warning: \[UngroupedOverloads\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Unnecessary call to NullPointerTester#setDefault',
-     'patterns': [r".*: warning: \[UnnecessarySetDefault\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Using static imports for types is unnecessary',
-     'patterns': [r".*: warning: \[UnnecessaryStaticImport\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: @Binds is a more efficient and declarative mechanism for delegating a binding.',
-     'patterns': [r".*: warning: \[UseBinds\] .+"]},
-    {'category': 'java',
-     'severity': Severity.LOW,
-     'description':
-         'Java: Wildcard imports, static or otherwise, should not be used',
-     'patterns': [r".*: warning: \[WildcardImport\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Method reference is ambiguous',
-     'patterns': [r".*: warning: \[AmbiguousMethodReference\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This method passes a pair of parameters through to String.format, but the enclosing method wasn\'t annotated @FormatMethod. Doing so gives compile-time rather than run-time protection against malformed format strings.',
-     'patterns': [r".*: warning: \[AnnotateFormatMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Annotations should be positioned after Javadocs, but before modifiers..',
-     'patterns': [r".*: warning: \[AnnotationPosition\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Arguments are in the wrong order or could be commented for clarity.',
-     'patterns': [r".*: warning: \[ArgumentSelectionDefectChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Arrays do not override equals() or hashCode, so comparisons will be done on reference equality only. If neither deduplication nor lookup are needed, consider using a List instead. Otherwise, use IdentityHashMap/Set, a Map from a library that handles object arrays, or an Iterable/List of pairs.',
-     'patterns': [r".*: warning: \[ArrayAsKeyOfSetOrMap\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Arguments are swapped in assertEquals-like call',
-     'patterns': [r".*: warning: \[AssertEqualsArgumentOrderChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Assertions may be disabled at runtime and do not guarantee that execution will halt here; consider throwing an exception instead',
-     'patterns': [r".*: warning: \[AssertFalse\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: The lambda passed to assertThrows should contain exactly one statement',
-     'patterns': [r".*: warning: \[AssertThrowsMultipleStatements\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This assertion throws an AssertionError if it fails, which will be caught by an enclosing try block.',
-     'patterns': [r".*: warning: \[AssertionFailureIgnored\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: @AssistedInject and @Inject should not be used on different constructors in the same class.',
-     'patterns': [r".*: warning: \[AssistedInjectAndInjectOnConstructors\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Make toString(), hashCode() and equals() final in AutoValue classes, so it is clear to readers that AutoValue is not overriding them',
-     'patterns': [r".*: warning: \[AutoValueFinalMethods\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Classes that implement Annotation must override equals and hashCode. Consider using AutoAnnotation instead of implementing Annotation by hand.',
-     'patterns': [r".*: warning: \[BadAnnotationImplementation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Possible sign flip from narrowing conversion',
-     'patterns': [r".*: warning: \[BadComparable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Importing nested classes/static methods/static fields with commonly-used names can make code harder to read, because it may not be clear from the context exactly which type is being referred to. Qualifying the name with that of the containing class can make the code clearer.',
-     'patterns': [r".*: warning: \[BadImport\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: instanceof used in a way that is equivalent to a null check.',
-     'patterns': [r".*: warning: \[BadInstanceof\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: BigDecimal#equals has surprising behavior: it also compares scale.',
-     'patterns': [r".*: warning: \[BigDecimalEquals\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: new BigDecimal(double) loses precision in this case.',
-     'patterns': [r".*: warning: \[BigDecimalLiteralDouble\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: A call to Binder.clearCallingIdentity() should be followed by Binder.restoreCallingIdentity() in a finally block. Otherwise the wrong Binder identity may be used by subsequent code.',
-     'patterns': [r".*: warning: \[BinderIdentityRestoredDangerously\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This code declares a binding for a common value type without a Qualifier annotation.',
-     'patterns': [r".*: warning: \[BindingToUnqualifiedCommonType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: valueOf or autoboxing provides better time and space performance',
-     'patterns': [r".*: warning: \[BoxedPrimitiveConstructor\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: ByteBuffer.array() shouldn\'t be called unless ByteBuffer.arrayOffset() is used or if the ByteBuffer was initialized using ByteBuffer.wrap() or ByteBuffer.allocate().',
-     'patterns': [r".*: warning: \[ByteBufferBackingArray\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Mockito cannot mock final classes',
-     'patterns': [r".*: warning: \[CannotMockFinalClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Duration can be expressed more clearly with different units',
-     'patterns': [r".*: warning: \[CanonicalDuration\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Logging or rethrowing exceptions should usually be preferred to catching and calling printStackTrace',
-     'patterns': [r".*: warning: \[CatchAndPrintStackTrace\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Ignoring exceptions and calling fail() is unnecessary, and makes test output less useful',
-     'patterns': [r".*: warning: \[CatchFail\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Inner class is non-static but does not reference enclosing class',
-     'patterns': [r".*: warning: \[ClassCanBeStatic\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Class.newInstance() bypasses exception checking; prefer getDeclaredConstructor().newInstance()',
-     'patterns': [r".*: warning: \[ClassNewInstance\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Providing Closeable resources makes their lifecycle unclear',
-     'patterns': [r".*: warning: \[CloseableProvides\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: The type of the array parameter of Collection.toArray needs to be compatible with the array type',
-     'patterns': [r".*: warning: \[CollectionToArraySafeParameter\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Collector.of() should not use state',
-     'patterns': [r".*: warning: \[CollectorShouldNotUseState\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Class should not implement both `Comparable` and `Comparator`',
-     'patterns': [r".*: warning: \[ComparableAndComparator\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Constructors should not invoke overridable methods.',
-     'patterns': [r".*: warning: \[ConstructorInvokesOverridable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Constructors should not pass the \'this\' reference out in method invocations, since the object may not be fully constructed.',
-     'patterns': [r".*: warning: \[ConstructorLeaksThis\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: DateFormat is not thread-safe, and should not be used as a constant field.',
-     'patterns': [r".*: warning: \[DateFormatConstant\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Implicit use of the platform default charset, which can result in differing behaviour between JVM executions or incorrect behavior if the encoding of the data source doesn\'t match expectations.',
-     'patterns': [r".*: warning: \[DefaultCharset\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Avoid deprecated Thread methods; read the method\'s javadoc for details.',
-     'patterns': [r".*: warning: \[DeprecatedThreadMethods\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Prefer collection factory methods or builders to the double-brace initialization pattern.',
-     'patterns': [r".*: warning: \[DoubleBraceInitialization\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Double-checked locking on non-volatile fields is unsafe',
-     'patterns': [r".*: warning: \[DoubleCheckedLocking\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Empty top-level type declaration',
-     'patterns': [r".*: warning: \[EmptyTopLevelDeclaration\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: equals() implementation may throw NullPointerException when given null',
-     'patterns': [r".*: warning: \[EqualsBrokenForNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Overriding Object#equals in a non-final class by using getClass rather than instanceof breaks substitutability of subclasses.',
-     'patterns': [r".*: warning: \[EqualsGetClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Classes that override equals should also override hashCode.',
-     'patterns': [r".*: warning: \[EqualsHashCode\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: An equality test between objects with incompatible types always returns false',
-     'patterns': [r".*: warning: \[EqualsIncompatibleType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: The contract of #equals states that it should return false for incompatible types, while this implementation may throw ClassCastException.',
-     'patterns': [r".*: warning: \[EqualsUnsafeCast\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Implementing #equals by just comparing hashCodes is fragile. Hashes collide frequently, and this will lead to false positives in #equals.',
-     'patterns': [r".*: warning: \[EqualsUsingHashCode\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Calls to ExpectedException#expect should always be followed by exactly one statement.',
-     'patterns': [r".*: warning: \[ExpectedExceptionChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: When only using JUnit Assert\'s static methods, you should import statically instead of extending.',
-     'patterns': [r".*: warning: \[ExtendingJUnitAssert\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Switch case may fall through',
-     'patterns': [r".*: warning: \[FallThrough\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: If you return or throw from a finally, then values returned or thrown from the try-catch block will be ignored. Consider using try-with-resources instead.',
-     'patterns': [r".*: warning: \[Finally\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Use parentheses to make the precedence explicit',
-     'patterns': [r".*: warning: \[FloatCast\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This fuzzy equality check is using a tolerance less than the gap to the next number. You may want a less restrictive tolerance, or to assert equality.',
-     'patterns': [r".*: warning: \[FloatingPointAssertionWithinEpsilon\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Floating point literal loses precision',
-     'patterns': [r".*: warning: \[FloatingPointLiteralPrecision\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Classes extending PreferenceActivity must implement isValidFragment such that it does not unconditionally return true to prevent vulnerability to fragment injection attacks.',
-     'patterns': [r".*: warning: \[FragmentInjection\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Subclasses of Fragment must be instantiable via Class#newInstance(): the class must be public, static and have a public nullary constructor',
-     'patterns': [r".*: warning: \[FragmentNotInstantiable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Overloads will be ambiguous when passing lambda arguments',
-     'patterns': [r".*: warning: \[FunctionalInterfaceClash\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Return value of methods returning Future must be checked. Ignoring returned Futures suppresses exceptions thrown from the code that completes the Future.',
-     'patterns': [r".*: warning: \[FutureReturnValueIgnored\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Calling getClass() on an enum may return a subclass of the enum type',
-     'patterns': [r".*: warning: \[GetClassOnEnum\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Hardcoded reference to /sdcard',
-     'patterns': [r".*: warning: \[HardCodedSdCardPath\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Hiding fields of superclasses may cause confusion and errors',
-     'patterns': [r".*: warning: \[HidingField\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Annotations should always be immutable',
-     'patterns': [r".*: warning: \[ImmutableAnnotationChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Enums should always be immutable',
-     'patterns': [r".*: warning: \[ImmutableEnumChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This annotation has incompatible modifiers as specified by its @IncompatibleModifiers annotation',
-     'patterns': [r".*: warning: \[IncompatibleModifiers\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: It is confusing to have a field and a parameter under the same scope that differ only in capitalization.',
-     'patterns': [r".*: warning: \[InconsistentCapitalization\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Including fields in hashCode which are not compared in equals violates the contract of hashCode.',
-     'patterns': [r".*: warning: \[InconsistentHashCode\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: The ordering of parameters in overloaded methods should be as consistent as possible (when viewed from left to right)',
-     'patterns': [r".*: warning: \[InconsistentOverloads\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This for loop increments the same variable in the header and in the body',
-     'patterns': [r".*: warning: \[IncrementInForLoopAndHeader\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Constructors on abstract classes are never directly @Injected, only the constructors of their subclasses can be @Inject\'ed.',
-     'patterns': [r".*: warning: \[InjectOnConstructorOfAbstractClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Please also override int read(byte[], int, int), otherwise multi-byte reads from this input stream are likely to be slow.',
-     'patterns': [r".*: warning: \[InputStreamSlowMultibyteRead\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Casting inside an if block should be plausibly consistent with the instanceof type',
-     'patterns': [r".*: warning: \[InstanceOfAndCastMatchWrongType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Expression of type int may overflow before being assigned to a long',
-     'patterns': [r".*: warning: \[IntLongMath\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This @param tag doesn\'t refer to a parameter of the method.',
-     'patterns': [r".*: warning: \[InvalidParam\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This tag is invalid.',
-     'patterns': [r".*: warning: \[InvalidTag\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: The documented method doesn\'t actually throw this checked exception.',
-     'patterns': [r".*: warning: \[InvalidThrows\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Class should not implement both `Iterable` and `Iterator`',
-     'patterns': [r".*: warning: \[IterableAndIterator\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Floating-point comparison without error tolerance',
-     'patterns': [r".*: warning: \[JUnit3FloatingPointComparisonWithoutDelta\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Some JUnit4 construct cannot be used in a JUnit3 context. Convert your class to JUnit4 style to use them.',
-     'patterns': [r".*: warning: \[JUnit4ClassUsedInJUnit3\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Test class inherits from JUnit 3\'s TestCase but has JUnit 4 @Test annotations.',
-     'patterns': [r".*: warning: \[JUnitAmbiguousTestClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Never reuse class names from java.lang',
-     'patterns': [r".*: warning: \[JavaLangClash\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Suggests alternatives to obsolete JDK classes.',
-     'patterns': [r".*: warning: \[JdkObsolete\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Calls to Lock#lock should be immediately followed by a try block which releases the lock.',
-     'patterns': [r".*: warning: \[LockNotBeforeTry\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Assignment where a boolean expression was expected; use == if this assignment wasn\'t expected or add parentheses for clarity.',
-     'patterns': [r".*: warning: \[LogicalAssignment\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Math.abs does not always give a positive result. Please consider other methods for positive random numbers.',
-     'patterns': [r".*: warning: \[MathAbsoluteRandom\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Switches on enum types should either handle all values, or have a default case.',
-     'patterns': [r".*: warning: \[MissingCasesInEnumSwitch\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: The Google Java Style Guide requires that each switch statement includes a default statement group, even if it contains no code. (This requirement is lifted for any switch statement that covers all values of an enum.)',
-     'patterns': [r".*: warning: \[MissingDefault\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Not calling fail() when expecting an exception masks bugs',
-     'patterns': [r".*: warning: \[MissingFail\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: method overrides method in supertype; expected @Override',
-     'patterns': [r".*: warning: \[MissingOverride\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: A collection or proto builder was created, but its values were never accessed.',
-     'patterns': [r".*: warning: \[ModifiedButNotUsed\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Modifying a collection while iterating over it in a loop may cause a ConcurrentModificationException to be thrown.',
-     'patterns': [r".*: warning: \[ModifyCollectionInEnhancedForLoop\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Multiple calls to either parallel or sequential are unnecessary and cause confusion.',
-     'patterns': [r".*: warning: \[MultipleParallelOrSequentialCalls\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Constant field declarations should use the immutable type (such as ImmutableList) instead of the general collection interface type (such as List)',
-     'patterns': [r".*: warning: \[MutableConstantField\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Method return type should use the immutable type (such as ImmutableList) instead of the general collection interface type (such as List)',
-     'patterns': [r".*: warning: \[MutableMethodReturnType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Compound assignments may hide dangerous casts',
-     'patterns': [r".*: warning: \[NarrowingCompoundAssignment\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Nested instanceOf conditions of disjoint types create blocks of code that never execute',
-     'patterns': [r".*: warning: \[NestedInstanceOfConditions\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Instead of returning a functional type, return the actual type that the returned function would return and use lambdas at use site.',
-     'patterns': [r".*: warning: \[NoFunctionalReturnType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This update of a volatile variable is non-atomic',
-     'patterns': [r".*: warning: \[NonAtomicVolatileUpdate\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Static import of member uses non-canonical name',
-     'patterns': [r".*: warning: \[NonCanonicalStaticMemberImport\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: equals method doesn\'t override Object.equals',
-     'patterns': [r".*: warning: \[NonOverridingEquals\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Constructors should not be annotated with @Nullable since they cannot return null',
-     'patterns': [r".*: warning: \[NullableConstructor\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Dereference of possibly-null value',
-     'patterns': [r".*: warning: \[NullableDereference\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: @Nullable should not be used for primitive types since they cannot be null',
-     'patterns': [r".*: warning: \[NullablePrimitive\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: void-returning methods should not be annotated with @Nullable, since they cannot return null',
-     'patterns': [r".*: warning: \[NullableVoid\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Calling toString on Objects that don\'t override toString() doesn\'t provide useful information',
-     'patterns': [r".*: warning: \[ObjectToString\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Objects.hashCode(Object o) should not be passed a primitive value',
-     'patterns': [r".*: warning: \[ObjectsHashCodePrimitive\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Use grouping parenthesis to make the operator precedence explicit',
-     'patterns': [r".*: warning: \[OperatorPrecedence\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: One should not call optional.get() inside an if statement that checks !optional.isPresent',
-     'patterns': [r".*: warning: \[OptionalNotPresent\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: String literal contains format specifiers, but is not passed to a format method',
-     'patterns': [r".*: warning: \[OrphanedFormatString\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: To return a custom message with a Throwable class, one should override getMessage() instead of toString() for Throwable.',
-     'patterns': [r".*: warning: \[OverrideThrowableToString\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Varargs doesn\'t agree for overridden method',
-     'patterns': [r".*: warning: \[Overrides\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This method is not annotated with @Inject, but it overrides a method that is annotated with @com.google.inject.Inject. Guice will inject this method, and it is recommended to annotate it explicitly.',
-     'patterns': [r".*: warning: \[OverridesGuiceInjectableMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Detects `/* name= */`-style comments on actual parameters where the name doesn\'t match the formal parameter',
-     'patterns': [r".*: warning: \[ParameterName\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Preconditions only accepts the %s placeholder in error message strings',
-     'patterns': [r".*: warning: \[PreconditionsInvalidPlaceholder\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Passing a primitive array to a varargs method is usually wrong',
-     'patterns': [r".*: warning: \[PrimitiveArrayPassedToVarargsMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: A field on a protocol buffer was set twice in the same chained expression.',
-     'patterns': [r".*: warning: \[ProtoRedundantSet\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Protos should not be used as a key to a map, in a set, or in a contains method on a descendant of a collection. Protos have non deterministic ordering and proto equality is deep, which is a performance issue.',
-     'patterns': [r".*: warning: \[ProtosAsKeyOfSetOrMap\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: BugChecker has incorrect ProvidesFix tag, please update',
-     'patterns': [r".*: warning: \[ProvidesFix\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Qualifiers/Scope annotations on @Inject methods don\'t have any effect. Move the qualifier annotation to the binding location.',
-     'patterns': [r".*: warning: \[QualifierOrScopeOnInjectMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Injection frameworks currently don\'t understand Qualifiers in TYPE_PARAMETER or TYPE_USE contexts.',
-     'patterns': [r".*: warning: \[QualifierWithTypeUse\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: reachabilityFence should always be called inside a finally block',
-     'patterns': [r".*: warning: \[ReachabilityFenceUsage\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Thrown exception is a subtype of another',
-     'patterns': [r".*: warning: \[RedundantThrows\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Comparison using reference equality instead of value equality',
-     'patterns': [r".*: warning: \[ReferenceEquality\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This annotation is missing required modifiers as specified by its @RequiredModifiers annotation',
-     'patterns': [r".*: warning: \[RequiredModifiers\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Void methods should not have a @return tag.',
-     'patterns': [r".*: warning: \[ReturnFromVoid\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         u'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.',
-     'patterns': [r".*: warning: \[ShortCircuitBoolean\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Writes to static fields should not be guarded by instance locks',
-     'patterns': [r".*: warning: \[StaticGuardedByInstance\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: A static variable or method should be qualified with a class name, not expression',
-     'patterns': [r".*: warning: \[StaticQualifiedUsingExpression\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Streams that encapsulate a closeable resource should be closed using try-with-resources',
-     'patterns': [r".*: warning: \[StreamResourceLeak\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: String comparison using reference equality instead of value equality',
-     'patterns': [r".*: warning: \[StringEquality\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: String.split(String) has surprising behavior',
-     'patterns': [r".*: warning: \[StringSplitter\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: SWIG generated code that can\'t call a C++ destructor will leak memory',
-     'patterns': [r".*: warning: \[SwigMemoryLeak\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Synchronizing on non-final fields is not safe: if the field is ever updated, different threads may end up locking on different objects.',
-     'patterns': [r".*: warning: \[SynchronizeOnNonFinalField\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Code that contains System.exit() is untestable.',
-     'patterns': [r".*: warning: \[SystemExitOutsideMain\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Using @Test(expected=...) is discouraged, since the test will pass if *any* statement in the test method throws the expected exception',
-     'patterns': [r".*: warning: \[TestExceptionChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Thread.join needs to be surrounded by a loop until it succeeds, as in Uninterruptibles.joinUninterruptibly.',
-     'patterns': [r".*: warning: \[ThreadJoinLoop\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: ThreadLocals should be stored in static fields',
-     'patterns': [r".*: warning: \[ThreadLocalUsage\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Relying on the thread scheduler is discouraged; see Effective Java Item 72 (2nd edition) / 84 (3rd edition).',
-     'patterns': [r".*: warning: \[ThreadPriorityCheck\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Three-letter time zone identifiers are deprecated, may be ambiguous, and might not do what you intend; the full IANA time zone ID should be used instead.',
-     'patterns': [r".*: warning: \[ThreeLetterTimeZoneID\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: An implementation of Object.toString() should never return null.',
-     'patterns': [r".*: warning: \[ToStringReturnsNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: The actual and expected values appear to be swapped, which results in poor assertion failure messages. The actual value should come first.',
-     'patterns': [r".*: warning: \[TruthAssertExpected\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Truth Library assert is called on a constant.',
-     'patterns': [r".*: warning: \[TruthConstantAsserts\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Argument is not compatible with the subject\'s type.',
-     'patterns': [r".*: warning: \[TruthIncompatibleType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Type parameter declaration shadows another named type',
-     'patterns': [r".*: warning: \[TypeNameShadowing\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Type parameter declaration overrides another type parameter already declared',
-     'patterns': [r".*: warning: \[TypeParameterShadowing\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Declaring a type parameter that is only used in the return type is a misuse of generics: operations on the type parameter are unchecked, it hides unsafe casts at invocations of the method, and it interacts badly with method overload resolution.',
-     'patterns': [r".*: warning: \[TypeParameterUnusedInFormals\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Avoid hash-based containers of java.net.URL--the containers rely on equals() and hashCode(), which cause java.net.URL to make blocking internet connections.',
-     'patterns': [r".*: warning: \[URLEqualsHashCode\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Collection, Iterable, Multimap, and Queue do not have well-defined equals behavior',
-     'patterns': [r".*: warning: \[UndefinedEquals\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Switch handles all enum values: an explicit default case is unnecessary and defeats error checking for non-exhaustive switches.',
-     'patterns': [r".*: warning: \[UnnecessaryDefaultInEnumSwitch\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Unnecessary use of grouping parentheses',
-     'patterns': [r".*: warning: \[UnnecessaryParentheses\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Finalizer may run before native code finishes execution',
-     'patterns': [r".*: warning: \[UnsafeFinalization\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Prefer `asSubclass` instead of casting the result of `newInstance`, to detect classes of incorrect type before invoking their constructors.This way, if the class is of the incorrect type,it will throw an exception before invoking its constructor.',
-     'patterns': [r".*: warning: \[UnsafeReflectiveConstructionCast\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Unsynchronized method overrides a synchronized method.',
-     'patterns': [r".*: warning: \[UnsynchronizedOverridesSynchronized\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Unused.',
-     'patterns': [r".*: warning: \[Unused\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: This catch block catches an exception and re-throws another, but swallows the caught exception rather than setting it as a cause. This can make debugging harder.',
-     'patterns': [r".*: warning: \[UnusedException\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Java assert is used in test. For testing purposes Assert.* matchers should be used.',
-     'patterns': [r".*: warning: \[UseCorrectAssertInTests\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Non-constant variable missing @Var annotation',
-     'patterns': [r".*: warning: \[Var\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: variableName and type with the same name would refer to the static field instead of the class',
-     'patterns': [r".*: warning: \[VariableNameSameAsType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: Because of spurious wakeups, Object.wait() and Condition.await() must always be called in a loop',
-     'patterns': [r".*: warning: \[WaitNotInLoop\] .+"]},
-    {'category': 'java',
-     'severity': Severity.MEDIUM,
-     'description':
-         'Java: A wakelock acquired with a timeout may be released by the system before calling `release`, even after checking `isHeld()`. If so, it will throw a RuntimeException. Please wrap in a try/catch block.',
-     'patterns': [r".*: warning: \[WakelockReleasedDangerously\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: AndroidInjection.inject() should always be invoked before calling super.lifecycleMethod()',
-     'patterns': [r".*: warning: \[AndroidInjectionBeforeSuper\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Use of class, field, or method that is not compatible with legacy Android devices',
-     'patterns': [r".*: warning: \[AndroidJdkLibsChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Reference equality used to compare arrays',
-     'patterns': [r".*: warning: \[ArrayEquals\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Arrays.fill(Object[], Object) called with incompatible types.',
-     'patterns': [r".*: warning: \[ArrayFillIncompatibleType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: hashcode method on array does not hash array contents',
-     'patterns': [r".*: warning: \[ArrayHashCode\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Calling toString on an array does not provide useful information',
-     'patterns': [r".*: warning: \[ArrayToString\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Arrays.asList does not autobox primitive arrays, as one might expect.',
-     'patterns': [r".*: warning: \[ArraysAsListPrimitiveArray\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: @AssistedInject and @Inject cannot be used on the same constructor.',
-     'patterns': [r".*: warning: \[AssistedInjectAndInjectOnSameConstructor\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: AsyncCallable should not return a null Future, only a Future whose result is null.',
-     'patterns': [r".*: warning: \[AsyncCallableReturnsNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: AsyncFunction should not return a null Future, only a Future whose result is null.',
-     'patterns': [r".*: warning: \[AsyncFunctionReturnsNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: @AutoFactory and @Inject should not be used in the same type.',
-     'patterns': [r".*: warning: \[AutoFactoryAtInject\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Arguments to AutoValue constructor are in the wrong order',
-     'patterns': [r".*: warning: \[AutoValueConstructorOrderChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Shift by an amount that is out of range',
-     'patterns': [r".*: warning: \[BadShiftAmount\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Object serialized in Bundle may have been flattened to base type.',
-     'patterns': [r".*: warning: \[BundleDeserializationCast\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: The called constructor accepts a parameter with the same name and type as one of its caller\'s parameters, but its caller doesn\'t pass that parameter to it.  It\'s likely that it was intended to.',
-     'patterns': [r".*: warning: \[ChainingConstructorIgnoresParameter\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Ignored return value of method that is annotated with @CheckReturnValue',
-     'patterns': [r".*: warning: \[CheckReturnValue\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: The source file name should match the name of the top-level class it contains',
-     'patterns': [r".*: warning: \[ClassName\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Incompatible type as argument to Object-accepting Java collections method',
-     'patterns': [r".*: warning: \[CollectionIncompatibleType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         u'Java:  Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.',
-     'patterns': [r".*: warning: \[ComparableType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: this == null is always false, this != null is always true',
-     'patterns': [r".*: warning: \[ComparingThisWithNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This comparison method violates the contract',
-     'patterns': [r".*: warning: \[ComparisonContractViolated\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Comparison to value that is out of range for the compared type',
-     'patterns': [r".*: warning: \[ComparisonOutOfRange\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: @CompatibleWith\'s value is not a type argument.',
-     'patterns': [r".*: warning: \[CompatibleWithAnnotationMisuse\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Non-compile-time constant expression passed to parameter with @CompileTimeConstant type annotation.',
-     'patterns': [r".*: warning: \[CompileTimeConstant\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Non-trivial compile time constant boolean expressions shouldn\'t be used.',
-     'patterns': [r".*: warning: \[ComplexBooleanConstant\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A conditional expression with numeric operands of differing types will perform binary numeric promotion of the operands; when these operands are of reference types, the expression\'s result may not be of the expected type.',
-     'patterns': [r".*: warning: \[ConditionalExpressionNumericPromotion\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Compile-time constant expression overflows',
-     'patterns': [r".*: warning: \[ConstantOverflow\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Dagger @Provides methods may not return null unless annotated with @Nullable',
-     'patterns': [r".*: warning: \[DaggerProvidesNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Exception created but not thrown',
-     'patterns': [r".*: warning: \[DeadException\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Thread created but not started',
-     'patterns': [r".*: warning: \[DeadThread\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Deprecated item is not annotated with @Deprecated',
-     'patterns': [r".*: warning: \[DepAnn\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Division by integer literal zero',
-     'patterns': [r".*: warning: \[DivZero\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This method should not be called.',
-     'patterns': [r".*: warning: \[DoNotCall\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Empty statement after if',
-     'patterns': [r".*: warning: \[EmptyIf\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: == NaN always returns false; use the isNaN methods instead',
-     'patterns': [r".*: warning: \[EqualsNaN\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: == must be used in equals method to check equality to itself or an infinite loop will occur.',
-     'patterns': [r".*: warning: \[EqualsReference\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Comparing different pairs of fields/getters in an equals implementation is probably a mistake.',
-     'patterns': [r".*: warning: \[EqualsWrongThing\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Method annotated @ForOverride must be protected or package-private and only invoked from declaring class, or from an override of the method',
-     'patterns': [r".*: warning: \[ForOverride\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Invalid printf-style format string',
-     'patterns': [r".*: warning: \[FormatString\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Invalid format string passed to formatting method.',
-     'patterns': [r".*: warning: \[FormatStringAnnotation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Casting a lambda to this @FunctionalInterface can cause a behavior change from casting to a functional superinterface, which is surprising to users.  Prefer decorator methods to this surprising behavior.',
-     'patterns': [r".*: warning: \[FunctionalInterfaceMethodChanged\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Futures.getChecked requires a checked exception type with a standard constructor.',
-     'patterns': [r".*: warning: \[FuturesGetCheckedIllegalExceptionType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: DoubleMath.fuzzyEquals should never be used in an Object.equals() method',
-     'patterns': [r".*: warning: \[FuzzyEqualsShouldNotBeUsedInEqualsMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Calling getClass() on an annotation may return a proxy class',
-     'patterns': [r".*: warning: \[GetClassOnAnnotation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Calling getClass() on an object of type Class returns the Class object for java.lang.Class; you probably meant to operate on the object directly',
-     'patterns': [r".*: warning: \[GetClassOnClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Checks for unguarded accesses to fields and methods with @GuardedBy annotations',
-     'patterns': [r".*: warning: \[GuardedBy\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Scope annotation on implementation class of AssistedInject factory is not allowed',
-     'patterns': [r".*: warning: \[GuiceAssistedInjectScoping\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A constructor cannot have two @Assisted parameters of the same type unless they are disambiguated with named @Assisted annotations.',
-     'patterns': [r".*: warning: \[GuiceAssistedParameters\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Although Guice allows injecting final fields, doing so is disallowed because the injected value may not be visible to other threads.',
-     'patterns': [r".*: warning: \[GuiceInjectOnFinalField\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: contains() is a legacy method that is equivalent to containsValue()',
-     'patterns': [r".*: warning: \[HashtableContains\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A binary expression where both operands are the same is usually incorrect.',
-     'patterns': [r".*: warning: \[IdentityBinaryExpression\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Type declaration annotated with @Immutable is not immutable',
-     'patterns': [r".*: warning: \[Immutable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Modifying an immutable collection is guaranteed to throw an exception and leave the collection unmodified',
-     'patterns': [r".*: warning: \[ImmutableModification\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Passing argument to a generic method with an incompatible type.',
-     'patterns': [r".*: warning: \[IncompatibleArgumentType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: The first argument to indexOf is a Unicode code point, and the second is the index to start the search from',
-     'patterns': [r".*: warning: \[IndexOfChar\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Conditional expression in varargs call contains array and non-array arguments',
-     'patterns': [r".*: warning: \[InexactVarargsConditional\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This method always recurses, and will cause a StackOverflowError',
-     'patterns': [r".*: warning: \[InfiniteRecursion\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A scoping annotation\'s Target should include TYPE and METHOD.',
-     'patterns': [r".*: warning: \[InjectInvalidTargetingOnScopingAnnotation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Using more than one qualifier annotation on the same element is not allowed.',
-     'patterns': [r".*: warning: \[InjectMoreThanOneQualifier\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A class can be annotated with at most one scope annotation.',
-     'patterns': [r".*: warning: \[InjectMoreThanOneScopeAnnotationOnClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Members shouldn\'t be annotated with @Inject if constructor is already annotated @Inject',
-     'patterns': [r".*: warning: \[InjectOnMemberAndConstructor\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Scope annotation on an interface or abstact class is not allowed',
-     'patterns': [r".*: warning: \[InjectScopeAnnotationOnInterfaceOrAbstractClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Scoping and qualifier annotations must have runtime retention.',
-     'patterns': [r".*: warning: \[InjectScopeOrQualifierAnnotationRetention\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Injected constructors cannot be optional nor have binding annotations',
-     'patterns': [r".*: warning: \[InjectedConstructorAnnotations\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A standard cryptographic operation is used in a mode that is prone to vulnerabilities',
-     'patterns': [r".*: warning: \[InsecureCryptoUsage\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Invalid syntax used for a regular expression',
-     'patterns': [r".*: warning: \[InvalidPatternSyntax\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Invalid time zone identifier. TimeZone.getTimeZone(String) will silently return GMT instead of the time zone you intended.',
-     'patterns': [r".*: warning: \[InvalidTimeZoneID\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: The argument to Class#isInstance(Object) should not be a Class',
-     'patterns': [r".*: warning: \[IsInstanceOfClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Log tag too long, cannot exceed 23 characters.',
-     'patterns': [r".*: warning: \[IsLoggableTagLength\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         u'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity',
-     'patterns': [r".*: warning: \[IterablePathParameter\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: jMock tests must have a @RunWith(JMock.class) annotation, or the Mockery field must have a @Rule JUnit annotation',
-     'patterns': [r".*: warning: \[JMockTestWithoutRunWithOrRuleAnnotation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Test method will not be run; please correct method signature (Should be public, non-static, and method name should begin with "test").',
-     'patterns': [r".*: warning: \[JUnit3TestNotRun\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This method should be static',
-     'patterns': [r".*: warning: \[JUnit4ClassAnnotationNonStatic\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: setUp() method will not be run; please add JUnit\'s @Before annotation',
-     'patterns': [r".*: warning: \[JUnit4SetUpNotRun\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: tearDown() method will not be run; please add JUnit\'s @After annotation',
-     'patterns': [r".*: warning: \[JUnit4TearDownNotRun\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This looks like a test method but is not run; please add @Test and @Ignore, or, if this is a helper method, reduce its visibility.',
-     'patterns': [r".*: warning: \[JUnit4TestNotRun\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: An object is tested for reference equality to itself using JUnit library.',
-     'patterns': [r".*: warning: \[JUnitAssertSameCheck\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Use of class, field, or method that is not compatible with JDK 7',
-     'patterns': [r".*: warning: \[Java7ApiChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Abstract and default methods are not injectable with javax.inject.Inject',
-     'patterns': [r".*: warning: \[JavaxInjectOnAbstractMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: @javax.inject.Inject cannot be put on a final field.',
-     'patterns': [r".*: warning: \[JavaxInjectOnFinalField\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This pattern will silently corrupt certain byte sequences from the serialized protocol message. Use ByteString or byte[] directly',
-     'patterns': [r".*: warning: \[LiteByteStringUtf8\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This method does not acquire the locks specified by its @LockMethod annotation',
-     'patterns': [r".*: warning: \[LockMethodChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Prefer \'L\' to \'l\' for the suffix to long literals',
-     'patterns': [r".*: warning: \[LongLiteralLowerCaseSuffix\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Loop condition is never modified in loop body.',
-     'patterns': [r".*: warning: \[LoopConditionChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Math.round(Integer) results in truncation',
-     'patterns': [r".*: warning: \[MathRoundIntLong\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Certain resources in `android.R.string` have names that do not match their content',
-     'patterns': [r".*: warning: \[MislabeledAndroidString\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Overriding method is missing a call to overridden super method',
-     'patterns': [r".*: warning: \[MissingSuperCall\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A terminating method call is required for a test helper to have any effect.',
-     'patterns': [r".*: warning: \[MissingTestCall\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Use of "YYYY" (week year) in a date pattern without "ww" (week in year). You probably meant to use "yyyy" (year) instead.',
-     'patterns': [r".*: warning: \[MisusedWeekYear\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: A bug in Mockito will cause this test to fail at runtime with a ClassCastException',
-     'patterns': [r".*: warning: \[MockitoCast\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Missing method call for verify(mock) here',
-     'patterns': [r".*: warning: \[MockitoUsage\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Using a collection function with itself as the argument.',
-     'patterns': [r".*: warning: \[ModifyingCollectionWithItself\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This class has more than one @Inject-annotated constructor. Please remove the @Inject annotation from all but one of them.',
-     'patterns': [r".*: warning: \[MoreThanOneInjectableConstructor\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: The result of this method must be closed.',
-     'patterns': [r".*: warning: \[MustBeClosedChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: The first argument to nCopies is the number of copies, and the second is the item to copy',
-     'patterns': [r".*: warning: \[NCopiesOfChar\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: @NoAllocation was specified on this method, but something was found that would trigger an allocation',
-     'patterns': [r".*: warning: \[NoAllocation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Static import of type uses non-canonical name',
-     'patterns': [r".*: warning: \[NonCanonicalStaticImport\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: @CompileTimeConstant parameters should be final or effectively final',
-     'patterns': [r".*: warning: \[NonFinalCompileTimeConstant\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Calling getAnnotation on an annotation that is not retained at runtime.',
-     'patterns': [r".*: warning: \[NonRuntimeAnnotation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This conditional expression may evaluate to null, which will result in an NPE when the result is unboxed.',
-     'patterns': [r".*: warning: \[NullTernary\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Numeric comparison using reference equality instead of value equality',
-     'patterns': [r".*: warning: \[NumericEquality\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Comparison using reference equality instead of value equality',
-     'patterns': [r".*: warning: \[OptionalEquality\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Annotations cannot be both Scope annotations and Qualifier annotations: this causes confusion when trying to use them.',
-     'patterns': [r".*: warning: \[OverlappingQualifierAndScopeAnnotation\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This method is not annotated with @Inject, but it overrides a method that is  annotated with @javax.inject.Inject. The method will not be Injected.',
-     'patterns': [r".*: warning: \[OverridesJavaxInjectableMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Declaring types inside package-info.java files is very bad form',
-     'patterns': [r".*: warning: \[PackageInfo\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Method parameter has wrong package',
-     'patterns': [r".*: warning: \[ParameterPackage\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Detects classes which implement Parcelable but don\'t have CREATOR',
-     'patterns': [r".*: warning: \[ParcelableCreator\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Literal passed as first argument to Preconditions.checkNotNull() can never be null',
-     'patterns': [r".*: warning: \[PreconditionsCheckNotNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: First argument to `Preconditions.checkNotNull()` is a primitive rather than an object reference',
-     'patterns': [r".*: warning: \[PreconditionsCheckNotNullPrimitive\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Using ::equals or ::isInstance as an incompatible Predicate; the predicate will always return false',
-     'patterns': [r".*: warning: \[PredicateIncompatibleType\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Access to a private protocol buffer field is forbidden. This protocol buffer carries a security contract, and can only be created using an approved library. Direct access to the fields is forbidden.',
-     'patterns': [r".*: warning: \[PrivateSecurityContractProtoAccess\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Protobuf fields cannot be null.',
-     'patterns': [r".*: warning: \[ProtoFieldNullComparison\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Comparing protobuf fields of type String using reference equality',
-     'patterns': [r".*: warning: \[ProtoStringFieldReferenceEquality\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: To get the tag number of a protocol buffer enum, use getNumber() instead.',
-     'patterns': [r".*: warning: \[ProtocolBufferOrdinal\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: @Provides methods need to be declared in a Module to have any effect.',
-     'patterns': [r".*: warning: \[ProvidesMethodOutsideOfModule\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Casting a random number in the range [0.0, 1.0) to an integer or long always results in 0.',
-     'patterns': [r".*: warning: \[RandomCast\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Use Random.nextInt(int).  Random.nextInt() % n can have negative results',
-     'patterns': [r".*: warning: \[RandomModInteger\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Return value of android.graphics.Rect.intersect() must be checked',
-     'patterns': [r".*: warning: \[RectIntersectReturnValueIgnored\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Use of method or class annotated with @RestrictTo',
-     'patterns': [r".*: warning: \[RestrictTo\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java:  Check for non-whitelisted callers to RestrictedApiChecker.',
-     'patterns': [r".*: warning: \[RestrictedApiChecker\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Return value of this method must be used',
-     'patterns': [r".*: warning: \[ReturnValueIgnored\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Variable assigned to itself',
-     'patterns': [r".*: warning: \[SelfAssignment\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: An object is compared to itself',
-     'patterns': [r".*: warning: \[SelfComparison\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Testing an object for equality with itself will always be true.',
-     'patterns': [r".*: warning: \[SelfEquals\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This method must be called with an even number of arguments.',
-     'patterns': [r".*: warning: \[ShouldHaveEvenArgs\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Comparison of a size >= 0 is always true, did you intend to check for non-emptiness?',
-     'patterns': [r".*: warning: \[SizeGreaterThanOrEqualsZero\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Static and default interface methods are not natively supported on older Android devices. ',
-     'patterns': [r".*: warning: \[StaticOrDefaultInterfaceMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Calling toString on a Stream does not provide useful information',
-     'patterns': [r".*: warning: \[StreamToString\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: StringBuilder does not have a char constructor; this invokes the int constructor.',
-     'patterns': [r".*: warning: \[StringBuilderInitWithChar\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: String.substring(0) returns the original String',
-     'patterns': [r".*: warning: \[SubstringOfZero\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Suppressing "deprecated" is probably a typo for "deprecation"',
-     'patterns': [r".*: warning: \[SuppressWarningsDeprecated\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: throwIfUnchecked(knownCheckedException) is a no-op.',
-     'patterns': [r".*: warning: \[ThrowIfUncheckedKnownChecked\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Throwing \'null\' always results in a NullPointerException being thrown.',
-     'patterns': [r".*: warning: \[ThrowNull\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: isEqualTo should not be used to test an object for equality with itself; the assertion will never fail.',
-     'patterns': [r".*: warning: \[TruthSelfEquals\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Catching Throwable/Error masks failures from fail() or assert*() in the try block',
-     'patterns': [r".*: warning: \[TryFailThrowable\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Type parameter used as type qualifier',
-     'patterns': [r".*: warning: \[TypeParameterQualifier\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: This method does not acquire the locks specified by its @UnlockMethod annotation',
-     'patterns': [r".*: warning: \[UnlockMethod\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Non-generic methods should not be invoked with type arguments',
-     'patterns': [r".*: warning: \[UnnecessaryTypeArgument\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Instance created but never used',
-     'patterns': [r".*: warning: \[UnusedAnonymousClass\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: Collection is modified in place, but the result is not used',
-     'patterns': [r".*: warning: \[UnusedCollectionModifiedInPlace\] .+"]},
-    {'category': 'java',
-     'severity': Severity.HIGH,
-     'description':
-         'Java: `var` should not be used as a type name.',
-     'patterns': [r".*: warning: \[VarTypeName\] .+"]},
+    java_low('Use parameter comments to document ambiguous literals',
+             [r".*: warning: \[BooleanParameter\] .+"]),
+    java_low('This class\'s name looks like a Type Parameter.',
+             [r".*: warning: \[ClassNamedLikeTypeParameter\] .+"]),
+    java_low('Field name is CONSTANT_CASE, but field is not static and final',
+             [r".*: warning: \[ConstantField\] .+"]),
+    java_low('@Multibinds is a more efficient and declarative mechanism for ensuring that a set multibinding is present in the graph.',
+             [r".*: warning: \[EmptySetMultibindingContributions\] .+"]),
+    java_low('Prefer assertThrows to ExpectedException',
+             [r".*: warning: \[ExpectedExceptionRefactoring\] .+"]),
+    java_low('This field is only assigned during initialization; consider making it final',
+             [r".*: warning: \[FieldCanBeFinal\] .+"]),
+    java_low('Fields that can be null should be annotated @Nullable',
+             [r".*: warning: \[FieldMissingNullable\] .+"]),
+    java_low('Refactors uses of the JSR 305 @Immutable to Error Prone\'s annotation',
+             [r".*: warning: \[ImmutableRefactoring\] .+"]),
+    java_low(u'Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.',
+             [r".*: warning: \[LambdaFunctionalInterface\] .+"]),
+    java_low('A private method that does not reference the enclosing instance can be static',
+             [r".*: warning: \[MethodCanBeStatic\] .+"]),
+    java_low('C-style array declarations should not be used',
+             [r".*: warning: \[MixedArrayDimensions\] .+"]),
+    java_low('Variable declarations should declare only one variable',
+             [r".*: warning: \[MultiVariableDeclaration\] .+"]),
+    java_low('Source files should not contain multiple top-level class declarations',
+             [r".*: warning: \[MultipleTopLevelClasses\] .+"]),
+    java_low('Avoid having multiple unary operators acting on the same variable in a method call',
+             [r".*: warning: \[MultipleUnaryOperatorsInMethodCall\] .+"]),
+    java_low('Package names should match the directory they are declared in',
+             [r".*: warning: \[PackageLocation\] .+"]),
+    java_low('Non-standard parameter comment; prefer `/* paramName= */ arg`',
+             [r".*: warning: \[ParameterComment\] .+"]),
+    java_low('Method parameters that aren\'t checked for null shouldn\'t be annotated @Nullable',
+             [r".*: warning: \[ParameterNotNullable\] .+"]),
+    java_low('Add a private constructor to modules that will not be instantiated by Dagger.',
+             [r".*: warning: \[PrivateConstructorForNoninstantiableModule\] .+"]),
+    java_low('Utility classes (only static members) are not designed to be instantiated and should be made noninstantiable with a default constructor.',
+             [r".*: warning: \[PrivateConstructorForUtilityClass\] .+"]),
+    java_low('Unused imports',
+             [r".*: warning: \[RemoveUnusedImports\] .+"]),
+    java_low('Methods that can return null should be annotated @Nullable',
+             [r".*: warning: \[ReturnMissingNullable\] .+"]),
+    java_low('Scopes on modules have no function and will soon be an error.',
+             [r".*: warning: \[ScopeOnModule\] .+"]),
+    java_low('The default case of a switch should appear at the end of the last statement group',
+             [r".*: warning: \[SwitchDefault\] .+"]),
+    java_low('Prefer assertThrows to @Test(expected=...)',
+             [r".*: warning: \[TestExceptionRefactoring\] .+"]),
+    java_low('Unchecked exceptions do not need to be declared in the method signature.',
+             [r".*: warning: \[ThrowsUncheckedException\] .+"]),
+    java_low('Prefer assertThrows to try/fail',
+             [r".*: warning: \[TryFailRefactoring\] .+"]),
+    java_low('Type parameters must be a single letter with an optional numeric suffix, or an UpperCamelCase name followed by the letter \'T\'.',
+             [r".*: warning: \[TypeParameterNaming\] .+"]),
+    java_low('Constructors and methods with the same name should appear sequentially with no other code in between. Please re-order or re-name methods.',
+             [r".*: warning: \[UngroupedOverloads\] .+"]),
+    java_low('Unnecessary call to NullPointerTester#setDefault',
+             [r".*: warning: \[UnnecessarySetDefault\] .+"]),
+    java_low('Using static imports for types is unnecessary',
+             [r".*: warning: \[UnnecessaryStaticImport\] .+"]),
+    java_low('@Binds is a more efficient and declarative mechanism for delegating a binding.',
+             [r".*: warning: \[UseBinds\] .+"]),
+    java_low('Wildcard imports, static or otherwise, should not be used',
+             [r".*: warning: \[WildcardImport\] .+"]),
+    java_medium('Method reference is ambiguous',
+                [r".*: warning: \[AmbiguousMethodReference\] .+"]),
+    java_medium('This method passes a pair of parameters through to String.format, but the enclosing method wasn\'t annotated @FormatMethod. Doing so gives compile-time rather than run-time protection against malformed format strings.',
+                [r".*: warning: \[AnnotateFormatMethod\] .+"]),
+    java_medium('Annotations should be positioned after Javadocs, but before modifiers..',
+                [r".*: warning: \[AnnotationPosition\] .+"]),
+    java_medium('Arguments are in the wrong order or could be commented for clarity.',
+                [r".*: warning: \[ArgumentSelectionDefectChecker\] .+"]),
+    java_medium('Arrays do not override equals() or hashCode, so comparisons will be done on reference equality only. If neither deduplication nor lookup are needed, consider using a List instead. Otherwise, use IdentityHashMap/Set, a Map from a library that handles object arrays, or an Iterable/List of pairs.',
+                [r".*: warning: \[ArrayAsKeyOfSetOrMap\] .+"]),
+    java_medium('Arguments are swapped in assertEquals-like call',
+                [r".*: warning: \[AssertEqualsArgumentOrderChecker\] .+"]),
+    java_medium('Assertions may be disabled at runtime and do not guarantee that execution will halt here; consider throwing an exception instead',
+                [r".*: warning: \[AssertFalse\] .+"]),
+    java_medium('The lambda passed to assertThrows should contain exactly one statement',
+                [r".*: warning: \[AssertThrowsMultipleStatements\] .+"]),
+    java_medium('This assertion throws an AssertionError if it fails, which will be caught by an enclosing try block.',
+                [r".*: warning: \[AssertionFailureIgnored\] .+"]),
+    java_medium('@AssistedInject and @Inject should not be used on different constructors in the same class.',
+                [r".*: warning: \[AssistedInjectAndInjectOnConstructors\] .+"]),
+    java_medium('Make toString(), hashCode() and equals() final in AutoValue classes, so it is clear to readers that AutoValue is not overriding them',
+                [r".*: warning: \[AutoValueFinalMethods\] .+"]),
+    java_medium('Classes that implement Annotation must override equals and hashCode. Consider using AutoAnnotation instead of implementing Annotation by hand.',
+                [r".*: warning: \[BadAnnotationImplementation\] .+"]),
+    java_medium('Possible sign flip from narrowing conversion',
+                [r".*: warning: \[BadComparable\] .+"]),
+    java_medium('Importing nested classes/static methods/static fields with commonly-used names can make code harder to read, because it may not be clear from the context exactly which type is being referred to. Qualifying the name with that of the containing class can make the code clearer.',
+                [r".*: warning: \[BadImport\] .+"]),
+    java_medium('instanceof used in a way that is equivalent to a null check.',
+                [r".*: warning: \[BadInstanceof\] .+"]),
+    java_medium('BigDecimal#equals has surprising behavior: it also compares scale.',
+                [r".*: warning: \[BigDecimalEquals\] .+"]),
+    java_medium('new BigDecimal(double) loses precision in this case.',
+                [r".*: warning: \[BigDecimalLiteralDouble\] .+"]),
+    java_medium('A call to Binder.clearCallingIdentity() should be followed by Binder.restoreCallingIdentity() in a finally block. Otherwise the wrong Binder identity may be used by subsequent code.',
+                [r".*: warning: \[BinderIdentityRestoredDangerously\] .+"]),
+    java_medium('This code declares a binding for a common value type without a Qualifier annotation.',
+                [r".*: warning: \[BindingToUnqualifiedCommonType\] .+"]),
+    java_medium('valueOf or autoboxing provides better time and space performance',
+                [r".*: warning: \[BoxedPrimitiveConstructor\] .+"]),
+    java_medium('ByteBuffer.array() shouldn\'t be called unless ByteBuffer.arrayOffset() is used or if the ByteBuffer was initialized using ByteBuffer.wrap() or ByteBuffer.allocate().',
+                [r".*: warning: \[ByteBufferBackingArray\] .+"]),
+    java_medium('Mockito cannot mock final classes',
+                [r".*: warning: \[CannotMockFinalClass\] .+"]),
+    java_medium('Duration can be expressed more clearly with different units',
+                [r".*: warning: \[CanonicalDuration\] .+"]),
+    java_medium('Logging or rethrowing exceptions should usually be preferred to catching and calling printStackTrace',
+                [r".*: warning: \[CatchAndPrintStackTrace\] .+"]),
+    java_medium('Ignoring exceptions and calling fail() is unnecessary, and makes test output less useful',
+                [r".*: warning: \[CatchFail\] .+"]),
+    java_medium('Inner class is non-static but does not reference enclosing class',
+                [r".*: warning: \[ClassCanBeStatic\] .+"]),
+    java_medium('Class.newInstance() bypasses exception checking; prefer getDeclaredConstructor().newInstance()',
+                [r".*: warning: \[ClassNewInstance\] .+"]),
+    java_medium('Providing Closeable resources makes their lifecycle unclear',
+                [r".*: warning: \[CloseableProvides\] .+"]),
+    java_medium('The type of the array parameter of Collection.toArray needs to be compatible with the array type',
+                [r".*: warning: \[CollectionToArraySafeParameter\] .+"]),
+    java_medium('Collector.of() should not use state',
+                [r".*: warning: \[CollectorShouldNotUseState\] .+"]),
+    java_medium('Class should not implement both `Comparable` and `Comparator`',
+                [r".*: warning: \[ComparableAndComparator\] .+"]),
+    java_medium('Constructors should not invoke overridable methods.',
+                [r".*: warning: \[ConstructorInvokesOverridable\] .+"]),
+    java_medium('Constructors should not pass the \'this\' reference out in method invocations, since the object may not be fully constructed.',
+                [r".*: warning: \[ConstructorLeaksThis\] .+"]),
+    java_medium('DateFormat is not thread-safe, and should not be used as a constant field.',
+                [r".*: warning: \[DateFormatConstant\] .+"]),
+    java_medium('Implicit use of the platform default charset, which can result in differing behaviour between JVM executions or incorrect behavior if the encoding of the data source doesn\'t match expectations.',
+                [r".*: warning: \[DefaultCharset\] .+"]),
+    java_medium('Avoid deprecated Thread methods; read the method\'s javadoc for details.',
+                [r".*: warning: \[DeprecatedThreadMethods\] .+"]),
+    java_medium('Prefer collection factory methods or builders to the double-brace initialization pattern.',
+                [r".*: warning: \[DoubleBraceInitialization\] .+"]),
+    java_medium('Double-checked locking on non-volatile fields is unsafe',
+                [r".*: warning: \[DoubleCheckedLocking\] .+"]),
+    java_medium('Empty top-level type declaration',
+                [r".*: warning: \[EmptyTopLevelDeclaration\] .+"]),
+    java_medium('equals() implementation may throw NullPointerException when given null',
+                [r".*: warning: \[EqualsBrokenForNull\] .+"]),
+    java_medium('Overriding Object#equals in a non-final class by using getClass rather than instanceof breaks substitutability of subclasses.',
+                [r".*: warning: \[EqualsGetClass\] .+"]),
+    java_medium('Classes that override equals should also override hashCode.',
+                [r".*: warning: \[EqualsHashCode\] .+"]),
+    java_medium('An equality test between objects with incompatible types always returns false',
+                [r".*: warning: \[EqualsIncompatibleType\] .+"]),
+    java_medium('The contract of #equals states that it should return false for incompatible types, while this implementation may throw ClassCastException.',
+                [r".*: warning: \[EqualsUnsafeCast\] .+"]),
+    java_medium('Implementing #equals by just comparing hashCodes is fragile. Hashes collide frequently, and this will lead to false positives in #equals.',
+                [r".*: warning: \[EqualsUsingHashCode\] .+"]),
+    java_medium('Calls to ExpectedException#expect should always be followed by exactly one statement.',
+                [r".*: warning: \[ExpectedExceptionChecker\] .+"]),
+    java_medium('When only using JUnit Assert\'s static methods, you should import statically instead of extending.',
+                [r".*: warning: \[ExtendingJUnitAssert\] .+"]),
+    java_medium('Switch case may fall through',
+                [r".*: warning: \[FallThrough\] .+"]),
+    java_medium('If you return or throw from a finally, then values returned or thrown from the try-catch block will be ignored. Consider using try-with-resources instead.',
+                [r".*: warning: \[Finally\] .+"]),
+    java_medium('Use parentheses to make the precedence explicit',
+                [r".*: warning: \[FloatCast\] .+"]),
+    java_medium('This fuzzy equality check is using a tolerance less than the gap to the next number. You may want a less restrictive tolerance, or to assert equality.',
+                [r".*: warning: \[FloatingPointAssertionWithinEpsilon\] .+"]),
+    java_medium('Floating point literal loses precision',
+                [r".*: warning: \[FloatingPointLiteralPrecision\] .+"]),
+    java_medium('Classes extending PreferenceActivity must implement isValidFragment such that it does not unconditionally return true to prevent vulnerability to fragment injection attacks.',
+                [r".*: warning: \[FragmentInjection\] .+"]),
+    java_medium('Subclasses of Fragment must be instantiable via Class#newInstance(): the class must be public, static and have a public nullary constructor',
+                [r".*: warning: \[FragmentNotInstantiable\] .+"]),
+    java_medium('Overloads will be ambiguous when passing lambda arguments',
+                [r".*: warning: \[FunctionalInterfaceClash\] .+"]),
+    java_medium('Return value of methods returning Future must be checked. Ignoring returned Futures suppresses exceptions thrown from the code that completes the Future.',
+                [r".*: warning: \[FutureReturnValueIgnored\] .+"]),
+    java_medium('Calling getClass() on an enum may return a subclass of the enum type',
+                [r".*: warning: \[GetClassOnEnum\] .+"]),
+    java_medium('Hardcoded reference to /sdcard',
+                [r".*: warning: \[HardCodedSdCardPath\] .+"]),
+    java_medium('Hiding fields of superclasses may cause confusion and errors',
+                [r".*: warning: \[HidingField\] .+"]),
+    java_medium('Annotations should always be immutable',
+                [r".*: warning: \[ImmutableAnnotationChecker\] .+"]),
+    java_medium('Enums should always be immutable',
+                [r".*: warning: \[ImmutableEnumChecker\] .+"]),
+    java_medium('This annotation has incompatible modifiers as specified by its @IncompatibleModifiers annotation',
+                [r".*: warning: \[IncompatibleModifiers\] .+"]),
+    java_medium('It is confusing to have a field and a parameter under the same scope that differ only in capitalization.',
+                [r".*: warning: \[InconsistentCapitalization\] .+"]),
+    java_medium('Including fields in hashCode which are not compared in equals violates the contract of hashCode.',
+                [r".*: warning: \[InconsistentHashCode\] .+"]),
+    java_medium('The ordering of parameters in overloaded methods should be as consistent as possible (when viewed from left to right)',
+                [r".*: warning: \[InconsistentOverloads\] .+"]),
+    java_medium('This for loop increments the same variable in the header and in the body',
+                [r".*: warning: \[IncrementInForLoopAndHeader\] .+"]),
+    java_medium('Constructors on abstract classes are never directly @Injected, only the constructors of their subclasses can be @Inject\'ed.',
+                [r".*: warning: \[InjectOnConstructorOfAbstractClass\] .+"]),
+    java_medium('Please also override int read(byte[], int, int), otherwise multi-byte reads from this input stream are likely to be slow.',
+                [r".*: warning: \[InputStreamSlowMultibyteRead\] .+"]),
+    java_medium('Casting inside an if block should be plausibly consistent with the instanceof type',
+                [r".*: warning: \[InstanceOfAndCastMatchWrongType\] .+"]),
+    java_medium('Expression of type int may overflow before being assigned to a long',
+                [r".*: warning: \[IntLongMath\] .+"]),
+    java_medium('This @param tag doesn\'t refer to a parameter of the method.',
+                [r".*: warning: \[InvalidParam\] .+"]),
+    java_medium('This tag is invalid.',
+                [r".*: warning: \[InvalidTag\] .+"]),
+    java_medium('The documented method doesn\'t actually throw this checked exception.',
+                [r".*: warning: \[InvalidThrows\] .+"]),
+    java_medium('Class should not implement both `Iterable` and `Iterator`',
+                [r".*: warning: \[IterableAndIterator\] .+"]),
+    java_medium('Floating-point comparison without error tolerance',
+                [r".*: warning: \[JUnit3FloatingPointComparisonWithoutDelta\] .+"]),
+    java_medium('Some JUnit4 construct cannot be used in a JUnit3 context. Convert your class to JUnit4 style to use them.',
+                [r".*: warning: \[JUnit4ClassUsedInJUnit3\] .+"]),
+    java_medium('Test class inherits from JUnit 3\'s TestCase but has JUnit 4 @Test annotations.',
+                [r".*: warning: \[JUnitAmbiguousTestClass\] .+"]),
+    java_medium('Never reuse class names from java.lang',
+                [r".*: warning: \[JavaLangClash\] .+"]),
+    java_medium('Suggests alternatives to obsolete JDK classes.',
+                [r".*: warning: \[JdkObsolete\] .+"]),
+    java_medium('Calls to Lock#lock should be immediately followed by a try block which releases the lock.',
+                [r".*: warning: \[LockNotBeforeTry\] .+"]),
+    java_medium('Assignment where a boolean expression was expected; use == if this assignment wasn\'t expected or add parentheses for clarity.',
+                [r".*: warning: \[LogicalAssignment\] .+"]),
+    java_medium('Math.abs does not always give a positive result. Please consider other methods for positive random numbers.',
+                [r".*: warning: \[MathAbsoluteRandom\] .+"]),
+    java_medium('Switches on enum types should either handle all values, or have a default case.',
+                [r".*: warning: \[MissingCasesInEnumSwitch\] .+"]),
+    java_medium('The Google Java Style Guide requires that each switch statement includes a default statement group, even if it contains no code. (This requirement is lifted for any switch statement that covers all values of an enum.)',
+                [r".*: warning: \[MissingDefault\] .+"]),
+    java_medium('Not calling fail() when expecting an exception masks bugs',
+                [r".*: warning: \[MissingFail\] .+"]),
+    java_medium('method overrides method in supertype; expected @Override',
+                [r".*: warning: \[MissingOverride\] .+"]),
+    java_medium('A collection or proto builder was created, but its values were never accessed.',
+                [r".*: warning: \[ModifiedButNotUsed\] .+"]),
+    java_medium('Modifying a collection while iterating over it in a loop may cause a ConcurrentModificationException to be thrown.',
+                [r".*: warning: \[ModifyCollectionInEnhancedForLoop\] .+"]),
+    java_medium('Multiple calls to either parallel or sequential are unnecessary and cause confusion.',
+                [r".*: warning: \[MultipleParallelOrSequentialCalls\] .+"]),
+    java_medium('Constant field declarations should use the immutable type (such as ImmutableList) instead of the general collection interface type (such as List)',
+                [r".*: warning: \[MutableConstantField\] .+"]),
+    java_medium('Method return type should use the immutable type (such as ImmutableList) instead of the general collection interface type (such as List)',
+                [r".*: warning: \[MutableMethodReturnType\] .+"]),
+    java_medium('Compound assignments may hide dangerous casts',
+                [r".*: warning: \[NarrowingCompoundAssignment\] .+"]),
+    java_medium('Nested instanceOf conditions of disjoint types create blocks of code that never execute',
+                [r".*: warning: \[NestedInstanceOfConditions\] .+"]),
+    java_medium('Instead of returning a functional type, return the actual type that the returned function would return and use lambdas at use site.',
+                [r".*: warning: \[NoFunctionalReturnType\] .+"]),
+    java_medium('This update of a volatile variable is non-atomic',
+                [r".*: warning: \[NonAtomicVolatileUpdate\] .+"]),
+    java_medium('Static import of member uses non-canonical name',
+                [r".*: warning: \[NonCanonicalStaticMemberImport\] .+"]),
+    java_medium('equals method doesn\'t override Object.equals',
+                [r".*: warning: \[NonOverridingEquals\] .+"]),
+    java_medium('Constructors should not be annotated with @Nullable since they cannot return null',
+                [r".*: warning: \[NullableConstructor\] .+"]),
+    java_medium('Dereference of possibly-null value',
+                [r".*: warning: \[NullableDereference\] .+"]),
+    java_medium('@Nullable should not be used for primitive types since they cannot be null',
+                [r".*: warning: \[NullablePrimitive\] .+"]),
+    java_medium('void-returning methods should not be annotated with @Nullable, since they cannot return null',
+                [r".*: warning: \[NullableVoid\] .+"]),
+    java_medium('Calling toString on Objects that don\'t override toString() doesn\'t provide useful information',
+                [r".*: warning: \[ObjectToString\] .+"]),
+    java_medium('Objects.hashCode(Object o) should not be passed a primitive value',
+                [r".*: warning: \[ObjectsHashCodePrimitive\] .+"]),
+    java_medium('Use grouping parenthesis to make the operator precedence explicit',
+                [r".*: warning: \[OperatorPrecedence\] .+"]),
+    java_medium('One should not call optional.get() inside an if statement that checks !optional.isPresent',
+                [r".*: warning: \[OptionalNotPresent\] .+"]),
+    java_medium('String literal contains format specifiers, but is not passed to a format method',
+                [r".*: warning: \[OrphanedFormatString\] .+"]),
+    java_medium('To return a custom message with a Throwable class, one should override getMessage() instead of toString() for Throwable.',
+                [r".*: warning: \[OverrideThrowableToString\] .+"]),
+    java_medium('Varargs doesn\'t agree for overridden method',
+                [r".*: warning: \[Overrides\] .+"]),
+    java_medium('This method is not annotated with @Inject, but it overrides a method that is annotated with @com.google.inject.Inject. Guice will inject this method, and it is recommended to annotate it explicitly.',
+                [r".*: warning: \[OverridesGuiceInjectableMethod\] .+"]),
+    java_medium('Detects `/* name= */`-style comments on actual parameters where the name doesn\'t match the formal parameter',
+                [r".*: warning: \[ParameterName\] .+"]),
+    java_medium('Preconditions only accepts the %s placeholder in error message strings',
+                [r".*: warning: \[PreconditionsInvalidPlaceholder\] .+"]),
+    java_medium('Passing a primitive array to a varargs method is usually wrong',
+                [r".*: warning: \[PrimitiveArrayPassedToVarargsMethod\] .+"]),
+    java_medium('A field on a protocol buffer was set twice in the same chained expression.',
+                [r".*: warning: \[ProtoRedundantSet\] .+"]),
+    java_medium('Protos should not be used as a key to a map, in a set, or in a contains method on a descendant of a collection. Protos have non deterministic ordering and proto equality is deep, which is a performance issue.',
+                [r".*: warning: \[ProtosAsKeyOfSetOrMap\] .+"]),
+    java_medium('BugChecker has incorrect ProvidesFix tag, please update',
+                [r".*: warning: \[ProvidesFix\] .+"]),
+    java_medium('Qualifiers/Scope annotations on @Inject methods don\'t have any effect. Move the qualifier annotation to the binding location.',
+                [r".*: warning: \[QualifierOrScopeOnInjectMethod\] .+"]),
+    java_medium('Injection frameworks currently don\'t understand Qualifiers in TYPE_PARAMETER or TYPE_USE contexts.',
+                [r".*: warning: \[QualifierWithTypeUse\] .+"]),
+    java_medium('reachabilityFence should always be called inside a finally block',
+                [r".*: warning: \[ReachabilityFenceUsage\] .+"]),
+    java_medium('Thrown exception is a subtype of another',
+                [r".*: warning: \[RedundantThrows\] .+"]),
+    java_medium('Comparison using reference equality instead of value equality',
+                [r".*: warning: \[ReferenceEquality\] .+"]),
+    java_medium('This annotation is missing required modifiers as specified by its @RequiredModifiers annotation',
+                [r".*: warning: \[RequiredModifiers\] .+"]),
+    java_medium('Void methods should not have a @return tag.',
+                [r".*: warning: \[ReturnFromVoid\] .+"]),
+    java_medium(u'Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.',
+                [r".*: warning: \[ShortCircuitBoolean\] .+"]),
+    java_medium('Writes to static fields should not be guarded by instance locks',
+                [r".*: warning: \[StaticGuardedByInstance\] .+"]),
+    java_medium('A static variable or method should be qualified with a class name, not expression',
+                [r".*: warning: \[StaticQualifiedUsingExpression\] .+"]),
+    java_medium('Streams that encapsulate a closeable resource should be closed using try-with-resources',
+                [r".*: warning: \[StreamResourceLeak\] .+"]),
+    java_medium('String comparison using reference equality instead of value equality',
+                [r".*: warning: \[StringEquality\] .+"]),
+    java_medium('String.split(String) has surprising behavior',
+                [r".*: warning: \[StringSplitter\] .+"]),
+    java_medium('SWIG generated code that can\'t call a C++ destructor will leak memory',
+                [r".*: warning: \[SwigMemoryLeak\] .+"]),
+    java_medium('Synchronizing on non-final fields is not safe: if the field is ever updated, different threads may end up locking on different objects.',
+                [r".*: warning: \[SynchronizeOnNonFinalField\] .+"]),
+    java_medium('Code that contains System.exit() is untestable.',
+                [r".*: warning: \[SystemExitOutsideMain\] .+"]),
+    java_medium('Using @Test(expected=...) is discouraged, since the test will pass if *any* statement in the test method throws the expected exception',
+                [r".*: warning: \[TestExceptionChecker\] .+"]),
+    java_medium('Thread.join needs to be surrounded by a loop until it succeeds, as in Uninterruptibles.joinUninterruptibly.',
+                [r".*: warning: \[ThreadJoinLoop\] .+"]),
+    java_medium('ThreadLocals should be stored in static fields',
+                [r".*: warning: \[ThreadLocalUsage\] .+"]),
+    java_medium('Relying on the thread scheduler is discouraged; see Effective Java Item 72 (2nd edition) / 84 (3rd edition).',
+                [r".*: warning: \[ThreadPriorityCheck\] .+"]),
+    java_medium('Three-letter time zone identifiers are deprecated, may be ambiguous, and might not do what you intend; the full IANA time zone ID should be used instead.',
+                [r".*: warning: \[ThreeLetterTimeZoneID\] .+"]),
+    java_medium('An implementation of Object.toString() should never return null.',
+                [r".*: warning: \[ToStringReturnsNull\] .+"]),
+    java_medium('The actual and expected values appear to be swapped, which results in poor assertion failure messages. The actual value should come first.',
+                [r".*: warning: \[TruthAssertExpected\] .+"]),
+    java_medium('Truth Library assert is called on a constant.',
+                [r".*: warning: \[TruthConstantAsserts\] .+"]),
+    java_medium('Argument is not compatible with the subject\'s type.',
+                [r".*: warning: \[TruthIncompatibleType\] .+"]),
+    java_medium('Type parameter declaration shadows another named type',
+                [r".*: warning: \[TypeNameShadowing\] .+"]),
+    java_medium('Type parameter declaration overrides another type parameter already declared',
+                [r".*: warning: \[TypeParameterShadowing\] .+"]),
+    java_medium('Declaring a type parameter that is only used in the return type is a misuse of generics: operations on the type parameter are unchecked, it hides unsafe casts at invocations of the method, and it interacts badly with method overload resolution.',
+                [r".*: warning: \[TypeParameterUnusedInFormals\] .+"]),
+    java_medium('Avoid hash-based containers of java.net.URL--the containers rely on equals() and hashCode(), which cause java.net.URL to make blocking internet connections.',
+                [r".*: warning: \[URLEqualsHashCode\] .+"]),
+    java_medium('Collection, Iterable, Multimap, and Queue do not have well-defined equals behavior',
+                [r".*: warning: \[UndefinedEquals\] .+"]),
+    java_medium('Switch handles all enum values: an explicit default case is unnecessary and defeats error checking for non-exhaustive switches.',
+                [r".*: warning: \[UnnecessaryDefaultInEnumSwitch\] .+"]),
+    java_medium('Unnecessary use of grouping parentheses',
+                [r".*: warning: \[UnnecessaryParentheses\] .+"]),
+    java_medium('Finalizer may run before native code finishes execution',
+                [r".*: warning: \[UnsafeFinalization\] .+"]),
+    java_medium('Prefer `asSubclass` instead of casting the result of `newInstance`, to detect classes of incorrect type before invoking their constructors.This way, if the class is of the incorrect type,it will throw an exception before invoking its constructor.',
+                [r".*: warning: \[UnsafeReflectiveConstructionCast\] .+"]),
+    java_medium('Unsynchronized method overrides a synchronized method.',
+                [r".*: warning: \[UnsynchronizedOverridesSynchronized\] .+"]),
+    java_medium('Unused.',
+                [r".*: warning: \[Unused\] .+"]),
+    java_medium('This catch block catches an exception and re-throws another, but swallows the caught exception rather than setting it as a cause. This can make debugging harder.',
+                [r".*: warning: \[UnusedException\] .+"]),
+    java_medium('Java assert is used in test. For testing purposes Assert.* matchers should be used.',
+                [r".*: warning: \[UseCorrectAssertInTests\] .+"]),
+    java_medium('Non-constant variable missing @Var annotation',
+                [r".*: warning: \[Var\] .+"]),
+    java_medium('variableName and type with the same name would refer to the static field instead of the class',
+                [r".*: warning: \[VariableNameSameAsType\] .+"]),
+    java_medium('Because of spurious wakeups, Object.wait() and Condition.await() must always be called in a loop',
+                [r".*: warning: \[WaitNotInLoop\] .+"]),
+    java_medium('A wakelock acquired with a timeout may be released by the system before calling `release`, even after checking `isHeld()`. If so, it will throw a RuntimeException. Please wrap in a try/catch block.',
+                [r".*: warning: \[WakelockReleasedDangerously\] .+"]),
+    java_high('AndroidInjection.inject() should always be invoked before calling super.lifecycleMethod()',
+              [r".*: warning: \[AndroidInjectionBeforeSuper\] .+"]),
+    java_high('Use of class, field, or method that is not compatible with legacy Android devices',
+              [r".*: warning: \[AndroidJdkLibsChecker\] .+"]),
+    java_high('Reference equality used to compare arrays',
+              [r".*: warning: \[ArrayEquals\] .+"]),
+    java_high('Arrays.fill(Object[], Object) called with incompatible types.',
+              [r".*: warning: \[ArrayFillIncompatibleType\] .+"]),
+    java_high('hashcode method on array does not hash array contents',
+              [r".*: warning: \[ArrayHashCode\] .+"]),
+    java_high('Calling toString on an array does not provide useful information',
+              [r".*: warning: \[ArrayToString\] .+"]),
+    java_high('Arrays.asList does not autobox primitive arrays, as one might expect.',
+              [r".*: warning: \[ArraysAsListPrimitiveArray\] .+"]),
+    java_high('@AssistedInject and @Inject cannot be used on the same constructor.',
+              [r".*: warning: \[AssistedInjectAndInjectOnSameConstructor\] .+"]),
+    java_high('AsyncCallable should not return a null Future, only a Future whose result is null.',
+              [r".*: warning: \[AsyncCallableReturnsNull\] .+"]),
+    java_high('AsyncFunction should not return a null Future, only a Future whose result is null.',
+              [r".*: warning: \[AsyncFunctionReturnsNull\] .+"]),
+    java_high('@AutoFactory and @Inject should not be used in the same type.',
+              [r".*: warning: \[AutoFactoryAtInject\] .+"]),
+    java_high('Arguments to AutoValue constructor are in the wrong order',
+              [r".*: warning: \[AutoValueConstructorOrderChecker\] .+"]),
+    java_high('Shift by an amount that is out of range',
+              [r".*: warning: \[BadShiftAmount\] .+"]),
+    java_high('Object serialized in Bundle may have been flattened to base type.',
+              [r".*: warning: \[BundleDeserializationCast\] .+"]),
+    java_high('The called constructor accepts a parameter with the same name and type as one of its caller\'s parameters, but its caller doesn\'t pass that parameter to it.  It\'s likely that it was intended to.',
+              [r".*: warning: \[ChainingConstructorIgnoresParameter\] .+"]),
+    java_high('Ignored return value of method that is annotated with @CheckReturnValue',
+              [r".*: warning: \[CheckReturnValue\] .+"]),
+    java_high('The source file name should match the name of the top-level class it contains',
+              [r".*: warning: \[ClassName\] .+"]),
+    java_high('Incompatible type as argument to Object-accepting Java collections method',
+              [r".*: warning: \[CollectionIncompatibleType\] .+"]),
+    java_high(u'Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.',
+              [r".*: warning: \[ComparableType\] .+"]),
+    java_high('this == null is always false, this != null is always true',
+              [r".*: warning: \[ComparingThisWithNull\] .+"]),
+    java_high('This comparison method violates the contract',
+              [r".*: warning: \[ComparisonContractViolated\] .+"]),
+    java_high('Comparison to value that is out of range for the compared type',
+              [r".*: warning: \[ComparisonOutOfRange\] .+"]),
+    java_high('@CompatibleWith\'s value is not a type argument.',
+              [r".*: warning: \[CompatibleWithAnnotationMisuse\] .+"]),
+    java_high('Non-compile-time constant expression passed to parameter with @CompileTimeConstant type annotation.',
+              [r".*: warning: \[CompileTimeConstant\] .+"]),
+    java_high('Non-trivial compile time constant boolean expressions shouldn\'t be used.',
+              [r".*: warning: \[ComplexBooleanConstant\] .+"]),
+    java_high('A conditional expression with numeric operands of differing types will perform binary numeric promotion of the operands; when these operands are of reference types, the expression\'s result may not be of the expected type.',
+              [r".*: warning: \[ConditionalExpressionNumericPromotion\] .+"]),
+    java_high('Compile-time constant expression overflows',
+              [r".*: warning: \[ConstantOverflow\] .+"]),
+    java_high('Dagger @Provides methods may not return null unless annotated with @Nullable',
+              [r".*: warning: \[DaggerProvidesNull\] .+"]),
+    java_high('Exception created but not thrown',
+              [r".*: warning: \[DeadException\] .+"]),
+    java_high('Thread created but not started',
+              [r".*: warning: \[DeadThread\] .+"]),
+    java_high('Deprecated item is not annotated with @Deprecated',
+              [r".*: warning: \[DepAnn\] .+"]),
+    java_high('Division by integer literal zero',
+              [r".*: warning: \[DivZero\] .+"]),
+    java_high('This method should not be called.',
+              [r".*: warning: \[DoNotCall\] .+"]),
+    java_high('Empty statement after if',
+              [r".*: warning: \[EmptyIf\] .+"]),
+    java_high('== NaN always returns false; use the isNaN methods instead',
+              [r".*: warning: \[EqualsNaN\] .+"]),
+    java_high('== must be used in equals method to check equality to itself or an infinite loop will occur.',
+              [r".*: warning: \[EqualsReference\] .+"]),
+    java_high('Comparing different pairs of fields/getters in an equals implementation is probably a mistake.',
+              [r".*: warning: \[EqualsWrongThing\] .+"]),
+    java_high('Method annotated @ForOverride must be protected or package-private and only invoked from declaring class, or from an override of the method',
+              [r".*: warning: \[ForOverride\] .+"]),
+    java_high('Invalid printf-style format string',
+              [r".*: warning: \[FormatString\] .+"]),
+    java_high('Invalid format string passed to formatting method.',
+              [r".*: warning: \[FormatStringAnnotation\] .+"]),
+    java_high('Casting a lambda to this @FunctionalInterface can cause a behavior change from casting to a functional superinterface, which is surprising to users.  Prefer decorator methods to this surprising behavior.',
+              [r".*: warning: \[FunctionalInterfaceMethodChanged\] .+"]),
+    java_high('Futures.getChecked requires a checked exception type with a standard constructor.',
+              [r".*: warning: \[FuturesGetCheckedIllegalExceptionType\] .+"]),
+    java_high('DoubleMath.fuzzyEquals should never be used in an Object.equals() method',
+              [r".*: warning: \[FuzzyEqualsShouldNotBeUsedInEqualsMethod\] .+"]),
+    java_high('Calling getClass() on an annotation may return a proxy class',
+              [r".*: warning: \[GetClassOnAnnotation\] .+"]),
+    java_high('Calling getClass() on an object of type Class returns the Class object for java.lang.Class; you probably meant to operate on the object directly',
+              [r".*: warning: \[GetClassOnClass\] .+"]),
+    java_high('Checks for unguarded accesses to fields and methods with @GuardedBy annotations',
+              [r".*: warning: \[GuardedBy\] .+"]),
+    java_high('Scope annotation on implementation class of AssistedInject factory is not allowed',
+              [r".*: warning: \[GuiceAssistedInjectScoping\] .+"]),
+    java_high('A constructor cannot have two @Assisted parameters of the same type unless they are disambiguated with named @Assisted annotations.',
+              [r".*: warning: \[GuiceAssistedParameters\] .+"]),
+    java_high('Although Guice allows injecting final fields, doing so is disallowed because the injected value may not be visible to other threads.',
+              [r".*: warning: \[GuiceInjectOnFinalField\] .+"]),
+    java_high('contains() is a legacy method that is equivalent to containsValue()',
+              [r".*: warning: \[HashtableContains\] .+"]),
+    java_high('A binary expression where both operands are the same is usually incorrect.',
+              [r".*: warning: \[IdentityBinaryExpression\] .+"]),
+    java_high('Type declaration annotated with @Immutable is not immutable',
+              [r".*: warning: \[Immutable\] .+"]),
+    java_high('Modifying an immutable collection is guaranteed to throw an exception and leave the collection unmodified',
+              [r".*: warning: \[ImmutableModification\] .+"]),
+    java_high('Passing argument to a generic method with an incompatible type.',
+              [r".*: warning: \[IncompatibleArgumentType\] .+"]),
+    java_high('The first argument to indexOf is a Unicode code point, and the second is the index to start the search from',
+              [r".*: warning: \[IndexOfChar\] .+"]),
+    java_high('Conditional expression in varargs call contains array and non-array arguments',
+              [r".*: warning: \[InexactVarargsConditional\] .+"]),
+    java_high('This method always recurses, and will cause a StackOverflowError',
+              [r".*: warning: \[InfiniteRecursion\] .+"]),
+    java_high('A scoping annotation\'s Target should include TYPE and METHOD.',
+              [r".*: warning: \[InjectInvalidTargetingOnScopingAnnotation\] .+"]),
+    java_high('Using more than one qualifier annotation on the same element is not allowed.',
+              [r".*: warning: \[InjectMoreThanOneQualifier\] .+"]),
+    java_high('A class can be annotated with at most one scope annotation.',
+              [r".*: warning: \[InjectMoreThanOneScopeAnnotationOnClass\] .+"]),
+    java_high('Members shouldn\'t be annotated with @Inject if constructor is already annotated @Inject',
+              [r".*: warning: \[InjectOnMemberAndConstructor\] .+"]),
+    java_high('Scope annotation on an interface or abstact class is not allowed',
+              [r".*: warning: \[InjectScopeAnnotationOnInterfaceOrAbstractClass\] .+"]),
+    java_high('Scoping and qualifier annotations must have runtime retention.',
+              [r".*: warning: \[InjectScopeOrQualifierAnnotationRetention\] .+"]),
+    java_high('Injected constructors cannot be optional nor have binding annotations',
+              [r".*: warning: \[InjectedConstructorAnnotations\] .+"]),
+    java_high('A standard cryptographic operation is used in a mode that is prone to vulnerabilities',
+              [r".*: warning: \[InsecureCryptoUsage\] .+"]),
+    java_high('Invalid syntax used for a regular expression',
+              [r".*: warning: \[InvalidPatternSyntax\] .+"]),
+    java_high('Invalid time zone identifier. TimeZone.getTimeZone(String) will silently return GMT instead of the time zone you intended.',
+              [r".*: warning: \[InvalidTimeZoneID\] .+"]),
+    java_high('The argument to Class#isInstance(Object) should not be a Class',
+              [r".*: warning: \[IsInstanceOfClass\] .+"]),
+    java_high('Log tag too long, cannot exceed 23 characters.',
+              [r".*: warning: \[IsLoggableTagLength\] .+"]),
+    java_high(u'Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity',
+              [r".*: warning: \[IterablePathParameter\] .+"]),
+    java_high('jMock tests must have a @RunWith(JMock.class) annotation, or the Mockery field must have a @Rule JUnit annotation',
+              [r".*: warning: \[JMockTestWithoutRunWithOrRuleAnnotation\] .+"]),
+    java_high('Test method will not be run; please correct method signature (Should be public, non-static, and method name should begin with "test").',
+              [r".*: warning: \[JUnit3TestNotRun\] .+"]),
+    java_high('This method should be static',
+              [r".*: warning: \[JUnit4ClassAnnotationNonStatic\] .+"]),
+    java_high('setUp() method will not be run; please add JUnit\'s @Before annotation',
+              [r".*: warning: \[JUnit4SetUpNotRun\] .+"]),
+    java_high('tearDown() method will not be run; please add JUnit\'s @After annotation',
+              [r".*: warning: \[JUnit4TearDownNotRun\] .+"]),
+    java_high('This looks like a test method but is not run; please add @Test and @Ignore, or, if this is a helper method, reduce its visibility.',
+              [r".*: warning: \[JUnit4TestNotRun\] .+"]),
+    java_high('An object is tested for reference equality to itself using JUnit library.',
+              [r".*: warning: \[JUnitAssertSameCheck\] .+"]),
+    java_high('Use of class, field, or method that is not compatible with JDK 7',
+              [r".*: warning: \[Java7ApiChecker\] .+"]),
+    java_high('Abstract and default methods are not injectable with javax.inject.Inject',
+              [r".*: warning: \[JavaxInjectOnAbstractMethod\] .+"]),
+    java_high('@javax.inject.Inject cannot be put on a final field.',
+              [r".*: warning: \[JavaxInjectOnFinalField\] .+"]),
+    java_high('This pattern will silently corrupt certain byte sequences from the serialized protocol message. Use ByteString or byte[] directly',
+              [r".*: warning: \[LiteByteStringUtf8\] .+"]),
+    java_high('This method does not acquire the locks specified by its @LockMethod annotation',
+              [r".*: warning: \[LockMethodChecker\] .+"]),
+    java_high('Prefer \'L\' to \'l\' for the suffix to long literals',
+              [r".*: warning: \[LongLiteralLowerCaseSuffix\] .+"]),
+    java_high('Loop condition is never modified in loop body.',
+              [r".*: warning: \[LoopConditionChecker\] .+"]),
+    java_high('Math.round(Integer) results in truncation',
+              [r".*: warning: \[MathRoundIntLong\] .+"]),
+    java_high('Certain resources in `android.R.string` have names that do not match their content',
+              [r".*: warning: \[MislabeledAndroidString\] .+"]),
+    java_high('Overriding method is missing a call to overridden super method',
+              [r".*: warning: \[MissingSuperCall\] .+"]),
+    java_high('A terminating method call is required for a test helper to have any effect.',
+              [r".*: warning: \[MissingTestCall\] .+"]),
+    java_high('Use of "YYYY" (week year) in a date pattern without "ww" (week in year). You probably meant to use "yyyy" (year) instead.',
+              [r".*: warning: \[MisusedWeekYear\] .+"]),
+    java_high('A bug in Mockito will cause this test to fail at runtime with a ClassCastException',
+              [r".*: warning: \[MockitoCast\] .+"]),
+    java_high('Missing method call for verify(mock) here',
+              [r".*: warning: \[MockitoUsage\] .+"]),
+    java_high('Using a collection function with itself as the argument.',
+              [r".*: warning: \[ModifyingCollectionWithItself\] .+"]),
+    java_high('This class has more than one @Inject-annotated constructor. Please remove the @Inject annotation from all but one of them.',
+              [r".*: warning: \[MoreThanOneInjectableConstructor\] .+"]),
+    java_high('The result of this method must be closed.',
+              [r".*: warning: \[MustBeClosedChecker\] .+"]),
+    java_high('The first argument to nCopies is the number of copies, and the second is the item to copy',
+              [r".*: warning: \[NCopiesOfChar\] .+"]),
+    java_high('@NoAllocation was specified on this method, but something was found that would trigger an allocation',
+              [r".*: warning: \[NoAllocation\] .+"]),
+    java_high('Static import of type uses non-canonical name',
+              [r".*: warning: \[NonCanonicalStaticImport\] .+"]),
+    java_high('@CompileTimeConstant parameters should be final or effectively final',
+              [r".*: warning: \[NonFinalCompileTimeConstant\] .+"]),
+    java_high('Calling getAnnotation on an annotation that is not retained at runtime.',
+              [r".*: warning: \[NonRuntimeAnnotation\] .+"]),
+    java_high('This conditional expression may evaluate to null, which will result in an NPE when the result is unboxed.',
+              [r".*: warning: \[NullTernary\] .+"]),
+    java_high('Numeric comparison using reference equality instead of value equality',
+              [r".*: warning: \[NumericEquality\] .+"]),
+    java_high('Comparison using reference equality instead of value equality',
+              [r".*: warning: \[OptionalEquality\] .+"]),
+    java_high('Annotations cannot be both Scope annotations and Qualifier annotations: this causes confusion when trying to use them.',
+              [r".*: warning: \[OverlappingQualifierAndScopeAnnotation\] .+"]),
+    java_high('This method is not annotated with @Inject, but it overrides a method that is  annotated with @javax.inject.Inject. The method will not be Injected.',
+              [r".*: warning: \[OverridesJavaxInjectableMethod\] .+"]),
+    java_high('Declaring types inside package-info.java files is very bad form',
+              [r".*: warning: \[PackageInfo\] .+"]),
+    java_high('Method parameter has wrong package',
+              [r".*: warning: \[ParameterPackage\] .+"]),
+    java_high('Detects classes which implement Parcelable but don\'t have CREATOR',
+              [r".*: warning: \[ParcelableCreator\] .+"]),
+    java_high('Literal passed as first argument to Preconditions.checkNotNull() can never be null',
+              [r".*: warning: \[PreconditionsCheckNotNull\] .+"]),
+    java_high('First argument to `Preconditions.checkNotNull()` is a primitive rather than an object reference',
+              [r".*: warning: \[PreconditionsCheckNotNullPrimitive\] .+"]),
+    java_high('Using ::equals or ::isInstance as an incompatible Predicate; the predicate will always return false',
+              [r".*: warning: \[PredicateIncompatibleType\] .+"]),
+    java_high('Access to a private protocol buffer field is forbidden. This protocol buffer carries a security contract, and can only be created using an approved library. Direct access to the fields is forbidden.',
+              [r".*: warning: \[PrivateSecurityContractProtoAccess\] .+"]),
+    java_high('Protobuf fields cannot be null.',
+              [r".*: warning: \[ProtoFieldNullComparison\] .+"]),
+    java_high('Comparing protobuf fields of type String using reference equality',
+              [r".*: warning: \[ProtoStringFieldReferenceEquality\] .+"]),
+    java_high('To get the tag number of a protocol buffer enum, use getNumber() instead.',
+              [r".*: warning: \[ProtocolBufferOrdinal\] .+"]),
+    java_high('@Provides methods need to be declared in a Module to have any effect.',
+              [r".*: warning: \[ProvidesMethodOutsideOfModule\] .+"]),
+    java_high('Casting a random number in the range [0.0, 1.0) to an integer or long always results in 0.',
+              [r".*: warning: \[RandomCast\] .+"]),
+    java_high('Use Random.nextInt(int).  Random.nextInt() % n can have negative results',
+              [r".*: warning: \[RandomModInteger\] .+"]),
+    java_high('Return value of android.graphics.Rect.intersect() must be checked',
+              [r".*: warning: \[RectIntersectReturnValueIgnored\] .+"]),
+    java_high('Use of method or class annotated with @RestrictTo',
+              [r".*: warning: \[RestrictTo\] .+"]),
+    java_high(' Check for non-whitelisted callers to RestrictedApiChecker.',
+              [r".*: warning: \[RestrictedApiChecker\] .+"]),
+    java_high('Return value of this method must be used',
+              [r".*: warning: \[ReturnValueIgnored\] .+"]),
+    java_high('Variable assigned to itself',
+              [r".*: warning: \[SelfAssignment\] .+"]),
+    java_high('An object is compared to itself',
+              [r".*: warning: \[SelfComparison\] .+"]),
+    java_high('Testing an object for equality with itself will always be true.',
+              [r".*: warning: \[SelfEquals\] .+"]),
+    java_high('This method must be called with an even number of arguments.',
+              [r".*: warning: \[ShouldHaveEvenArgs\] .+"]),
+    java_high('Comparison of a size >= 0 is always true, did you intend to check for non-emptiness?',
+              [r".*: warning: \[SizeGreaterThanOrEqualsZero\] .+"]),
+    java_high('Static and default interface methods are not natively supported on older Android devices. ',
+              [r".*: warning: \[StaticOrDefaultInterfaceMethod\] .+"]),
+    java_high('Calling toString on a Stream does not provide useful information',
+              [r".*: warning: \[StreamToString\] .+"]),
+    java_high('StringBuilder does not have a char constructor; this invokes the int constructor.',
+              [r".*: warning: \[StringBuilderInitWithChar\] .+"]),
+    java_high('String.substring(0) returns the original String',
+              [r".*: warning: \[SubstringOfZero\] .+"]),
+    java_high('Suppressing "deprecated" is probably a typo for "deprecation"',
+              [r".*: warning: \[SuppressWarningsDeprecated\] .+"]),
+    java_high('throwIfUnchecked(knownCheckedException) is a no-op.',
+              [r".*: warning: \[ThrowIfUncheckedKnownChecked\] .+"]),
+    java_high('Throwing \'null\' always results in a NullPointerException being thrown.',
+              [r".*: warning: \[ThrowNull\] .+"]),
+    java_high('isEqualTo should not be used to test an object for equality with itself; the assertion will never fail.',
+              [r".*: warning: \[TruthSelfEquals\] .+"]),
+    java_high('Catching Throwable/Error masks failures from fail() or assert*() in the try block',
+              [r".*: warning: \[TryFailThrowable\] .+"]),
+    java_high('Type parameter used as type qualifier',
+              [r".*: warning: \[TypeParameterQualifier\] .+"]),
+    java_high('This method does not acquire the locks specified by its @UnlockMethod annotation',
+              [r".*: warning: \[UnlockMethod\] .+"]),
+    java_high('Non-generic methods should not be invoked with type arguments',
+              [r".*: warning: \[UnnecessaryTypeArgument\] .+"]),
+    java_high('Instance created but never used',
+              [r".*: warning: \[UnusedAnonymousClass\] .+"]),
+    java_high('Collection is modified in place, but the result is not used',
+              [r".*: warning: \[UnusedCollectionModifiedInPlace\] .+"]),
+    java_high('`var` should not be used as a type name.',
+              [r".*: warning: \[VarTypeName\] .+"]),
 
     # End warnings generated by Error Prone
 
-    {'category': 'java',
-     'severity': Severity.UNKNOWN,
-     'description': 'Java: Unclassified/unrecognized warnings',
-     'patterns': [r".*: warning: \[.+\] .+"]},
+    java_warn(Severity.UNKNOWN,
+              'Unclassified/unrecognized warnings',
+              [r".*: warning: \[.+\] .+"]),  # TODO(chh) use more specific pattern
 
+    # aapt warnings
     {'category': 'aapt', 'severity': Severity.MEDIUM,
      'description': 'aapt: No default translation',
      'patterns': [r".*: warning: string '.+' has no default translation in .*"]},
@@ -2169,6 +1229,8 @@
     {'category': 'aapt', 'severity': Severity.MEDIUM,
      'description': 'aapt: empty span in string',
      'patterns': [r".*: warning: empty '.+' span found in text '.+"]},
+
+    # C/C++ warnings
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
      'description': 'Taking address of temporary',
      'patterns': [r".*: warning: taking address of temporary"]},
@@ -2184,11 +1246,11 @@
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wundefined-inline',
      'description': 'Inline function is not defined',
      'patterns': [r".*: warning: inline function '.*' is not defined"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Warray-bounds',
-     'description': 'Array subscript out of bounds',
-     'patterns': [r".*: warning: array subscript is above array bounds",
-                  r".*: warning: Array subscript is undefined",
-                  r".*: warning: array subscript is below array bounds"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Warray-bounds',
+    #  'description': 'Array subscript out of bounds',
+    #  'patterns': [r".*: warning: array subscript is above array bounds",
+    #               r".*: warning: Array subscript is undefined",
+    #               r".*: warning: array subscript is below array bounds"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
      'description': 'Excess elements in initializer',
      'patterns': [r".*: warning: excess elements in .+ initializer"]},
@@ -2289,14 +1351,7 @@
      'patterns': [r".*: warning: multi-line comment"]},
     {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wcomment',
      'description': 'Comment inside comment',
-     'patterns': [r".*: warning: "".+"" within comment"]},
-    # Warning "value stored is never read" could be from clang-tidy or clang static analyzer.
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Value stored is never read',
-     'patterns': [r".*: warning: Value stored to .+ is never read.*clang-analyzer-deadcode.DeadStores"]},
-    {'category': 'C/C++', 'severity': Severity.LOW,
-     'description': 'Value stored is never read',
-     'patterns': [r".*: warning: Value stored to .+ is never read"]},
+     'patterns': [r".*: warning: '.+' within block comment .*-Wcomment"]},
     {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wdeprecated-declarations',
      'description': 'Deprecated declarations',
      'patterns': [r".*: warning: .+ is deprecated.+deprecated-declarations"]},
@@ -2311,7 +1366,8 @@
      'patterns': [r".*: warning: extra tokens at end of #endif directive"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wenum-compare',
      'description': 'Comparison between different enums',
-     'patterns': [r".*: warning: comparison between '.+' and '.+'.+Wenum-compare"]},
+     'patterns': [r".*: warning: comparison between '.+' and '.+'.+Wenum-compare",
+                  r".*: warning: comparison of .* enumeration types .*-Wenum-compare-switch"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wconversion',
      'description': 'Conversion may change value',
      'patterns': [r".*: warning: converting negative value '.+' to '.+'",
@@ -2329,8 +1385,9 @@
      'description': 'Zero used as null pointer',
      'patterns': [r".*: warning: expression .* zero treated as a null pointer constant"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Implicit conversion changes value',
-     'patterns': [r".*: warning: implicit conversion .* changes value from .* to .*-conversion"]},
+     'description': 'Implicit conversion changes value or loses precision',
+     'patterns': [r".*: warning: implicit conversion .* changes value from .* to .*-conversion",
+                  r".*: warning: implicit conversion loses integer precision:"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
      'description': 'Passing NULL as non-pointer argument',
      'patterns': [r".*: warning: passing NULL to non-pointer argument [0-9]+ of '.+'"]},
@@ -2361,9 +1418,9 @@
     {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Wextra',
      'description': 'Base should be explicitly initialized in copy constructor',
      'patterns': [r".*: warning: base class '.+' should be explicitly initialized in the copy constructor"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'VLA has zero or negative size',
-     'patterns': [r".*: warning: Declared variable-length array \(VLA\) has .+ size"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'VLA has zero or negative size',
+    #  'patterns': [r".*: warning: Declared variable-length array \(VLA\) has .+ size"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
      'description': 'Return value from void function',
      'patterns': [r".*: warning: 'return' with a value, in function returning void"]},
@@ -2420,9 +1477,9 @@
     {'category': 'logtags', 'severity': Severity.LOW, 'option': 'overloaded-virtual',
      'description': 'Hides overloaded virtual function',
      'patterns': [r".*: '.+' hides overloaded virtual function"]},
-    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'incompatible-pointer-types',
+    {'category': 'logtags', 'severity': Severity.LOW,
      'description': 'Incompatible pointer types',
-     'patterns': [r".*: warning: incompatible pointer types .+Wincompatible-pointer-types"]},
+     'patterns': [r".*: warning: incompatible .*pointer types .*-Wincompatible-.*pointer-types"]},
     {'category': 'logtags', 'severity': Severity.LOW, 'option': 'asm-operand-widths',
      'description': 'ASM value size does not match register size',
      'patterns': [r".*: warning: value size does not match register size specified by the constraint and modifier"]},
@@ -2474,35 +1531,38 @@
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': 'switch',
      'description': 'case value not in enumerated type',
      'patterns': [r".*: warning: case value not in enumerated type '.+'"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Undefined result',
-     'patterns': [r".*: warning: The result of .+ is undefined",
-                  r".*: warning: passing an object that .+ has undefined behavior \[-Wvarargs\]",
-                  r".*: warning: 'this' pointer cannot be null in well-defined C\+\+ code;",
-                  r".*: warning: shifting a negative signed value is undefined"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Division by zero',
-     'patterns': [r".*: warning: Division by zero"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'Undefined result',
+    #  'patterns': [r".*: warning: The result of .+ is undefined",
+    #               r".*: warning: passing an object that .+ has undefined behavior \[-Wvarargs\]",
+    #               r".*: warning: 'this' pointer cannot be null in well-defined C\+\+ code;",
+    #               r".*: warning: shifting a negative signed value is undefined"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'Division by zero',
+    #  'patterns': [r".*: warning: Division by zero"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
      'description': 'Use of deprecated method',
      'patterns': [r".*: warning: '.+' is deprecated .+"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
      'description': 'Use of garbage or uninitialized value',
-     'patterns': [r".*: warning: .+ is a garbage value",
-                  r".*: warning: Function call argument is an uninitialized value",
-                  r".*: warning: Undefined or garbage value returned to caller",
-                  r".*: warning: Called .+ pointer is.+uninitialized",
-                  r".*: warning: Called .+ pointer is.+uninitalized",  # match a typo in compiler message
-                  r".*: warning: Use of zero-allocated memory",
-                  r".*: warning: Dereference of undefined pointer value",
-                  r".*: warning: Passed-by-value .+ contains uninitialized data",
-                  r".*: warning: Branch condition evaluates to a garbage value",
-                  r".*: warning: The .+ of .+ is an uninitialized value.",
-                  r".*: warning: .+ is used uninitialized whenever .+sometimes-uninitialized",
-                  r".*: warning: Assigned value is garbage or undefined"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Result of malloc type incompatible with sizeof operand type',
-     'patterns': [r".*: warning: Result of '.+' is converted to .+ incompatible with sizeof operand type"]},
+     'patterns': [r".*: warning: .+ uninitialized .+\[-Wsometimes-uninitialized\]"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'Use of garbage or uninitialized value',
+    #  'patterns': [r".*: warning: .+ is a garbage value",
+    #               r".*: warning: Function call argument is an uninitialized value",
+    #               r".*: warning: Undefined or garbage value returned to caller",
+    #               r".*: warning: Called .+ pointer is.+uninitialized",
+    #               r".*: warning: Called .+ pointer is.+uninitalized",  # match a typo in compiler message
+    #               r".*: warning: Use of zero-allocated memory",
+    #               r".*: warning: Dereference of undefined pointer value",
+    #               r".*: warning: Passed-by-value .+ contains uninitialized data",
+    #               r".*: warning: Branch condition evaluates to a garbage value",
+    #               r".*: warning: The .+ of .+ is an uninitialized value.",
+    #               r".*: warning: .+ is used uninitialized whenever .+sometimes-uninitialized",
+    #               r".*: warning: Assigned value is garbage or undefined"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'Result of malloc type incompatible with sizeof operand type',
+    #  'patterns': [r".*: warning: Result of '.+' is converted to .+ incompatible with sizeof operand type"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wsizeof-array-argument',
      'description': 'Sizeof on array argument',
      'patterns': [r".*: warning: sizeof on array function parameter will return"]},
@@ -2515,12 +1575,12 @@
     {'category': 'C/C++', 'severity': Severity.MEDIUM,
      'description': 'Possible heap pollution',
      'patterns': [r".*: warning: .*Possible heap pollution from .+ type .+"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Allocation size of 0 byte',
-     'patterns': [r".*: warning: Call to .+ has an allocation size of 0 byte"]},
-    {'category': 'C/C++', 'severity': Severity.MEDIUM,
-     'description': 'Result of malloc type incompatible with sizeof operand type',
-     'patterns': [r".*: warning: Result of '.+' is converted to .+ incompatible with sizeof operand type"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'Allocation size of 0 byte',
+    #  'patterns': [r".*: warning: Call to .+ has an allocation size of 0 byte"]},
+    # {'category': 'C/C++', 'severity': Severity.MEDIUM,
+    #  'description': 'Result of malloc type incompatible with sizeof operand type',
+    #  'patterns': [r".*: warning: Result of '.+' is converted to .+ incompatible with sizeof operand type"]},
     {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wfor-loop-analysis',
      'description': 'Variable used in loop condition not modified in loop body',
      'patterns': [r".*: warning: variable '.+' used in loop condition.*Wfor-loop-analysis"]},
@@ -2554,12 +1614,15 @@
     {'category': 'FindEmulator', 'severity': Severity.HARMLESS,
      'description': 'FindEmulator: No such file or directory',
      'patterns': [r".*: warning: FindEmulator: .* No such file or directory"]},
-    {'category': 'google_tests', 'severity': Severity.HARMLESS,
-     'description': 'google_tests: unknown installed file',
+    {'category': 'make', 'severity': Severity.HARMLESS,
+     'description': 'make: unknown installed file',
      'patterns': [r".*: warning: .*_tests: Unknown installed file for module"]},
     {'category': 'make', 'severity': Severity.HARMLESS,
      'description': 'unusual tags debug eng',
      'patterns': [r".*: warning: .*: unusual tags debug eng"]},
+    {'category': 'make', 'severity': Severity.MEDIUM,
+     'description': 'make: please convert to soong',
+     'patterns': [r".*: warning: .* has been deprecated. Please convert to Soong."]},
 
     # these next ones are to deal with formatting problems resulting from the log being mixed up by 'make -j'
     {'category': 'C/C++', 'severity': Severity.SKIP,
@@ -2574,6 +1637,7 @@
 
     # warnings from clang-tidy
     group_tidy_warn_pattern('android'),
+    simple_tidy_warn_pattern('abseil-string-find-startswith'),
     simple_tidy_warn_pattern('bugprone-argument-comment'),
     simple_tidy_warn_pattern('bugprone-copy-constructor-init'),
     simple_tidy_warn_pattern('bugprone-fold-init-type'),
@@ -2633,56 +1697,104 @@
     simple_tidy_warn_pattern('performance-type-promotion-in-math-fn'),
     simple_tidy_warn_pattern('performance-unnecessary-copy-initialization'),
     simple_tidy_warn_pattern('performance-unnecessary-value-param'),
+    simple_tidy_warn_pattern('portability-simd-intrinsics'),
     group_tidy_warn_pattern('performance'),
     group_tidy_warn_pattern('readability'),
 
     # warnings from clang-tidy's clang-analyzer checks
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Unreachable code',
-     'patterns': [r".*: warning: This statement is never executed.*UnreachableCode"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Size of malloc may overflow',
-     'patterns': [r".*: warning: .* size of .* may overflow .*MallocOverflow"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Stream pointer might be NULL',
-     'patterns': [r".*: warning: Stream pointer might be NULL .*unix.Stream"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Opened file never closed',
-     'patterns': [r".*: warning: Opened File never closed.*unix.Stream"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer sozeof() on a pointer type',
-     'patterns': [r".*: warning: .*calls sizeof.* on a pointer type.*SizeofPtr"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Pointer arithmetic on non-array variables',
-     'patterns': [r".*: warning: Pointer arithmetic on non-array variables .*PointerArithm"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Subtraction of pointers of different memory chunks',
-     'patterns': [r".*: warning: Subtraction of two pointers .*PointerSub"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Access out-of-bound array element',
-     'patterns': [r".*: warning: Access out-of-bound array element .*ArrayBound"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Out of bound memory access',
-     'patterns': [r".*: warning: Out of bound memory access .*ArrayBoundV2"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Possible lock order reversal',
-     'patterns': [r".*: warning: .* Possible lock order reversal.*PthreadLock"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer Argument is a pointer to uninitialized value',
-     'patterns': [r".*: warning: .* argument is a pointer to uninitialized value .*CallAndMessage"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer cast to struct',
-     'patterns': [r".*: warning: Casting a non-structure type to a structure type .*CastToStruct"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer call path problems',
-     'patterns': [r".*: warning: Call Path : .+"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer excessive padding',
-     'patterns': [r".*: warning: Excessive padding in '.*'"]},
-    {'category': 'C/C++', 'severity': Severity.ANALYZER,
-     'description': 'clang-analyzer other',
-     'patterns': [r".*: .+\[clang-analyzer-.+\]$",
-                  r".*: Call Path : .+$"]},
+    analyzer_high('clang-analyzer-core, null pointer',
+                  [r".*: warning: .+ pointer is null .*\[clang-analyzer-core"]),
+    analyzer_high('clang-analyzer-core, uninitialized value',
+                  [r".*: warning: .+ uninitialized (value|data) .*\[clang-analyzer-core"]),
+    analyzer_warn('clang-analyzer-optin.performance.Padding',
+                  [r".*: warning: Excessive padding in '.*'"]),
+    # analyzer_warn('clang-analyzer Unreachable code',
+    #               [r".*: warning: This statement is never executed.*UnreachableCode"]),
+    analyzer_warn('clang-analyzer Size of malloc may overflow',
+                  [r".*: warning: .* size of .* may overflow .*MallocOverflow"]),
+    analyzer_warn('clang-analyzer sozeof() on a pointer type',
+                  [r".*: warning: .*calls sizeof.* on a pointer type.*SizeofPtr"]),
+    analyzer_warn('clang-analyzer Pointer arithmetic on non-array variables',
+                  [r".*: warning: Pointer arithmetic on non-array variables .*PointerArithm"]),
+    analyzer_warn('clang-analyzer Subtraction of pointers of different memory chunks',
+                  [r".*: warning: Subtraction of two pointers .*PointerSub"]),
+    analyzer_warn('clang-analyzer Access out-of-bound array element',
+                  [r".*: warning: Access out-of-bound array element .*ArrayBound"]),
+    analyzer_warn('clang-analyzer Out of bound memory access',
+                  [r".*: warning: Out of bound memory access .*ArrayBoundV2"]),
+    analyzer_warn('clang-analyzer Possible lock order reversal',
+                  [r".*: warning: .* Possible lock order reversal.*PthreadLock"]),
+    analyzer_warn('clang-analyzer call path problems',
+                  [r".*: warning: Call Path : .+"]),
+    analyzer_warn_check('clang-analyzer-core.CallAndMessage'),
+    analyzer_high_check('clang-analyzer-core.NonNullParamChecker'),
+    analyzer_high_check('clang-analyzer-core.NullDereference'),
+    analyzer_warn_check('clang-analyzer-core.UndefinedBinaryOperatorResult'),
+    analyzer_warn_check('clang-analyzer-core.DivideZero'),
+    analyzer_warn_check('clang-analyzer-core.VLASize'),
+    analyzer_warn_check('clang-analyzer-core.uninitialized.ArraySubscript'),
+    analyzer_warn_check('clang-analyzer-core.uninitialized.Assign'),
+    analyzer_warn_check('clang-analyzer-core.uninitialized.UndefReturn'),
+    analyzer_warn_check('clang-analyzer-cplusplus.Move'),
+    analyzer_warn_check('clang-analyzer-deadcode.DeadStores'),
+    analyzer_warn_check('clang-analyzer-optin.cplusplus.UninitializedObject'),
+    analyzer_warn_check('clang-analyzer-optin.cplusplus.VirtualCall'),
+    analyzer_warn_check('clang-analyzer-portability.UnixAPI'),
+    analyzer_warn_check('clang-analyzer-unix.cstring.NullArg'),
+    analyzer_high_check('clang-analyzer-unix.MallocSizeof'),
+    analyzer_warn_check('clang-analyzer-valist.Uninitialized'),
+    analyzer_warn_check('clang-analyzer-valist.Unterminated'),
+    analyzer_group_check('clang-analyzer-core.uninitialized'),
+    analyzer_group_check('clang-analyzer-deadcode'),
+    analyzer_warn_check('clang-analyzer-security.insecureAPI.strcpy'),
+    analyzer_group_high('clang-analyzer-security.insecureAPI'),
+    analyzer_group_high('clang-analyzer-security'),
+    analyzer_high_check('clang-analyzer-unix.Malloc'),
+    analyzer_high_check('clang-analyzer-cplusplus.NewDeleteLeaks'),
+    analyzer_high_check('clang-analyzer-cplusplus.NewDelete'),
+    analyzer_group_check('clang-analyzer-unix'),
+    analyzer_group_check('clang-analyzer'),  # catch al
+
+    # Assembler warnings
+    {'category': 'Asm', 'severity': Severity.MEDIUM,
+     'description': 'Asm: IT instruction is deprecated',
+     'patterns': [r".*: warning: applying IT instruction .* is deprecated"]},
+
+    # NDK warnings
+    {'category': 'NDK', 'severity': Severity.HIGH,
+     'description': 'NDK: Generate guard with empty availability, obsoleted',
+     'patterns': [r".*: warning: .* generate guard with empty availability: obsoleted ="]},
+
+    # Protoc warnings
+    {'category': 'Protoc', 'severity': Severity.MEDIUM,
+     'description': 'Proto: Enum name colision after strip',
+     'patterns': [r".*: warning: Enum .* has the same name .* ignore case and strip"]},
+    {'category': 'Protoc', 'severity': Severity.MEDIUM,
+     'description': 'Proto: Import not used',
+     'patterns': [r".*: warning: Import .*/.*\.proto but not used.$"]},
+
+    # Kotlin warnings
+    {'category': 'Kotlin', 'severity': Severity.MEDIUM,
+     'description': 'Kotlin: never used parameter or variable',
+     'patterns': [r".*: warning: (parameter|variable) '.*' is never used$"]},
+    {'category': 'Kotlin', 'severity': Severity.MEDIUM,
+     'description': 'Kotlin: Deprecated in Java',
+     'patterns': [r".*: warning: '.*' is deprecated. Deprecated in Java"]},
+    {'category': 'Kotlin', 'severity': Severity.MEDIUM,
+     'description': 'Kotlin: library has Kotlin runtime',
+     'patterns': [r".*: warning: library has Kotlin runtime bundled into it",
+                  r".*: warning: some JAR files .* have the Kotlin Runtime library"]},
+
+    # rustc warnings
+    {'category': 'Rust', 'severity': Severity.HIGH,
+     'description': 'Rust: Does not derive Copy',
+     'patterns': [r".*: warning: .+ does not derive Copy"]},
+    {'category': 'Rust', 'severity': Severity.MEDIUM,
+     'description': 'Rust: Deprecated range pattern',
+     'patterns': [r".*: warning: .+ range patterns are deprecated"]},
+    {'category': 'Rust', 'severity': Severity.MEDIUM,
+     'description': 'Rust: Deprecated missing explicit \'dyn\'',
+     'patterns': [r".*: warning: .+ without an explicit `dyn` are deprecated"]},
 
     # catch-all for warnings this script doesn't know about yet
     {'category': 'C/C++', 'severity': Severity.UNKNOWN,
@@ -3208,16 +2320,42 @@
   global target_variant
   line_counter = 0
 
-  # handle only warning messages with a file path
-  warning_pattern = re.compile('^[^ ]*/[^ ]*: warning: .*')
+  # rustc warning messages have two lines that should be combined:
+  #     warning: description
+  #        --> file_path:line_number:column_number
+  # Some warning messages have no file name:
+  #     warning: macro replacement list ... [bugprone-macro-parentheses]
+  # Some makefile warning messages have no line number:
+  #     some/path/file.mk: warning: description
+  # C/C++ compiler warning messages have line and column numbers:
+  #     some/path/file.c:line_number:column_number: warning: description
+  warning_pattern = re.compile('(^[^ ]*/[^ ]*: warning: .*)|(^warning: .*)')
+  warning_without_file = re.compile('^warning: .*')
+  rustc_file_position = re.compile('^[ ]+--> [^ ]*/[^ ]*:[0-9]+:[0-9]+')
 
   # Collect all warnings into the warning_lines set.
   warning_lines = set()
+  prev_warning = ''
   for line in infile:
+    if prev_warning:
+      if rustc_file_position.match(line):
+        # must be a rustc warning, combine 2 lines into one warning
+        line = line.strip().replace('--> ', '') + ': ' + prev_warning
+        warning_lines.add(normalize_warning_line(line))
+        prev_warning = ''
+        continue
+      # add prev_warning, and then process the current line
+      prev_warning = 'unknown_source_file: ' + prev_warning
+      warning_lines.add(normalize_warning_line(prev_warning))
+      prev_warning = ''
     if warning_pattern.match(line):
-      line = normalize_warning_line(line)
-      warning_lines.add(line)
-    elif line_counter < 100:
+      if warning_without_file.match(line):
+        # save this line and combine it with the next line
+        prev_warning = line
+      else:
+        warning_lines.add(normalize_warning_line(line))
+      continue
+    if line_counter < 100:
       # save a little bit of time by only doing this for the first few lines
       line_counter += 1
       m = re.search('(?<=^PLATFORM_VERSION=).*', line)