Merge "Delete VINTF files from target files package."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index a84e793..8219afc 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,25 @@
 $(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)
+
+# Migrate preopt files to system_other for some devices
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/*/*app/*/oat)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 5ae99b7..1b4a0da 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)
@@ -3122,29 +3289,55 @@
   $(error BOARD_AVB_VBMETA_SYSTEM and BOARD_AVB_VBMETA_VENDOR cannot have duplicates)
 endif
 
+# When building a standalone recovery image for non-A/B devices, recovery image must be self-signed
+# to be verified independently, and cannot be chained into vbmeta.img. See the link below for
+# details.
+ifneq ($(AB_OTA_UPDATER),true)
+ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
+$(if $(BOARD_AVB_RECOVERY_KEY_PATH),,\
+    $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for non-A/B devices. \
+            See https://android.googlesource.com/platform/external/avb/+/master/README.md#booting-into-recovery))
+endif
+endif
+
 # Appends os version and security patch level as a AVB property descriptor
 
 BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.system.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.system.os_version:$(PLATFORM_VERSION) \
     --prop com.android.build.system.security_patch:$(PLATFORM_SECURITY_PATCH)
 
 BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.product.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.product.os_version:$(PLATFORM_VERSION) \
     --prop com.android.build.product.security_patch:$(PLATFORM_SECURITY_PATCH)
 
 BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.system_ext.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.system_ext.os_version:$(PLATFORM_VERSION) \
     --prop com.android.build.system_ext.security_patch:$(PLATFORM_SECURITY_PATCH)
 
 BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.boot.os_version:$(PLATFORM_VERSION)
 
+BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.vendor_boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
+
+BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.recovery.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
+
 BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.vendor.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.vendor.os_version:$(PLATFORM_VERSION)
 
 BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.odm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
     --prop com.android.build.odm.os_version:$(PLATFORM_VERSION)
 
+BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS += \
+    --prop com.android.build.dtbo.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
+
 # The following vendor- and odm-specific images needs explicit SPL set per board.
 ifdef BOOT_SECURITY_PATCH
 BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
@@ -3162,6 +3355,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
@@ -3190,8 +3384,11 @@
 $(eval $(_signing_args) := \
     --algorithm $($(_signing_algorithm)) --key $($(_key_path)))
 
-$(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
-    --chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey)
+# The recovery partition in non-A/B devices should be verified separately. Skip adding the chain
+# partition descriptor for recovery partition into vbmeta.img.
+$(if $(or $(filter true,$(AB_OTA_UPDATER)),$(filter-out recovery,$(part))),\
+    $(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
+        --chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey))
 
 # Set rollback_index via footer args for non-chained vbmeta image. Chained vbmeta image will pick up
 # the index via a separate flag (e.g. BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX).
@@ -3220,6 +3417,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
@@ -3295,6 +3496,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)
@@ -3382,6 +3586,7 @@
 $(INSTALLED_VBMETAIMAGE_TARGET): \
 	    $(AVBTOOL) \
 	    $(INSTALLED_BOOTIMAGE_TARGET) \
+	    $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
 	    $(INSTALLED_SYSTEMIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
 	    $(INSTALLED_PRODUCTIMAGE_TARGET) \
@@ -3600,7 +3805,7 @@
 ifeq ($(build_otatools_package),true)
 
 INTERNAL_OTATOOLS_MODULES := \
-  aapt \
+  aapt2 \
   add_img_to_target_files \
   append2simg \
   avbtool \
@@ -3638,7 +3843,6 @@
   mkbootfs \
   mkbootimg \
   mke2fs \
-  mke2fs.conf \
   mkf2fsuserimg.sh \
   mksquashfs \
   mksquashfsimage.sh \
@@ -3749,6 +3953,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
@@ -3790,6 +3998,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)" >> $@
@@ -3801,6 +4012,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)" >> $@
@@ -3923,6 +4140,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
@@ -3979,6 +4208,7 @@
 $(BUILT_TARGET_FILES_PACKAGE): \
 	    $(INSTALLED_RAMDISK_TARGET) \
 	    $(INSTALLED_BOOTIMAGE_TARGET) \
+	    $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
 	    $(INSTALLED_RADIOIMAGE_TARGET) \
 	    $(INSTALLED_RECOVERYIMAGE_TARGET) \
 	    $(INSTALLED_USERDATAIMAGE_TARGET) \
@@ -4027,33 +4257,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
@@ -4069,25 +4303,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, \
@@ -4164,10 +4415,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.
@@ -4240,6 +4489,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
@@ -4269,9 +4521,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
@@ -4479,25 +4733,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))
@@ -4809,6 +5066,7 @@
 	$(target_notice_file_txt) \
 	$(tools_notice_file_txt) \
 	$(OUT_DOCS)/offline-sdk-timestamp \
+	$(SDK_METADATA_FILES) \
 	$(SYMBOLS_ZIP) \
 	$(COVERAGE_ZIP) \
 	$(APPCOMPAT_ZIP) \
@@ -4924,3 +5182,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 86dc10a..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
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 7147f6d..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
 
 
 
diff --git a/core/binary.mk b/core/binary.mk
index d9763f9..51259b2 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -120,8 +120,6 @@
     $(error $(LOCAL_PATH): LOCAL_SDK_VERSION cannot be used in host module)
   endif
 
-  my_cflags += -D__ANDROID_NDK__
-
   # Make sure we've built the NDK.
   my_additional_dependencies += $(SOONG_OUT_DIR)/ndk_base.timestamp
 
diff --git a/core/board_config.mk b/core/board_config.mk
index a6aef87..4c128f1 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -86,6 +86,8 @@
 
 _build_broken_var_list := \
   BUILD_BROKEN_DUP_RULES \
+  BUILD_BROKEN_PREBUILT_ELF_FILES \
+  BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW \
   BUILD_BROKEN_USES_NETWORK \
 
 _build_broken_var_list += \
@@ -262,6 +264,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 +339,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),)
@@ -490,9 +507,9 @@
 ###########################################
 # Now we can substitute with the real value of TARGET_COPY_OUT_ODM
 ifeq ($(TARGET_COPY_OUT_ODM),$(_odm_path_placeholder))
-  TARGET_COPY_OUT_ODM := vendor/odm
-else ifeq ($(filter odm vendor/odm,$(TARGET_COPY_OUT_ODM)),)
-  $(error TARGET_COPY_OUT_ODM must be either 'odm' or 'vendor/odm', seeing '$(TARGET_COPY_OUT_ODM)'.)
+  TARGET_COPY_OUT_ODM := $(TARGET_COPY_OUT_VENDOR)/odm
+else ifeq ($(filter odm system/vendor/odm vendor/odm,$(TARGET_COPY_OUT_ODM)),)
+  $(error TARGET_COPY_OUT_ODM must be either 'odm', 'system/vendor/odm' or 'vendor/odm', seeing '$(TARGET_COPY_OUT_ODM)'.)
 endif
 PRODUCT_COPY_FILES := $(subst $(_odm_path_placeholder),$(TARGET_COPY_OUT_ODM),$(PRODUCT_COPY_FILES))
 
@@ -569,8 +586,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/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 b98027d..007235e 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -73,6 +73,7 @@
 LOCAL_DROIDDOC_DOC_ZIP :=
 LOCAL_DROIDDOC_JDIFF_DOC_ZIP :=
 LOCAL_DROIDDOC_HTML_DIR:=
+LOCAL_DROIDDOC_METADATA_ZIP:=
 LOCAL_DROIDDOC_OPTIONS:=
 LOCAL_DROIDDOC_SOURCE_PATH:=
 LOCAL_DROIDDOC_STUB_OUT_DIR:=
@@ -115,12 +116,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:=
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 f521813..241ac8d 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.
@@ -640,21 +630,16 @@
 USE_OPENJDK9 := true
 
 ifeq ($(EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9),)
-TARGET_OPENJDK9 :=
+TARGET_OPENJDK9 := true
 else ifeq ($(EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9),true)
 TARGET_OPENJDK9 := true
+else ifeq ($(EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9),false)
+TARGET_OPENJDK9 :=
 endif
 
 # 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
@@ -808,7 +793,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))
@@ -1188,8 +1173,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 8e4a46c..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))
@@ -79,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))
@@ -99,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..a8bf4d5 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)
@@ -2279,7 +2279,7 @@
 # Align STORED entries of a package on 4-byte boundaries to make them easier to mmap.
 #
 define align-package
-$(hide) if ! $(ZIPALIGN) -c $(ZIPALIGN_PAGE_ALIGN_FLAGS) 4 $@ >/dev/null ; then \
+$(hide) if ! $(ZIPALIGN) -c -p 4 $@ >/dev/null ; then \
   mv $@ $@.unaligned; \
   $(ZIPALIGN) \
     -f \
@@ -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..cfe918f 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -4,7 +4,8 @@
 DEX_PREOPT_DEFAULT ?= true
 
 # The default filter for which files go into the system_other image (if it is
-# being used). To bundle everything one should set this to '%'
+# being used). Note that each pattern p here matches both '/<p>' and /system/<p>'.
+# To bundle everything one should set this to '%'.
 SYSTEM_OTHER_ODEX_FILTER ?= \
     app/% \
     priv-app/% \
@@ -99,7 +100,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 c61760b..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
@@ -500,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)),)
@@ -513,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)
@@ -582,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 \
@@ -644,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)
@@ -678,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 \
@@ -728,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)
@@ -778,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 := \
@@ -825,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 := \
@@ -860,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
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/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..29c5a4c 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}
 
@@ -232,6 +220,9 @@
 ADDITIONAL_BUILD_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn
 endif
 
+# Define ro.sanitize.<name> properties for all global sanitizers.
+ADDITIONAL_BUILD_PROPERTIES += $(foreach s,$(SANITIZE_TARGET),ro.sanitize.$(s)=true)
+
 # Sets the default value of ro.postinstall.fstab.prefix to /system.
 # Device board config should override the value to /product when needed by:
 #
@@ -494,7 +485,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 +498,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
@@ -1160,6 +1141,7 @@
   libdt_socket.so \
   libicui18n.so \
   libicuuc.so \
+  libicu_jni.so \
   libjavacore.so \
   libjdwp.so \
   libm.so \
@@ -1365,7 +1347,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 +1482,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 +1494,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 +1513,9 @@
 .PHONY: vendorimage
 vendorimage: $(INSTALLED_VENDORIMAGE_TARGET)
 
+.PHONY: vendorbootimage
+vendorbootimage: $(INSTALLED_VENDOR_BOOTIMAGE_TARGET)
+
 .PHONY: productimage
 productimage: $(INSTALLED_PRODUCTIMAGE_TARGET)
 
@@ -1547,6 +1537,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 +1561,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 +1657,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 +1707,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/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/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_droiddoc_prebuilt.mk b/core/soong_droiddoc_prebuilt.mk
index bf1f10b..c0467df 100644
--- a/core/soong_droiddoc_prebuilt.mk
+++ b/core/soong_droiddoc_prebuilt.mk
@@ -38,3 +38,7 @@
 .PHONY: $(LOCAL_MODULE) $(LOCAL_MODULE)-jdiff
 $(LOCAL_MODULE) $(LOCAL_MODULE)-jdiff : $(OUT_DOCS)/$(LOCAL_MODULE)-jdiff-docs.zip
 endif
+
+ifdef LOCAL_DROIDDOC_METADATA_ZIP
+$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_METADATA_ZIP),$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)-metadata.zip))
+endif
diff --git a/core/soong_rust_prebuilt.mk b/core/soong_rust_prebuilt.mk
index ea43078..23d18c4 100644
--- a/core/soong_rust_prebuilt.mk
+++ b/core/soong_rust_prebuilt.mk
@@ -28,21 +28,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 rlib and dylib libraries for translated arch
-      ifeq ($(filter RLIB_LIBRARIES DYLIB_LIBRARIES PROC_MACRO_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
-        skip_module := true
-      endif
-    endif
-  endif
-endif
-
-
-ifndef skip_module
-
 # Don't install rlib/proc_macro libraries.
 ifndef LOCAL_UNINSTALLABLE_MODULE
   ifneq ($(filter RLIB_LIBRARIES PROC_MACRO_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
@@ -121,7 +106,3 @@
 
 $(notice_target): | $(installed_static_library_notice_file_targets)
 $(LOCAL_INSTALLED_MODULE): | $(notice_target)
-endif # !skip_module
-
-skip_module :=
-
diff --git a/core/android_vts_host_config.mk b/core/suite_host_config.mk
similarity index 89%
rename from core/android_vts_host_config.mk
rename to core/suite_host_config.mk
index 38ba19d..d575c5b 100644
--- a/core/android_vts_host_config.mk
+++ b/core/suite_host_config.mk
@@ -16,11 +16,9 @@
 
 LOCAL_MODULE_CLASS := FAKE
 LOCAL_IS_HOST_MODULE := true
-LOCAL_COMPATIBILITY_SUITE := vts
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
 $(LOCAL_BUILT_MODULE):
-	@echo "VTS host-driven test target: $(PRIVATE_MODULE)"
+	@echo "$(LOCAL_COMPATIBILITY_SUITE) host-driven test target: $(PRIVATE_MODULE)"
 	$(hide) touch $@
-
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..ff5fb42 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-10-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 ff6defd..52ba814 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -49,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%
rename from target/board/generic_x86_64_ab/BoardConfig.mk
rename 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%
copy from target/board/generic_x86_64_ab/BoardConfig.mk
copy 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 cd98a48..7cc3270 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,6 +356,7 @@
     adb_keys \
     arping \
     gdbserver \
+    idlcli \
     init-debug.rc \
     iotop \
     iperf3 \
@@ -364,6 +364,7 @@
     logpersist.start \
     logtagd.rc \
     procrank \
+    remount \
     showmap \
     sqlite3 \
     ss \
@@ -384,7 +385,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 018bbb0..2b288e6 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -150,6 +150,9 @@
 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 4b6c010..8fed53c 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,11 +71,13 @@
 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.boot@1.1.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
@@ -85,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
@@ -98,29 +103,41 @@
 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.neuralnetworks@1.3.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
@@ -142,36 +159,45 @@
 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.vibrator@1.4.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 +209,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 +236,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 +250,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 1ada3c7..cd6a0f7 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)
 
@@ -66,8 +64,8 @@
 # For ringtones that rely on forward lock encryption
 PRODUCT_PACKAGES += libfwdlockengine
 
-# System libraries commonly depended on by things on the product partition.
-# This list will be pruned periodically.
+# System libraries commonly depended on by things on the system_ext or product partitions.
+# These lists will be pruned periodically.
 PRODUCT_PACKAGES += \
     android.hardware.biometrics.fingerprint@2.1 \
     android.hardware.radio@1.0 \
@@ -80,6 +78,7 @@
     android.hardware.secure_element@1.0 \
     android.hardware.wifi@1.0 \
     libaudio-resampler \
+    libaudiohal \
     libdrm \
     liblogwrap \
     liblz4 \
@@ -87,6 +86,18 @@
     libnl \
     libprotobuf-cpp-full \
 
+# These libraries are empty and have been combined into libhidlbase, but are still depended
+# on by things off /system.
+# TODO(b/135686713): remove these
+PRODUCT_PACKAGES += \
+    libhidltransport \
+    libhwbinder \
+
+# Camera service uses 'libdepthphoto' for adding dynamic depth
+# metadata inside depth jpegs.
+PRODUCT_PACKAGES += \
+    libdepthphoto \
+
 PRODUCT_PACKAGES_DEBUG += \
     avbctl \
     bootctl \
@@ -102,6 +113,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/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..d6a8b53 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)),)
@@ -60,30 +80,3 @@
 	    $(extra_recovery_keys)
 	$(SOONG_ZIP) -o $@ -j \
 	    $(foreach key_file, $(PRIVATE_CERT) $(PRIVATE_EXTRA_RECOVERY_KEYS), -f $(key_file))
-
-
-#######################################
-# update_engine_payload_key, used by update_engine. We use the same key as otacerts but in RSA
-# public key format.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := update_engine_payload_key
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_STEM := update-payload-key.pub.pem
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/update_engine
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem
-	openssl x509 -pubkey -noout -in $< > $@
-
-
-#######################################
-# update_engine_payload_key for recovery image, used by update_engine.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := update_engine_payload_key.recovery
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_STEM := update-payload-key.pub.pem
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/etc/update_engine
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem
-	openssl x509 -pubkey -noout -in $< > $@
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 3308f3d..6cde77e 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -105,6 +105,7 @@
     ],
     required: [
         "brillo_update_payload",
+        "checkvintf",
     ],
 }
 
@@ -180,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",
@@ -343,6 +344,9 @@
         "releasetools_img_from_target_files",
         "releasetools_ota_from_target_files",
     ],
+    required: [
+        "checkvintf",
+    ],
 }
 
 python_binary_host {
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 18ad8ce..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:
@@ -187,6 +192,7 @@
       payload_info['apex.key'],
       payload_info['Algorithm'],
       payload_info['Salt'],
+      no_hashtree,
       signing_args)
 
   # 1b. Update the embedded payload public key.
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/common.py b/tools/releasetools/common.py
index 8339cad..031db1d 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -47,22 +47,23 @@
 
 
 class Options(object):
+
   def __init__(self):
-    base_out_path = os.getenv('OUT_DIR_COMMON_BASE')
-    if base_out_path is None:
-      base_search_path = "out"
-    else:
-      base_search_path = os.path.join(base_out_path,
-                                      os.path.basename(os.getcwd()))
+    # Set up search path, in order to find framework/ and lib64/. At the time of
+    # running this function, user-supplied search path (`--path`) hasn't been
+    # available. So the value set here is the default, which might be overridden
+    # by commandline flag later.
+    exec_path = sys.argv[0]
+    if exec_path.endswith('.py'):
+      script_name = os.path.basename(exec_path)
+      # logger hasn't been initialized yet at this point. Use print to output
+      # warnings.
+      print(
+          'Warning: releasetools script should be invoked as hermetic Python '
+          'executable -- build and run `{}` directly.'.format(script_name[:-3]),
+          file=sys.stderr)
+    self.search_path = os.path.realpath(os.path.join(exec_path, '..'))
 
-    # Python >= 3.3 returns 'linux', whereas Python 2.7 gives 'linux2'.
-    platform_search_path = {
-        "linux": os.path.join(base_search_path, "host/linux-x86"),
-        "linux2": os.path.join(base_search_path, "host/linux-x86"),
-        "darwin": os.path.join(base_search_path, "host/darwin-x86"),
-    }
-
-    self.search_path = platform_search_path.get(sys.platform)
     self.signapk_path = "framework/signapk.jar"  # Relative to search_path
     self.signapk_shared_library_path = "lib64"   # Relative to search_path
     self.extra_signapk_args = []
@@ -100,7 +101,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 +285,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 +613,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 +629,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 +733,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)
@@ -629,7 +854,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
@@ -649,12 +874,21 @@
 
   # Check if chain partition is used.
   key_path = info_dict.get("avb_" + partition + "_key_path")
-  if key_path:
-    chained_partition_arg = GetAvbChainedPartitionArg(partition, info_dict)
-    return ["--chain_partition", chained_partition_arg]
-  else:
+  if not key_path:
     return ["--include_descriptors_from_image", image]
 
+  # For a non-A/B device, we don't chain /recovery nor include its descriptor
+  # into vbmeta.img. The recovery image will be configured on an independent
+  # boot chain, to be verified with AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION.
+  # See details at
+  # https://android.googlesource.com/platform/external/avb/+/master/README.md#booting-into-recovery.
+  if info_dict.get("ab_update") != "true" and partition == "recovery":
+    return []
+
+  # Otherwise chain the partition into vbmeta.
+  chained_partition_arg = GetAvbChainedPartitionArg(partition, info_dict)
+  return ["--chain_partition", chained_partition_arg]
+
 
 def GetAvbChainedPartitionArg(partition, info_dict, key=None):
   """Constructs and returns the arg to build or verify a chained partition.
@@ -741,6 +975,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.
@@ -754,24 +1007,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
 
@@ -784,7 +1019,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"
@@ -946,6 +1181,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, \
@@ -1200,7 +1534,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:
@@ -1213,12 +1547,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"):
@@ -1226,7 +1560,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):
@@ -2435,13 +2769,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.
@@ -2454,7 +2800,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 = ""
 
@@ -2471,10 +2817,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"
@@ -2486,10 +2838,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" || \\
@@ -2507,9 +2859,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/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 61c4f4e..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.
@@ -106,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
 
@@ -372,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,
@@ -594,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
@@ -611,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:
@@ -621,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,
@@ -757,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
 
@@ -779,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)
@@ -914,11 +882,6 @@
 
   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 67cec1c..dfcfb49 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -171,8 +171,16 @@
   --payload_signer_args <args>
       Specify the arguments needed for payload signer.
 
+  --payload_signer_maximum_signature_size <signature_size>
+      The maximum signature size (in bytes) that would be generated by the given
+      payload signer. Only meaningful when custom payload signer is specified
+      via '--payload_signer'.
+      If the signer uses a RSA key, this should be the number of bytes to
+      represent the modulus. If it uses an EC key, this is the size of a
+      DER-encoded ECDSA signature.
+
   --payload_signer_key_size <key_size>
-      Specify the key size in bytes of the payload signer.
+      Deprecated. Use the '--payload_signer_maximum_signature_size' instead.
 
   --skip_postinstall
       Skip the postinstall hooks when generating an A/B OTA package (default:
@@ -231,7 +239,7 @@
 OPTIONS.log_diff = None
 OPTIONS.payload_signer = None
 OPTIONS.payload_signer_args = []
-OPTIONS.payload_signer_key_size = None
+OPTIONS.payload_signer_maximum_signature_size = None
 OPTIONS.extracted_input = None
 OPTIONS.key_passwords = []
 OPTIONS.skip_postinstall = False
@@ -251,214 +259,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):
@@ -491,35 +296,31 @@
       self.signer = "openssl"
       self.signer_args = ["pkeyutl", "-sign", "-inkey", signing_key,
                           "-pkeyopt", "digest:sha256"]
-      self.key_size = self._GetKeySizeInBytes(signing_key)
+      self.maximum_signature_size = self._GetMaximumSignatureSizeInBytes(
+          signing_key)
     else:
       self.signer = OPTIONS.payload_signer
       self.signer_args = OPTIONS.payload_signer_args
-      if OPTIONS.payload_signer_key_size:
-        self.key_size = int(OPTIONS.payload_signer_key_size)
-        assert self.key_size == 256 or self.key_size == 512, \
-            "Unsupported key size {}".format(OPTIONS.payload_signer_key_size)
+      if OPTIONS.payload_signer_maximum_signature_size:
+        self.maximum_signature_size = int(
+            OPTIONS.payload_signer_maximum_signature_size)
       else:
-        self.key_size = 256
+        # The legacy config uses RSA2048 keys.
+        logger.warning("The maximum signature size for payload signer is not"
+                       " set, default to 256 bytes.")
+        self.maximum_signature_size = 256
 
   @staticmethod
-  def _GetKeySizeInBytes(signing_key):
-    modulus_file = common.MakeTempFile(prefix="modulus-")
-    cmd = ["openssl", "rsa", "-inform", "PEM", "-in", signing_key, "-modulus",
-           "-noout", "-out", modulus_file]
-    common.RunAndCheckOutput(cmd, verbose=False)
-
-    with open(modulus_file) as f:
-      modulus_string = f.read()
-    # The modulus string has the format "Modulus=$data", where $data is the
-    # concatenation of hex dump of the modulus.
-    MODULUS_PREFIX = "Modulus="
-    assert modulus_string.startswith(MODULUS_PREFIX)
-    modulus_string = modulus_string[len(MODULUS_PREFIX):]
-    key_size = len(modulus_string) // 2
-    assert key_size == 256 or key_size == 512, \
-        "Unsupported key size {}".format(key_size)
-    return key_size
+  def _GetMaximumSignatureSizeInBytes(signing_key):
+    out_signature_size_file = common.MakeTempFile("signature_size")
+    cmd = ["delta_generator", "--out_maximum_signature_size_file={}".format(
+        out_signature_size_file), "--private_key={}".format(signing_key)]
+    common.RunAndCheckOutput(cmd)
+    with open(out_signature_size_file) as f:
+      signature_size = f.read().rstrip()
+    logger.info("% outputs the maximum signature size: %", cmd[0],
+                signature_size)
+    return int(signature_size)
 
   def Sign(self, in_file):
     """Signs the given input file. Returns the output filename."""
@@ -599,7 +400,7 @@
     metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
     cmd = ["brillo_update_payload", "hash",
            "--unsigned_payload", self.payload_file,
-           "--signature_size", str(payload_signer.key_size),
+           "--signature_size", str(payload_signer.maximum_signature_size),
            "--metadata_hash_file", metadata_sig_file,
            "--payload_hash_file", payload_sig_file]
     self._Run(cmd)
@@ -614,7 +415,7 @@
     cmd = ["brillo_update_payload", "sign",
            "--unsigned_payload", self.payload_file,
            "--payload", signed_payload_file,
-           "--signature_size", str(payload_signer.key_size),
+           "--signature_size", str(payload_signer.maximum_signature_size),
            "--metadata_signature_file", signed_metadata_sig_file,
            "--payload_signature_file", signed_payload_sig_file]
     self._Run(cmd)
@@ -715,10 +516,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):
@@ -879,7 +689,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
@@ -909,7 +719,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")
@@ -1105,8 +915,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,
@@ -1519,8 +1329,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"]
@@ -1792,6 +1602,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)
 
@@ -1809,12 +1656,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)
 
@@ -1941,10 +1809,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.
@@ -2141,8 +2009,13 @@
       OPTIONS.payload_signer = a
     elif o == "--payload_signer_args":
       OPTIONS.payload_signer_args = shlex.split(a)
+    elif o == "--payload_signer_maximum_signature_size":
+      OPTIONS.payload_signer_maximum_signature_size = a
     elif o == "--payload_signer_key_size":
-      OPTIONS.payload_signer_key_size = a
+      # TODO(Xunchang) remove this option after cleaning up the callers.
+      logger.warning("The option '--payload_signer_key_size' is deprecated."
+                     " Use '--payload_signer_maximum_signature_size' instead.")
+      OPTIONS.payload_signer_maximum_signature_size = a
     elif o == "--extracted_input_target_files":
       OPTIONS.extracted_input = a
     elif o == "--skip_postinstall":
@@ -2183,6 +2056,7 @@
                                  "log_diff=",
                                  "payload_signer=",
                                  "payload_signer_args=",
+                                 "payload_signer_maximum_signature_size=",
                                  "payload_signer_key_size=",
                                  "extracted_input_target_files=",
                                  "skip_postinstall",
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..0f4f1da 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -153,6 +153,20 @@
 OPTIONS.avb_extra_args = {}
 
 
+AVB_FOOTER_ARGS_BY_PARTITION = {
+    'boot' : 'avb_boot_add_hash_footer_args',
+    'dtbo' : 'avb_dtbo_add_hash_footer_args',
+    'recovery' : 'avb_recovery_add_hash_footer_args',
+    'system' : 'avb_system_add_hashtree_footer_args',
+    'system_other' : 'avb_system_other_add_hashtree_footer_args',
+    'vendor' : 'avb_vendor_add_hashtree_footer_args',
+    'vendor_boot' : 'avb_vendor_boot_add_hash_footer_args',
+    'vbmeta' : 'avb_vbmeta_args',
+    'vbmeta_system' : 'avb_vbmeta_system_args',
+    'vbmeta_vendor' : 'avb_vbmeta_vendor_args',
+}
+
+
 def GetApkCerts(certmap):
   # apply the key remapping to the contents of the file
   for apk, cert in certmap.items():
@@ -479,7 +493,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:
@@ -542,14 +557,13 @@
       OPTIONS.rebuild_recovery = True
 
     # Don't copy OTA certs if we're replacing them.
+    # Replacement of update-payload-key.pub.pem was removed in b/116660991.
     elif (
         OPTIONS.replace_ota_keys and
         filename in (
             "BOOT/RAMDISK/system/etc/security/otacerts.zip",
-            "BOOT/RAMDISK/system/etc/update_engine/update-payload-key.pub.pem",
             "RECOVERY/RAMDISK/system/etc/security/otacerts.zip",
-            "SYSTEM/etc/security/otacerts.zip",
-            "SYSTEM/etc/update_engine/update-payload-key.pub.pem")):
+            "SYSTEM/etc/security/otacerts.zip")):
       pass
 
     # Skip META/misc_info.txt since we will write back the new values later.
@@ -602,11 +616,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:
@@ -616,6 +635,10 @@
   # Replace the AVB signing keys, if any.
   ReplaceAvbSigningKeys(misc_info)
 
+  # Rewrite the props in AVB signing args.
+  if misc_info.get('avb_enable') == 'true':
+    RewriteAvbProps(misc_info)
+
   # Write back misc_info with the latest values.
   ReplaceMiscInfoTxt(input_tf_zip, output_tf_zip, misc_info)
 
@@ -808,24 +831,6 @@
   # We DO NOT include the extra_recovery_keys (if any) here.
   WriteOtacerts(output_tf_zip, "SYSTEM/etc/security/otacerts.zip", mapped_keys)
 
-  # For A/B devices, update the payload verification key.
-  if misc_info.get("ab_update") == "true":
-    # Unlike otacerts.zip that may contain multiple keys, we can only specify
-    # ONE payload verification key.
-    if len(mapped_keys) > 1:
-      print("\n  WARNING: Found more than one OTA keys; Using the first one"
-            " as payload verification key.\n\n")
-
-    print("Using %s for payload verification." % (mapped_keys[0],))
-    pubkey = common.ExtractPublicKey(mapped_keys[0])
-    common.ZipWriteStr(
-        output_tf_zip,
-        "SYSTEM/etc/update_engine/update-payload-key.pub.pem",
-        pubkey)
-    common.ZipWriteStr(
-        output_tf_zip,
-        "BOOT/RAMDISK/system/etc/update_engine/update-payload-key.pub.pem",
-        pubkey)
 
 
 def ReplaceVerityPublicKey(output_zip, filename, key_path):
@@ -904,18 +909,6 @@
 def ReplaceAvbSigningKeys(misc_info):
   """Replaces the AVB signing keys."""
 
-  AVB_FOOTER_ARGS_BY_PARTITION = {
-      'boot' : 'avb_boot_add_hash_footer_args',
-      'dtbo' : 'avb_dtbo_add_hash_footer_args',
-      'recovery' : 'avb_recovery_add_hash_footer_args',
-      'system' : 'avb_system_add_hashtree_footer_args',
-      'system_other' : 'avb_system_other_add_hashtree_footer_args',
-      'vendor' : 'avb_vendor_add_hashtree_footer_args',
-      'vbmeta' : 'avb_vbmeta_args',
-      'vbmeta_system' : 'avb_vbmeta_system_args',
-      'vbmeta_vendor' : 'avb_vbmeta_vendor_args',
-  }
-
   def ReplaceAvbPartitionSigningKey(partition):
     key = OPTIONS.avb_keys.get(partition)
     if not key:
@@ -940,6 +933,32 @@
     ReplaceAvbPartitionSigningKey(partition)
 
 
+def RewriteAvbProps(misc_info):
+  """Rewrites the props in AVB signing args."""
+  for partition, args_key in AVB_FOOTER_ARGS_BY_PARTITION.items():
+    args = misc_info.get(args_key)
+    if not args:
+      continue
+
+    tokens = []
+    changed = False
+    for token in args.split(' '):
+      fingerprint_key = 'com.android.build.{}.fingerprint'.format(partition)
+      if not token.startswith(fingerprint_key):
+        tokens.append(token)
+        continue
+      prefix, tag = token.rsplit('/', 1)
+      tokens.append('{}/{}'.format(prefix, EditTags(tag)))
+      changed = True
+
+    if changed:
+      result = ' '.join(tokens)
+      print('Rewriting AVB prop for {}:\n'.format(partition))
+      print('  replace: {}'.format(args))
+      print('     with: {}'.format(result))
+      misc_info[args_key] = result
+
+
 def BuildKeyMap(misc_info, key_mapping_options):
   for s, d in key_mapping_options:
     if s is None:   # -d option
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
index a1328c2..79f9018 100644
--- a/tools/releasetools/test_check_target_files_vintf.py
+++ b/tools/releasetools/test_check_target_files_vintf.py
@@ -78,6 +78,8 @@
     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)
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index ceb023f..8a52419 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()
@@ -1161,6 +1373,39 @@
     self.assertEqual('5', chained_partition_args[1])
     self.assertTrue(os.path.exists(chained_partition_args[2]))
 
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_AppendVBMetaArgsForPartition_recoveryAsChainedPartition_nonAb(self):
+    testdata_dir = test_utils.get_testdata_dir()
+    pubkey = os.path.join(testdata_dir, 'testkey.pubkey.pem')
+    info_dict = {
+        'avb_avbtool': 'avbtool',
+        'avb_recovery_key_path': pubkey,
+        'avb_recovery_rollback_index_location': 3,
+    }
+    cmd = common.GetAvbPartitionArg(
+        'recovery', '/path/to/recovery.img', info_dict)
+    self.assertFalse(cmd)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_AppendVBMetaArgsForPartition_recoveryAsChainedPartition_ab(self):
+    testdata_dir = test_utils.get_testdata_dir()
+    pubkey = os.path.join(testdata_dir, 'testkey.pubkey.pem')
+    info_dict = {
+        'ab_update': 'true',
+        'avb_avbtool': 'avbtool',
+        'avb_recovery_key_path': pubkey,
+        'avb_recovery_rollback_index_location': 3,
+    }
+    cmd = common.GetAvbPartitionArg(
+        'recovery', '/path/to/recovery.img', info_dict)
+    self.assertEqual(2, len(cmd))
+    self.assertEqual('--chain_partition', cmd[0])
+    chained_partition_args = cmd[1].split(':')
+    self.assertEqual(3, len(chained_partition_args))
+    self.assertEqual('recovery', chained_partition_args[0])
+    self.assertEqual('3', chained_partition_args[1])
+    self.assertTrue(os.path.exists(chained_partition_args[2]))
+
 
 class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
   """Checks the format of install-recovery.sh.
@@ -1224,24 +1469,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 +1506,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..38faf64 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."""
@@ -1030,10 +885,28 @@
       payload_offset, metadata_total = (
           property_files._GetPayloadMetadataOffsetAndSize(input_zip))
 
-    # Read in the metadata signature directly.
+    # The signature proto has the following format (details in
+    #  /platform/system/update_engine/update_metadata.proto):
+    #  message Signature {
+    #    optional uint32 version = 1;
+    #    optional bytes data = 2;
+    #    optional fixed32 unpadded_signature_size = 3;
+    #  }
+    #
+    # According to the protobuf encoding, the tail of the signature message will
+    # be [signature string(256 bytes) + encoding of the fixed32 number 256]. And
+    # 256 is encoded as 'x1d\x00\x01\x00\x00':
+    # [3 (field number) << 3 | 5 (type) + byte reverse of 0x100 (256)].
+    # Details in (https://developers.google.com/protocol-buffers/docs/encoding)
+    signature_tail_length = self.SIGNATURE_SIZE + 5
+    self.assertGreater(metadata_total, signature_tail_length)
     with open(output_file, 'rb') as verify_fp:
-      verify_fp.seek(payload_offset + metadata_total - self.SIGNATURE_SIZE)
-      metadata_signature = verify_fp.read(self.SIGNATURE_SIZE)
+      verify_fp.seek(payload_offset + metadata_total - signature_tail_length)
+      metadata_signature_proto_tail = verify_fp.read(signature_tail_length)
+
+    self.assertEqual(b'\x1d\x00\x01\x00\x00',
+                     metadata_signature_proto_tail[-5:])
+    metadata_signature = metadata_signature_proto_tail[:-5]
 
     # Now we extract the metadata hash via brillo_update_payload script, which
     # will serve as the oracle result.
@@ -1195,11 +1068,13 @@
     with open(file1, 'rb') as fp1, open(file2, 'rb') as fp2:
       self.assertEqual(fp1.read(), fp2.read())
 
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_init(self):
     payload_signer = PayloadSigner()
     self.assertEqual('openssl', payload_signer.signer)
-    self.assertEqual(256, payload_signer.key_size)
+    self.assertEqual(256, payload_signer.maximum_signature_size)
 
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_init_withPassword(self):
     common.OPTIONS.package_key = os.path.join(
         self.testdata_dir, 'testkey_with_passwd')
@@ -1212,18 +1087,27 @@
   def test_init_withExternalSigner(self):
     common.OPTIONS.payload_signer = 'abc'
     common.OPTIONS.payload_signer_args = ['arg1', 'arg2']
-    common.OPTIONS.payload_signer_key_size = '512'
+    common.OPTIONS.payload_signer_maximum_signature_size = '512'
     payload_signer = PayloadSigner()
     self.assertEqual('abc', payload_signer.signer)
     self.assertEqual(['arg1', 'arg2'], payload_signer.signer_args)
-    self.assertEqual(512, payload_signer.key_size)
+    self.assertEqual(512, payload_signer.maximum_signature_size)
 
-  def test_GetKeySizeInBytes_512Bytes(self):
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_GetMaximumSignatureSizeInBytes_512Bytes(self):
     signing_key = os.path.join(self.testdata_dir, 'testkey_RSA4096.key')
     # pylint: disable=protected-access
-    key_size = PayloadSigner._GetKeySizeInBytes(signing_key)
-    self.assertEqual(512, key_size)
+    signature_size = PayloadSigner._GetMaximumSignatureSizeInBytes(signing_key)
+    self.assertEqual(512, signature_size)
 
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_GetMaximumSignatureSizeInBytes_ECKey(self):
+    signing_key = os.path.join(self.testdata_dir, 'testkey_EC.key')
+    # pylint: disable=protected-access
+    signature_size = PayloadSigner._GetMaximumSignatureSizeInBytes(signing_key)
+    self.assertEqual(72, signature_size)
+
+  @test_utils.SkipIfExternalToolsUnavailable()
   def test_Sign(self):
     payload_signer = PayloadSigner()
     input_file = os.path.join(self.testdata_dir, self.SIGFILE)
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 70c147e..2b84413 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -23,7 +23,8 @@
 import test_utils
 from sign_target_files_apks import (
     CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ReadApexKeysInfo,
-    ReplaceCerts, ReplaceVerityKeyId, RewriteProps, WriteOtacerts)
+    ReplaceCerts, ReplaceVerityKeyId, RewriteAvbProps, RewriteProps,
+    WriteOtacerts)
 
 
 class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
@@ -52,6 +53,40 @@
     # Tags are sorted.
     self.assertEqual(EditTags('xyz,abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
 
+  def test_RewriteAvbProps(self):
+    misc_info = {
+      'avb_boot_add_hash_footer_args':
+          ('--prop com.android.build.boot.os_version:R '
+           '--prop com.android.build.boot.security_patch:2019-09-05'),
+      'avb_system_add_hashtree_footer_args':
+          ('--prop com.android.build.system.os_version:R '
+           '--prop com.android.build.system.security_patch:2019-09-05 '
+           '--prop com.android.build.system.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/test-keys'),
+      'avb_vendor_add_hashtree_footer_args':
+          ('--prop com.android.build.vendor.os_version:R '
+           '--prop com.android.build.vendor.security_patch:2019-09-05 '
+           '--prop com.android.build.vendor.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/dev-keys'),
+    }
+    expected_dict = {
+      'avb_boot_add_hash_footer_args':
+          ('--prop com.android.build.boot.os_version:R '
+           '--prop com.android.build.boot.security_patch:2019-09-05'),
+      'avb_system_add_hashtree_footer_args':
+          ('--prop com.android.build.system.os_version:R '
+           '--prop com.android.build.system.security_patch:2019-09-05 '
+           '--prop com.android.build.system.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/release-keys'),
+      'avb_vendor_add_hashtree_footer_args':
+          ('--prop com.android.build.vendor.os_version:R '
+           '--prop com.android.build.vendor.security_patch:2019-09-05 '
+           '--prop com.android.build.vendor.fingerprint:'
+           'Android/aosp_taimen/taimen:R/QT/foo:userdebug/release-keys'),
+    }
+    RewriteAvbProps(misc_info)
+    self.assertDictEqual(expected_dict, misc_info)
+
   def test_RewriteProps(self):
     props = (
         ('', ''),
@@ -525,3 +560,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/testkey_EC.key b/tools/releasetools/testdata/testkey_EC.key
new file mode 100644
index 0000000..9e65a68
--- /dev/null
+++ b/tools/releasetools/testdata/testkey_EC.key
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGaguGj8Yb1KkqKHd
+ISblUsjtOCbzAuVpX81i02sm8FWhRANCAARBnuotwKOsuvjH6iwTDhOAi7Q5pLWz
+xDkZjg2pcfbfi9FFTvLYETas7B2W6fx9PUezUmHTFTDV2JZuMYYFdZOw
+-----END PRIVATE KEY-----
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index d189499..9c2bc51 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'):
@@ -326,20 +346,25 @@
       key = info_dict['avb_vbmeta_key_path']
 
     # avbtool verifies all the images that have descriptors listed in vbmeta.
+    # Using `--follow_chain_partitions` so it would additionally verify chained
+    # vbmeta partitions (e.g. vbmeta_system).
     image = os.path.join(input_tmp, 'IMAGES', 'vbmeta.img')
     cmd = [info_dict['avb_avbtool'], 'verify_image', '--image', image,
-           '--key', key]
+           '--key', key, '--follow_chain_partitions']
 
     # Append the args for chained partitions if any.
     for partition in common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS:
       key_name = 'avb_' + partition + '_key_path'
       if info_dict.get(key_name) is not None:
+        if info_dict.get('ab_update') != 'true' and partition == 'recovery':
+          continue
+
         # Use the key file from command line if specified; otherwise fall back
         # to the one in info dict.
         key_file = options.get(key_name, info_dict[key_name])
         chained_partition_arg = common.GetAvbChainedPartitionArg(
             partition, info_dict, key_file)
-        cmd.extend(["--expected_chain_partition", chained_partition_arg])
+        cmd.extend(['--expected_chain_partition', chained_partition_arg])
 
     proc = common.Run(cmd)
     stdoutdata, _ = proc.communicate()
@@ -351,6 +376,22 @@
         'Verified %s with avbtool (key: %s):\n%s', image, key,
         stdoutdata.rstrip())
 
+    # avbtool verifies recovery image for non-A/B devices.
+    if (info_dict.get('ab_update') != 'true' and
+        info_dict.get('no_recovery') != 'true'):
+      image = os.path.join(input_tmp, 'IMAGES', 'recovery.img')
+      key = info_dict['avb_recovery_key_path']
+      cmd = [info_dict['avb_avbtool'], 'verify_image', '--image', image,
+             '--key', key]
+      proc = common.Run(cmd)
+      stdoutdata, _ = proc.communicate()
+      assert proc.returncode == 0, \
+          'Failed to verify {} with avbtool (key: {}):\n{}'.format(
+              image, key, stdoutdata)
+      logging.info(
+          'Verified %s with avbtool (key: %s):\n%s', image, key,
+          stdoutdata.rstrip())
+
 
 def main():
   parser = argparse.ArgumentParser(
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..6218f93 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,
@@ -3152,7 +2264,7 @@
       i['compiled_patterns'].append(re.compile(pat))
 
 
-def find_android_root(path):
+def find_warn_py_and_android_root(path):
   """Set and return android_root path if it is found."""
   global android_root
   parts = path.split('/')
@@ -3161,8 +2273,36 @@
     # Android root directory should contain this script.
     if os.path.exists(root_path + '/build/make/tools/warn.py'):
       android_root = root_path
-      return root_path
-  return ''
+      return True
+  return False
+
+
+def find_android_root():
+  """Guess android_root from common prefix of file paths."""
+  # Use the longest common prefix of the absolute file paths
+  # of the first 10000 warning messages as the android_root.
+  global android_root
+  warning_lines = set()
+  warning_pattern = re.compile('^/[^ ]*/[^ ]*: warning: .*')
+  count = 0
+  infile = io.open(args.buildlog, mode='r', encoding='utf-8')
+  for line in infile:
+    if warning_pattern.match(line):
+      warning_lines.add(line)
+      count += 1
+      if count > 9999:
+        break
+      # Try to find warn.py and use its location to find
+      # the source tree root.
+      if count < 100:
+        path = os.path.normpath(re.sub(':.*$', '', line))
+        if find_warn_py_and_android_root(path):
+          return
+  # Do not use common prefix of a small number of paths.
+  if count > 10:
+    root_path = os.path.commonprefix(warning_lines)
+    if len(root_path) > 2 and root_path[len(root_path) - 1] == '/':
+      android_root = root_path[:-1]
 
 
 def remove_android_root_prefix(path):
@@ -3177,13 +2317,10 @@
   """Normalize file path relative to android_root."""
   # If path is not an absolute path, just normalize it.
   path = os.path.normpath(path)
-  if path[0] != '/':
-    return path
   # Remove known prefix of root path and normalize the suffix.
-  if android_root or find_android_root(path):
+  if path[0] == '/' and android_root:
     return remove_android_root_prefix(path)
-  else:
-    return path
+  return path
 
 
 def normalize_warning_line(line):
@@ -3208,16 +2345,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)
@@ -3532,6 +2695,7 @@
 
 
 def main():
+  find_android_root()
   # We must use 'utf-8' codec to parse some non-ASCII code in warnings.
   warning_lines = parse_input_file(
       io.open(args.buildlog, mode='r', encoding='utf-8'))