For ds builds only, emit a separate metadata file for samples only.
am: a9fcf48078

Change-Id: Ic2b786401a3431896e6441c8c2c61545a6aaea1b
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..a1455d4
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,8 @@
+LOCAL_PATH := $(call my-dir)
+
+# We're relocating the build project to a subdirectory, then using symlinks
+# to expose the subdirectories where they used to be. If the manifest hasn't
+# been updated, we need to include all the subdirectories.
+ifeq ($(LOCAL_PATH),build)
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 3c8d6ce..a3b5f3c 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -374,6 +374,9 @@
 # $(PRODUCT_OUT)/recovery/root/sdcard goes from symlink to folder.
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sdcard)
 
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/previous_overlays.txt)
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/current_packages.txt)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/buildspec.mk.default b/buildspec.mk.default
index d14208e..a7ac7ec 100644
--- a/buildspec.mk.default
+++ b/buildspec.mk.default
@@ -61,9 +61,6 @@
 # will be added to LOCAL_CFLAGS when building the module.
 #DEBUG_MODULE_ModuleName:=true
 
-# Specify an alternative tool chain prefix if needed.
-#TARGET_TOOLS_PREFIX:=
-
 # Specify the extra CFLAGS to use when building a module whose
 # DEBUG_MODULE_ variable is set.  Host and device flags are handled
 # separately.
@@ -108,4 +105,4 @@
 # variable will be changed.  After you have modified this file with the new
 # changes (see buildspec.mk.default), update this to the new value from
 # buildspec.mk.default.
-BUILD_ENV_SEQUENCE_NUMBER := 10
+BUILD_ENV_SEQUENCE_NUMBER := 12
diff --git a/core/Makefile b/core/Makefile
index d804c37..7a1041a 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -284,7 +284,7 @@
 # -----------------------------------------------------------------
 # vendor build.prop
 #
-# For verifying that the vendor build is what we thing it is
+# For verifying that the vendor build is what we think it is
 ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
 INSTALLED_VENDOR_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR)/build.prop
 ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_BUILD_PROP_TARGET)
@@ -386,7 +386,31 @@
 endif
 
 # -----------------------------------------------------------------
+# build system stats
+BUILD_SYSTEM_STATS := $(PRODUCT_OUT)/build_system_stats.txt
+$(BUILD_SYSTEM_STATS):
+	@rm -f $@
+	@$(foreach s,$(STATS.MODULE_TYPE),echo "modules_type_make,$(s),$(words $(STATS.MODULE_TYPE.$(s)))" >>$@;)
+	@$(foreach s,$(STATS.SOONG_MODULE_TYPE),echo "modules_type_soong,$(s),$(STATS.SOONG_MODULE_TYPE.$(s))" >>$@;)
+$(call dist-for-goals,droidcore,$(BUILD_SYSTEM_STATS))
 
+# -----------------------------------------------------------------
+# Modules ready to be converted to Soong, ordered by how many
+# modules depend on them.
+SOONG_CONV := $(sort $(SOONG_CONV))
+SOONG_CONV_DATA := $(call intermediates-dir-for,PACKAGING,soong_conversion)/soong_conv_data
+$(SOONG_CONV_DATA):
+	@rm -f $@
+	@$(foreach s,$(SOONG_CONV),echo "$(s),$(sort $(SOONG_CONV.$(s).PROBLEMS)),$(sort $(filter-out $(SOONG_ALREADY_CONV),$(SOONG_CONV.$(s).DEPS)))" >>$@;)
+
+SOONG_TO_CONVERT_SCRIPT := build/tools/soong_to_convert.py
+SOONG_TO_CONVERT := $(PRODUCT_OUT)/soong_to_convert.txt
+$(SOONG_TO_CONVERT): $(SOONG_CONV_DATA) $(SOONG_TO_CONVERT_SCRIPT)
+	@rm -f $@
+	$(hide) $(SOONG_TO_CONVERT_SCRIPT) $< >$@
+$(call dist-for-goals,droidcore,$(SOONG_TO_CONVERT))
+
+# -----------------------------------------------------------------
 # The dev key is used to sign this package, and as the key required
 # for future OTA packages installed by this system.  Actual product
 # deliverables will be re-signed by hand.  We expect this file to
@@ -420,9 +444,9 @@
 pdk_fusion_log_tags_file := $(patsubst $(PRODUCT_OUT)/%,$(_pdk_fusion_intermediates)/%,$(filter $(event_log_tags_file),$(ALL_PDK_FUSION_FILES)))
 
 $(all_event_log_tags_file): PRIVATE_SRC_FILES := $(all_event_log_tags_src) $(pdk_fusion_log_tags_file)
-$(all_event_log_tags_file): $(all_event_log_tags_src) $(pdk_fusion_log_tags_file)
+$(all_event_log_tags_file): $(all_event_log_tags_src) $(pdk_fusion_log_tags_file) $(MERGETAGS) build/tools/event_log_tags.py
 	$(hide) mkdir -p $(dir $@)
-	$(hide) build/tools/merge-event-log-tags.py -o $@ $(PRIVATE_SRC_FILES)
+	$(hide) $(MERGETAGS) -o $@ $(PRIVATE_SRC_FILES)
 
 # Include tags from all packages included in this product, plus all
 # tags that are part of the system (ie, not in a vendor/ or device/
@@ -436,9 +460,9 @@
 
 $(event_log_tags_file): PRIVATE_SRC_FILES := $(event_log_tags_src) $(pdk_fusion_log_tags_file)
 $(event_log_tags_file): PRIVATE_MERGED_FILE := $(all_event_log_tags_file)
-$(event_log_tags_file): $(event_log_tags_src) $(all_event_log_tags_file) $(pdk_fusion_log_tags_file)
+$(event_log_tags_file): $(event_log_tags_src) $(all_event_log_tags_file) $(pdk_fusion_log_tags_file) $(MERGETAGS) build/tools/event_log_tags.py
 	$(hide) mkdir -p $(dir $@)
-	$(hide) build/tools/merge-event-log-tags.py -o $@ -m $(PRIVATE_MERGED_FILE) $(PRIVATE_SRC_FILES)
+	$(hide) $(MERGETAGS) -o $@ -m $(PRIVATE_MERGED_FILE) $(PRIVATE_SRC_FILES)
 
 event-log-tags: $(event_log_tags_file)
 
@@ -468,7 +492,6 @@
 # -----------------------------------------------------------------
 # the ramdisk
 INTERNAL_RAMDISK_FILES := $(filter $(TARGET_ROOT_OUT)/%, \
-	$(ALL_PREBUILT) \
 	$(ALL_GENERATED_SOURCES) \
 	$(ALL_DEFAULT_INSTALLED_MODULES))
 
@@ -499,11 +522,6 @@
 
 INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
 
-BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
-ifdef BOARD_KERNEL_CMDLINE
-  INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
-endif
-
 BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
 ifdef BOARD_KERNEL_BASE
   INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
@@ -514,6 +532,18 @@
   INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
 endif
 
+ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
+ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
+                | grep keyid | sed 's/://g' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/keyid//g'`
+endif
+endif
+
+BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
+ifdef BOARD_KERNEL_CMDLINE
+INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
+endif
+
 INTERNAL_MKBOOTIMG_VERSION_ARGS := \
     --os_version $(PLATFORM_VERSION) \
     --os_patch_level $(PLATFORM_SECURITY_PATCH)
@@ -531,7 +561,31 @@
 ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
 ifeq ($(TARGET_BOOTIMAGE_USE_EXT2),true)
 $(error TARGET_BOOTIMAGE_USE_EXT2 is not supported anymore)
-else ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)) # TARGET_BOOTIMAGE_USE_EXT2 != true
+
+else ifeq (true,$(BOARD_AVB_ENABLE)) # TARGET_BOOTIMAGE_USE_EXT2 != true
+
+$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES)
+	$(call pretty,"Target boot image: $@")
+	$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
+	$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+	$(hide) $(AVBTOOL) add_hash_footer \
+	  --image $@ \
+	  --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
+	  --partition_name boot $(INTERNAL_AVB_SIGNING_ARGS) \
+	  $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+
+.PHONY: bootimage-nodeps
+bootimage-nodeps: $(MKBOOTIMG) $(AVBTOOL)
+	@echo "make $@: ignoring dependencies"
+	$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET)
+	$(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+	$(hide) $(AVBTOOL) add_hash_footer \
+	  --image $@ \
+	  --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
+	  --partition_name boot $(INTERNAL_AVB_SIGNING_ARGS) \
+	  $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+
+else ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)) # BOARD_AVB_ENABLE != true
 
 $(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER)
 	$(call pretty,"Target boot image: $@")
@@ -664,7 +718,7 @@
 $(target_notice_file_html_gz): $(target_notice_file_html) | $(MINIGZIP)
 	$(hide) $(MINIGZIP) -9 < $< > $@
 installed_notice_html_gz := $(TARGET_OUT)/etc/NOTICE.html.gz
-$(installed_notice_html_gz): $(target_notice_file_html_gz) | $(ACP)
+$(installed_notice_html_gz): $(target_notice_file_html_gz)
 	$(copy-file-to-target)
 
 # if we've been run my mm, mmm, etc, don't reinstall this every time
@@ -708,6 +762,10 @@
 	$(hide) rm -f $@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) openssl x509 -pubkey -noout -in $< > $@
+
+ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_RECOVERY_ROOT_OUT)/etc/update_engine/update-payload-key.pub.pem
+$(TARGET_RECOVERY_ROOT_OUT)/etc/update_engine/update-payload-key.pub.pem: $(TARGET_OUT_ETC)/update_engine/update-payload-key.pub.pem
+	$(hide) cp -f $< $@
 endif
 endif
 
@@ -876,6 +934,11 @@
 else
 recovery_fstab := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery.fstab))
 endif
+ifdef TARGET_RECOVERY_BRICK
+recovery_brick := $(TARGET_RECOVERY_BRICK)
+else
+recovery_brick :=
+endif
 
 # Prior to A/B update, we used to have:
 #   boot.img + recovery-from-boot.p + recovery-resource.dat = recovery.img.
@@ -961,6 +1024,8 @@
     cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/$(newline))
   $(hide) $(foreach item,$(recovery_fstab), \
     cp -f $(item) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.fstab)
+  $(if $(strip $(recovery_brick)), \
+    $(hide) cp -f $(recovery_brick) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.brick)
   $(hide) cp $(RECOVERY_INSTALL_OTA_KEYS) $(TARGET_RECOVERY_ROOT_OUT)/res/keys
   $(hide) cat $(INSTALLED_DEFAULT_PROP_TARGET) $(recovery_build_prop) \
           > $(TARGET_RECOVERY_ROOT_OUT)/default.prop
@@ -1048,7 +1113,6 @@
         $(ALL_PDK_FUSION_FILES))
 
 INTERNAL_SYSTEMIMAGE_FILES := $(filter $(TARGET_OUT)/%, \
-    $(ALL_PREBUILT) \
     $(ALL_GENERATED_SOURCES) \
     $(ALL_DEFAULT_INSTALLED_MODULES) \
     $(PDK_FUSION_SYSIMG_FILES) \
@@ -1079,7 +1143,7 @@
 BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
 
 # Create symlink /system/vendor to /vendor if necessary.
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+ifdef BOARD_USES_VENDORIMAGE
 define create-system-vendor-symlink
 $(hide) if [ -d $(TARGET_OUT)/vendor ] && [ ! -h $(TARGET_OUT)/vendor ]; then \
   echo 'Non-symlink $(TARGET_OUT)/vendor detected!' 1>&2; \
@@ -1116,9 +1180,16 @@
            fi; \
            mkdir -p $(DIST_DIR); cp $(INSTALLED_FILES_FILE) $(DIST_DIR)/installed-files-rescued.txt; \
            exit 1 )
+  $(if $(BOARD_AVB_ENABLE), \
+    $(hide) $(AVBTOOL) add_hashtree_footer \
+      --image $(1) \
+      --partition_size $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) \
+      --partition_name system \
+      $(INTERNAL_AVB_SIGNING_ARGS) \
+      $(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS))
 endef
 
-$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
+$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE) $(BUILD_IMAGE_SRCS)
 	$(call build-systemimage-target,$@)
 
 INSTALLED_SYSTEMIMAGE := $(PRODUCT_OUT)/system.img
@@ -1146,7 +1217,7 @@
 endif
 
 
-$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH) | $(ACP)
+$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH)
 	@echo "Install system fs image: $@"
 	$(copy-file-to-target)
 	$(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
@@ -1332,7 +1403,8 @@
 # We just build this directly to the install location.
 INSTALLED_USERDATAIMAGE_TARGET := $(BUILT_USERDATAIMAGE_TARGET)
 $(INSTALLED_USERDATAIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) \
-                                   $(INTERNAL_USERDATAIMAGE_FILES)
+                                   $(INTERNAL_USERDATAIMAGE_FILES) \
+                                   $(BUILD_IMAGE_SRCS)
 	$(build-userdataimage-target)
 
 .PHONY: userdataimage-nodeps
@@ -1358,12 +1430,48 @@
 $(INSTALLED_USERDATATARBALL_TARGET): $(FS_GET_STATS) $(INTERNAL_USERDATAIMAGE_FILES)
 	$(build-userdatatarball-target)
 
+$(call dist-for-goals,userdatatarball,$(INSTALLED_USERDATATARBALL_TARGET))
+
 .PHONY: userdatatarball-nodeps
 userdatatarball-nodeps: $(FS_GET_STATS)
 	$(build-userdatatarball-target)
 
 
 # -----------------------------------------------------------------
+# partition table image
+ifdef BOARD_BPT_INPUT_FILES
+
+BUILT_BPTIMAGE_TARGET := $(PRODUCT_OUT)/partition-table.img
+BUILT_BPTJSON_TARGET := $(PRODUCT_OUT)/partition-table.bpt
+
+INTERNAL_BVBTOOL_MAKE_TABLE_ARGS := \
+	--output_gpt $(BUILT_BPTIMAGE_TARGET) \
+	--output_json $(BUILT_BPTJSON_TARGET) \
+	$(foreach file, $(BOARD_BPT_INPUT_FILES), --input $(file))
+
+ifdef BOARD_BPT_DISK_SIZE
+INTERNAL_BVBTOOL_MAKE_TABLE_ARGS += --disk_size $(BOARD_BPT_DISK_SIZE)
+endif
+
+define build-bptimage-target
+  $(call pretty,"Target partition table image: $(INSTALLED_BPTIMAGE_TARGET)")
+  $(hide) $(BPTTOOL) make_table $(INTERNAL_BVBTOOL_MAKE_TABLE_ARGS) $(BOARD_BPT_MAKE_TABLE_ARGS)
+endef
+
+INSTALLED_BPTIMAGE_TARGET := $(BUILT_BPTIMAGE_TARGET)
+$(BUILT_BPTJSON_TARGET): $(INSTALLED_BPTIMAGE_TARGET)
+	$(hide) touch -c $(BUILT_BPTJSON_TARGET)
+
+$(INSTALLED_BPTIMAGE_TARGET): $(BPTTOOL) $(BOARD_BPT_INPUT_FILES)
+	$(build-bptimage-target)
+
+.PHONY: bptimage-nodeps
+bptimage-nodeps:
+	$(build-bptimage-target)
+
+endif # BOARD_BPT_INPUT_FILES
+
+# -----------------------------------------------------------------
 # cache partition image
 ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
 INTERNAL_CACHEIMAGE_FILES := \
@@ -1386,7 +1494,7 @@
 
 # We just build this directly to the install location.
 INSTALLED_CACHEIMAGE_TARGET := $(BUILT_CACHEIMAGE_TARGET)
-$(INSTALLED_CACHEIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES)
+$(INSTALLED_CACHEIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES) $(BUILD_IMAGE_SRCS)
 	$(build-cacheimage-target)
 
 .PHONY: cacheimage-nodeps
@@ -1395,6 +1503,60 @@
 
 endif # BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
 
+# -----------------------------------------------------------------
+# vbmeta image
+ifeq ($(BOARD_AVB_ENABLE),true)
+
+BUILT_VBMETAIMAGE_TARGET := $(PRODUCT_OUT)/vbmeta.img
+
+INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS := \
+    --include_descriptors_from_image $(INSTALLED_BOOTIMAGE_TARGET) \
+    --include_descriptors_from_image $(INSTALLED_SYSTEMIMAGE) \
+    --generate_dm_verity_cmdline_from_hashtree $(INSTALLED_SYSTEMIMAGE)
+
+ifdef BOARD_AVB_ROLLBACK_INDEX
+INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += --rollback_index $(BOARD_AVB_ROLLBACK_INDEX)
+endif
+
+ifndef BOARD_AVB_KEY_PATH
+# If key path isn't specified, use the 4096-bit test key.
+INTERNAL_AVB_SIGNING_ARGS := \
+    --algorithm SHA256_RSA4096 \
+    --key external/avb/test/data/testkey_rsa4096.pem
+else
+INTERNAL_AVB_SIGNING_ARGS := \
+    --algorithm $(BOARD_AVB_ALGORITHM) --key $(BOARD_AVB_KEY_PATH)
+endif
+
+ifndef BOARD_BOOTIMAGE_PARTITION_SIZE
+  $(error BOARD_BOOTIMAGE_PARTITION_SIZE must be set for BOARD_AVB_ENABLE)
+endif
+
+ifndef BOARD_SYSTEMIMAGE_PARTITION_SIZE
+  $(error BOARD_SYSTEMIMAGE_PARTITION_SIZE must be set for BOARD_AVB_ENABLE)
+endif
+
+define build-vbmetaimage-target
+  $(call pretty,"Target vbmeta image: $(INSTALLED_VBMETAIMAGE_TARGET)")
+  $(hide) $(AVBTOOL) make_vbmeta_image \
+    $(INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS) \
+    $(INTERNAL_AVB_SIGNING_ARGS) \
+    $(BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS) \
+    --output $@
+endef
+
+INSTALLED_VBMETAIMAGE_TARGET := $(BUILT_VBMETAIMAGE_TARGET)
+$(INSTALLED_VBMETAIMAGE_TARGET): $(AVBTOOL) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_SYSTEMIMAGE)
+	$(build-vbmetaimage-target)
+
+.PHONY: vbmetaimage-nodeps
+vbmetaimage-nodeps:
+	$(build-vbmetaimage-target)
+
+# We need $(AVBTOOL) for system.img generation.
+FULL_SYSTEMIMAGE_DEPS += $(AVBTOOL)
+
+endif # BOARD_AVB_ENABLE
 
 # -----------------------------------------------------------------
 # vendor partition image
@@ -1431,14 +1593,17 @@
 
 # We just build this directly to the install location.
 INSTALLED_VENDORIMAGE_TARGET := $(BUILT_VENDORIMAGE_TARGET)
-$(INSTALLED_VENDORIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDORIMAGE_FILES) $(INSTALLED_FILES_FILE_VENDOR)
+$(INSTALLED_VENDORIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDORIMAGE_FILES) $(INSTALLED_FILES_FILE_VENDOR) $(BUILD_IMAGE_SRCS)
 	$(build-vendorimage-target)
 
 .PHONY: vendorimage-nodeps
 vendorimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
 	$(build-vendorimage-target)
 
-endif # BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+else ifdef BOARD_PREBUILT_VENDORIMAGE
+INSTALLED_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vendor.img
+$(eval $(call copy-one-file,$(BOARD_PREBUILT_VENDORIMAGE),$(INSTALLED_VENDORIMAGE_TARGET)))
+endif
 
 # -----------------------------------------------------------------
 # bring in the installer image generation defines if necessary
@@ -1513,8 +1678,6 @@
   $(HOST_LIBRARY_PATH)/libcutils$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libselinux$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libcrypto-host$(HOST_SHLIB_SUFFIX) \
-  $(HOST_LIBRARY_PATH)/libdivsufsort$(HOST_SHLIB_SUFFIX) \
-  $(HOST_LIBRARY_PATH)/libdivsufsort64$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libext2fs-host$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libext2_blkid-host$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libext2_com_err-host$(HOST_SHLIB_SUFFIX) \
@@ -1525,7 +1688,6 @@
   $(HOST_LIBRARY_PATH)/libconscrypt_openjdk_jni$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libbrillo$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libbrillo-stream$(HOST_SHLIB_SUFFIX) \
-  $(HOST_LIBRARY_PATH)/libbrillo-http$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libchrome$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libcurl-host$(HOST_SHLIB_SUFFIX) \
   $(HOST_LIBRARY_PATH)/libevent-host$(HOST_SHLIB_SUFFIX) \
@@ -1605,10 +1767,14 @@
 $(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_RELEASETOOLS_EXTENSIONS)
 endif
 
+ifeq ($(AB_OTA_UPDATER),true)
+# Build zlib fingerprint if using the AB Updater.
+updater_dep := $(TARGET_OUT_COMMON_GEN)/zlib_fingerprint
+else
 # Build OTA tools if not using the AB Updater.
-ifneq ($(AB_OTA_UPDATER),true)
-$(BUILT_TARGET_FILES_PACKAGE): $(built_ota_tools)
+updater_dep := $(built_ota_tools)
 endif
+$(BUILT_TARGET_FILES_PACKAGE): $(updater_dep)
 
 # If we are using recovery as boot, output recovery files to BOOT/.
 ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
@@ -1630,10 +1796,12 @@
 		$(INSTALLED_ANDROID_INFO_TXT_TARGET) \
 		$(SELINUX_FC) \
 		$(APKCERTS_FILE) \
+		$(SOONG_ZIP) \
 		$(HOST_OUT_EXECUTABLES)/fs_config \
+		build/tools/releasetools/add_img_to_target_files \
 		| $(ACP)
 	@echo "Package target files: $@"
-	$(hide) rm -rf $@ $(zip_root)
+	$(hide) rm -rf $@ $@.list $(zip_root)
 	$(hide) mkdir -p $(dir $@) $(zip_root)
 ifneq (,$(INSTALLED_RECOVERYIMAGE_TARGET)$(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
 	@# Components of the recovery image
@@ -1772,6 +1940,23 @@
 ifeq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
 	$(hide) echo "full_recovery_image=true" >> $(zip_root)/META/misc_info.txt
 endif
+ifeq ($(BOARD_AVB_ENABLE),true)
+	$(hide) echo "board_avb_enable=true" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_avb_rollback_index=$(BOARD_AVB_ROLLBACK_INDEX)" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_avb_key_path=$(BOARD_AVB_KEY_PATH)" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_avb_algorithm=$(BOARD_AVB_ALGORITHM)" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_avb_boot_add_hash_footer_args=$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_avb_system_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS)" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_avb_make_vbmeta_image_args=$(BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS)" >> $(zip_root)/META/misc_info.txt
+endif
+ifdef BOARD_BPT_INPUT_FILES
+	$(hide) echo "board_bpt_enable=true" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_bpt_make_table_args=$(BOARD_BPT_MAKE_TABLE_ARGS)" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "board_bpt_input_files=$(BOARD_BPT_INPUT_FILES)" >> $(zip_root)/META/misc_info.txt
+endif
+ifdef BOARD_BPT_DISK_SIZE
+	$(hide) echo "board_bpt_disk_size=$(BOARD_BPT_DISK_SIZE)" >> $(zip_root)/META/misc_info.txt
+endif
 	$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
@@ -1780,6 +1965,7 @@
 ifeq ($(AB_OTA_UPDATER),true)
 	@# When using the A/B updater, include the updater config files in the zip.
 	$(hide) $(ACP) $(TOPDIR)system/update_engine/update_engine.conf $(zip_root)/META/update_engine_config.txt
+	$(hide) $(ACP) $(TARGET_OUT_COMMON_GEN)/zlib_fingerprint $(zip_root)/META/zlib_fingerprint.txt
 	$(hide) for part in $(AB_OTA_PARTITIONS); do \
 	  echo "$${part}" >> $(zip_root)/META/ab_partitions.txt; \
 	done
@@ -1789,6 +1975,17 @@
 	@# Include the build type in META/misc_info.txt so the server can easily differentiate production builds.
 	$(hide) echo "build_type=$(TARGET_BUILD_VARIANT)" >> $(zip_root)/META/misc_info.txt
 	$(hide) echo "ab_update=true" >> $(zip_root)/META/misc_info.txt
+ifdef BRILLO_VENDOR_PARTITIONS
+	$(hide) mkdir -p $(zip_root)/VENDOR_IMAGES
+	$(hide) for f in $(BRILLO_VENDOR_PARTITIONS); do \
+	  pair1="$$(echo $$f | awk -F':' '{print $$1}')"; \
+	  pair2="$$(echo $$f | awk -F':' '{print $$2}')"; \
+	  src=$${pair1}/$${pair2}; \
+	  dest=$(zip_root)/VENDOR_IMAGES/$${pair2}; \
+	  mkdir -p $$(dirname "$${dest}"); \
+	  $(ACP) $${src} $${dest}; \
+	done;
+endif
 ifdef OSRELEASED_DIRECTORY
 	$(hide) $(ACP) $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)/product_id $(zip_root)/META/product_id.txt
 	$(hide) $(ACP) $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)/product_version $(zip_root)/META/product_version.txt
@@ -1798,11 +1995,15 @@
 	@# If breakpad symbols have been generated, add them to the zip.
 	$(hide) $(ACP) -r $(TARGET_OUT_BREAKPAD) $(zip_root)/BREAKPAD
 endif
+ifdef BOARD_PREBUILT_VENDORIMAGE
+	$(hide) mkdir -p $(zip_root)/IMAGES
+	$(hide) cp $(INSTALLED_VENDORIMAGE_TARGET) $(zip_root)/IMAGES/
+endif
 	@# Zip everything up, preserving symlinks and placing META/ files first to
 	@# help early validation of the .zip file while uploading it.
-	$(hide) (cd $(zip_root) && \
-	        zip -qryX ../$(notdir $@) ./META && \
-	        zip -qryXu ../$(notdir $@) .)
+	$(hide) find $(zip_root)/META | sort >$@.list
+	$(hide) find $(zip_root) | grep -v "^$(zip_root)/META/" | sort >>$@.list
+	$(hide) $(SOONG_ZIP) -d -o $@ -C $(zip_root) -l $@.list
 	@# Run fs_config on all the system, vendor, boot ramdisk,
 	@# and recovery ramdisk files in the zip, and save the output
 	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt
@@ -1816,7 +2017,7 @@
 endif
 	$(hide) (cd $(zip_root) && zip -qX ../$(notdir $@) META/*filesystem_config.txt)
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
-	    ./build/tools/releasetools/add_img_to_target_files -v -p $(HOST_OUT) $@
+	    ./build/tools/releasetools/add_img_to_target_files -a -v -p $(HOST_OUT) $@
 
 .PHONY: target-files-package
 target-files-package: $(BUILT_TARGET_FILES_PACKAGE)
@@ -1839,7 +2040,8 @@
 
 $(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
 
-$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE)
+$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) \
+		build/tools/releasetools/ota_from_target_files
 	@echo "Package OTA: $@"
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	   ./build/tools/releasetools/ota_from_target_files -v \
@@ -1865,12 +2067,10 @@
 
 INTERNAL_UPDATE_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
 
-$(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE)
+$(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(ZIP2ZIP)
 	@echo "Package: $@"
-	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
-	   ./build/tools/releasetools/img_from_target_files -v \
-	   -p $(HOST_OUT) \
-	   $(BUILT_TARGET_FILES_PACKAGE) $@
+	$(hide) $(ZIP2ZIP) -i $(BUILT_TARGET_FILES_PACKAGE) -o $@ \
+	   OTA/android-info.txt:android-info.txt "IMAGES/*.img:."
 
 .PHONY: updatepackage
 updatepackage: $(INTERNAL_UPDATE_PACKAGE_TARGET)
@@ -1888,13 +2088,41 @@
 SYMBOLS_ZIP := $(PRODUCT_OUT)/$(name).zip
 # For apps_only build we'll establish the dependency later in build/core/main.mk.
 ifndef TARGET_BUILD_APPS
-$(SYMBOLS_ZIP): $(INSTALLED_SYSTEMIMAGE) $(INSTALLED_BOOTIMAGE_TARGET)
+$(SYMBOLS_ZIP): $(INSTALLED_SYSTEMIMAGE) \
+		$(INSTALLED_BOOTIMAGE_TARGET) \
+		$(INSTALLED_USERDATAIMAGE_TARGET) \
+		$(INSTALLED_VENDORIMAGE_TARGET) \
+		$(updater_dep)
 endif
-$(SYMBOLS_ZIP):
+$(SYMBOLS_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,symbols)/filelist
+$(SYMBOLS_ZIP): $(SOONG_ZIP)
 	@echo "Package symbols: $@"
-	$(hide) rm -rf $@
-	$(hide) mkdir -p $(dir $@) $(TARGET_OUT_UNSTRIPPED)
-	$(hide) zip -qrX $@ $(TARGET_OUT_UNSTRIPPED)
+	$(hide) rm -rf $@ $(PRIVATE_LIST_FILE)
+	$(hide) mkdir -p $(dir $@) $(TARGET_OUT_UNSTRIPPED) $(dir $(PRIVATE_LIST_FILE))
+	$(hide) find $(TARGET_OUT_UNSTRIPPED) | sort >$(PRIVATE_LIST_FILE)
+	$(hide) $(SOONG_ZIP) -d -o $@ -C . -l $(PRIVATE_LIST_FILE)
+# -----------------------------------------------------------------
+# A zip of the coverage directory.
+#
+name := $(TARGET_PRODUCT)
+ifeq ($(TARGET_BUILD_TYPE),debug)
+name := $(name)_debug
+endif
+name := $(name)-coverage-$(FILE_NAME_TAG)
+COVERAGE_ZIP := $(PRODUCT_OUT)/$(name).zip
+ifndef TARGET_BUILD_APPS
+$(COVERAGE_ZIP): $(INSTALLED_SYSTEMIMAGE) \
+		$(INSTALLED_BOOTIMAGE_TARGET) \
+		$(INSTALLED_USERDATAIMAGE_TARGET) \
+		$(INSTALLED_VENDORIMAGE_TARGET)
+endif
+$(COVERAGE_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,coverage)/filelist
+$(COVERAGE_ZIP): $(SOONG_ZIP)
+	@echo "Package coverage: $@"
+	$(hide) rm -rf $@ $(PRIVATE_LIST_FILE)
+	$(hide) mkdir -p $(dir $@) $(TARGET_OUT_COVERAGE) $(dir $(PRIVATE_LIST_FILE))
+	$(hide) find $(TARGET_OUT_COVERAGE) | sort >$(PRIVATE_LIST_FILE)
+	$(hide) $(SOONG_ZIP) -d -o $@ -C $(TARGET_OUT_COVERAGE) -l $(PRIVATE_LIST_FILE)
 
 # -----------------------------------------------------------------
 # A zip of the Android Apps. Not keeping full path so that we don't
@@ -1942,7 +2170,7 @@
 # the dependency will be set up later in build/core/main.mk.
 $(PROGUARD_DICT_ZIP) :
 	@echo "Packaging Proguard obfuscation dictionary files."
-	$(hide) dict_files=`find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary`; \
+	$(hide) dict_files=`find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary -o -name jack_dictionary`; \
 		if [ -n "$$dict_files" ]; then \
 		  unobfuscated_jars=$${dict_files//proguard_dictionary/classes.jar}; \
 		  zip -qX $@ $$dict_files $$unobfuscated_jars; \
@@ -2019,7 +2247,6 @@
 # if we don't have a real list, then use "everything"
 ifeq ($(strip $(ATREE_FILES)),)
 ATREE_FILES := \
-	$(ALL_PREBUILT) \
 	$(ALL_DEFAULT_INSTALLED_MODULES) \
 	$(INSTALLED_RAMDISK_TARGET) \
 	$(ALL_DOCS) \
@@ -2054,6 +2281,7 @@
 	$(tools_notice_file_txt) \
 	$(OUT_DOCS)/offline-sdk-timestamp \
 	$(SYMBOLS_ZIP) \
+	$(COVERAGE_ZIP) \
 	$(INSTALLED_SYSTEMIMAGE) \
 	$(INSTALLED_USERDATAIMAGE_TARGET) \
 	$(INSTALLED_RAMDISK_TARGET) \
@@ -2151,6 +2379,8 @@
 -include $(sort $(wildcard vendor/*/*/build/tasks/*.mk))
 -include $(sort $(wildcard device/*/*/build/tasks/*.mk))
 -include $(sort $(wildcard product/*/*/build/tasks/*.mk))
+# Also add test specifc tasks
+include $(sort $(wildcard platform_testing/build/tasks/*.mk))
 endif
 
 include $(BUILD_SYSTEM)/product-graph.mk
diff --git a/core/aux_config.mk b/core/aux_config.mk
new file mode 100644
index 0000000..decff34
--- /dev/null
+++ b/core/aux_config.mk
@@ -0,0 +1,183 @@
+variant_list := $(filter AUX-%,$(MAKECMDGOALS))
+
+ifdef variant_list
+AUX_OS_VARIANT_LIST := $(patsubst AUX-%,%,$(variant_list))
+else
+AUX_OS_VARIANT_LIST := $(TARGET_AUX_OS_VARIANT_LIST)
+endif
+
+# exclude AUX targets from build
+ifeq ($(AUX_OS_VARIANT_LIST),none)
+AUX_OS_VARIANT_LIST :=
+endif
+
+# temporary workaround to support external toolchain
+ifeq ($(NANOHUB_TOOLCHAIN),)
+AUX_OS_VARIANT_LIST :=
+endif
+
+# setup toolchain paths for various CPU architectures
+# this one will come from android prebuilts eventually
+AUX_TOOLCHAIN_cortexm4 := $(NANOHUB_TOOLCHAIN)
+ifeq ($(wildcard $(AUX_TOOLCHAIN_cortexm4)gcc),)
+AUX_TOOLCHAIN_cortexm4:=
+endif
+
+# there is no MAKE var that defines path to HOST toolchain
+# all the interesting paths are hardcoded in soong, and are not available from here
+# There is no other way but to hardcode them again, as we may need host x86 toolcain for AUX
+ifeq ($(HOST_OS),linux)
+AUX_TOOLCHAIN_x86 := prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/bin/x86_64-linux-
+endif
+
+# setup AUX globals
+AUX_SHLIB_SUFFIX := .so
+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
+# moment on.
+#
+# $(1) - variant
+# no return value
+define aux-variant-setup-paths
+$(eval AUX_OUT_ROOT_$(1) := $(PRODUCT_OUT)/aux/$(1)) \
+$(eval AUX_COMMON_OUT_ROOT_$(1) := $(AUX_OUT_ROOT_$(1))/common) \
+$(eval AUX_OUT_$(1) := $(AUX_OUT_ROOT_$(1))/$(AUX_OS_$(1))-$(AUX_ARCH_$(1))-$(AUX_CPU_$(1))) \
+$(eval AUX_OUT_INTERMEDIATES_$(1) := $(AUX_OUT_$(1))/obj) \
+$(eval AUX_OUT_COMMON_INTERMEDIATES_$(1) := $(AUX_COMMON_OUT_ROOT_$(1))/obj) \
+$(eval AUX_OUT_HEADERS_$(1) := $(AUX_OUT_INTERMEDIATES_$(1))/include) \
+$(eval AUX_OUT_INTERMEDIATE_LIBRARIES_$(1) := $(AUX_OUT_INTERMEDIATES_$(1))/lib) \
+$(eval AUX_OUT_NOTICE_FILES_$(1) := $(AUX_OUT_INTERMEDIATES_$(1))/NOTICE_FILES) \
+$(eval AUX_OUT_FAKE_$(1) := $(AUX_OUT_$(1))/fake_packages) \
+$(eval AUX_OUT_GEN_$(1) := $(AUX_OUT_$(1))/gen) \
+$(eval AUX_OUT_COMMON_GEN_$(1) := $(AUX_COMMON_OUT_ROOT_$(1))/gen) \
+$(eval AUX_OUT_EXECUTABLES_$(1) := $(AUX_OUT_$(1))/bin) \
+$(eval AUX_OUT_UNSTRIPPED_$(1) := $(AUX_OUT_$(1))/symbols)
+endef
+
+# Copy "indexed" AUX environment for given VARIANT into
+# volatile not-indexed set of variables for simplicity of access.
+# Injection of index support throughout the build system is suboptimal
+# hence volatile environment is constructed
+# Unlike HOST*, TARGET* variables, AUX* variables are NOT read-only, but their
+# indexed versions are.
+#
+# $(1) - variant
+# no return value
+define aux-variant-load-env
+$(eval AUX_OS_VARIANT:=$(1)) \
+$(eval AUX_OS:=$(AUX_OS_$(1))) \
+$(eval AUX_ARCH:=$(AUX_ARCH_$(1))) \
+$(eval AUX_SUBARCH:=$(AUX_SUBARCH_$(1))) \
+$(eval AUX_CPU:=$(AUX_CPU_$(1))) \
+$(eval AUX_OS_PATH:=$(AUX_OS_PATH_$(1))) \
+$(eval AUX_OUT_ROOT := $(AUX_OUT_ROOT_$(1))) \
+$(eval AUX_COMMON_OUT_ROOT := $(AUX_COMMON_OUT_ROOT_$(1))) \
+$(eval AUX_OUT := $(AUX_OUT_$(1))) \
+$(eval AUX_OUT_INTERMEDIATES := $(AUX_OUT_INTERMEDIATES_$(1))) \
+$(eval AUX_OUT_COMMON_INTERMEDIATES := $(AUX_OUT_COMMON_INTERMEDIATES_$(1))) \
+$(eval AUX_OUT_HEADERS := $(AUX_OUT_HEADERS_$(1))) \
+$(eval AUX_OUT_INTERMEDIATE_LIBRARIES := $(AUX_OUT_INTERMEDIATE_LIBRARIES_$(1))) \
+$(eval AUX_OUT_NOTICE_FILES := $(AUX_OUT_NOTICE_FILES_$(1))) \
+$(eval AUX_OUT_FAKE := $(AUX_OUT_FAKE_$(1))) \
+$(eval AUX_OUT_GEN := $(AUX_OUT_GEN_$(1))) \
+$(eval AUX_OUT_COMMON_GEN := $(AUX_OUT_COMMON_GEN_$(1))) \
+$(eval AUX_OUT_EXECUTABLES := $(AUX_OUT_EXECUTABLES_$(1))) \
+$(eval AUX_OUT_UNSTRIPPED := $(AUX_OUT_UNSTRIPPED_$(1)))
+endef
+
+# given a variant:path pair, load the variant conviguration with aux-variant-setup-paths from file
+# this is a build system extension mechainsm, since configuration typically resides in non-build
+# project space
+#
+# $(1) - variant:path pair
+# $(2) - file suffix
+# no return value
+define aux-variant-import-from-pair
+$(eval _pair := $(subst :, ,$(1))) \
+$(eval _name:=$(word 1,$(_pair))) \
+$(eval _path:=$(word 2,$(_pair))) \
+$(eval include $(_path)/$(_name)$(2)) \
+$(eval AUX_OS_VARIANT_LIST_$(AUX_OS_$(1)):=) \
+$(call aux-variant-setup-paths,$(_name)) \
+$(eval AUX_ALL_VARIANTS += $(_name)) \
+$(eval AUX_ALL_OSES := $(filterout $(AUX_OS_$(_name)),$(AUX_ALL_OSES)) $(AUX_OS_$(_name))) \
+$(eval AUX_ALL_CPUS := $(filterout $(AUX_CPU_$(_name)),$(AUX_ALL_CPUS)) $(AUX_CPU_$(_name))) \
+$(eval AUX_ALL_ARCHS := $(filterout $(AUX_ARCH_$(_name)),$(AUX_ALL_ARCHS)) $(AUX_ARCH_$(_name))) \
+$(eval AUX_ALL_SUBARCHS := $(filterout $(AUX_SUBARCH_$(_name)),$(AUX_ALL_SUBARCHS)) $(AUX_SUBARCH_$(_name)))
+endef
+
+# Load system configuration referenced by AUX variant config;
+# this is a build extension mechanism; typically system config
+# resides in a non-build projects;
+# system config may define new rules and globally visible BUILD*
+# includes to support project-specific build steps and toolchains
+# MAintains list of valiants that reference this os config in OS "indexed" var
+# this facilitates multivariant build of the OS (or whataver it is the name of common component these variants share)
+#
+# $(1) - variant
+# no return value
+define aux-import-os-config
+$(eval _aioc_os := $(AUX_OS_$(1))) \
+$(eval AUX_OS_PATH_$(1) := $(patsubst $(_aioc_os):%,%,$(filter $(_aioc_os):%,$(AUX_ALL_OS_PATHS)))) \
+$(eval _aioc_os_cfg := $(AUX_OS_PATH_$(1))/$(_aioc_os)$(os_sfx)) \
+$(if $(wildcard $(_aioc_os_cfg)),,$(error AUX '$(_aioc_os)' OS config file [$(notdir $(_aioc_os_cfg))] required by AUX variant '$(1)' does not exist)) \
+$(if $(filter $(_aioc_os),$(_os_list)),,$(eval include $(_aioc_os_cfg))) \
+$(eval AUX_OS_VARIANT_LIST_$(_aioc_os) += $(1)) \
+$(eval _os_list += $(_aioc_os))
+endef
+
+# make sure that AUX config variables are minimally sane;
+# as a bare minimum they must contain the vars described by aux_env
+# Generate error if requirement is not met.
+#
+#$(1) - variant
+# no return value
+define aux-variant-validate
+$(eval _all:=) \
+$(eval _req:=$(addsuffix _$(1),$(aux_env))) \
+$(foreach var,$(_req),$(eval _all += $(var))) \
+$(eval _missing := $(filterout $(_all),$(_req))) \
+$(if $(_missing),$(error AUX variant $(1) must define vars: $(_missing)))
+endef
+
+AUX_ALL_VARIANTS :=
+AUX_ALL_OSES :=
+AUX_ALL_CPUS :=
+AUX_ALL_ARCHS :=
+AUX_ALL_SUBARCHS :=
+
+variant_sfx :=_aux_variant_config.mk
+os_sfx :=_aux_os_config.mk
+
+all_configs := $(shell find device vendor -maxdepth 4 -name '*$(variant_sfx)' -o -name '*$(os_sfx)' | sort)
+all_os_configs := $(filter %$(os_sfx),$(all_configs))
+all_variant_configs := $(filter %$(variant_sfx),$(all_configs))
+
+AUX_ALL_OS_PATHS := $(foreach f,$(all_os_configs),$(patsubst %$(os_sfx),%,$(notdir $(f))):$(patsubst %/,%,$(dir $(f))))
+AUX_ALL_OS_VARIANT_PATHS := $(foreach f,$(all_variant_configs),$(patsubst %$(variant_sfx),%,$(notdir $(f))):$(patsubst %/,%,$(dir $(f))))
+
+my_variant_pairs := $(foreach v,$(AUX_OS_VARIANT_LIST),$(filter $(v):%,$(AUX_ALL_OS_VARIANT_PATHS)))
+my_missing_variants := $(foreach v,$(AUX_OS_VARIANT_LIST),$(if $(filter $(v):%,$(AUX_ALL_OS_VARIANT_PATHS)),,$(v)))
+
+ifneq ($(strip $(my_missing_variants)),)
+$(error Don't know how to build variant(s): $(my_missing_variants))
+endif
+
+# mandatory variables
+aux_env := AUX_OS AUX_ARCH AUX_SUBARCH AUX_CPU
+
+$(foreach v,$(my_variant_pairs),$(if $(filter $(v),$(AUX_ALL_VARIANTS)),,$(call aux-variant-import-from-pair,$(v),$(variant_sfx))))
+
+ifdef AUX_ALL_VARIANTS
+_os_list :=
+$(foreach v,$(AUX_ALL_VARIANTS),\
+  $(call aux-import-os-config,$(v)) \
+  $(call aux-variant-validate,$(v)) \
+)
+endif
+
+INSTALLED_AUX_TARGETS :=
+
+droidcore: auxiliary
diff --git a/core/aux_executable.mk b/core/aux_executable.mk
new file mode 100644
index 0000000..daf30e7
--- /dev/null
+++ b/core/aux_executable.mk
@@ -0,0 +1,96 @@
+# caller might have included aux_toolchain, e.g. if custom build steps are defined
+ifeq ($(LOCAL_IS_AUX_MODULE),)
+include $(BUILD_SYSTEM)/aux_toolchain.mk
+endif
+
+ifeq ($(AUX_BUILD_NOT_COMPATIBLE),)
+
+###########################################################
+## Standard rules for building an executable file.
+##
+## Additional inputs from base_rules.make:
+## None.
+###########################################################
+
+ifeq ($(strip $(LOCAL_MODULE_CLASS)),)
+LOCAL_MODULE_CLASS := EXECUTABLES
+endif
+
+$(call $(aux-executable-hook))
+
+###########################################################
+## Standard rules for building any target-side binaries
+## with dynamic linkage (dynamic libraries or executables
+## that link with dynamic libraries)
+##
+## Files including this file must define a rule to build
+## the target $(linked_module).
+###########################################################
+
+# The name of the target file, without any path prepended.
+# This duplicates logic from base_rules.mk because we need to
+# know its results before base_rules.mk is included.
+include $(BUILD_SYSTEM)/configure_module_stem.mk
+
+intermediates := $(call local-intermediates-dir)
+
+# Define the target that is the unmodified output of the linker.
+# The basename of this target must be the same as the final output
+# binary name, because it's used to set the "soname" in the binary.
+# The includer of this file will define a rule to build this target.
+linked_module := $(intermediates)/LINKED/$(my_built_module_stem)
+
+ALL_ORIGINAL_DYNAMIC_BINARIES += $(linked_module)
+
+# Because AUX_SYMBOL_FILTER_FILE depends on ALL_ORIGINAL_DYNAMIC_BINARIES,
+# the linked_module rules won't necessarily inherit the PRIVATE_
+# variables from LOCAL_BUILT_MODULE.  This tells binary.make to explicitly
+# define the PRIVATE_ variables for linked_module as well as for
+# LOCAL_BUILT_MODULE.
+LOCAL_INTERMEDIATE_TARGETS += $(linked_module)
+
+###################################
+include $(BUILD_SYSTEM)/binary.mk
+###################################
+
+aux_output := $(linked_module)
+
+ifneq ($(LOCAL_CUSTOM_BUILD_STEP_INPUT),)
+ifneq ($(LOCAL_CUSTOM_BUILD_STEP_OUTPUT),)
+
+# injecting custom build steps
+$(LOCAL_CUSTOM_BUILD_STEP_INPUT): $(aux_output)
+	@echo "$(AUX_DISPLAY) custom copy: $(PRIVATE_MODULE) ($@)"
+	@mkdir -p $(dir $@)
+	$(hide) $(copy-file-to-target)
+
+aux_output := $(LOCAL_CUSTOM_BUILD_STEP_OUTPUT)
+
+endif
+endif
+
+$(LOCAL_BUILT_MODULE): $(aux_output)
+	@echo "$(AUX_DISPLAY) final copy: $(PRIVATE_MODULE) ($@)"
+	@mkdir -p $(dir $@)
+	$(hide) $(copy-file-to-target)
+
+INSTALLED_AUX_TARGETS += $(LOCAL_INSTALLED_MODULE)
+
+$(cleantarget): PRIVATE_CLEAN_FILES += \
+    $(linked_module) \
+
+# Define PRIVATE_ variables from global vars
+$(linked_module): PRIVATE_TARGET_OUT_INTERMEDIATE_LIBRARIES := $(AUX_OUT_INTERMEDIATE_LIBRARIES)
+$(linked_module): PRIVATE_POST_LINK_CMD := $(LOCAL_POST_LINK_CMD)
+
+ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
+$(linked_module): $(all_objects) $(all_libraries) $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(transform-o-to-aux-static-executable)
+	$(PRIVATE_POST_LINK_CMD)
+else
+$(linked_module): $(all_objects) $(all_libraries) $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(transform-o-to-aux-executable)
+	$(PRIVATE_POST_LINK_CMD)
+endif
+
+endif # AUX_BUILD_NOT_COMPATIBLE
diff --git a/core/aux_static_library.mk b/core/aux_static_library.mk
new file mode 100644
index 0000000..d88478d
--- /dev/null
+++ b/core/aux_static_library.mk
@@ -0,0 +1,27 @@
+ifeq ($(LOCAL_IS_AUX_MODULE),)
+include $(BUILD_SYSTEM)/aux_toolchain.mk
+endif
+
+ifeq ($(AUX_BUILD_NOT_COMPATIBLE),)
+
+ifeq ($(strip $(LOCAL_MODULE_CLASS)),)
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+endif
+ifeq ($(strip $(LOCAL_MODULE_SUFFIX)),)
+LOCAL_MODULE_SUFFIX := .a
+endif
+
+LOCAL_UNINSTALLABLE_MODULE := true
+
+ifneq ($(strip $(LOCAL_MODULE_STEM)$(LOCAL_BUILT_MODULE_STEM)),)
+$(error $(LOCAL_PATH): Cannot set module stem for a library)
+endif
+
+include $(BUILD_SYSTEM)/binary.mk
+
+$(LOCAL_BUILT_MODULE) : PRIVATE_AR := $(AUX_AR)
+$(LOCAL_BUILT_MODULE) : $(built_whole_libraries)
+$(LOCAL_BUILT_MODULE) : $(all_objects)
+	$(transform-o-to-aux-static-lib)
+
+endif # AUX_BUILD_NOT_COMPATIBLE
diff --git a/core/aux_toolchain.mk b/core/aux_toolchain.mk
new file mode 100644
index 0000000..de0b139
--- /dev/null
+++ b/core/aux_toolchain.mk
@@ -0,0 +1,53 @@
+###########################################################
+# takes form LOCAL_AUX_TOOLCHAIN_$(LOCAL_AUX_CPU)
+###########################################################
+
+###############################
+# setup AUX environment
+###############################
+
+# shortcuts for targets with a single instance of OS, ARCH, VARIANT, CPU
+AUX_TOOLCHAIN := $(if $(LOCAL_AUX_TOOLCHAIN),$(LOCAL_AUX_TOOLCHAIN),$(AUX_TOOLCHAIN_$(AUX_CPU)))
+AUX_BUILD_NOT_COMPATIBLE:=
+ifeq ($(strip $(AUX_TOOLCHAIN)),)
+  ifeq ($(strip $(AUX_CPU)),)
+    $(warning $(LOCAL_PATH): $(LOCAL_MODULE): Undefined CPU for AUX toolchain)
+    AUX_BUILD_NOT_COMPATIBLE += TOOLCHAIN
+  else
+    $(warning $(LOCAL_PATH): $(LOCAL_MODULE): Undefined AUX toolchain for CPU=$(AUX_CPU))
+    AUX_BUILD_NOT_COMPATIBLE += TOOLCHAIN
+  endif
+endif
+
+AUX_BUILD_NOT_COMPATIBLE += $(foreach var,OS ARCH SUBARCH CPU OS_VARIANT,$(if $(LOCAL_AUX_$(var)),$(if \
+    $(filter $(LOCAL_AUX_$(var)),$(AUX_$(var))),,$(var))))
+
+AUX_BUILD_NOT_COMPATIBLE := $(strip $(AUX_BUILD_NOT_COMPATIBLE))
+
+ifneq ($(AUX_BUILD_NOT_COMPATIBLE),)
+$(info $(LOCAL_PATH): $(LOCAL_MODULE): not compatible: "$(AUX_BUILD_NOT_COMPATIBLE)" with)
+$(info ====> OS=$(AUX_OS) CPU=$(AUX_CPU) ARCH=$(AUX_ARCH) SUBARCH=$(AUX_SUBARCH) OS_VARIANT=$(AUX_OS_VARIANT))
+$(info ====> TOOLCHAIN=$(AUX_TOOLCHAIN))
+endif
+
+AUX_AR := $(AUX_TOOLCHAIN)ar
+AUX_AS := $(AUX_TOOLCHAIN)gcc
+AUX_CC := $(AUX_TOOLCHAIN)gcc
+AUX_CXX := $(AUX_TOOLCHAIN)g++
+AUX_LINKER := $(AUX_TOOLCHAIN)ld
+AUX_OBJCOPY := $(AUX_TOOLCHAIN)objcopy
+AUX_OBJDUMP := $(AUX_TOOLCHAIN)objdump
+
+###############################
+# setup Android environment
+###############################
+
+LOCAL_IS_AUX_MODULE := true
+LOCAL_2ND_ARCH_VAR_PREFIX :=
+LOCAL_CC := $(AUX_CC)
+LOCAL_CXX := $(AUX_CXX)
+LOCAL_NO_DEFAULT_COMPILER_FLAGS := true
+LOCAL_SYSTEM_SHARED_LIBRARIES :=
+LOCAL_CXX_STL := none
+LOCAL_NO_PIC := true
+LOCAL_NO_LIBCOMPILER_RT := true
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 6722af4..56df2a9 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -14,6 +14,9 @@
 # limitations under the License.
 #
 
+# Catch users that directly include base_rules.mk
+$(call record-module-type,base_rules)
+
 # Users can define base-rules-hook in their buildspec.mk to perform
 # arbitrary operations as each module is included.
 ifdef base-rules-hook
@@ -30,6 +33,7 @@
 endif
 
 LOCAL_IS_HOST_MODULE := $(strip $(LOCAL_IS_HOST_MODULE))
+LOCAL_IS_AUX_MODULE := $(strip $(LOCAL_IS_AUX_MODULE))
 ifdef LOCAL_IS_HOST_MODULE
   ifneq ($(LOCAL_IS_HOST_MODULE),true)
     $(error $(LOCAL_PATH): LOCAL_IS_HOST_MODULE must be "true" or empty, not "$(LOCAL_IS_HOST_MODULE)")
@@ -40,8 +44,18 @@
     my_prefix := $(LOCAL_HOST_PREFIX)
   endif
   my_host := host-
+  my_kind := HOST
 else
-  my_prefix := TARGET_
+  ifdef LOCAL_IS_AUX_MODULE
+    ifneq ($(LOCAL_IS_AUX_MODULE),true)
+      $(error $(LOCAL_PATH): LOCAL_IS_AUX_MODULE must be "true" or empty, not "$(LOCAL_IS_AUX_MODULE)")
+    endif
+    my_prefix := AUX_
+    my_kind := AUX
+  else
+    my_prefix := TARGET_
+    my_kind :=
+  endif
   my_host :=
 endif
 
@@ -55,8 +69,13 @@
 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
 
-ifdef BUILDING_WITH_NINJA
 # Ninja has an implicit dependency on the command being run, and kati will
 # regenerate the ninja manifest if any read makefile changes, so there is no
 # need to have dependencies on makefiles.
@@ -64,7 +83,6 @@
 # a .mk file, because a few users of LOCAL_ADDITIONAL_DEPENDENCIES don't include
 # base_rules.mk, but it will fix the most common ones.
 LOCAL_ADDITIONAL_DEPENDENCIES := $(filter-out %.mk,$(LOCAL_ADDITIONAL_DEPENDENCIES))
-endif
 
 ###########################################################
 ## Validate and define fallbacks for input LOCAL_* variables.
@@ -125,7 +143,17 @@
 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
@@ -142,6 +170,8 @@
     partition_tag := _OEM
   else ifeq (true,$(LOCAL_ODM_MODULE))
     partition_tag := _ODM
+  else ifeq (NATIVE_TESTS,$(LOCAL_MODULE_CLASS))
+    partition_tag := _DATA
   else
     # The definition of should-install-to-system will be different depending
     # on which goal (e.g., sdk or just droid) is being built.
@@ -176,9 +206,21 @@
 my_register_name := $(my_register_name)$($(my_prefix)2ND_ARCH_MODULE_SUFFIX)
 endif
 endif
+
+ifeq ($(my_host_cross),true)
+  my_all_targets := host_cross_$(my_register_name)_all_targets
+else ifneq ($(LOCAL_IS_HOST_MODULE),)
+  my_all_targets := host_$(my_register_name)_all_targets
+else
+  my_all_targets := device_$(my_register_name)_all_targets
+endif
+
+# variant is enough to make nano class unique; it serves as a key to lookup (OS,ARCH) tuple
+aux_class := $($(my_prefix)OS_VARIANT)
 # Make sure that this IS_HOST/CLASS/MODULE combination is unique.
 module_id := MODULE.$(if \
-    $(LOCAL_IS_HOST_MODULE),$($(my_prefix)OS),TARGET).$(LOCAL_MODULE_CLASS).$(my_register_name)
+    $(LOCAL_IS_HOST_MODULE),$($(my_prefix)OS),$(if \
+    $(LOCAL_IS_AUX_MODULE),$(aux_class),TARGET)).$(LOCAL_MODULE_CLASS).$(my_register_name)
 ifdef $(module_id)
 $(error $(LOCAL_PATH): $(module_id) already defined by $($(module_id)))
 endif
@@ -239,7 +281,7 @@
 # Kati adds restat=1 to ninja. GNU make does nothing for this.
 .KATI_RESTAT: $(LOCAL_BUILT_MODULE).toc
 # Build .toc file when using mm, mma, or make $(my_register_name)
-$(my_register_name): $(LOCAL_BUILT_MODULE).toc
+$(my_all_targets): $(LOCAL_BUILT_MODULE).toc
 endif
 endif
 
@@ -247,7 +289,7 @@
 ## logtags: Add .logtags files to global list
 ###########################################################
 
-logtags_sources := $(filter %.logtags,$(LOCAL_SRC_FILES))
+logtags_sources := $(filter %.logtags,$(LOCAL_SRC_FILES)) $(LOCAL_LOGTAGS_FILES)
 
 ifneq ($(strip $(logtags_sources)),)
 event_log_tags := $(addprefix $(LOCAL_PATH)/,$(logtags_sources))
@@ -273,6 +315,7 @@
 ###########################################################
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_PATH:=$(LOCAL_PATH)
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_IS_HOST_MODULE := $(LOCAL_IS_HOST_MODULE)
+$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_IS_AUX_MODULE := $(LOCAL_IS_AUX_MODULE)
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_HOST:= $(my_host)
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_PREFIX := $(my_prefix)
 
@@ -285,8 +328,17 @@
 # Provide a short-hand for building this module.
 # We name both BUILT and INSTALLED in case
 # LOCAL_UNINSTALLABLE_MODULE is set.
+.PHONY: $(my_all_targets)
+$(my_all_targets): $(LOCAL_BUILT_MODULE) $(LOCAL_INSTALLED_MODULE)
+
 .PHONY: $(my_register_name)
-$(my_register_name): $(LOCAL_BUILT_MODULE) $(LOCAL_INSTALLED_MODULE)
+$(my_register_name): $(my_all_targets)
+
+ifneq ($(my_register_name),$(LOCAL_MODULE))
+# $(LOCAL_MODULE) covers all the multilib targets.
+.PHONY: $(LOCAL_MODULE)
+$(LOCAL_MODULE) : $(my_all_targets)
+endif
 
 # Set up phony targets that covers all modules under the given paths.
 # This allows us to build everything in given paths by running mmma/mma.
@@ -295,51 +347,46 @@
 $(foreach c, $(my_path_components),\
   $(eval my_path_prefix := $(my_path_prefix)-$(c))\
   $(eval .PHONY : $(my_path_prefix))\
-  $(eval $(my_path_prefix) : $(my_register_name)))
+  $(eval $(my_path_prefix) : $(my_all_targets)))
 
 ###########################################################
 ## Module installation rule
 ###########################################################
 
-# Some hosts do not have ACP; override the LOCAL version if that's the case.
-ifneq ($(strip $(HOST_ACP_UNAVAILABLE)),)
-  LOCAL_ACP_UNAVAILABLE := $(strip $(HOST_ACP_UNAVAILABLE))
-endif
-
+my_init_rc_installed :=
+my_init_rc_pairs :=
+my_installed_symlinks :=
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
-  # Define a copy rule to install the module.
-  # acp and libraries that it uses can't use acp for
-  # installation;  hence, LOCAL_ACP_UNAVAILABLE.
 $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD)
-ifneq ($(LOCAL_ACP_UNAVAILABLE),true)
-$(LOCAL_INSTALLED_MODULE): $(LOCAL_BUILT_MODULE) | $(ACP)
+$(LOCAL_INSTALLED_MODULE): $(LOCAL_BUILT_MODULE)
 	@echo "Install: $@"
 	$(copy-file-to-new-target)
 	$(PRIVATE_POST_INSTALL_CMD)
-else
-$(LOCAL_INSTALLED_MODULE): $(LOCAL_BUILT_MODULE)
-	@echo "Install: $@"
-	$(copy-file-to-target-with-cp)
-endif
 
+ifndef LOCAL_IS_HOST_MODULE
 # Rule to install the module's companion init.rc.
-my_init_rc := $(LOCAL_INIT_RC_$(my_32_64_bit_suffix))
-my_init_rc_src :=
-my_init_rc_installed :=
-ifndef my_init_rc
-my_init_rc := $(LOCAL_INIT_RC)
-# Make sure we don't define the rule twice in multilib module.
-LOCAL_INIT_RC :=
-endif
-ifdef my_init_rc
-my_init_rc_src := $(LOCAL_PATH)/$(my_init_rc)
-my_init_rc_installed := $(TARGET_OUT$(partition_tag)_ETC)/init/$(notdir $(my_init_rc_src))
-$(my_init_rc_installed) : $(my_init_rc_src) | $(ACP)
-	@echo "Install: $@"
-	$(copy-file-to-new-target)
+my_init_rc := $(LOCAL_INIT_RC_$(my_32_64_bit_suffix)) $(LOCAL_INIT_RC)
+ifneq ($(strip $(my_init_rc)),)
+my_init_rc_pairs := $(foreach rc,$(my_init_rc),$(LOCAL_PATH)/$(rc):$(TARGET_OUT$(partition_tag)_ETC)/init/$(notdir $(rc)))
+my_init_rc_installed := $(foreach rc,$(my_init_rc_pairs),$(call word-colon,2,$(rc)))
 
-$(my_register_name) : $(my_init_rc_installed)
+# Make sure we only set up the copy rules once, even if another arch variant
+# shares a common LOCAL_INIT_RC.
+my_init_rc_new_pairs := $(filter-out $(ALL_INIT_RC_INSTALLED_PAIRS),$(my_init_rc_pairs))
+my_init_rc_new_installed := $(call copy-many-files,$(my_init_rc_new_pairs))
+ALL_INIT_RC_INSTALLED_PAIRS += $(my_init_rc_new_pairs)
+
+$(my_all_targets) : $(my_init_rc_installed)
 endif # my_init_rc
+endif # !LOCAL_IS_HOST_MODULE
+
+# Rule to install the module's companion symlinks
+my_installed_symlinks := $(addprefix $(my_module_path)/,$(LOCAL_MODULE_SYMLINKS) $(LOCAL_MODULE_SYMLINKS_$(my_32_64_bit_suffix)))
+$(foreach symlink,$(my_installed_symlinks),\
+    $(call symlink-file,$(LOCAL_INSTALLED_MODULE),$(my_installed_module_stem),$(symlink)))
+
+$(my_all_targets) : | $(my_installed_symlinks)
+
 endif # !LOCAL_UNINSTALLABLE_MODULE
 
 ###########################################################
@@ -408,7 +455,7 @@
   $(my_compat_files)
 
 # Copy over the compatibility files when user runs mm/mmm.
-$(my_register_name) : $(my_compat_files)
+$(my_all_targets) : $(my_compat_files)
 endif  # LOCAL_COMPATIBILITY_SUITE
 
 ###########################################################
@@ -432,11 +479,11 @@
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 ALL_MODULES.$(my_register_name).INSTALLED := \
     $(strip $(ALL_MODULES.$(my_register_name).INSTALLED) \
-    $(LOCAL_INSTALLED_MODULE) $(my_init_rc_installed))
+    $(LOCAL_INSTALLED_MODULE) $(my_init_rc_installed) $(my_installed_symlinks))
 ALL_MODULES.$(my_register_name).BUILT_INSTALLED := \
     $(strip $(ALL_MODULES.$(my_register_name).BUILT_INSTALLED) \
     $(LOCAL_BUILT_MODULE):$(LOCAL_INSTALLED_MODULE) \
-    $(addprefix $(my_init_rc_src):,$(my_init_rc_installed)))
+    $(my_init_rc_pairs))
 endif
 ifdef LOCAL_PICKUP_FILES
 # Files or directories ready to pick up by the build system
@@ -496,7 +543,7 @@
 ## umbrella targets used to verify builds
 ###########################################################
 j_or_n :=
-ifneq (,$(filter EXECUTABLES SHARED_LIBRARIES STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS)))
+ifneq (,$(filter EXECUTABLES SHARED_LIBRARIES STATIC_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)))
 j_or_n := native
 else
 ifneq (,$(filter JAVA_LIBRARIES APPS,$(LOCAL_MODULE_CLASS)))
@@ -514,6 +561,7 @@
 ifneq (,$(filter $(my_module_tags),tests))
 $(j_or_n)-$(h_or_t)-tests $(j_or_n)-tests $(h_or_t)-tests : $(my_checked_module)
 endif
+$(LOCAL_MODULE)-$(h_or_t) : $(my_all_targets)
 endif
 
 ###########################################################
diff --git a/core/binary.mk b/core/binary.mk
index 918a28d..7f6f2fb 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -30,6 +30,8 @@
   endif
 endif
 
+my_soong_problems :=
+
 # The following LOCAL_ variables will be modified in this file.
 # Because the same LOCAL_ variables may be used to define modules for both 1st arch and 2nd arch,
 # we can't modify them in place.
@@ -52,9 +54,15 @@
 my_cxx_wrapper := $(CXX_WRAPPER)
 my_c_includes := $(LOCAL_C_INCLUDES)
 my_generated_sources := $(LOCAL_GENERATED_SOURCES)
-my_native_coverage := $(LOCAL_NATIVE_COVERAGE)
-my_additional_dependencies := $(LOCAL_MODULE_MAKEFILE_DEP) $(LOCAL_ADDITIONAL_DEPENDENCIES)
+my_additional_dependencies := $(LOCAL_ADDITIONAL_DEPENDENCIES)
 my_export_c_include_dirs := $(LOCAL_EXPORT_C_INCLUDE_DIRS)
+my_export_c_include_deps := $(LOCAL_EXPORT_C_INCLUDE_DEPS)
+
+ifneq (,$(foreach dir,$(COVERAGE_PATHS),$(filter $(dir)%,$(LOCAL_PATH))))
+  my_native_coverage := true
+else
+  my_native_coverage := false
+endif
 
 ifdef LOCAL_IS_HOST_MODULE
 my_allow_undefined_symbols := true
@@ -66,15 +74,54 @@
 my_ndk_sysroot_include :=
 my_ndk_sysroot_lib :=
 ifdef LOCAL_SDK_VERSION
-  ifdef LOCAL_NDK_VERSION
-    $(error $(LOCAL_PATH): LOCAL_NDK_VERSION is now retired.)
-  endif
   ifdef LOCAL_IS_HOST_MODULE
     $(error $(LOCAL_PATH): LOCAL_SDK_VERSION cannot be used in host module)
   endif
-  my_ndk_source_root := $(HISTORICAL_NDK_VERSIONS_ROOT)/current/sources
-  my_ndk_sysroot := $(HISTORICAL_NDK_VERSIONS_ROOT)/current/platforms/android-$(LOCAL_SDK_VERSION)/arch-$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
-  my_ndk_sysroot_include := $(my_ndk_sysroot)/usr/include
+
+  # Make sure we've built the NDK.
+  my_additional_dependencies += $(SOONG_OUT_DIR)/ndk.timestamp
+
+  # mips32r6 is not supported by the NDK. No released NDK contains these
+  # libraries, but the r10 in prebuilts/ndk had a local hack to add them :(
+  #
+  # We need to find a real solution to this problem, but until we do just drop
+  # mips32r6 things back to r10 to get the tree building again.
+  ifeq (mips32r6,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH_VARIANT))
+    ifeq ($(LOCAL_NDK_VERSION), current)
+      LOCAL_NDK_VERSION := r10
+    endif
+  endif
+
+  my_arch := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+  ifneq (,$(filter arm64 mips64 x86_64,$(my_arch)))
+    my_min_sdk_version := 21
+  else
+    my_min_sdk_version := 9
+  endif
+
+  # Historically we've just set up a bunch of symlinks in prebuilts/ndk to map
+  # missing API levels to existing ones where necessary, but we're not doing
+  # that for the generated libraries. Clip the API level to the minimum where
+  # appropriate.
+  my_ndk_api := \
+    $(shell if [ $(LOCAL_SDK_VERSION) -lt $(my_min_sdk_version) ]; then \
+        echo $(my_min_sdk_version); else echo $(LOCAL_SDK_VERSION); fi)
+
+  # Traditionally this has come from android/api-level.h, but with the libc
+  # headers unified it must be set by the build system since we don't have
+  # per-API level copies of that header now.
+  my_cflags += -D__ANDROID_API__=$(my_ndk_api)
+
+  my_ndk_source_root := \
+      $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources
+  my_ndk_sysroot := \
+    $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/platforms/android-$(my_ndk_api)/arch-$(my_arch)
+  my_built_ndk := $(SOONG_OUT_DIR)/ndk
+  my_ndk_triple := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_NDK_TRIPLE)
+  my_ndk_sysroot_include := \
+      $(my_built_ndk)/sysroot/usr/include \
+      $(my_built_ndk)/sysroot/usr/include/$(my_ndk_triple) \
+      $(my_ndk_sysroot)/usr/include \
 
   # x86_64 and and mips64 are both multilib toolchains, so their libraries are
   # installed in /usr/lib64. Aarch64, on the other hand, is not a multilib
@@ -83,14 +130,19 @@
   # Mips32r6 is yet another variation, with libraries installed in libr6.
   #
   # For the rest, the libraries are installed simply to /usr/lib.
-  ifneq (,$(filter x86_64 mips64,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)))
-    my_ndk_sysroot_lib := $(my_ndk_sysroot)/usr/lib64
+  ifneq (,$(filter x86_64 mips64,$(my_arch)))
+    my_ndk_libdir_name := lib64
   else ifeq (mips32r6,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH_VARIANT))
-    my_ndk_sysroot_lib := $(my_ndk_sysroot)/usr/libr6
+    my_ndk_libdir_name := libr6
   else
-    my_ndk_sysroot_lib := $(my_ndk_sysroot)/usr/lib
+    my_ndk_libdir_name := lib
   endif
 
+  my_ndk_platform_dir := \
+      $(my_built_ndk)/platforms/android-$(my_ndk_api)/arch-$(my_arch)
+  my_built_ndk_libs := $(my_ndk_platform_dir)/usr/$(my_ndk_libdir_name)
+  my_ndk_sysroot_lib := $(my_ndk_sysroot)/usr/$(my_ndk_libdir_name)
+
   # The bionic linker now has support for packed relocations and gnu style
   # hashes (which are much faster!), but shipping to older devices requires
   # the old style hash. Fortunately, we can build with both and it'll work
@@ -108,7 +160,6 @@
   # See ndk/docs/CPLUSPLUS-SUPPORT.html
   my_ndk_stl_include_path :=
   my_ndk_stl_shared_lib_fullpath :=
-  my_ndk_stl_shared_lib :=
   my_ndk_stl_static_lib :=
   my_ndk_stl_cppflags :=
   my_cpu_variant := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)CPU_ABI)
@@ -131,21 +182,61 @@
     my_system_shared_libraries += libstdc++
     ifeq (stlport_static,$(LOCAL_NDK_STL_VARIANT))
       my_ndk_stl_static_lib := $(my_ndk_source_root)/cxx-stl/stlport/libs/$(my_cpu_variant)/libstlport_static.a
+      my_ldlibs += -ldl
     else
       my_ndk_stl_shared_lib_fullpath := $(my_ndk_source_root)/cxx-stl/stlport/libs/$(my_cpu_variant)/libstlport_shared.so
-      my_ndk_stl_shared_lib := -lstlport_shared
     endif
   else # LOCAL_NDK_STL_VARIANT is not stlport_* either
   ifneq (,$(filter c++_%, $(LOCAL_NDK_STL_VARIANT)))
-    my_ndk_stl_include_path := $(my_ndk_source_root)/cxx-stl/llvm-libc++/libcxx/include \
-                               $(my_ndk_source_root)/cxx-stl/llvm-libc++/gabi++/include \
-                               $(my_ndk_source_root)/android/support/include
-    ifeq (c++_static,$(LOCAL_NDK_STL_VARIANT))
-      my_ndk_stl_static_lib := $(my_ndk_source_root)/cxx-stl/llvm-libc++/libs/$(my_cpu_variant)/libc++_static.a
+    # Pre-r11 NDKs used libgabi++ for libc++'s C++ ABI, but r11 and later use
+    # libc++abi.
+    #
+    # r13 no longer has the inner directory as a side effect of just using
+    # external/libcxx.
+    ifeq (r10,$(LOCAL_NDK_VERSION))
+      my_ndk_stl_include_path := \
+        $(my_ndk_source_root)/cxx-stl/llvm-libc++/libcxx/include
+      my_ndk_stl_include_path += \
+        $(my_ndk_source_root)/cxx-stl/llvm-libc++/gabi++/include
+    else ifeq (r11,$(LOCAL_NDK_VERSION))
+      my_ndk_stl_include_path := \
+        $(my_ndk_source_root)/cxx-stl/llvm-libc++/libcxx/include
+      my_ndk_stl_include_path += \
+        $(my_ndk_source_root)/cxx-stl/llvm-libc++abi/libcxxabi/include
     else
-      my_ndk_stl_shared_lib_fullpath := $(my_ndk_source_root)/cxx-stl/llvm-libc++/libs/$(my_cpu_variant)/libc++_shared.so
-      my_ndk_stl_shared_lib := -lc++_shared
+      my_ndk_stl_include_path := \
+        $(my_ndk_source_root)/cxx-stl/llvm-libc++/include
+      my_ndk_stl_include_path += \
+        $(my_ndk_source_root)/cxx-stl/llvm-libc++abi/include
     endif
+    my_ndk_stl_include_path += $(my_ndk_source_root)/android/support/include
+
+    my_libcxx_libdir := \
+      $(my_ndk_source_root)/cxx-stl/llvm-libc++/libs/$(my_cpu_variant)
+
+    ifneq (,$(filter r10 r11,$(LOCAL_NDK_VERSION)))
+      ifeq (c++_static,$(LOCAL_NDK_STL_VARIANT))
+        my_ndk_stl_static_lib := $(my_libcxx_libdir)/libc++_static.a
+      else
+        my_ndk_stl_shared_lib_fullpath := $(my_libcxx_libdir)/libc++_shared.so
+      endif
+    else
+      ifeq (c++_static,$(LOCAL_NDK_STL_VARIANT))
+        my_ndk_stl_static_lib := \
+          $(my_libcxx_libdir)/libc++_static.a \
+          $(my_libcxx_libdir)/libc++abi.a
+      else
+        my_ndk_stl_shared_lib_fullpath := $(my_libcxx_libdir)/libc++_shared.so
+      endif
+
+      my_ndk_stl_static_lib += $(my_libcxx_libdir)/libandroid_support.a
+      ifneq (,$(filter armeabi armeabi-v7a,$(my_cpu_variant)))
+        my_ndk_stl_static_lib += $(my_libcxx_libdir)/libunwind.a
+      endif
+    endif
+
+    my_ldlibs += -ldl
+
     my_ndk_stl_cppflags := -std=c++11
   else # LOCAL_NDK_STL_VARIANT is not c++_* either
   ifneq (,$(filter gnustl_%, $(LOCAL_NDK_STL_VARIANT)))
@@ -160,16 +251,49 @@
   endif
 endif
 
+ifndef LOCAL_IS_HOST_MODULE
+# For device libraries, move LOCAL_LDLIBS references to my_shared_libraries. We
+# no longer need to use my_ldlibs to pick up NDK prebuilt libraries since we're
+# linking my_shared_libraries by full path now.
+my_allowed_ldlibs :=
+
+# Sort ldlibs and ldflags between -l and other linker flags
+# We'll do this again later, since there are still changes happening, but that's fine.
+my_ldlib_flags := $(my_ldflags) $(my_ldlibs)
+my_ldlibs := $(filter -l%,$(my_ldlib_flags))
+my_ldflags := $(filter-out -l%,$(my_ldlib_flags))
+my_ldlib_flags :=
+
+# Move other ldlibs back to shared libraries
+my_shared_libraries += $(patsubst -l%,lib%,$(filter-out $(my_allowed_ldlibs),$(my_ldlibs)))
+my_ldlibs := $(filter $(my_allowed_ldlibs),$(my_ldlibs))
+endif
+
+ifdef LOCAL_SDK_VERSION
+  my_all_ndk_libraries := \
+      $(NDK_MIGRATED_LIBS) $(addprefix lib,$(NDK_PREBUILT_SHARED_LIBRARIES))
+  my_ndk_shared_libraries := \
+      $(filter $(my_all_ndk_libraries),\
+        $(my_shared_libraries) $(my_system_shared_libraries))
+
+  my_shared_libraries := \
+      $(filter-out $(my_all_ndk_libraries),$(my_shared_libraries))
+  my_system_shared_libraries := \
+      $(filter-out $(my_all_ndk_libraries),$(my_system_shared_libraries))
+endif
+
 # MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
 # all code is position independent, and then those warnings get promoted to
 # errors.
+ifneq ($(LOCAL_NO_PIC),true)
 ifneq ($($(my_prefix)OS),windows)
-ifeq ($(LOCAL_MODULE_CLASS),EXECUTABLES)
+ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
 my_cflags += -fpie
 else
 my_cflags += -fPIC
 endif
 endif
+endif
 
 ifdef LOCAL_IS_HOST_MODULE
 my_src_files += $(LOCAL_SRC_FILES_$($(my_prefix)OS)) $(LOCAL_SRC_FILES_$($(my_prefix)OS)_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
@@ -209,13 +333,32 @@
 my_clang := $(strip $(LOCAL_CLANG_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)))
 endif
 
+# if custom toolchain is in use, default is not to use clang, if not explicitly required
+ifneq ($(my_cc)$(my_cxx),)
+    ifeq ($(my_clang),)
+        my_clang := false
+    endif
+endif
+# Issue warning if LOCAL_CLANG* is set to false and the local makefile is not found
+# in the exception project list.
+ifeq ($(my_clang),false)
+    ifeq ($(call find_in_local_clang_exception_projects,$(LOCAL_MODULE_MAKEFILE)),)
+        $(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): LOCAL_CLANG is set to false)
+    endif
+endif
+
 # clang is enabled by default for host builds
 # enable it unless we've specifically disabled clang above
 ifdef LOCAL_IS_HOST_MODULE
-    ifneq ($($(my_prefix)OS),windows)
-    ifeq ($(my_clang),)
-        my_clang := true
-    endif
+    ifeq ($($(my_prefix)OS),windows)
+        ifeq ($(my_clang),true)
+            $(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Clang is not yet supported for windows binaries)
+        endif
+        my_clang := false
+    else
+        ifeq ($(my_clang),)
+            my_clang := true
+        endif
     endif
 # Add option to make gcc the default for device build
 else ifeq ($(USE_CLANG_PLATFORM_BUILD),false)
@@ -269,15 +412,27 @@
 ifneq ($(strip $(CUSTOM_$(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)LINKER)),)
   my_linker := $(CUSTOM_$(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)LINKER)
 else
-  my_linker := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LINKER)
+  my_linker := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)LINKER)
 endif
 
 include $(BUILD_SYSTEM)/config_sanitizers.mk
 
+ifneq ($(LOCAL_NO_LIBCOMPILER_RT),true)
 # Add in libcompiler_rt for all regular device builds
-ifeq (,$(LOCAL_SDK_VERSION)$(WITHOUT_LIBCOMPILER_RT))
+ifeq (,$(WITHOUT_LIBCOMPILER_RT))
   my_static_libraries += $(COMPILER_RT_CONFIG_EXTRA_STATIC_LIBRARIES)
 endif
+endif
+
+ifneq ($(filter ../%,$(my_src_files)),)
+my_soong_problems += dotdot_srcs
+endif
+ifneq ($(foreach i,$(my_c_includes),$(filter %/..,$(i))$(findstring /../,$(i))),)
+my_soong_problems += dotdot_incs
+endif
+ifneq ($(filter %.arm,$(my_src_files)),)
+my_soong_problems += srcs_dotarm
+endif
 
 ####################################################
 ## Add FDO flags if FDO is turned on and supported
@@ -312,29 +467,33 @@
 ###########################################################
 ifndef LOCAL_IS_HOST_MODULE
 ifdef LOCAL_SDK_VERSION
-my_target_project_includes :=
-my_target_c_includes := $(my_ndk_stl_include_path) $(my_ndk_sysroot_include)
+my_target_global_c_includes :=
+my_target_global_c_system_includes := $(my_ndk_stl_include_path) $(my_ndk_sysroot_include)
 my_target_global_cppflags := $(my_ndk_stl_cppflags)
 else
-my_target_project_includes := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_PROJECT_INCLUDES)
-my_target_c_includes := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_C_INCLUDES)
+my_target_global_c_includes := $(SRC_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
+my_target_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
 my_target_global_cppflags :=
 endif # LOCAL_SDK_VERSION
 
 ifeq ($(my_clang),true)
-my_target_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_TARGET_GLOBAL_CFLAGS)
-my_target_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_TARGET_GLOBAL_CONLYFLAGS)
-my_target_global_cppflags += $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_TARGET_GLOBAL_CPPFLAGS)
-my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_TARGET_GLOBAL_LDFLAGS)
+my_target_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CFLAGS)
+my_target_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CONLYFLAGS)
+my_target_global_cppflags += $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CPPFLAGS)
+my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LDFLAGS)
 else
-my_target_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CFLAGS)
-my_target_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CONLYFLAGS)
-my_target_global_cppflags += $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CPPFLAGS)
-my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LDFLAGS)
+my_target_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_CFLAGS)
+my_target_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_CONLYFLAGS)
+my_target_global_cppflags += $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_CPPFLAGS)
+my_target_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_LDFLAGS)
 endif # my_clang
 
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_PROJECT_INCLUDES := $(my_target_project_includes)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_C_INCLUDES := $(my_target_c_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_INCLUDES := $(my_target_global_c_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_SYSTEM_INCLUDES := $(my_target_global_c_system_includes)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CFLAGS := $(my_target_global_cflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CONLYFLAGS := $(my_target_global_conlyflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CPPFLAGS := $(my_target_global_cppflags)
@@ -342,21 +501,27 @@
 
 else # LOCAL_IS_HOST_MODULE
 
+my_host_global_c_includes := $(SRC_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
+my_host_global_c_system_includes := $(SRC_SYSTEM_HEADERS) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)PROJECT_SYSTEM_INCLUDES) \
+    $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_SYSTEM_INCLUDES)
+
 ifeq ($(my_clang),true)
 my_host_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CFLAGS)
 my_host_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CONLYFLAGS)
 my_host_global_cppflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_CPPFLAGS)
 my_host_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)CLANG_$(my_prefix)GLOBAL_LDFLAGS)
-my_host_c_includes := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
 else
 my_host_global_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_CFLAGS)
 my_host_global_conlyflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_CONLYFLAGS)
 my_host_global_cppflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_CPPFLAGS)
 my_host_global_ldflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_LDFLAGS)
-my_host_c_includes := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)C_INCLUDES)
 endif # my_clang
 
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_C_INCLUDES := $(my_host_c_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_INCLUDES := $(my_host_global_c_includes)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_GLOBAL_C_SYSTEM_INCLUDES := $(my_host_global_c_system_includes)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CFLAGS := $(my_host_global_cflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CONLYFLAGS := $(my_host_global_conlyflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HOST_GLOBAL_CPPFLAGS := $(my_host_global_cppflags)
@@ -378,28 +543,25 @@
         my_cflags += --coverage -O0
         my_ldflags += --coverage
     endif
+
+    ifeq ($(my_clang),true)
+        my_coverage_lib := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)LIBPROFILE_RT)
+    else
+        my_coverage_lib := $(call intermediates-dir-for,STATIC_LIBRARIES,libgcov,$(filter AUX,$(my_kind)),,$(LOCAL_2ND_ARCH_VAR_PREFIX))/libgcov.a
+    endif
+
+    $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_COVERAGE_LIB := $(my_coverage_lib)
+    $(LOCAL_INTERMEDIATE_TARGETS): $(my_coverage_lib)
 else
     my_native_coverage := false
 endif
 
-ifeq ($(my_clang),true)
-    my_coverage_lib := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBPROFILE_RT)
-else
-    my_coverage_lib := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCOV)
-endif
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_COVERAGE_LIB := $(my_coverage_lib)
-
 ###########################################################
 ## Define PRIVATE_ variables used by multiple module types
 ###########################################################
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_NO_DEFAULT_COMPILER_FLAGS := \
     $(strip $(LOCAL_NO_DEFAULT_COMPILER_FLAGS))
 
-ifeq ($(strip $(WITH_SYNTAX_CHECK)),)
-  LOCAL_NO_SYNTAX_CHECK := true
-endif
-
 ifeq ($(strip $(WITH_STATIC_ANALYZER)),)
   LOCAL_NO_STATIC_ANALYZER := true
 endif
@@ -413,7 +575,7 @@
 ifneq ($(strip $(LOCAL_IS_HOST_MODULE)),)
   my_syntax_arch := host
 else
-  my_syntax_arch := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+  my_syntax_arch := $($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
 endif
 
 ifeq ($(strip $(my_cc)),)
@@ -428,10 +590,6 @@
 ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
   my_cc := CCC_CC=$(CLANG) CLANG=$(CLANG) \
            $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer
-else
-ifneq ($(LOCAL_NO_SYNTAX_CHECK),true)
-  my_cc := $(my_cc) -fsyntax-only
-endif
 endif
 
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CC := $(my_cc)
@@ -448,10 +606,6 @@
 ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
   my_cxx := CCC_CXX=$(CLANG_CXX) CLANG_CXX=$(CLANG_CXX) \
             $(SYNTAX_TOOLS_PREFIX)/c++-analyzer
-else
-ifneq ($(LOCAL_NO_SYNTAX_CHECK),true)
-  my_cxx := $(my_cxx) -fsyntax-only
-endif
 endif
 
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LINKER := $(my_linker)
@@ -468,7 +622,7 @@
 # up if --no-undefined is passed to the linker.
 ifeq ($(strip $(LOCAL_NO_DEFAULT_COMPILER_FLAGS)),)
 ifeq ($(my_allow_undefined_symbols),)
-  my_ldflags +=  $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)NO_UNDEFINED_LDFLAGS)
+  my_ldflags += -Wl,--no-undefined
 endif
 endif
 
@@ -492,8 +646,8 @@
 arm_objects_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)$(arm_objects_mode)_CFLAGS)
 normal_objects_cflags := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)$(normal_objects_mode)_CFLAGS)
 ifeq ($(my_clang),true)
-arm_objects_cflags := $(call $(LOCAL_2ND_ARCH_VAR_PREFIX)convert-to-$(my_host)clang-flags,$(arm_objects_cflags))
-normal_objects_cflags := $(call $(LOCAL_2ND_ARCH_VAR_PREFIX)convert-to-$(my_host)clang-flags,$(normal_objects_cflags))
+arm_objects_cflags := $(call convert-to-clang-flags,$(arm_objects_cflags))
+normal_objects_cflags := $(call convert-to-clang-flags,$(normal_objects_cflags))
 endif
 
 else
@@ -530,7 +684,7 @@
 
 my_gen_sources_copy := $(patsubst $(generated_sources_dir)/%,$(intermediates)/%,$(filter $(generated_sources_dir)/%,$(my_generated_sources)))
 
-$(my_gen_sources_copy): $(intermediates)/% : $(generated_sources_dir)/% | $(ACP)
+$(my_gen_sources_copy): $(intermediates)/% : $(generated_sources_dir)/%
 	@echo "Copy: $@"
 	$(copy-file-to-target)
 
@@ -551,6 +705,7 @@
 renderscript_sources := $(filter %.rs %.fs,$(my_src_files))
 
 ifneq (,$(renderscript_sources))
+my_soong_problems += rs
 
 renderscript_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(renderscript_sources))
 RenderScript_file_stamp := $(intermediates)/RenderScriptCPP.stamp
@@ -629,57 +784,58 @@
 ## Compile the .proto files to .cc (or .c) and then to .o
 ###########################################################
 proto_sources := $(filter %.proto,$(my_src_files))
-proto_generated_objects :=
-proto_generated_headers :=
 ifneq ($(proto_sources),)
-proto_generated_sources_dir := $(generated_sources_dir)/proto
-proto_generated_obj_dir := $(intermediates)/proto
+my_soong_problems += proto
+proto_gen_dir := $(generated_sources_dir)/proto
+proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
 
+my_rename_cpp_ext :=
 ifneq (,$(filter nanopb-c nanopb-c-enable_malloc, $(LOCAL_PROTOC_OPTIMIZE_TYPE)))
 my_proto_source_suffix := .c
 my_proto_c_includes := external/nanopb-c
-my_protoc_flags := --nanopb_out=$(proto_generated_sources_dir) \
+my_protoc_flags := --nanopb_out=$(proto_gen_dir) \
     --plugin=external/nanopb-c/generator/protoc-gen-nanopb
+my_protoc_deps := $(NANOPB_SRCS) $(proto_sources_fullpath:%.proto=%.options)
 else
-my_proto_source_suffix := .cc
+my_proto_source_suffix := $(LOCAL_CPP_EXTENSION)
+ifneq ($(my_proto_source_suffix),.cc)
+# aprotoc is hardcoded to write out only .cc file.
+# We need to rename the extension to $(LOCAL_CPP_EXTENSION) if it's not .cc.
+my_rename_cpp_ext := true
+endif
 my_proto_c_includes := external/protobuf/src
 my_cflags += -DGOOGLE_PROTOBUF_NO_RTTI
-my_protoc_flags := --cpp_out=$(proto_generated_sources_dir)
+my_protoc_flags := --cpp_out=$(proto_gen_dir)
+my_protoc_deps :=
 endif
-my_proto_c_includes += $(proto_generated_sources_dir)
+my_proto_c_includes += $(proto_gen_dir)
 
-proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
-proto_generated_sources := $(addprefix $(proto_generated_sources_dir)/, \
+proto_generated_cpps := $(addprefix $(proto_gen_dir)/, \
     $(patsubst %.proto,%.pb$(my_proto_source_suffix),$(proto_sources_fullpath)))
-proto_generated_headers := $(patsubst %.pb$(my_proto_source_suffix),%.pb.h, $(proto_generated_sources))
-proto_generated_objects := $(addprefix $(proto_generated_obj_dir)/, \
-    $(patsubst %.proto,%.pb.o,$(proto_sources_fullpath)))
-$(call track-src-file-obj,$(proto_sources),$(proto_generated_objects))
 
 # Ensure the transform-proto-to-cc rule is only defined once in multilib build.
-ifndef $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined
-$(proto_generated_sources): PRIVATE_PROTO_INCLUDES := $(TOP)
-$(proto_generated_sources): PRIVATE_PROTOC_FLAGS := $(LOCAL_PROTOC_FLAGS) $(my_protoc_flags)
-$(proto_generated_sources): $(proto_generated_sources_dir)/%.pb$(my_proto_source_suffix): %.proto $(PROTOC)
+ifndef $(my_host)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined
+$(proto_generated_cpps): PRIVATE_PROTO_INCLUDES := $(TOP)
+$(proto_generated_cpps): PRIVATE_PROTOC_FLAGS := $(LOCAL_PROTOC_FLAGS) $(my_protoc_flags)
+$(proto_generated_cpps): PRIVATE_RENAME_CPP_EXT := $(my_rename_cpp_ext)
+$(proto_generated_cpps): $(proto_gen_dir)/%.pb$(my_proto_source_suffix): %.proto $(my_protoc_deps) $(PROTOC)
 	$(transform-proto-to-cc)
 
-# This is just a dummy rule to make sure gmake doesn't skip updating the dependents.
-$(proto_generated_headers): $(proto_generated_sources_dir)/%.pb.h: $(proto_generated_sources_dir)/%.pb$(my_proto_source_suffix)
-	@echo "Updated header file $@."
-	$(hide) touch $@
-
-$(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined := true
-endif  # transform-proto-to-cc rule included only once
-
-$(proto_generated_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
-$(proto_generated_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-$(proto_generated_objects): $(proto_generated_obj_dir)/%.o: $(proto_generated_sources_dir)/%$(my_proto_source_suffix) $(proto_generated_headers)
-ifeq ($(my_proto_source_suffix),.c)
-	$(transform-$(PRIVATE_HOST)c-to-o)
-else
-	$(transform-$(PRIVATE_HOST)cpp-to-o)
+$(my_host)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined := true
 endif
-$(call include-depfiles-for-objs, $(proto_generated_objects))
+# Ideally we can generate the source directly into $(intermediates).
+# But many Android.mks assume the .pb.hs are in $(generated_sources_dir).
+# As a workaround, we make a copy in the $(intermediates).
+proto_intermediate_dir := $(intermediates)/proto
+proto_intermediate_cpps := $(patsubst $(proto_gen_dir)/%,$(proto_intermediate_dir)/%,\
+    $(proto_generated_cpps))
+$(proto_intermediate_cpps) : $(proto_intermediate_dir)/% : $(proto_gen_dir)/%
+	@echo "Copy: $@"
+	$(copy-file-to-target)
+	$(hide) cp $(basename $<).h $(basename $@).h
+$(call track-src-file-gen,$(proto_sources),$(proto_intermediate_cpps))
+
+my_generated_sources += $(proto_intermediate_cpps)
 
 my_c_includes += $(my_proto_c_includes)
 # Auto-export the generated proto source dir.
@@ -695,6 +851,8 @@
     else
         my_shared_libraries += libprotobuf-cpp-full
     endif
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),lite-static)
+    my_static_libraries += libprotobuf-cpp-lite
 else
     ifdef LOCAL_SDK_VERSION
         my_static_libraries += libprotobuf-cpp-lite-ndk
@@ -710,6 +868,7 @@
 dbus_definitions := $(filter %.dbus-xml,$(my_src_files))
 dbus_generated_headers :=
 ifneq ($(dbus_definitions),)
+my_soong_problems += dbus
 
 dbus_definition_paths := $(addprefix $(LOCAL_PATH)/,$(dbus_definitions))
 dbus_service_config := $(filter %dbus-service-config.json,$(my_src_files))
@@ -765,6 +924,7 @@
 aidl_src := $(strip $(filter %.aidl,$(my_src_files)))
 aidl_gen_cpp :=
 ifneq ($(aidl_src),)
+my_soong_problems += aidl
 
 # Use the intermediates directory to avoid writing our own .cpp -> .o rules.
 aidl_gen_cpp_root := $(intermediates)/aidl-generated/src
@@ -797,6 +957,7 @@
 vts_src := $(strip $(filter %.vts,$(my_src_files)))
 vts_gen_cpp :=
 ifneq ($(vts_src),)
+my_soong_problems += vts
 
 # Use the intermediates directory to avoid writing our own .cpp -> .o rules.
 vts_gen_cpp_root := $(intermediates)/vts-generated/src
@@ -831,7 +992,7 @@
     $(intermediates)/,$(y_yacc_sources:.y=.c))
 ifneq ($(y_yacc_cs),)
 $(y_yacc_cs): $(intermediates)/%.c: \
-    $(TOPDIR)$(LOCAL_PATH)/%.y \
+    $(TOPDIR)$(LOCAL_PATH)/%.y $(BISON) $(BISON_DATA) \
     $(my_additional_dependencies)
 	$(call transform-y-to-c-or-cpp)
 $(call track-src-file-gen,$(y_yacc_sources),$(y_yacc_cs))
@@ -844,7 +1005,7 @@
     $(intermediates)/,$(yy_yacc_sources:.yy=$(LOCAL_CPP_EXTENSION)))
 ifneq ($(yy_yacc_cpps),)
 $(yy_yacc_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
-    $(TOPDIR)$(LOCAL_PATH)/%.yy \
+    $(TOPDIR)$(LOCAL_PATH)/%.yy $(BISON) $(BISON_DATA) \
     $(my_additional_dependencies)
 	$(call transform-y-to-c-or-cpp)
 $(call track-src-file-gen,$(yy_yacc_sources),$(yy_yacc_cpps))
@@ -897,7 +1058,7 @@
 dotdot_arm_objects :=
 $(foreach s,$(dotdot_arm_sources),\
   $(eval $(call compile-dotdot-cpp-file,$(s),\
-  $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+  $(my_additional_dependencies),\
   dotdot_arm_objects)))
 $(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
 
@@ -905,7 +1066,7 @@
 dotdot_objects :=
 $(foreach s,$(dotdot_sources),\
   $(eval $(call compile-dotdot-cpp-file,$(s),\
-    $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+    $(my_additional_dependencies),\
     dotdot_objects)))
 $(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
 
@@ -923,7 +1084,6 @@
 ifneq ($(strip $(cpp_objects)),)
 $(cpp_objects): $(intermediates)/%.o: \
     $(TOPDIR)$(LOCAL_PATH)/%$(LOCAL_CPP_EXTENSION) \
-    $(yacc_cpps) $(proto_generated_headers) \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)cpp-to-o)
 $(call include-depfiles-for-objs, $(cpp_objects))
@@ -945,8 +1105,7 @@
 $(gen_cpp_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(gen_cpp_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 $(gen_cpp_objects): $(intermediates)/%.o: \
-    $(intermediates)/%$(LOCAL_CPP_EXTENSION) $(yacc_cpps) \
-    $(proto_generated_headers) \
+    $(intermediates)/%$(LOCAL_CPP_EXTENSION) \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)cpp-to-o)
 $(call include-depfiles-for-objs, $(gen_cpp_objects))
@@ -1001,7 +1160,7 @@
 dotdot_arm_objects :=
 $(foreach s,$(dotdot_arm_sources),\
   $(eval $(call compile-dotdot-c-file,$(s),\
-    $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+    $(my_additional_dependencies),\
     dotdot_arm_objects)))
 $(call track-src-file-obj,$(patsubst %,%.arm,$(dotdot_arm_sources)),$(dotdot_arm_objects))
 
@@ -1009,7 +1168,7 @@
 dotdot_objects :=
 $(foreach s, $(dotdot_sources),\
   $(eval $(call compile-dotdot-c-file,$(s),\
-    $(yacc_cpps) $(proto_generated_headers) $(my_additional_dependencies),\
+    $(my_additional_dependencies),\
     dotdot_objects)))
 $(call track-src-file-obj,$(dotdot_sources),$(dotdot_objects))
 
@@ -1025,7 +1184,7 @@
 c_objects        := $(c_arm_objects) $(c_normal_objects)
 
 ifneq ($(strip $(c_objects)),)
-$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c $(yacc_cpps) $(proto_generated_headers) \
+$(c_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.c \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)c-to-o)
 $(call include-depfiles-for-objs, $(c_objects))
@@ -1046,7 +1205,7 @@
 # TODO: support compiling certain generated files as arm.
 $(gen_c_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(gen_c_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-$(gen_c_objects): $(intermediates)/%.o: $(intermediates)/%.c $(yacc_cpps) $(proto_generated_headers) \
+$(gen_c_objects): $(intermediates)/%.o: $(intermediates)/%.c \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)c-to-o)
 $(call include-depfiles-for-objs, $(gen_c_objects))
@@ -1061,7 +1220,8 @@
 $(call track-src-file-obj,$(objc_sources),$(objc_objects))
 
 ifneq ($(strip $(objc_objects)),)
-$(objc_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.m $(yacc_cpps) $(proto_generated_headers) \
+my_soong_problems += objc
+$(objc_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.m \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)m-to-o)
 $(call include-depfiles-for-objs, $(objc_objects))
@@ -1076,7 +1236,8 @@
 $(call track-src-file-obj,$(objcpp_sources),$(objcpp_objects))
 
 ifneq ($(strip $(objcpp_objects)),)
-$(objcpp_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.mm $(yacc_cpps) $(proto_generated_headers) \
+my_soong_problems += objc
+$(objcpp_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.mm \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)mm-to-o)
 $(call include-depfiles-for-objs, $(objcpp_objects))
@@ -1172,11 +1333,11 @@
 import_includes := $(intermediates)/import_includes
 import_includes_deps := $(strip \
     $(foreach l, $(installed_shared_library_module_names), \
-      $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),$(LOCAL_IS_HOST_MODULE),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes) \
+      $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes) \
     $(foreach l, $(my_static_libraries) $(my_whole_static_libraries), \
-      $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(LOCAL_IS_HOST_MODULE),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
+      $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
 $(import_includes): PRIVATE_IMPORT_EXPORT_INCLUDES := $(import_includes_deps)
-$(import_includes) : $(LOCAL_MODULE_MAKEFILE_DEP) $(import_includes_deps)
+$(import_includes) : $(import_includes_deps)
 	@echo Import includes file: $@
 	$(hide) mkdir -p $(dir $@) && rm -f $@
 ifdef import_includes_deps
@@ -1187,13 +1348,46 @@
 	$(hide) touch $@
 endif
 
+####################################################
+## Verify that NDK-built libraries only link against
+## other NDK-built libraries
+####################################################
+
+my_link_type := $(intermediates)/link_type
+all_link_types: $(my_link_type)
+ifdef LOCAL_SDK_VERSION
+$(my_link_type): PRIVATE_LINK_TYPE := native:ndk
+$(my_link_type): PRIVATE_WARN_TYPES :=
+$(my_link_type): PRIVATE_ALLOWED_TYPES := native:ndk
+else
+$(my_link_type): PRIVATE_LINK_TYPE := native:platform
+$(my_link_type): PRIVATE_WARN_TYPES :=
+$(my_link_type): PRIVATE_ALLOWED_TYPES := native:ndk native:platform
+endif
+$(eval $(call link-type-partitions,$(my_link_type)))
+my_link_type_deps := $(strip \
+   $(foreach l,$(my_whole_static_libraries) $(my_static_libraries), \
+     $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/link_type))
+ifneq ($(LOCAL_MODULE_CLASS),STATIC_LIBRARIES)
+my_link_type_deps += $(strip \
+   $(foreach l,$(my_shared_libraries), \
+     $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/link_type))
+endif
+$(my_link_type): PRIVATE_DEPS := $(my_link_type_deps)
+$(my_link_type): PRIVATE_MODULE := $(LOCAL_MODULE)
+$(my_link_type): PRIVATE_MAKEFILE := $(LOCAL_MODULE_MAKEFILE)
+$(my_link_type): $(my_link_type_deps) $(CHECK_LINK_TYPE)
+	@echo Check module type: $@
+	$(check-link-type)
+
+
 ###########################################################
 ## Common object handling.
 ###########################################################
 
 my_unused_src_files := $(filter-out $(logtags_sources) $(my_tracked_src_files),$(my_src_files) $(my_gen_src_files))
 ifneq ($(my_unused_src_files),)
-  $(warning $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Unused source files: $(my_unused_src_files))
+  $(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Unused source files: $(my_unused_src_files))
 endif
 
 # some rules depend on asm_objects being first.  If your code depends on
@@ -1206,8 +1400,7 @@
     $(c_objects) \
     $(gen_c_objects) \
     $(objc_objects) \
-    $(objcpp_objects) \
-    $(proto_generated_objects)
+    $(objcpp_objects)
 
 new_order_normal_objects := $(foreach f,$(my_src_files),$(my_src_file_obj_$(f)))
 new_order_normal_objects += $(foreach f,$(my_gen_src_files),$(my_src_file_obj_$(f)))
@@ -1238,16 +1431,17 @@
   my_c_includes += $(JNI_H_INCLUDE)
 endif
 
+my_outside_includes := $(filter-out $(OUT_DIR)/%,$(filter /%,$(my_c_includes)))
+ifneq ($(my_outside_includes),)
+$(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): C_INCLUDES must be under the source or output directories: $(my_outside_includes))
+endif
+
 # all_objects includes gen_o_objects which were part of LOCAL_GENERATED_SOURCES;
 # use normal_objects here to avoid creating circular dependencies. This assumes
 # that custom build rules which generate .o files don't consume other generated
 # sources as input (or if they do they take care of that dependency themselves).
 $(normal_objects) : | $(my_generated_sources)
-ifeq ($(BUILDING_WITH_NINJA),true)
 $(all_objects) : $(import_includes)
-else
-$(all_objects) : | $(import_includes)
-endif
 ALL_C_CPP_ETC_OBJECTS += $(all_objects)
 
 
@@ -1297,7 +1491,19 @@
     $(addprefix $(my_ndk_sysroot_lib)/, \
         $(addsuffix $(so_suffix), $(my_system_shared_libraries)))
 
-built_shared_libraries += $(my_system_shared_libraries_fullpath)
+# We need to preserve the ordering of LOCAL_SHARED_LIBRARIES regardless of
+# whether the libs are generated or prebuilt, so we simply can't split into two
+# lists and use addprefix.
+my_ndk_shared_libraries_fullpath := \
+    $(foreach _lib,$(my_ndk_shared_libraries),\
+        $(if $(filter $(NDK_MIGRATED_LIBS),$(_lib)),\
+            $(my_built_ndk_libs)/$(_lib)$(so_suffix),\
+            $(my_ndk_sysroot_lib)/$(_lib)$(so_suffix)))
+
+built_shared_libraries += \
+    $(my_ndk_shared_libraries_fullpath) \
+    $(my_system_shared_libraries_fullpath) \
+
 else
 built_shared_libraries := \
     $(addprefix $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT_INTERMEDIATE_LIBRARIES)/, \
@@ -1316,7 +1522,7 @@
 built_static_libraries := \
     $(foreach lib,$(my_static_libraries), \
       $(call intermediates-dir-for, \
-        STATIC_LIBRARIES,$(lib),$(LOCAL_IS_HOST_MODULE),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/$(lib)$(a_suffix))
+        STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/$(lib)$(a_suffix))
 
 ifdef LOCAL_SDK_VERSION
 built_static_libraries += $(my_ndk_stl_static_lib)
@@ -1325,7 +1531,7 @@
 built_whole_libraries := \
     $(foreach lib,$(my_whole_static_libraries), \
       $(call intermediates-dir-for, \
-        STATIC_LIBRARIES,$(lib),$(LOCAL_IS_HOST_MODULE),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/$(lib)$(a_suffix))
+        STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/$(lib)$(a_suffix))
 
 # We don't care about installed static libraries, since the
 # libraries have already been linked into the module at that point.
@@ -1358,10 +1564,14 @@
 my_cppflags += $(LOCAL_CLANG_CPPFLAGS_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_CLANG_CPPFLAGS_$(my_32_64_bit_suffix))
 my_ldflags += $(LOCAL_CLANG_LDFLAGS_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_CLANG_LDFLAGS_$(my_32_64_bit_suffix))
 my_asflags += $(LOCAL_CLANG_ASFLAGS_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_CLANG_ASFLAGS_$(my_32_64_bit_suffix))
-my_cflags := $(call $(LOCAL_2ND_ARCH_VAR_PREFIX)convert-to-$(my_host)clang-flags,$(my_cflags))
-my_cppflags := $(call $(LOCAL_2ND_ARCH_VAR_PREFIX)convert-to-$(my_host)clang-flags,$(my_cppflags))
-my_asflags := $(call $(LOCAL_2ND_ARCH_VAR_PREFIX)convert-to-$(my_host)clang-flags,$(my_asflags))
-my_ldflags := $(call $(LOCAL_2ND_ARCH_VAR_PREFIX)convert-to-$(my_host)clang-flags,$(my_ldflags))
+my_cflags := $(call convert-to-clang-flags,$(my_cflags))
+my_cppflags := $(call convert-to-clang-flags,$(my_cppflags))
+my_asflags := $(call convert-to-clang-flags,$(my_asflags))
+my_ldflags := $(call convert-to-clang-flags,$(my_ldflags))
+else
+# gcc does not handle hidden functions in a manner compatible with LLVM libcxx
+# see b/27908145
+my_cflags += -Wno-attributes
 endif
 
 ifeq ($(my_fdo_build), true)
@@ -1379,6 +1589,87 @@
 my_cppflags := $(filter-out $(my_illegal_flags),$(my_cppflags))
 my_conlyflags := $(filter-out $(my_illegal_flags),$(my_conlyflags))
 
+# We can enforce some rules more strictly in the code we own. my_strict
+# indicates if this is code that we can be stricter with. If we have rules that
+# we want to apply to *our* code (but maybe can't for vendor/device specific
+# things), we could extend this to be a ternary value.
+my_strict := true
+ifneq ($(filter external/%,$(LOCAL_PATH)),)
+    my_strict := false
+endif
+
+# Can be used to make some annotations stricter for code we can fix (such as
+# when we mark functions as deprecated).
+ifeq ($(my_strict),true)
+    my_cflags += -DANDROID_STRICT
+endif
+
+# Disable clang-tidy if it is not found.
+ifeq ($(PATH_TO_CLANG_TIDY),)
+  my_tidy_enabled := false
+else
+  # If LOCAL_TIDY is not defined, use global WITH_TIDY
+  my_tidy_enabled := $(LOCAL_TIDY)
+  ifeq ($(my_tidy_enabled),)
+    my_tidy_enabled := $(WITH_TIDY)
+  endif
+endif
+
+# my_tidy_checks is empty if clang-tidy is disabled.
+my_tidy_checks :=
+my_tidy_flags :=
+ifneq (,$(filter 1 true,$(my_tidy_enabled)))
+  ifneq ($(my_clang),true)
+    # Disable clang-tidy if clang is disabled.
+    my_tidy_enabled := false
+  else
+    tidy_only: $(cpp_objects) $(c_objects)
+    # Set up global default checks
+    my_tidy_checks := $(WITH_TIDY_CHECKS)
+    ifeq ($(my_tidy_checks),)
+      my_tidy_checks := $(call default_global_tidy_checks,$(LOCAL_PATH))
+    endif
+    # Append local clang-tidy checks.
+    ifneq ($(LOCAL_TIDY_CHECKS),)
+      my_tidy_checks := $(my_tidy_checks),$(LOCAL_TIDY_CHECKS)
+    endif
+    # Set up global default clang-tidy flags, which is none.
+    my_tidy_flags := $(WITH_TIDY_FLAGS)
+    # Use local clang-tidy flags if specified.
+    ifneq ($(LOCAL_TIDY_FLAGS),)
+      my_tidy_flags := $(LOCAL_TIDY_FLAGS)
+    endif
+    # If tidy flags are not specified, default to check all header files.
+    ifeq ($(my_tidy_flags),)
+      my_tidy_flags := $(call default_tidy_header_filter,$(LOCAL_PATH))
+    endif
+  endif
+endif
+
+my_tidy_checks := $(subst $(space),,$(my_tidy_checks))
+
+# Move -l* entries from ldflags to ldlibs, and everything else to ldflags
+my_ldlib_flags := $(my_ldflags) $(my_ldlibs)
+my_ldlibs := $(filter -l%,$(my_ldlib_flags))
+my_ldflags := $(filter-out -l%,$(my_ldlib_flags))
+
+# One last verification check for ldlibs
+ifndef LOCAL_IS_HOST_MODULE
+my_allowed_ldlibs :=
+ifdef LOCAL_SDK_VERSION
+  my_allowed_ldlibs := $(addprefix -l,$(NDK_PREBUILT_SHARED_LIBRARIES))
+endif
+
+my_bad_ldlibs := $(filter-out $(my_allowed_ldlibs),$(my_ldlibs))
+ifneq ($(my_bad_ldlibs),)
+  $(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Bad LOCAL_LDLIBS entries: $(my_bad_ldlibs))
+endif
+endif
+
+# my_cxx_ldlibs may contain linker flags need to wrap certain libraries
+# (start-group/end-group), so append after the check above.
+my_ldlibs += $(my_cxx_ldlibs)
+
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_YACCFLAGS := $(LOCAL_YACCFLAGS)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASFLAGS := $(my_asflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CONLYFLAGS := $(my_conlyflags)
@@ -1392,13 +1683,15 @@
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_IMPORT_INCLUDES := $(import_includes)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LDFLAGS := $(my_ldflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LDLIBS := $(my_ldlibs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TIDY_CHECKS := $(my_tidy_checks)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TIDY_FLAGS := $(my_tidy_flags)
 
 # this is really the way to get the files onto the command line instead
 # of using $^, because then LOCAL_ADDITIONAL_DEPENDENCIES doesn't work
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_SHARED_LIBRARIES := $(built_shared_libraries)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_STATIC_LIBRARIES := $(built_static_libraries)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_WHOLE_STATIC_LIBRARIES := $(built_whole_libraries)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_OBJECTS := $(all_objects)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_OBJECTS := $(strip $(all_objects))
 
 ###########################################################
 # Define library dependencies.
@@ -1420,32 +1713,62 @@
 ###########################################################
 export_includes := $(intermediates)/export_includes
 $(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(my_export_c_include_dirs)
-# Make sure .pb.h are already generated before any dependent source files get compiled.
-# Similarly, the generated DBus headers need to exist before we export their location.
-# People are not going to consume the aidl generated cpp file, but the cpp file is
-# generated after the headers, so this is a convenient way to ensure the headers exist.
-$(export_includes) : $(LOCAL_MODULE_MAKEFILE_DEP) $(proto_generated_headers) $(dbus_generated_headers) $(aidl_gen_cpp) $(vts_gen_cpp)
+# Headers exported by whole static libraries are also exported by this library.
+export_include_deps := $(strip \
+   $(foreach l,$(my_whole_static_libraries), \
+     $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
+# Re-export requested headers from shared libraries.
+export_include_deps += $(strip \
+   $(foreach l,$(LOCAL_EXPORT_SHARED_LIBRARY_HEADERS), \
+     $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
+# Re-export requested headers from static libraries.
+export_include_deps += $(strip \
+   $(foreach l,$(LOCAL_EXPORT_STATIC_LIBRARY_HEADERS), \
+     $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
+$(export_includes): PRIVATE_REEXPORTED_INCLUDES := $(export_include_deps)
+# By adding $(my_generated_sources) it makes sure the headers get generated
+# before any dependent source files get compiled.
+$(export_includes) : $(my_export_c_include_deps) $(my_generated_sources) $(export_include_deps)
 	@echo Export includes file: $< -- $@
-	$(hide) mkdir -p $(dir $@) && rm -f $@.tmp
+	$(hide) mkdir -p $(dir $@) && rm -f $@.tmp && touch $@.tmp
 ifdef my_export_c_include_dirs
 	$(hide) for d in $(PRIVATE_EXPORT_C_INCLUDE_DIRS); do \
 	        echo "-I $$d" >> $@.tmp; \
 	        done
-else
-	$(hide) touch $@.tmp
 endif
-ifeq ($(BUILDING_WITH_NINJA),true)
+ifdef export_include_deps
+	$(hide) for f in $(PRIVATE_REEXPORTED_INCLUDES); do \
+		cat $$f >> $@.tmp; \
+		done
+endif
 	$(hide) if cmp -s $@.tmp $@ ; then \
 	  rm $@.tmp ; \
 	else \
 	  mv $@.tmp $@ ; \
 	fi
-else
-	mv $@.tmp $@ ;
-endif
 
 # Kati adds restat=1 to ninja. GNU make does nothing for this.
 .KATI_RESTAT: $(export_includes)
 
 # Make sure export_includes gets generated when you are running mm/mmm
-$(LOCAL_BUILT_MODULE) : | $(export_includes)
+$(LOCAL_BUILT_MODULE) : | $(export_includes) $(my_link_type)
+
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+SOONG_CONV.$(LOCAL_MODULE).PROBLEMS := \
+    $(SOONG_CONV.$(LOCAL_MODULE).PROBLEMS) $(my_soong_problems)
+SOONG_CONV.$(LOCAL_MODULE).DEPS := \
+    $(SOONG_CONV.$(LOCAL_MODULE).DEPS) \
+    $(my_static_libraries) \
+    $(my_whole_static_libraries) \
+    $(my_shared_libraries) \
+    $(my_system_shared_libraries)
+SOONG_CONV := $(SOONG_CONV) $(LOCAL_MODULE)
+endif
+
+###########################################################
+# Coverage packaging.
+###########################################################
+ifeq ($(my_native_coverage),true)
+LOCAL_GCNO_FILES := $(patsubst %.o,%.gcno,$(all_objects))
+$(foreach f,$(all_objects),$(eval $(call gcno-touch-rule,$(f),$(f:.o=.gcno))))
+endif
diff --git a/core/build-system.html b/core/build-system.html
index bddde6a..95f35ce 100644
--- a/core/build-system.html
+++ b/core/build-system.html
@@ -438,7 +438,7 @@
 GEN := $(intermediates)/<font color=red>file.c</font>
 $(GEN): PRIVATE_INPUT_FILE := $(LOCAL_PATH)/<font color=red>input.file</font>
 $(GEN): PRIVATE_CUSTOM_TOOL = <font color=red>cat $(PRIVATE_INPUT_FILE) &gt; $@</font>
-$(GEN): <font color=red>$(LOCAL_PATH)/file.c</font>
+$(GEN): <font color=red>$(LOCAL_PATH)/input.file</font>
 	$(transform-generated-source)
 LOCAL_GENERATED_SOURCES += $(GEN)
 </pre>
diff --git a/core/ccache.mk b/core/ccache.mk
index 5c2ae23..d67bce6 100644
--- a/core/ccache.mk
+++ b/core/ccache.mk
@@ -17,7 +17,7 @@
 ifneq ($(filter-out false,$(USE_CCACHE)),)
   # The default check uses size and modification time, causing false misses
   # since the mtime depends when the repo was checked out
-  export CCACHE_COMPILERCHECK := content
+  export CCACHE_COMPILERCHECK ?= content
 
   # See man page, optimizations to get more cache hits
   # implies that __DATE__ and __TIME__ are not critical for functionality.
diff --git a/core/clang/HOST_CROSS_x86.mk b/core/clang/HOST_CROSS_x86.mk
index b78a074..bf48f95 100644
--- a/core/clang/HOST_CROSS_x86.mk
+++ b/core/clang/HOST_CROSS_x86.mk
@@ -1,56 +1 @@
-
-include $(BUILD_SYSTEM)/clang/x86.mk
-
-CLANG_CONFIG_x86_HOST_CROSS_TRIPLE := i686-pc-mingw32
-
-CLANG_CONFIG_x86_HOST_CROSS_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_COMBO_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_x86_HOST_CROSS_TRIPLE)
-
-CLANG_CONFIG_x86_HOST_CROSS_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_COMBO_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_x86_HOST_CROSS_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_COMBO_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_x86_HOST_CROSS_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_COMBO_EXTRA_CPPFLAGS) \
-  -target $(CLANG_CONFIG_x86_HOST_CROSS_TRIPLE)
-
-CLANG_CONFIG_x86_HOST_CROSS_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_COMBO_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_x86_HOST_CROSS_TRIPLE)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_CFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_EXTRA_CFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_CONLYFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_EXTRA_CONLYFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_CPPFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_EXTRA_CPPFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_LDFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_CROSS_EXTRA_LDFLAGS)
-
 $(clang_2nd_arch_prefix)HOST_CROSS_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i686.a
diff --git a/core/clang/HOST_CROSS_x86_64.mk b/core/clang/HOST_CROSS_x86_64.mk
index b6f2de9..f921a1c 100644
--- a/core/clang/HOST_CROSS_x86_64.mk
+++ b/core/clang/HOST_CROSS_x86_64.mk
@@ -1,56 +1 @@
-
-include $(BUILD_SYSTEM)/clang/x86_64.mk
-
-CLANG_CONFIG_x86_64_HOST_CROSS_TRIPLE := x86_64-pc-mingw32
-
-CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_COMBO_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_HOST_CROSS_TRIPLE)
-
-CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_COMBO_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_COMBO_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_COMBO_EXTRA_CPPFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_HOST_CROSS_TRIPLE)
-
-CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_HOST_CROSS_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_COMBO_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_HOST_CROSS_TRIPLE)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_CFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_CFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_CONLYFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_CONLYFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_CPPFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_CPPFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_CROSS_GLOBAL_LDFLAGS := \
-  $(call convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_CROSS_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_CROSS_EXTRA_LDFLAGS)
-
 $(clang_2nd_arch_prefix)HOST_CROSS_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-x86_64.a
diff --git a/core/clang/HOST_x86.mk b/core/clang/HOST_x86.mk
index 0ec64ad..0722b2a 100644
--- a/core/clang/HOST_x86.mk
+++ b/core/clang/HOST_x86.mk
@@ -1,77 +1 @@
-
-include $(BUILD_SYSTEM)/clang/x86.mk
-include $(BUILD_SYSTEM)/clang/HOST_x86_common.mk
-
-ifeq ($(HOST_OS),linux)
-CLANG_CONFIG_x86_HOST_TRIPLE := i686-linux-gnu
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_ASFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_ASFLAGS)
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_CFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CFLAGS)
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_CPPFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CPPFLAGS)
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_LDFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_LDFLAGS)
-endif
-ifeq ($(HOST_OS),darwin)
-CLANG_CONFIG_x86_HOST_TRIPLE := i686-apple-darwin
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_ASFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_ASFLAGS)
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_CFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CFLAGS)
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_CPPFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CPPFLAGS)
-CLANG_CONFIG_x86_HOST_COMBO_EXTRA_LDFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_LDFLAGS)
-endif
-
-CLANG_CONFIG_x86_HOST_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_COMBO_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_x86_HOST_TRIPLE)
-
-CLANG_CONFIG_x86_HOST_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_COMBO_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_x86_HOST_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_COMBO_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_x86_HOST_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_COMBO_EXTRA_CPPFLAGS) \
-  -target $(CLANG_CONFIG_x86_HOST_TRIPLE)
-
-CLANG_CONFIG_x86_HOST_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_HOST_COMBO_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_x86_HOST_TRIPLE)
-
-define $(clang_2nd_arch_prefix)convert-to-host-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-x86-flags,\
-  $(filter-out $(CLANG_CONFIG_x86_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-$(clang_2nd_arch_prefix)CLANG_HOST_GLOBAL_CFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_EXTRA_CFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_GLOBAL_CONLYFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_EXTRA_CONLYFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_GLOBAL_CPPFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_EXTRA_CPPFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_HOST_GLOBAL_LDFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-host-clang-flags,$($(clang_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_x86_HOST_EXTRA_LDFLAGS)
-
 $(clang_2nd_arch_prefix)HOST_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i686.a
diff --git a/core/clang/HOST_x86_64.mk b/core/clang/HOST_x86_64.mk
index d46cb67..4fdffd8 100644
--- a/core/clang/HOST_x86_64.mk
+++ b/core/clang/HOST_x86_64.mk
@@ -1,77 +1 @@
-
-include $(BUILD_SYSTEM)/clang/x86_64.mk
-include $(BUILD_SYSTEM)/clang/HOST_x86_common.mk
-
-ifeq ($(HOST_OS),linux)
-CLANG_CONFIG_x86_64_HOST_TRIPLE := x86_64-linux-gnu
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_ASFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_ASFLAGS)
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_CFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CFLAGS)
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_CPPFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CPPFLAGS)
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_LDFLAGS := $(CLANG_CONFIG_x86_LINUX_HOST_EXTRA_LDFLAGS)
-endif
-ifeq ($(HOST_OS),darwin)
-CLANG_CONFIG_x86_64_HOST_TRIPLE := x86_64-apple-darwin
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_ASFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_ASFLAGS)
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_CFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CFLAGS)
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_CPPFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CPPFLAGS)
-CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_LDFLAGS := $(CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_LDFLAGS)
-endif
-
-CLANG_CONFIG_x86_64_HOST_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_HOST_TRIPLE)
-
-CLANG_CONFIG_x86_64_HOST_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_x86_64_HOST_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_x86_64_HOST_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_CPPFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_HOST_TRIPLE)
-
-CLANG_CONFIG_x86_64_HOST_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_HOST_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_64_HOST_COMBO_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_HOST_TRIPLE)
-
-define convert-to-host-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-x86_64-flags,\
-  $(filter-out $(CLANG_CONFIG_x86_64_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-CLANG_HOST_GLOBAL_CFLAGS := \
-  $(call convert-to-host-clang-flags,$(HOST_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_EXTRA_CFLAGS)
-
-CLANG_HOST_GLOBAL_CONLYFLAGS := \
-  $(call convert-to-host-clang-flags,$(HOST_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_EXTRA_CONLYFLAGS)
-
-CLANG_HOST_GLOBAL_CPPFLAGS := \
-  $(call convert-to-host-clang-flags,$(HOST_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_EXTRA_CPPFLAGS)
-
-CLANG_HOST_GLOBAL_LDFLAGS := \
-  $(call convert-to-host-clang-flags,$(HOST_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_x86_64_HOST_EXTRA_LDFLAGS)
-
 HOST_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-x86_64.a
diff --git a/core/clang/HOST_x86_common.mk b/core/clang/HOST_x86_common.mk
deleted file mode 100644
index 9e71750..0000000
--- a/core/clang/HOST_x86_common.mk
+++ /dev/null
@@ -1,54 +0,0 @@
-# Shared by HOST_x86.mk and HOST_x86_64.mk.
-
-ifeq ($(HOST_OS),darwin)
-CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_ASFLAGS := \
-  -integrated-as
-
-CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CFLAGS := \
-  -integrated-as
-
-CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CFLAGS += -fstack-protector-strong
-endif
-
-ifeq ($(HOST_OS),linux)
-CLANG_CONFIG_x86_LINUX_HOST_EXTRA_ASFLAGS := \
-  --gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG) \
-  --sysroot $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/sysroot
-
-CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CFLAGS := \
-  --gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)
-
-CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CFLAGS += -fstack-protector-strong
-
-ifneq ($(strip $($(clang_2nd_arch_prefix)HOST_IS_64_BIT)),)
-CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CPPFLAGS := \
-  --gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG) \
-  --sysroot $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/sysroot \
-  -isystem $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/include/c++/4.8 \
-  -isystem $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/include/c++/4.8/x86_64-linux \
-  -isystem $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/include/c++/4.8/backward
-
-CLANG_CONFIG_x86_LINUX_HOST_EXTRA_LDFLAGS := \
-  --gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG) \
-  --sysroot $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/sysroot \
-  -B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/bin \
-  -B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/lib/gcc/x86_64-linux/4.8 \
-  -L$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/lib/gcc/x86_64-linux/4.8 \
-  -L$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/lib64/
-else
-CLANG_CONFIG_x86_LINUX_HOST_EXTRA_CPPFLAGS := \
-  --gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG) \
-  --sysroot $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/sysroot \
-  -isystem $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/include/c++/4.8 \
-  -isystem $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/include/c++/4.8/x86_64-linux/32 \
-  -isystem $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/include/c++/4.8/backward
-
-CLANG_CONFIG_x86_LINUX_HOST_EXTRA_LDFLAGS := \
-  --gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG) \
-  --sysroot $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/sysroot \
-  -B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/bin \
-  -B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/lib/gcc/x86_64-linux/4.8/32 \
-  -L$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/lib/gcc/x86_64-linux/4.8/32 \
-  -L$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/lib32/
-endif
-endif  # Linux
diff --git a/core/clang/TARGET_arm.mk b/core/clang/TARGET_arm.mk
index 5c1bf6f..30313f9 100644
--- a/core/clang/TARGET_arm.mk
+++ b/core/clang/TARGET_arm.mk
@@ -1,66 +1,3 @@
-
-include $(BUILD_SYSTEM)/clang/arm.mk
-
-CLANG_CONFIG_arm_TARGET_TRIPLE := arm-linux-androideabi
-CLANG_CONFIG_arm_TARGET_TOOLCHAIN_PREFIX := \
-  $($(clang_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT)/$(CLANG_CONFIG_arm_TARGET_TRIPLE)/bin
-
-CLANG_CONFIG_arm_TARGET_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_arm_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_arm_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_arm_TARGET_TOOLCHAIN_PREFIX)
-
-CLANG_CONFIG_arm_TARGET_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_arm_EXTRA_CFLAGS) \
-  -target $(CLANG_CONFIG_arm_TARGET_TRIPLE) \
-  $(CLANG_CONFIG_arm_TARGET_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_arm_TARGET_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_arm_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_arm_TARGET_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_arm_EXTRA_CPPFLAGS) \
-  -target $(CLANG_CONFIG_arm_TARGET_TRIPLE)
-
-CLANG_CONFIG_arm_TARGET_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_arm_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_arm_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_arm_TARGET_TOOLCHAIN_PREFIX)
-
-
-define $(clang_2nd_arch_prefix)convert-to-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-arm-flags,\
-  $(filter-out $(CLANG_CONFIG_arm_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_arm_TARGET_EXTRA_CFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CONLYFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_arm_TARGET_EXTRA_CONLYFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CPPFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_arm_TARGET_EXTRA_CPPFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_LDFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_arm_TARGET_EXTRA_LDFLAGS)
-
 $(clang_2nd_arch_prefix)RS_TRIPLE := armv7-linux-androideabi
 $(clang_2nd_arch_prefix)RS_TRIPLE_CFLAGS :=
 $(clang_2nd_arch_prefix)RS_COMPAT_TRIPLE := armv7-none-linux-gnueabi
@@ -68,5 +5,4 @@
 $(clang_2nd_arch_prefix)TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-arm-android.a
 
 # Address sanitizer clang config
-$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan-arm-android
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
diff --git a/core/clang/TARGET_arm64.mk b/core/clang/TARGET_arm64.mk
index 15b0172..d504600 100644
--- a/core/clang/TARGET_arm64.mk
+++ b/core/clang/TARGET_arm64.mk
@@ -1,64 +1,3 @@
-
-include $(BUILD_SYSTEM)/clang/arm64.mk
-
-CLANG_CONFIG_arm64_TARGET_TRIPLE := aarch64-linux-android
-CLANG_CONFIG_arm64_TARGET_TOOLCHAIN_PREFIX := \
-  $(TARGET_TOOLCHAIN_ROOT)/$(CLANG_CONFIG_arm64_TARGET_TRIPLE)/bin
-
-CLANG_CONFIG_arm64_TARGET_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_arm64_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_arm64_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_arm64_TARGET_TOOLCHAIN_PREFIX)
-
-CLANG_CONFIG_arm64_TARGET_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_arm64_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_arm64_TARGET_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_arm64_TARGET_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_arm64_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_arm64_TARGET_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_arm64_EXTRA_CPPFLAGS) \
-
-CLANG_CONFIG_arm64_TARGET_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_arm64_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_arm64_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_arm64_TARGET_TOOLCHAIN_PREFIX)
-
-
-define convert-to-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-arm64-flags,\
-  $(filter-out $(CLANG_CONFIG_arm64_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-CLANG_TARGET_GLOBAL_CFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_arm64_TARGET_EXTRA_CFLAGS)
-
-CLANG_TARGET_GLOBAL_CONLYFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_arm64_TARGET_EXTRA_CONLYFLAGS)
-
-CLANG_TARGET_GLOBAL_CPPFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_arm64_TARGET_EXTRA_CPPFLAGS)
-
-CLANG_TARGET_GLOBAL_LDFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_arm64_TARGET_EXTRA_LDFLAGS)
-
 RS_TRIPLE := aarch64-linux-android
 RS_TRIPLE_CFLAGS :=
 RS_COMPAT_TRIPLE := aarch64-linux-android
@@ -66,5 +5,4 @@
 TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-aarch64-android.a
 
 # Address sanitizer clang config
-ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan-aarch64-android
 ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
diff --git a/core/clang/TARGET_mips.mk b/core/clang/TARGET_mips.mk
index 1a0176a..df96c5a 100644
--- a/core/clang/TARGET_mips.mk
+++ b/core/clang/TARGET_mips.mk
@@ -1,67 +1,8 @@
-
-include $(BUILD_SYSTEM)/clang/mips.mk
-
-CLANG_CONFIG_mips_TARGET_TRIPLE := mipsel-linux-android
-CLANG_CONFIG_mips_TARGET_TOOLCHAIN_PREFIX := \
-  $($(clang_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT)/mips64el-linux-android/bin
-
-CLANG_CONFIG_mips_TARGET_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_mips_EXTRA_ASFLAGS) \
-  -fPIC \
-  -target $(CLANG_CONFIG_mips_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_mips_TARGET_TOOLCHAIN_PREFIX)
-
-CLANG_CONFIG_mips_TARGET_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_mips_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_mips_TARGET_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_mips_TARGET_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_mips_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_mips_TARGET_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_mips_EXTRA_CPPFLAGS) \
-
-CLANG_CONFIG_mips_TARGET_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_mips_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_mips_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_mips_TARGET_TOOLCHAIN_PREFIX)
-
-
-define $(clang_2nd_arch_prefix)convert-to-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-mips-flags,\
-  $(filter-out $(CLANG_CONFIG_mips_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_mips_TARGET_EXTRA_CFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CONLYFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_mips_TARGET_EXTRA_CONLYFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CPPFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_mips_TARGET_EXTRA_CPPFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_LDFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_mips_TARGET_EXTRA_LDFLAGS)
-
 $(clang_2nd_arch_prefix)RS_TRIPLE := armv7-linux-androideabi
 $(clang_2nd_arch_prefix)RS_TRIPLE_CFLAGS :=
 RS_COMPAT_TRIPLE := mipsel-linux-android
 
 $(clang_2nd_arch_prefix)TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-mipsel-android.a
+
+# Address sanitizer clang config
+$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
diff --git a/core/clang/TARGET_mips64.mk b/core/clang/TARGET_mips64.mk
index 104fb70..785752a 100644
--- a/core/clang/TARGET_mips64.mk
+++ b/core/clang/TARGET_mips64.mk
@@ -1,66 +1,8 @@
-
-include $(BUILD_SYSTEM)/clang/mips64.mk
-
-CLANG_CONFIG_mips64_TARGET_TRIPLE := mips64el-linux-android
-CLANG_CONFIG_mips64_TARGET_TOOLCHAIN_PREFIX := \
-  $(TARGET_TOOLCHAIN_ROOT)/$(CLANG_CONFIG_mips64_TARGET_TRIPLE)/bin
-
-CLANG_CONFIG_mips64_TARGET_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_mips64_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_mips64_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_mips64_TARGET_TOOLCHAIN_PREFIX)
-
-CLANG_CONFIG_mips64_TARGET_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_mips64_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_mips64_TARGET_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_mips64_TARGET_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_mips64_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_mips64_TARGET_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_mips64_EXTRA_CPPFLAGS) \
-
-CLANG_CONFIG_mips64_TARGET_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_mips64_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_mips64_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_mips64_TARGET_TOOLCHAIN_PREFIX)
-
-
-define convert-to-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-mips64-flags,\
-  $(filter-out $(CLANG_CONFIG_mips64_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-CLANG_TARGET_GLOBAL_CFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_mips64_TARGET_EXTRA_CFLAGS)
-
-CLANG_TARGET_GLOBAL_CONLYFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_mips64_TARGET_EXTRA_CONLYFLAGS)
-
-CLANG_TARGET_GLOBAL_CPPFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_mips64_TARGET_EXTRA_CPPFLAGS)
-
-CLANG_TARGET_GLOBAL_LDFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_mips64_TARGET_EXTRA_LDFLAGS)
-
 RS_TRIPLE := aarch64-linux-android
 RS_TRIPLE_CFLAGS :=
 RS_COMPAT_TRIPLE := mips64el-linux-android
 
 TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-mips64el-android.a
+
+# Address sanitizer clang config
+$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
diff --git a/core/clang/TARGET_x86.mk b/core/clang/TARGET_x86.mk
index 741768b..f00eb41 100644
--- a/core/clang/TARGET_x86.mk
+++ b/core/clang/TARGET_x86.mk
@@ -1,71 +1,3 @@
-
-include $(BUILD_SYSTEM)/clang/x86.mk
-
-CLANG_CONFIG_x86_TARGET_TRIPLE := i686-linux-android
-# NOTE: There is no i686-linux-android prebuilt, so we must hardcode the
-# x86_64 target instead.
-CLANG_CONFIG_x86_TARGET_TOOLCHAIN_PREFIX := \
-  $($(clang_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT)/x86_64-linux-android/bin
-
-CLANG_CONFIG_x86_TARGET_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_x86_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_x86_TARGET_TOOLCHAIN_PREFIX)
-
-CLANG_CONFIG_x86_TARGET_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_TARGET_EXTRA_ASFLAGS) \
-  -mstackrealign
-
-# -mstackrealign is needed to realign stack in native code
-# that could be called from JNI, so that movaps instruction
-# will work on assumed stack aligned local variables.
-
-CLANG_CONFIG_x86_TARGET_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_x86_TARGET_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_CPPFLAGS) \
-
-CLANG_CONFIG_x86_TARGET_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_x86_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_x86_TARGET_TOOLCHAIN_PREFIX)
-
-
-define $(clang_2nd_arch_prefix)convert-to-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-x86-flags,\
-  $(filter-out $(CLANG_CONFIG_x86_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_x86_TARGET_EXTRA_CFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CONLYFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_x86_TARGET_EXTRA_CONLYFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_CPPFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_x86_TARGET_EXTRA_CPPFLAGS)
-
-$(clang_2nd_arch_prefix)CLANG_TARGET_GLOBAL_LDFLAGS := \
-  $(call $(clang_2nd_arch_prefix)convert-to-clang-flags,$($(clang_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_x86_TARGET_EXTRA_LDFLAGS)
-
 $(clang_2nd_arch_prefix)RS_TRIPLE := armv7-linux-androideabi
 $(clang_2nd_arch_prefix)RS_TRIPLE_CFLAGS := -D__i386__
 $(clang_2nd_arch_prefix)RS_COMPAT_TRIPLE := i686-linux-android
@@ -73,5 +5,4 @@
 $(clang_2nd_arch_prefix)TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i686-android.a
 
 # Address sanitizer clang config
-$(clang_2nd_arch_prefix)ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan-i686-android
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
diff --git a/core/clang/TARGET_x86_64.mk b/core/clang/TARGET_x86_64.mk
index e44382d..0d615f2 100644
--- a/core/clang/TARGET_x86_64.mk
+++ b/core/clang/TARGET_x86_64.mk
@@ -1,64 +1,3 @@
-
-include $(BUILD_SYSTEM)/clang/x86_64.mk
-
-CLANG_CONFIG_x86_64_TARGET_TRIPLE := x86_64-linux-android
-CLANG_CONFIG_x86_64_TARGET_TOOLCHAIN_PREFIX := \
-  $(TARGET_TOOLCHAIN_ROOT)/$(CLANG_CONFIG_x86_64_TARGET_TRIPLE)/bin
-
-CLANG_CONFIG_x86_64_TARGET_EXTRA_ASFLAGS := \
-  $(CLANG_CONFIG_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_ASFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_ASFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_x86_64_TARGET_TOOLCHAIN_PREFIX)
-
-CLANG_CONFIG_x86_64_TARGET_EXTRA_CFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CFLAGS) \
-  $(CLANG_CONFIG_x86_64_TARGET_EXTRA_ASFLAGS)
-
-CLANG_CONFIG_x86_64_TARGET_EXTRA_CONLYFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CONLYFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CONLYFLAGS)
-
-CLANG_CONFIG_x86_64_TARGET_EXTRA_CPPFLAGS := \
-  $(CLANG_CONFIG_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_CPPFLAGS) \
-
-CLANG_CONFIG_x86_64_TARGET_EXTRA_LDFLAGS := \
-  $(CLANG_CONFIG_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_TARGET_EXTRA_LDFLAGS) \
-  $(CLANG_CONFIG_x86_64_EXTRA_LDFLAGS) \
-  -target $(CLANG_CONFIG_x86_64_TARGET_TRIPLE) \
-  -B$(CLANG_CONFIG_x86_64_TARGET_TOOLCHAIN_PREFIX)
-
-
-define convert-to-clang-flags
-  $(strip \
-  $(call subst-clang-incompatible-x86_64-flags,\
-  $(filter-out $(CLANG_CONFIG_x86_64_UNKNOWN_CFLAGS),\
-  $(1))))
-endef
-
-CLANG_TARGET_GLOBAL_CFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CFLAGS)) \
-  $(CLANG_CONFIG_x86_64_TARGET_EXTRA_CFLAGS)
-
-CLANG_TARGET_GLOBAL_CONLYFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CONLYFLAGS)) \
-  $(CLANG_CONFIG_x86_64_TARGET_EXTRA_CONLYFLAGS)
-
-CLANG_TARGET_GLOBAL_CPPFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_CPPFLAGS)) \
-  $(CLANG_CONFIG_x86_64_TARGET_EXTRA_CPPFLAGS)
-
-CLANG_TARGET_GLOBAL_LDFLAGS := \
-  $(call convert-to-clang-flags,$(TARGET_GLOBAL_LDFLAGS)) \
-  $(CLANG_CONFIG_x86_64_TARGET_EXTRA_LDFLAGS)
-
 RS_TRIPLE := aarch64-linux-android
 RS_TRIPLE_CFLAGS := -D__x86_64__
 RS_COMPAT_TRIPLE := x86_64-linux-android
diff --git a/core/clang/arm.mk b/core/clang/arm.mk
deleted file mode 100644
index 4053bb2..0000000
--- a/core/clang/arm.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Clang flags for arm arch, target or host.
-
-CLANG_CONFIG_arm_EXTRA_ASFLAGS :=
-
-CLANG_CONFIG_arm_EXTRA_CFLAGS :=
-
-ifneq (,$(filter krait,$(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)))
-  # Android's clang support's krait as a CPU whereas GCC doesn't. Specify
-  # -mcpu here rather than the more normal core/combo/arch/arm/armv7-a-neon.mk.
-  CLANG_CONFIG_arm_EXTRA_CFLAGS += -mcpu=krait -mfpu=neon-vfpv4
-endif
-
-CLANG_CONFIG_arm_EXTRA_CPPFLAGS :=
-
-CLANG_CONFIG_arm_EXTRA_LDFLAGS :=
-
-# Include common unknown flags
-CLANG_CONFIG_arm_UNKNOWN_CFLAGS := \
-  $(CLANG_CONFIG_UNKNOWN_CFLAGS) \
-  -mthumb-interwork \
-  -fgcse-after-reload \
-  -frerun-cse-after-loop \
-  -frename-registers \
-  -fno-align-jumps \
-  -fno-builtin-sin \
-  -fno-caller-saves \
-  -fno-early-inlining \
-  -fno-move-loop-invariants \
-  -fno-partial-inlining \
-  -fno-strict-volatile-bitfields \
-  -fno-tree-copy-prop \
-  -fno-tree-loop-optimize
-
-define subst-clang-incompatible-arm-flags
-  $(subst -march=armv5te,-march=armv5t,\
-  $(subst -march=armv5e,-march=armv5,\
-  $(1)))
-endef
diff --git a/core/clang/arm64.mk b/core/clang/arm64.mk
deleted file mode 100644
index cad7321..0000000
--- a/core/clang/arm64.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-# Clang flags for arm64 arch, target or host.
-
-CLANG_CONFIG_arm64_EXTRA_ASFLAGS :=
-
-CLANG_CONFIG_arm64_EXTRA_CFLAGS :=
-
-CLANG_CONFIG_arm64_EXTRA_LDFLAGS :=
-
-# Include common unknown flags
-CLANG_CONFIG_arm64_UNKNOWN_CFLAGS := \
-  $(CLANG_CONFIG_UNKNOWN_CFLAGS) \
-  -fgcse-after-reload \
-  -frerun-cse-after-loop \
-  -frename-registers \
-  -fno-strict-volatile-bitfields \
-  -fno-align-jumps
-
-# We don't have any arm64 flags to substitute yet.
-define subst-clang-incompatible-arm64-flags
-  $(1)
-endef
diff --git a/core/clang/config.mk b/core/clang/config.mk
index 6cc3446..c2a0bf4 100644
--- a/core/clang/config.mk
+++ b/core/clang/config.mk
@@ -3,10 +3,11 @@
 LLVM_PREBUILTS_PATH := $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/bin
 LLVM_RTLIB_PATH := $(LLVM_PREBUILTS_PATH)/../lib64/clang/$(LLVM_RELEASE_VERSION)/lib/linux/
 
-CLANG := $(LLVM_PREBUILTS_PATH)/clang$(BUILD_EXECUTABLE_SUFFIX)
-CLANG_CXX := $(LLVM_PREBUILTS_PATH)/clang++$(BUILD_EXECUTABLE_SUFFIX)
-LLVM_AS := $(LLVM_PREBUILTS_PATH)/llvm-as$(BUILD_EXECUTABLE_SUFFIX)
-LLVM_LINK := $(LLVM_PREBUILTS_PATH)/llvm-link$(BUILD_EXECUTABLE_SUFFIX)
+# These will come from Soong, drop the environment versions
+unexport CLANG
+unexport CLANG_CXX
+unexport CCC_CC
+unexport CCC_CXX
 
 CLANG_TBLGEN := $(BUILD_OUT_EXECUTABLES)/clang-tblgen$(BUILD_EXECUTABLE_SUFFIX)
 LLVM_TBLGEN := $(BUILD_OUT_EXECUTABLES)/llvm-tblgen$(BUILD_EXECUTABLE_SUFFIX)
@@ -14,55 +15,13 @@
 # RenderScript-specific tools
 # These are tied to the version of LLVM directly in external/, so they might
 # trail the host prebuilts being used for the rest of the build process.
-RS_LLVM_PREBUILTS_VERSION := clang-2690385
+RS_LLVM_PREBUILTS_VERSION := clang-2812033
 RS_LLVM_PREBUILTS_BASE := prebuilts/clang/host
 RS_LLVM_PREBUILTS_PATH := $(RS_LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(RS_LLVM_PREBUILTS_VERSION)/bin
 RS_CLANG := $(RS_LLVM_PREBUILTS_PATH)/clang$(BUILD_EXECUTABLE_SUFFIX)
 RS_LLVM_AS := $(RS_LLVM_PREBUILTS_PATH)/llvm-as$(BUILD_EXECUTABLE_SUFFIX)
 RS_LLVM_LINK := $(RS_LLVM_PREBUILTS_PATH)/llvm-link$(BUILD_EXECUTABLE_SUFFIX)
 
-# Clang flags for all host or target rules
-CLANG_CONFIG_EXTRA_ASFLAGS :=
-CLANG_CONFIG_EXTRA_CFLAGS :=
-CLANG_CONFIG_EXTRA_CONLYFLAGS := -std=gnu99
-CLANG_CONFIG_EXTRA_CPPFLAGS :=
-CLANG_CONFIG_EXTRA_LDFLAGS :=
-
-CLANG_CONFIG_EXTRA_CFLAGS += \
-  -D__compiler_offsetof=__builtin_offsetof
-
-# Help catch common 32/64-bit errors.
-CLANG_CONFIG_EXTRA_CFLAGS += \
-  -Werror=int-conversion
-
-# Disable overly aggressive warning for macros defined with a leading underscore
-# This used to happen in AndroidConfig.h, which was included everywhere.
-# TODO: can we remove this now?
-CLANG_CONFIG_EXTRA_CFLAGS += \
-  -Wno-reserved-id-macro
-
-# Disable overly aggressive warning for format strings.
-# Bug: 20148343
-CLANG_CONFIG_EXTRA_CFLAGS += \
-  -Wno-format-pedantic
-
-# Workaround for ccache with clang.
-# See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html.
-CLANG_CONFIG_EXTRA_CFLAGS += \
-  -Wno-unused-command-line-argument
-
-# Disable -Winconsistent-missing-override until we can clean up the existing
-# codebase for it.
-CLANG_CONFIG_EXTRA_CPPFLAGS += \
-  -Wno-inconsistent-missing-override
-
-# Force clang to always output color diagnostics.  Ninja will strip the ANSI
-# color codes if it is not running in a terminal.
-ifdef BUILDING_WITH_NINJA
-CLANG_CONFIG_EXTRA_CFLAGS += \
-  -fcolor-diagnostics
-endif
-
 CLANG_CONFIG_UNKNOWN_CFLAGS := \
   -finline-functions \
   -finline-limit=64 \
@@ -90,25 +49,30 @@
   -Wunused-but-set-parameter \
   -Wunused-but-set-variable \
   -fdiagnostics-color \
-  -fdebug-prefix-map=/proc/self/cwd=
+  -mthumb-interwork \
+  -fgcse-after-reload \
+  -frerun-cse-after-loop \
+  -frename-registers \
+  -fno-align-jumps \
+  -fno-builtin-sin \
+  -fno-caller-saves \
+  -fno-early-inlining \
+  -fno-move-loop-invariants \
+  -fno-partial-inlining \
+  -fno-strict-volatile-bitfields \
+  -fno-tree-copy-prop \
+  -fno-tree-loop-optimize \
+  -msynci \
+  -mno-synci \
+  -mno-fused-madd \
+  -finline-limit=300 \
+  -fno-inline-functions-called-once \
+  -mfpmath=sse \
+  -mbionic
 
-# Clang flags for all host rules
-CLANG_CONFIG_HOST_EXTRA_ASFLAGS :=
-CLANG_CONFIG_HOST_EXTRA_CFLAGS :=
-CLANG_CONFIG_HOST_EXTRA_CPPFLAGS :=
-CLANG_CONFIG_HOST_EXTRA_LDFLAGS :=
-
-# Clang flags for all host cross rules
-CLANG_CONFIG_HOST_CROSS_EXTRA_ASFLAGS :=
-CLANG_CONFIG_HOST_CROSS_EXTRA_CFLAGS :=
-CLANG_CONFIG_HOST_CROSS_EXTRA_CPPFLAGS :=
-CLANG_CONFIG_HOST_CROSS_EXTRA_LDFLAGS :=
-
-# Clang flags for all target rules
-CLANG_CONFIG_TARGET_EXTRA_ASFLAGS :=
-CLANG_CONFIG_TARGET_EXTRA_CFLAGS := -nostdlibinc
-CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS := -nostdlibinc
-CLANG_CONFIG_TARGET_EXTRA_LDFLAGS :=
+define convert-to-clang-flags
+$(strip $(filter-out $(CLANG_CONFIG_UNKNOWN_CFLAGS),$(1)))
+endef
 
 CLANG_DEFAULT_UB_CHECKS := \
   bool \
@@ -168,14 +132,30 @@
 ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS := -fno-omit-frame-pointer
 ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS := -Wl,-u,__asan_preinit
 
-ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES :=
 ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES := libasan
 
 # This allows us to use the superset of functionality that compiler-rt
 # provides to Clang (for supporting features like -ftrapv).
 COMPILER_RT_CONFIG_EXTRA_STATIC_LIBRARIES := libcompiler_rt-extras
 
-ifeq ($(HOST_PREFER_32_BIT),true)
-# We don't have 32-bit prebuilt libLLVM/libclang, so force to build them from source.
-FORCE_BUILD_LLVM_COMPONENTS := true
-endif
+# A list of projects that are allowed to set LOCAL_CLANG to false.
+# INTERNAL_LOCAL_CLANG_EXCEPTION_PROJECTS is defined later in other config.mk.
+LOCAL_CLANG_EXCEPTION_PROJECTS = \
+  bionic/tests/ \
+  device/huawei/angler/ \
+  device/lge/bullhead/ \
+  external/gentoo/integration/ \
+  external/valgrind/ \
+  hardware/qcom/ \
+  $(INTERNAL_LOCAL_CLANG_EXCEPTION_PROJECTS)
+
+# Find $1 in the exception project list.
+define find_in_local_clang_exception_projects
+$(subst $(space),, \
+  $(foreach project,$(LOCAL_CLANG_EXCEPTION_PROJECTS), \
+    $(if $(filter $(project)%,$(1)),$(project)) \
+  ) \
+)
+endef
+
+include $(BUILD_SYSTEM)/clang/tidy.mk
diff --git a/core/clang/mips.mk b/core/clang/mips.mk
deleted file mode 100644
index 4a8f812..0000000
--- a/core/clang/mips.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Clang flags for mips arch, target or host.
-
-CLANG_CONFIG_mips_EXTRA_ASFLAGS :=
-CLANG_CONFIG_mips_EXTRA_CFLAGS :=
-CLANG_CONFIG_mips_EXTRA_LDFLAGS :=
-
-# Include common unknown flags
-CLANG_CONFIG_mips_UNKNOWN_CFLAGS := \
-  $(CLANG_CONFIG_UNKNOWN_CFLAGS) \
-  -fno-strict-volatile-bitfields \
-  -fgcse-after-reload \
-  -frerun-cse-after-loop \
-  -frename-registers \
-  -msynci \
-  -mno-synci \
-  -mno-fused-madd
-
-# Temporary workaround for Mips clang++ problem,  creates
-#   relocated ptrs in read-only pic .gcc_exception_table;
-#   permanent fix pending at http://reviews.llvm.org/D9669
-CLANG_CONFIG_mips_UNKNOWN_CFLAGS += -Wl,--warn-shared-textrel
-
-# We don't have any mips flags to substitute yet.
-define subst-clang-incompatible-mips-flags
-  $(1)
-endef
diff --git a/core/clang/mips64.mk b/core/clang/mips64.mk
deleted file mode 100644
index 1b72e05..0000000
--- a/core/clang/mips64.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Clang flags for mips64 arch, target or host.
-
-CLANG_CONFIG_mips64_EXTRA_ASFLAGS :=
-CLANG_CONFIG_mips64_EXTRA_CFLAGS :=
-CLANG_CONFIG_mips64_EXTRA_LDFLAGS :=
-
-# Include common unknown flags
-CLANG_CONFIG_mips64_UNKNOWN_CFLAGS := \
-  $(CLANG_CONFIG_UNKNOWN_CFLAGS) \
-  -fno-strict-volatile-bitfields \
-  -fgcse-after-reload \
-  -frerun-cse-after-loop \
-  -frename-registers \
-  -msynci \
-  -mno-synci \
-  -mno-fused-madd
-
-# Temporary workaround for Mips clang++ problem creating
-#   relocated ptrs in read-only pic .gcc_exception_table;
-#   permanent fix pending at http://reviews.llvm.org/D9669
-CLANG_CONFIG_mips64_UNKNOWN_CFLAGS += -Wl,--warn-shared-textrel
-
-# We don't have any mips64 flags to substitute yet.
-define subst-clang-incompatible-mips64-flags
-  $(1)
-endef
diff --git a/core/clang/tidy.mk b/core/clang/tidy.mk
new file mode 100644
index 0000000..c156f31
--- /dev/null
+++ b/core/clang/tidy.mk
@@ -0,0 +1,100 @@
+#
+# Copyright (C) 2016 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.
+#
+
+# Most Android source files are not clang-tidy clean yet.
+# Global tidy checks include only google*, performance*,
+# and misc-macro-parentheses, but not google-readability*
+# or google-runtime-references.
+DEFAULT_GLOBAL_TIDY_CHECKS := \
+  $(subst $(space),, \
+    -*,google* \
+    ,misc-macro-parentheses \
+    ,performance* \
+    ,-google-readability* \
+    ,-google-runtime-references \
+  )
+
+# There are too many clang-tidy warnings in external and vendor projects.
+# Enable only some google checks for these projects.
+DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS := \
+  $(subst $(space),, \
+    -*,google* \
+    ,-google-build-using-namespace \
+    ,-google-default-arguments \
+    ,-google-explicit-constructor \
+    ,-google-readability* \
+    ,-google-runtime-int \
+    ,-google-runtime-references \
+  )
+
+# Every word in DEFAULT_LOCAL_TIDY_CHECKS list has the following format:
+#   <local_path_prefix>:,<tidy-checks>
+# The last matched local_path_prefix should be the most specific to be used.
+DEFAULT_LOCAL_TIDY_CHECKS := \
+  external/:$(DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS) \
+  external/google:$(DEFAULT_GLOBAL_TIDY_CHECKS) \
+  external/webrtc:$(DEFAULT_GLOBAL_TIDY_CHECKS) \
+  frameworks/compile/mclinker/:$(DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS) \
+  hardware/qcom:$(DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS) \
+  vendor/:$(DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS) \
+  vendor/google:$(DEFAULT_GLOBAL_TIDY_CHECKS) \
+  vendor/google_devices:$(DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS) \
+
+# Returns 2nd word of $(1) if $(2) has prefix of the 1st word of $(1).
+define find_default_local_tidy_check2
+$(if $(filter $(word 1,$(1))%,$(2)/),$(word 2,$(1)))
+endef
+
+# Returns 2nd part of $(1) if $(2) has prefix of the 1st part of $(1).
+define find_default_local_tidy_check
+$(call find_default_local_tidy_check2,$(subst :,$(space),$(1)),$(2))
+endef
+
+# Returns the default tidy check list for local project path $(1).
+# Match $(1) with all patterns in DEFAULT_LOCAL_TIDY_CHECKS and use the last
+# most specific pattern.
+define default_global_tidy_checks
+$(lastword \
+  $(DEFAULT_GLOBAL_TIDY_CHECKS) \
+  $(foreach pattern,$(DEFAULT_LOCAL_TIDY_CHECKS), \
+    $(call find_default_local_tidy_check,$(pattern),$(1)) \
+  ) \
+)
+endef
+
+# Give warnings to header files only in selected directories.
+# Do not give warnings to external or vendor header files,
+# which contain too many warnings.
+DEFAULT_TIDY_HEADER_DIRS := \
+  $(subst $(space),, \
+     art/ \
+    |bionic/ \
+    |bootable/ \
+    |build/ \
+    |cts/ \
+    |dalvik/ \
+    |developers/ \
+    |development/ \
+    |frameworks/ \
+    |libcore/ \
+    |libnativehelper/ \
+    |system/ \
+  )
+
+# Default filter contains current directory $1 and DEFAULT_TIDY_HEADER_DIRS.
+define default_tidy_header_filter
+  -header-filter="($(subst $(space),,$1|$(DEFAULT_TIDY_HEADER_DIRS)))"
+endef
diff --git a/core/clang/versions.mk b/core/clang/versions.mk
index 81bd3b8..03341d9 100644
--- a/core/clang/versions.mk
+++ b/core/clang/versions.mk
@@ -1,5 +1,5 @@
 ## Clang/LLVM release versions.
 
 LLVM_RELEASE_VERSION := 3.8
-LLVM_PREBUILTS_VERSION ?= clang-2690385
+LLVM_PREBUILTS_VERSION ?= clang-3289846
 LLVM_PREBUILTS_BASE ?= prebuilts/clang/host
diff --git a/core/clang/x86.mk b/core/clang/x86.mk
deleted file mode 100644
index 69c3fb2..0000000
--- a/core/clang/x86.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Clang flags for x86 arch, target or host.
-
-CLANG_CONFIG_x86_EXTRA_ASFLAGS := \
-  -msse3
-CLANG_CONFIG_x86_EXTRA_CFLAGS :=
-CLANG_CONFIG_x86_EXTRA_LDFLAGS :=
-
-# Include common unknown flags
-CLANG_CONFIG_x86_UNKNOWN_CFLAGS := \
-  $(CLANG_CONFIG_UNKNOWN_CFLAGS) \
-  -finline-limit=300 \
-  -fno-inline-functions-called-once \
-  -mfpmath=sse \
-  -mbionic
-
-# We don't have any x86 flags to substitute yet.
-define subst-clang-incompatible-x86-flags
-  $(1)
-endef
diff --git a/core/clang/x86_64.mk b/core/clang/x86_64.mk
deleted file mode 100644
index cba10d4..0000000
--- a/core/clang/x86_64.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-# Clang flags for x86_64 arch, target or host.
-
-CLANG_CONFIG_x86_64_EXTRA_ASFLAGS :=
-CLANG_CONFIG_x86_64_EXTRA_CFLAGS :=
-CLANG_CONFIG_x86_64_EXTRA_LDFLAGS :=
-
-# Include common unknown flags
-CLANG_CONFIG_x86_64_UNKNOWN_CFLAGS := \
-  $(CLANG_CONFIG_UNKNOWN_CFLAGS) \
-  -finline-limit=300 \
-  -fno-inline-functions-called-once \
-  -mfpmath=sse \
-  -mbionic
-
-# We don't have any x86_64 flags to substitute yet.
-define subst-clang-incompatible-x86_64-flags
-  $(1)
-endef
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index 0d6a406..6a29585 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -151,28 +151,18 @@
 # necessary to keep things consistent.
 
 previous_build_config_file := $(PRODUCT_OUT)/previous_build_config.mk
-
-# A change in the list of aapt configs warrants an installclean, too.
-aapt_config_list := $(strip $(PRODUCT_AAPT_CONFIG) $(PRODUCT_AAPT_PREF_CONFIG))
+current_build_config_file := $(PRODUCT_OUT)/current_build_config.mk
 
 current_build_config := \
-    $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)-{$(aapt_config_list)}
-current_sanitize_target := $(strip $(SANITIZE_TARGET))
-ifeq (,$(current_sanitize_target))
-  current_sanitize_target := false
-endif
-aapt_config_list :=
+    $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)
 force_installclean := false
-force_objclean := false
 
 # Read the current state from the file, if present.
 # Will set PREVIOUS_BUILD_CONFIG.
 #
 PREVIOUS_BUILD_CONFIG :=
-PREVIOUS_SANITIZE_TARGET :=
 -include $(previous_build_config_file)
 PREVIOUS_BUILD_CONFIG := $(strip $(PREVIOUS_BUILD_CONFIG))
-PREVIOUS_SANITIZE_TARGET := $(strip $(PREVIOUS_SANITIZE_TARGET))
 
 ifdef PREVIOUS_BUILD_CONFIG
   ifneq "$(current_build_config)" "$(PREVIOUS_BUILD_CONFIG)"
@@ -185,27 +175,19 @@
   endif
 endif  # else, this is the first build, so no need to clean.
 
-ifdef PREVIOUS_SANITIZE_TARGET
-  ifneq "$(current_sanitize_target)" "$(PREVIOUS_SANITIZE_TARGET)"
-    $(info *** SANITIZE_TARGET changed: "$(PREVIOUS_SANITIZE_TARGET)" -> "$(current_sanitize_target)")
-    force_objclean := true
-  endif
-endif  # else, this is the first build, so no need to clean.
-
 # Write the new state to the file.
 #
-ifneq ($(PREVIOUS_BUILD_CONFIG)-$(PREVIOUS_SANITIZE_TARGET),$(current_build_config)-$(current_sanitize_target))
 $(shell \
-  mkdir -p $(dir $(previous_build_config_file)) && \
+  mkdir -p $(dir $(current_build_config_file)) && \
   echo "PREVIOUS_BUILD_CONFIG := $(current_build_config)" > \
-      $(previous_build_config_file) && \
-  echo "PREVIOUS_SANITIZE_TARGET := $(current_sanitize_target)" >> \
-      $(previous_build_config_file) \
+      $(current_build_config_file) \
  )
-endif
+$(shell cmp $(current_build_config_file) $(previous_build_config_file) > /dev/null 2>&1 || \
+  mv -f $(current_build_config_file) $(previous_build_config_file))
+
 PREVIOUS_BUILD_CONFIG :=
-PREVIOUS_SANITIZE_TARGET :=
 previous_build_config_file :=
+current_build_config_file :=
 current_build_config :=
 
 #
@@ -236,7 +218,6 @@
 	$(PRODUCT_OUT)/kernel \
 	$(PRODUCT_OUT)/data \
 	$(PRODUCT_OUT)/skin \
-	$(PRODUCT_OUT)/obj/APPS \
 	$(PRODUCT_OUT)/obj/NOTICE_FILES \
 	$(PRODUCT_OUT)/obj/PACKAGING \
 	$(PRODUCT_OUT)/recovery \
@@ -244,17 +225,7 @@
 	$(PRODUCT_OUT)/system \
 	$(PRODUCT_OUT)/vendor \
 	$(PRODUCT_OUT)/oem \
-	$(PRODUCT_OUT)/dex_bootjars \
-	$(PRODUCT_OUT)/obj/JAVA_LIBRARIES \
-	$(PRODUCT_OUT)/obj/FAKE \
-	$(PRODUCT_OUT)/obj/EXECUTABLES/adbd_intermediates \
-	$(PRODUCT_OUT)/obj/EXECUTABLES/logd_intermediates \
-	$(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libfs_mgr_intermediates \
-	$(PRODUCT_OUT)/obj/EXECUTABLES/init_intermediates \
-	$(PRODUCT_OUT)/obj/ETC/mac_permissions.xml_intermediates \
-	$(PRODUCT_OUT)/obj/ETC/sepolicy_intermediates \
-	$(PRODUCT_OUT)/obj/ETC/sepolicy.recovery_intermediates \
-	$(PRODUCT_OUT)/obj/ETC/init.environ.rc_intermediates
+	$(PRODUCT_OUT)/obj/FAKE
 
 # The files/dirs to delete during a dataclean, which removes any files
 # in the staging and emulator data partitions.
@@ -263,12 +234,6 @@
 	$(PRODUCT_OUT)/data-qemu/* \
 	$(PRODUCT_OUT)/userdata-qemu.img
 
-# The files/dirs to delete during an objclean, which removes any files
-# in the staging and emulator data partitions.
-objclean_files := \
-	$(TARGET_OUT_INTERMEDIATES) \
-	$($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES)
-
 # make sure *_OUT is set so that we won't result in deleting random parts
 # of the filesystem.
 ifneq (2,$(words $(HOST_OUT) $(PRODUCT_OUT)))
@@ -288,12 +253,6 @@
 	$(hide) rm -rf $(FILES)
 	@echo "Deleted images and staging directories."
 
-.PHONY: objclean
-objclean: FILES := $(objclean_files)
-objclean:
-	$(hide) rm -rf $(FILES)
-	@echo "Deleted images and staging directories."
-
 ifeq "$(force_installclean)" "true"
   $(info *** Forcing "make installclean"...)
   $(info *** rm -rf $(dataclean_files) $(installclean_files))
@@ -302,14 +261,6 @@
 endif
 force_installclean :=
 
-ifeq "$(force_objclean)" "true"
-  $(info *** Forcing cleanup of intermediate files...)
-  $(info *** rm -rf $(objclean_files))
-  $(shell rm -rf $(objclean_files))
-  $(info *** Done with the cleaning, now starting the real build.)
-endif
-force_objclean :=
-
 ###########################################################
 
 .PHONY: clean-jack-files
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 59e907b..1d927b0 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -25,7 +25,6 @@
 LOCAL_MANIFEST_PACKAGE_NAME:=
 LOCAL_PACKAGE_SPLITS:=
 LOCAL_REQUIRED_MODULES:=
-LOCAL_ACP_UNAVAILABLE:=
 LOCAL_MODULE_TAGS:=
 LOCAL_SRC_FILES:=
 LOCAL_SRC_FILES_EXCLUDE:=
@@ -36,6 +35,8 @@
 # Group static libraries with "-Wl,--start-group" and "-Wl,--end-group" when linking.
 LOCAL_GROUP_STATIC_LIBRARIES:=
 LOCAL_WHOLE_STATIC_LIBRARIES:=
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS:=
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS:=
 LOCAL_SHARED_LIBRARIES:=
 LOCAL_IS_HOST_MODULE:=
 LOCAL_CC:=
@@ -55,6 +56,7 @@
 LOCAL_CONLYFLAGS:=
 LOCAL_RTTI_FLAG:=
 LOCAL_C_INCLUDES:=
+LOCAL_EXPORT_C_INCLUDE_DEPS:=
 LOCAL_EXPORT_C_INCLUDE_DIRS:=
 LOCAL_LDFLAGS:=
 LOCAL_CLANG_LDFLAGS:=
@@ -75,6 +77,8 @@
 LOCAL_NO_STANDARD_LIBRARIES:=
 LOCAL_CLASSPATH:=
 LOCAL_JACK_CLASSPATH:=
+LOCAL_JACK_PLUGIN_PATH:=
+LOCAL_JACK_PLUGIN:=
 LOCAL_DROIDDOC_USE_STANDARD_DOCLET:=
 LOCAL_DROIDDOC_SOURCE_PATH:=
 LOCAL_DROIDDOC_TEMPLATE_DIR:=
@@ -109,12 +113,11 @@
 LOCAL_JARJAR_RULES:=
 LOCAL_ADDITIONAL_JAVA_DIR:=
 LOCAL_ALLOW_UNDEFINED_SYMBOLS:=
-LOCAL_DX_FLAGS:=
-LOCAL_JACK_ENABLED:=$(DEFAULT_JACK_ENABLED) # '' (ie disabled), disabled, full, incremental
+# full or incremental
+LOCAL_JACK_ENABLED:=full
 LOCAL_JACK_FLAGS:=
 LOCAL_JACK_COVERAGE_INCLUDE_FILTER:=
 LOCAL_JACK_COVERAGE_EXCLUDE_FILTER:=
-LOCAL_JILL_FLAGS:=
 LOCAL_CERTIFICATE:=
 LOCAL_SDK_VERSION:=
 LOCAL_MIN_SDK_VERSION:=
@@ -145,7 +148,9 @@
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS:=
 LOCAL_VTSC_FLAGS:=
 LOCAL_NO_CRT:=
+LOCAL_NO_LIBCOMPILER_RT:=
 LOCAL_NO_LIBGCC:=
+LOCAL_NO_PIC:=
 LOCAL_PROPRIETARY_MODULE:=
 LOCAL_OEM_MODULE:=
 LOCAL_ODM_MODULE:=
@@ -162,15 +167,16 @@
 LOCAL_SOURCE_FILES_ALL_GENERATED:= # '',true
 # Don't delete the META_INF dir when merging static Java libraries.
 LOCAL_DONT_DELETE_JAR_META_INF:=
-LOCAL_DONT_DELETE_JAR_DIRS:=
 LOCAL_ADDITIONAL_CERTIFICATES:=
 LOCAL_PREBUILT_MODULE_FILE:=
 LOCAL_POST_LINK_CMD:=
 LOCAL_POST_INSTALL_CMD:=
 LOCAL_HAL_STATIC_LIBRARIES:=
 LOCAL_RMTYPEDEFS:=
-LOCAL_NO_SYNTAX_CHECK:=
 LOCAL_NO_STATIC_ANALYZER:=
+LOCAL_TIDY:=
+LOCAL_TIDY_CHECKS:=
+LOCAL_TIDY_FLAGS:=
 LOCAL_32_BIT_ONLY:= # '',true
 LOCAL_MULTILIB:=
 LOCAL_MODULE_TARGET_ARCH:=
@@ -187,14 +193,16 @@
 LOCAL_MODULE_UNSUPPORTED_HOST_CROSS_ARCH_WARN:=
 LOCAL_NO_FPIE :=
 LOCAL_CXX_STL := default
-LOCAL_NATIVE_COVERAGE :=
 LOCAL_DPI_VARIANTS:=
 LOCAL_DPI_FILE_STEM:=
 LOCAL_SANITIZE:=
 LOCAL_SANITIZE_RECOVER:=
+LOCAL_SANITIZE_DIAG:=
+LOCAL_NOSANITIZE:=
 LOCAL_DATA_BINDING:=
 LOCAL_DBUS_PROXY_PREFIX:=
 LOCAL_INIT_RC:=
+LOCAL_MODULE_SYMLINKS:=
 LOCAL_MODULE_HOST_OS:=
 LOCAL_FINDBUGS_FLAGS:=
 LOCAL_NOTICE_FILE:=
@@ -204,6 +212,10 @@
 # Used to replace the installed file of a presigned prebuilt apk in PDK fusion build,
 # to avoid installing the presigned apks with classes.dex unstripped.
 LOCAL_REPLACE_PREBUILT_APK_INSTALLED:=
+LOCAL_NDK_VERSION:=current
+LOCAL_COPY_TO_INTERMEDIATE_LIBRARIES:=
+LOCAL_LOGTAGS_FILES:=
+LOCAL_RECORDED_MODULE_TYPE:=
 
 # arch specific variables
 LOCAL_SRC_FILES_$(TARGET_ARCH):=
@@ -226,6 +238,7 @@
 LOCAL_PREBUILT_JNI_LIBS_$(TARGET_ARCH):=
 LOCAL_STRIP_MODULE_$(TARGET_ARCH):=
 LOCAL_PACK_MODULE_RELOCATIONS_$(TARGET_ARCH):=
+LOCAL_GCNO_FILES:=
 ifdef TARGET_2ND_ARCH
 LOCAL_SRC_FILES_$(TARGET_2ND_ARCH):=
 LOCAL_SRC_FILES_EXCLUDE_$(TARGET_2ND_ARCH):=
@@ -360,7 +373,20 @@
 LOCAL_CLANG_64:=
 LOCAL_INIT_RC_32:=
 LOCAL_INIT_RC_64:=
+LOCAL_MODULE_SYMLINKS_32:=
+LOCAL_MODULE_SYMLINKS_64:=
 LOCAL_JAVA_LANGUAGE_VERSION:=
+LOCAL_CTS_GTEST_LIST_EXECUTABLE:=
+
+LOCAL_IS_AUX_MODULE :=
+LOCAL_AUX_TOOLCHAIN :=
+LOCAL_AUX_OS :=
+LOCAL_AUX_ARCH :=
+LOCAL_AUX_SUBARCH :=
+LOCAL_AUX_CPU :=
+LOCAL_AUX_OS_VARIANT :=
+LOCAL_CUSTOM_BUILD_STEP_INPUT:=
+LOCAL_CUSTOM_BUILD_STEP_OUTPUT:=
 
 # Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to
 # iterate over thousands of entries every time.
diff --git a/core/combo/HOST_CROSS_windows-x86.mk b/core/combo/HOST_CROSS_windows-x86.mk
index 6180a26..d924901 100644
--- a/core/combo/HOST_CROSS_windows-x86.mk
+++ b/core/combo/HOST_CROSS_windows-x86.mk
@@ -17,49 +17,7 @@
 # Settings to use MinGW as a cross-compiler under Linux
 # Included by combo/select.make
 
-$(combo_var_prefix)GLOBAL_CFLAGS += -DUSE_MINGW -DWIN32_LEAN_AND_MEAN
-$(combo_var_prefix)GLOBAL_CFLAGS += -Wno-unused-parameter
-$(combo_var_prefix)GLOBAL_CFLAGS += --sysroot prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32
-$(combo_var_prefix)GLOBAL_CFLAGS += -m32
-$(combo_var_prefix)GLOBAL_LDFLAGS += -m32
-TOOLS_PREFIX := prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/bin/x86_64-w64-mingw32-
-$(combo_var_prefix)C_INCLUDES += prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/include
-$(combo_var_prefix)C_INCLUDES += prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/lib/gcc/x86_64-w64-mingw32/4.8.3/include
-$(combo_var_prefix)GLOBAL_LD_DIRS += -Lprebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib32
-
-# Workaround differences in inttypes.h between host and target.
-# See bug 12708004.
-$(combo_var_prefix)GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-# Use C99-compliant printf functions (%zd).
-$(combo_var_prefix)GLOBAL_CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
-# Admit to using >= Vista. Both are needed because of <_mingw.h>.
-$(combo_var_prefix)GLOBAL_CFLAGS += -D_WIN32_WINNT=0x0600 -DWINVER=0x0600
-# Get 64-bit off_t and related functions.
-$(combo_var_prefix)GLOBAL_CFLAGS += -D_FILE_OFFSET_BITS=64
-
-$(combo_var_prefix)CC := $(TOOLS_PREFIX)gcc
-$(combo_var_prefix)CXX := $(TOOLS_PREFIX)g++
-$(combo_var_prefix)AR := $(TOOLS_PREFIX)ar
-$(combo_var_prefix)NM := $(TOOLS_PREFIX)nm
-$(combo_var_prefix)OBJDUMP := $(TOOLS_PREFIX)objdump
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OBJDUMP) -x $(1) | grep "^Name" | cut -f3 -d" " > $(2)
 $(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)NM) -g -f p $(1) | cut -f1-2 -d" " >> $(2)
 endef
-
-$(combo_var_prefix)GLOBAL_LDFLAGS += \
-    --enable-stdcall-fixup
-
-ifneq ($(strip $(BUILD_HOST_static)),)
-# Statically-linked binaries are desirable for sandboxed environment
-$(combo_var_prefix)GLOBAL_LDFLAGS += -static
-endif # BUILD_HOST_static
-
-$(combo_var_prefix)SHLIB_SUFFIX := .dll
-$(combo_var_prefix)EXECUTABLE_SUFFIX := .exe
-
-$(combo_var_prefix)IS_64_BIT :=
-
-# The mingw gcc is 4.8, 4.9 is required for color diagnostics
-$(combo_var_prefix)UNKNOWN_CFLAGS := -fdiagnostics-color
diff --git a/core/combo/HOST_CROSS_windows-x86_64.mk b/core/combo/HOST_CROSS_windows-x86_64.mk
index e9b19cf..d924901 100644
--- a/core/combo/HOST_CROSS_windows-x86_64.mk
+++ b/core/combo/HOST_CROSS_windows-x86_64.mk
@@ -17,49 +17,7 @@
 # Settings to use MinGW as a cross-compiler under Linux
 # Included by combo/select.make
 
-$(combo_var_prefix)GLOBAL_CFLAGS += -DUSE_MINGW -DWIN32_LEAN_AND_MEAN
-$(combo_var_prefix)GLOBAL_CFLAGS += -Wno-unused-parameter
-$(combo_var_prefix)GLOBAL_CFLAGS += --sysroot prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32
-$(combo_var_prefix)GLOBAL_CFLAGS += -m64
-$(combo_var_prefix)GLOBAL_LDFLAGS += -m64
-TOOLS_PREFIX := prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/bin/x86_64-w64-mingw32-
-$(combo_var_prefix)C_INCLUDES += prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/include
-$(combo_var_prefix)C_INCLUDES += prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/lib/gcc/x86_64-w64-mingw32/4.8.3/include
-$(combo_var_prefix)GLOBAL_LD_DIRS += -Lprebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib64
-
-# Workaround differences in inttypes.h between host and target.
-# See bug 12708004.
-$(combo_var_prefix)GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-# Use C99-compliant printf functions (%zd).
-$(combo_var_prefix)GLOBAL_CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
-# Admit to using >= Vista. Both are needed because of <_mingw.h>.
-$(combo_var_prefix)GLOBAL_CFLAGS += -D_WIN32_WINNT=0x0600 -DWINVER=0x0600
-# Get 64-bit off_t and related functions.
-$(combo_var_prefix)GLOBAL_CFLAGS += -D_FILE_OFFSET_BITS=64
-
-$(combo_var_prefix)CC := $(TOOLS_PREFIX)gcc
-$(combo_var_prefix)CXX := $(TOOLS_PREFIX)g++
-$(combo_var_prefix)AR := $(TOOLS_PREFIX)ar
-$(combo_var_prefix)NM := $(TOOLS_PREFIX)nm
-$(combo_var_prefix)OBJDUMP := $(TOOLS_PREFIX)objdump
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OBJDUMP) -x $(1) | grep "^Name" | cut -f3 -d" " > $(2)
 $(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)NM) -g -f p $(1) | cut -f1-2 -d" " >> $(2)
 endef
-
-$(combo_var_prefix)GLOBAL_LDFLAGS += \
-    --enable-stdcall-fixup
-
-ifneq ($(strip $(BUILD_HOST_static)),)
-# Statically-linked binaries are desirable for sandboxed environment
-$(combo_var_prefix)GLOBAL_LDFLAGS += -static
-endif # BUILD_HOST_static
-
-$(combo_var_prefix)SHLIB_SUFFIX := .dll
-$(combo_var_prefix)EXECUTABLE_SUFFIX := .exe
-
-$(combo_var_prefix)IS_64_BIT := true
-
-# The mingw gcc is 4.8, 4.9 is required for color diagnostics
-$(combo_var_prefix)UNKNOWN_CFLAGS := -fdiagnostics-color
diff --git a/core/combo/HOST_darwin-x86.mk b/core/combo/HOST_darwin-x86.mk
index fc56e52..9a55cb5 100644
--- a/core/combo/HOST_darwin-x86.mk
+++ b/core/combo/HOST_darwin-x86.mk
@@ -17,45 +17,10 @@
 # Configuration for Darwin (Mac OS X) on x86.
 # Included by combo/select.mk
 
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -m32
-$(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -m32
-
-ifneq ($(strip $(BUILD_HOST_static)),)
-# Statically-linked binaries are desirable for sandboxed environment
-$(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -static
-endif # BUILD_HOST_static
-
-# Workaround differences in inttypes.h between host and target.
-# See bug 12708004.
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-
-include $(BUILD_COMBOS)/mac_version.mk
-
-$(combo_2nd_arch_prefix)HOST_TOOLCHAIN_ROOT := prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1
-$(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_ROOT)/bin/i686-apple-darwin$(gcc_darwin_version)
-$(combo_2nd_arch_prefix)HOST_CC  := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)-gcc
-$(combo_2nd_arch_prefix)HOST_CXX := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)-g++
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_macho,$(1),$(2))
 endef
 
-# gcc location for clang; to be updated when clang is updated
-# HOST_TOOLCHAIN_ROOT is a Darwin-specific define
-$(combo_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_ROOT)
-
-$(combo_2nd_arch_prefix)HOST_AR := $(AR)
-
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -isysroot $(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version) -DMACOSX_DEPLOYMENT_TARGET=$(mac_sdk_version)
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CPPFLAGS += -isystem $(mac_sdk_path)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
-$(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -isysroot $(mac_sdk_root) -Wl,-syslibroot,$(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version)
-
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -fPIC -funwind-tables
-$(combo_2nd_arch_prefix)HOST_NO_UNDEFINED_LDFLAGS := -Wl,-undefined,error
-
-$(combo_2nd_arch_prefix)HOST_SHLIB_SUFFIX := .dylib
-$(combo_2nd_arch_prefix)HOST_JNILIB_SUFFIX := .jnilib
-
 $(combo_2nd_arch_prefix)HOST_GLOBAL_ARFLAGS := cqs
 
 ############################################################
@@ -66,14 +31,13 @@
 define transform-host-o-to-shared-lib-inner
 $(hide) $(PRIVATE_CXX) \
         -dynamiclib -single_module -read_only_relocs suppress \
-        $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_LD_DIRS) \
         $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
             $(PRIVATE_HOST_GLOBAL_LDFLAGS) \
         ) \
         $(PRIVATE_ALL_OBJECTS) \
         $(addprefix -force_load , $(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
-        $(call normalize-host-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-        $(call normalize-host-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+        $(PRIVATE_ALL_SHARED_LIBRARIES) \
+        $(PRIVATE_ALL_STATIC_LIBRARIES) \
         $(PRIVATE_LDLIBS) \
         -o $@ \
         -install_name @rpath/$(notdir $@) \
@@ -84,18 +48,17 @@
 
 define transform-host-o-to-executable-inner
 $(hide) $(PRIVATE_CXX) \
-        -Wl,-rpath,@loader_path/../$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)) \
-        -Wl,-rpath,@loader_path/$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)) \
+        $(foreach path,$(PRIVATE_RPATHS), \
+          -Wl,-rpath,@loader_path/$(path)) \
         -o $@ \
         -Wl,-headerpad_max_install_names \
-        $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_LD_DIRS) \
         $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
            $(PRIVATE_HOST_GLOBAL_LDFLAGS) \
         ) \
-        $(call normalize-host-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+        $(PRIVATE_ALL_SHARED_LIBRARIES) \
         $(PRIVATE_ALL_OBJECTS) \
-        $(call normalize-host-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
-        $(call normalize-host-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+        $(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
+        $(PRIVATE_ALL_STATIC_LIBRARIES) \
         $(PRIVATE_LDFLAGS) \
         $(PRIVATE_LDLIBS)
 endef
diff --git a/core/combo/HOST_darwin-x86_64.mk b/core/combo/HOST_darwin-x86_64.mk
index 251455f..6cca167 100644
--- a/core/combo/HOST_darwin-x86_64.mk
+++ b/core/combo/HOST_darwin-x86_64.mk
@@ -17,45 +17,10 @@
 # Configuration for Darwin (Mac OS X) on x86_64.
 # Included by combo/select.mk
 
-HOST_GLOBAL_CFLAGS += -m64
-HOST_GLOBAL_LDFLAGS += -m64
-
-ifneq ($(strip $(BUILD_HOST_static)),)
-# Statically-linked binaries are desirable for sandboxed environment
-HOST_GLOBAL_LDFLAGS += -static
-endif # BUILD_HOST_static
-
-# Workaround differences in inttypes.h between host and target.
-# See bug 12708004.
-HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-
-include $(BUILD_COMBOS)/mac_version.mk
-
-HOST_TOOLCHAIN_ROOT := prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1
-HOST_TOOLCHAIN_PREFIX := $(HOST_TOOLCHAIN_ROOT)/bin/i686-apple-darwin$(gcc_darwin_version)
-HOST_CC  := $(HOST_TOOLCHAIN_PREFIX)-gcc
-HOST_CXX := $(HOST_TOOLCHAIN_PREFIX)-g++
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_macho,$(1),$(2))
 endef
 
-# gcc location for clang; to be updated when clang is updated
-# HOST_TOOLCHAIN_ROOT is a Darwin-specific define
-HOST_TOOLCHAIN_FOR_CLANG := $(HOST_TOOLCHAIN_ROOT)
-
-HOST_AR := $(AR)
-
-HOST_GLOBAL_CFLAGS += -isysroot $(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version) -DMACOSX_DEPLOYMENT_TARGET=$(mac_sdk_version)
-HOST_GLOBAL_CPPFLAGS += -isystem $(mac_sdk_path)/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
-HOST_GLOBAL_LDFLAGS += -isysroot $(mac_sdk_root) -Wl,-syslibroot,$(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version)
-
-HOST_GLOBAL_CFLAGS += -fPIC -funwind-tables
-HOST_NO_UNDEFINED_LDFLAGS := -Wl,-undefined,error
-
-HOST_SHLIB_SUFFIX := .dylib
-HOST_JNILIB_SUFFIX := .jnilib
-
 HOST_GLOBAL_ARFLAGS := cqs
 
 # We Reuse the following functions with the same name from HOST_darwin-x86.mk:
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index 169e2d2..4e83dc4 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -17,46 +17,10 @@
 # Configuration for builds hosted on linux-x86.
 # Included by combo/select.mk
 
-ifeq ($(strip $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)),)
-$(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX := prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/bin/x86_64-linux-
-endif
-$(combo_2nd_arch_prefix)HOST_CC  := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)gcc
-$(combo_2nd_arch_prefix)HOST_CXX := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)g++
-$(combo_2nd_arch_prefix)HOST_AR  := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)ar
-$(combo_2nd_arch_prefix)HOST_READELF  := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)readelf
-$(combo_2nd_arch_prefix)HOST_NM  := $($(combo_2nd_arch_prefix)HOST_TOOLCHAIN_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
 
-# gcc location for clang; to be updated when clang is updated
-$(combo_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG := prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8
-
-# We expect SSE3 floating point math.
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -msse3 -mfpmath=sse -m32 -Wa,--noexecstack -march=prescott
-$(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -m32 -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--no-undefined-version
-
-ifneq ($(strip $(BUILD_HOST_static)),)
-# Statically-linked binaries are desirable for sandboxed environment
-$(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -static
-endif # BUILD_HOST_static
-
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -fPIC \
-  -no-canonical-prefixes \
-
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector
-
-# Workaround differences in inttypes.h between host and target.
-# See bug 12708004.
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-
-# We build a 32-bit host art, and right now that also means building *all* host libraries
-# both 32- and 64-bit (whether art uses them or not --- 9d59f417767991246848c3e101cb27d2dfea5988).
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1
-
-$(combo_2nd_arch_prefix)HOST_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
 ############################################################
 ## Macros after this line are shared by the 64-bit config.
 
diff --git a/core/combo/HOST_linux-x86_64.mk b/core/combo/HOST_linux-x86_64.mk
index 9766f2b..845733f 100644
--- a/core/combo/HOST_linux-x86_64.mk
+++ b/core/combo/HOST_linux-x86_64.mk
@@ -17,37 +17,6 @@
 # Configuration for builds hosted on linux-x86_64.
 # Included by combo/select.mk
 
-ifeq ($(strip $(HOST_TOOLCHAIN_PREFIX)),)
-HOST_TOOLCHAIN_PREFIX := prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8/bin/x86_64-linux-
-endif
-HOST_CC  := $(HOST_TOOLCHAIN_PREFIX)gcc
-HOST_CXX := $(HOST_TOOLCHAIN_PREFIX)g++
-HOST_AR  := $(HOST_TOOLCHAIN_PREFIX)ar
-HOST_READELF  := $(HOST_TOOLCHAIN_PREFIX)readelf
-HOST_NM  := $(HOST_TOOLCHAIN_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
-
-# gcc location for clang; to be updated when clang is updated
-HOST_TOOLCHAIN_FOR_CLANG := prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.15-4.8
-
-HOST_GLOBAL_CFLAGS += -m64 -Wa,--noexecstack
-HOST_GLOBAL_LDFLAGS += -m64 -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--no-undefined-version
-
-ifneq ($(strip $(BUILD_HOST_static)),)
-# Statically-linked binaries are desirable for sandboxed environment
-HOST_GLOBAL_LDFLAGS += -static
-endif # BUILD_HOST_static
-
-HOST_GLOBAL_CFLAGS += -fPIC \
-  -no-canonical-prefixes \
-
-HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector
-
-# Workaround differences in inttypes.h between host and target.
-# See bug 12708004.
-HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
-
-HOST_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 510aae5..2e179f6 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -33,15 +33,6 @@
 TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := armv5te
 endif
 
-# Decouple NDK library selection with platform compiler version
-$(combo_2nd_arch_prefix)TARGET_NDK_GCC_VERSION := 4.9
-
-ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := 4.9
-else
-$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
-endif
-
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_$(combo_2nd_arch_prefix)ARCH)/$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
 $(error Unknown ARM architecture version: $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
@@ -50,146 +41,10 @@
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 include $(BUILD_SYSTEM)/combo/fdo.mk
 
-# You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)),)
-$(combo_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-$($(combo_2nd_arch_prefix)TARGET_GCC_VERSION)
-$(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX := $($(combo_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT)/bin/arm-linux-androideabi-
-endif
-
-$(combo_2nd_arch_prefix)TARGET_CC := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)gcc
-$(combo_2nd_arch_prefix)TARGET_CXX := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)g++
-$(combo_2nd_arch_prefix)TARGET_AR := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ar
-$(combo_2nd_arch_prefix)TARGET_OBJCOPY := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)objcopy
-$(combo_2nd_arch_prefix)TARGET_LD := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ld
-$(combo_2nd_arch_prefix)TARGET_READELF := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)readelf
-$(combo_2nd_arch_prefix)TARGET_STRIP := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)strip
-$(combo_2nd_arch_prefix)TARGET_NM := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
 
-$(combo_2nd_arch_prefix)TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
-$(combo_2nd_arch_prefix)TARGET_arm_CFLAGS :=    -O2 \
-                        -fomit-frame-pointer \
-                        -fstrict-aliasing    \
-                        -funswitch-loops
-
-# Modules can choose to compile some source as thumb.
-$(combo_2nd_arch_prefix)TARGET_thumb_CFLAGS :=  -mthumb \
-                        -Os \
-                        -fomit-frame-pointer \
-                        -fno-strict-aliasing
-
-# Set FORCE_ARM_DEBUGGING to "true" in your buildspec.mk
-# or in your environment to force a full arm build, even for
-# files that are normally built as thumb; this can make
-# gdb debugging easier.  Don't forget to do a clean build.
-#
-# NOTE: if you try to build a -O0 build with thumb, several
-# of the libraries (libpv, libwebcore, libkjs) need to be built
-# with -mlong-calls.  When built at -O0, those libraries are
-# too big for a thumb "BL <label>" to go from one end to the other.
-ifeq ($(FORCE_ARM_DEBUGGING),true)
-  $(combo_2nd_arch_prefix)TARGET_arm_CFLAGS += -fno-omit-frame-pointer -fno-strict-aliasing
-  $(combo_2nd_arch_prefix)TARGET_thumb_CFLAGS += -marm -fno-omit-frame-pointer
-endif
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += \
-			-msoft-float \
-			-ffunction-sections \
-			-fdata-sections \
-			-funwind-tables \
-			-fstack-protector-strong \
-			-Wa,--noexecstack \
-			-Werror=format-security \
-			-D_FORTIFY_SOURCE=2 \
-			-fno-short-enums \
-			-no-canonical-prefixes \
-			-fno-canonical-system-headers \
-			$(arch_variant_cflags) \
-
-# The "-Wunused-but-set-variable" option often breaks projects that enable
-# "-Wall -Werror" due to a commom idiom "ALOGV(mesg)" where ALOGV is turned
-# into no-op in some builds while mesg is defined earlier. So we explicitly
-# disable "-Wunused-but-set-variable" here.
-ifneq ($(filter 4.6 4.6.% 4.7 4.7.% 4.8 4.9, $($(combo_2nd_arch_prefix)TARGET_GCC_VERSION)),)
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -fno-builtin-sin \
-			-fno-strict-volatile-bitfields
-endif
-
-# This is to avoid the dreaded warning compiler message:
-#   note: the mangling of 'va_list' has changed in GCC 4.4
-#
-# The fact that the mangling changed does not affect the NDK ABI
-# very fortunately (since none of the exposed APIs used va_list
-# in their exported C++ functions). Also, GCC 4.5 has already
-# removed the warning from the compiler.
-#
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -Wno-psabi
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += \
-			-Wl,-z,noexecstack \
-			-Wl,-z,relro \
-			-Wl,-z,now \
-			-Wl,--build-id=md5 \
-			-Wl,--warn-shared-textrel \
-			-Wl,--fatal-warnings \
-			-Wl,--icf=safe \
-			-Wl,--hash-style=gnu \
-			-Wl,--no-undefined-version \
-			$(arch_variant_ldflags)
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -mthumb-interwork
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
-
-# More flags/options can be added here
-$(combo_2nd_arch_prefix)TARGET_RELEASE_CFLAGS := \
-			-DNDEBUG \
-			-g \
-			-Wstrict-aliasing=2 \
-			-fgcse-after-reload \
-			-frerun-cse-after-loop \
-			-frename-registers
-
-libc_root := bionic/libc
-libm_root := bionic/libm
-
-
-## on some hosts, the target cross-compiler is not available so do not run this command
-ifneq ($(wildcard $($(combo_2nd_arch_prefix)TARGET_CC)),)
-# We compile with the global cflags to ensure that
-# any flags which affect libgcc are correctly taken
-# into account.
-$(combo_2nd_arch_prefix)TARGET_LIBGCC := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) \
-        $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-libgcc-file-name)
-$(combo_2nd_arch_prefix)TARGET_LIBATOMIC := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) \
-        $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-file-name=libatomic.a)
-$(combo_2nd_arch_prefix)TARGET_LIBGCOV := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) \
-        $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-file-name=libgcov.a)
-endif
-
-KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi
-KERNEL_HEADERS_COMMON += $(libc_root)/kernel/common
-KERNEL_HEADERS_ARCH   := $(libc_root)/kernel/uapi/asm-$(TARGET_$(combo_2nd_arch_prefix)ARCH)
-KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
-
-$(combo_2nd_arch_prefix)TARGET_C_INCLUDES := \
-	$(libc_root)/arch-arm/include \
-	$(libc_root)/include \
-	$(KERNEL_HEADERS) \
-	$(libm_root)/include \
-	$(libm_root)/include/arm \
-
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_STATIC_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_DYNAMIC_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
-$(combo_2nd_arch_prefix)TARGET_CRTEND_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
-
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_SO_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
-$(combo_2nd_arch_prefix)TARGET_CRTEND_SO_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
-
 $(combo_2nd_arch_prefix)TARGET_PACK_MODULE_RELOCATIONS := true
 
 $(combo_2nd_arch_prefix)TARGET_LINKER := /system/bin/linker
diff --git a/core/combo/TARGET_linux-arm64.mk b/core/combo/TARGET_linux-arm64.mk
index 6a1d861..a3f59a7 100644
--- a/core/combo/TARGET_linux-arm64.mk
+++ b/core/combo/TARGET_linux-arm64.mk
@@ -33,15 +33,6 @@
 TARGET_ARCH_VARIANT := armv8
 endif
 
-# Decouple NDK library selection with platform compiler version
-TARGET_NDK_GCC_VERSION := 4.9
-
-ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-TARGET_GCC_VERSION := 4.9
-else
-TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
-endif
-
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
 $(error Unknown ARM architecture version: $(TARGET_ARCH_VARIANT))
@@ -50,119 +41,10 @@
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 include $(BUILD_SYSTEM)/combo/fdo.mk
 
-# You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
-TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/aarch64/aarch64-linux-android-$(TARGET_GCC_VERSION)
-TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/aarch64-linux-android-
-endif
-
-TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc
-TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++
-TARGET_AR := $(TARGET_TOOLS_PREFIX)ar
-TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy
-TARGET_LD := $(TARGET_TOOLS_PREFIX)ld
-TARGET_READELF := $(TARGET_TOOLS_PREFIX)readelf
-TARGET_STRIP := $(TARGET_TOOLS_PREFIX)strip
-TARGET_NM := $(TARGET_TOOLS_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
 
-TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
-TARGET_GLOBAL_CFLAGS += \
-    -fno-strict-aliasing \
-
-TARGET_GLOBAL_CFLAGS += \
-			-fstack-protector-strong \
-			-ffunction-sections \
-			-fdata-sections \
-			-funwind-tables \
-			-Wa,--noexecstack \
-			-Werror=format-security \
-			-D_FORTIFY_SOURCE=2 \
-			-fno-short-enums \
-			-no-canonical-prefixes \
-			-fno-canonical-system-headers \
-			$(arch_variant_cflags) \
-
-# Help catch common 32/64-bit errors.
-TARGET_GLOBAL_CFLAGS += \
-    -Werror=pointer-to-int-cast \
-    -Werror=int-to-pointer-cast \
-    -Werror=implicit-function-declaration \
-
-TARGET_GLOBAL_CFLAGS += -fno-strict-volatile-bitfields
-
-# This is to avoid the dreaded warning compiler message:
-#   note: the mangling of 'va_list' has changed in GCC 4.4
-#
-# The fact that the mangling changed does not affect the NDK ABI
-# very fortunately (since none of the exposed APIs used va_list
-# in their exported C++ functions). Also, GCC 4.5 has already
-# removed the warning from the compiler.
-#
-TARGET_GLOBAL_CFLAGS += -Wno-psabi
-
-TARGET_GLOBAL_LDFLAGS += \
-			-Wl,-z,noexecstack \
-			-Wl,-z,relro \
-			-Wl,-z,now \
-			-Wl,--build-id=md5 \
-			-Wl,--warn-shared-textrel \
-			-Wl,--fatal-warnings \
-			-Wl,-maarch64linux \
-			-Wl,--hash-style=gnu \
-			-Wl,--fix-cortex-a53-843419 \
-			-fuse-ld=gold \
-			-Wl,--icf=safe \
-			-Wl,--no-undefined-version \
-			$(arch_variant_ldflags)
-
-# Disable transitive dependency library symbol resolving.
-TARGET_GLOBAL_LDFLAGS += -Wl,--allow-shlib-undefined
-
-TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
-
-# More flags/options can be added here
-TARGET_RELEASE_CFLAGS := \
-			-DNDEBUG \
-			-O2 -g \
-			-Wstrict-aliasing=2 \
-			-fgcse-after-reload \
-			-frerun-cse-after-loop \
-			-frename-registers
-
-libc_root := bionic/libc
-libm_root := bionic/libm
-
-TARGET_LIBGCC := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \
-	-print-libgcc-file-name)
-TARGET_LIBATOMIC := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \
-	-print-file-name=libatomic.a)
-TARGET_LIBGCOV := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \
-	-print-file-name=libgcov.a)
-
-KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi
-KERNEL_HEADERS_COMMON += $(libc_root)/kernel/common
-KERNEL_HEADERS_ARCH   := $(libc_root)/kernel/uapi/asm-$(TARGET_ARCH)
-KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
-
-TARGET_C_INCLUDES := \
-	$(libc_root)/arch-arm64/include \
-	$(libc_root)/include \
-	$(KERNEL_HEADERS) \
-	$(libm_root)/include \
-	$(libm_root)/include/arm64 \
-
-TARGET_CRTBEGIN_STATIC_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
-TARGET_CRTBEGIN_DYNAMIC_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
-TARGET_CRTEND_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
-
-TARGET_CRTBEGIN_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
-TARGET_CRTEND_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
-
 TARGET_PACK_MODULE_RELOCATIONS := true
 
 TARGET_LINKER := /system/bin/linker64
diff --git a/core/combo/TARGET_linux-mips.mk b/core/combo/TARGET_linux-mips.mk
index 186d88f..ba76969 100644
--- a/core/combo/TARGET_linux-mips.mk
+++ b/core/combo/TARGET_linux-mips.mk
@@ -33,15 +33,6 @@
 TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := mips32r2-fp
 endif
 
-# Decouple NDK library selection with platform compiler version
-$(combo_2nd_arch_prefix)TARGET_NDK_GCC_VERSION := 4.9
-
-ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := 4.9
-else
-$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
-endif
-
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_$(combo_2nd_arch_prefix)ARCH)/$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
 $(error Unknown MIPS architecture variant: $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
@@ -50,121 +41,10 @@
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 include $(BUILD_SYSTEM)/combo/fdo.mk
 
-# You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)),)
-$(combo_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mips64el-linux-android-$($(combo_2nd_arch_prefix)TARGET_GCC_VERSION)
-$(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX := $($(combo_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT)/bin/mips64el-linux-android-
-endif
-
-$(combo_2nd_arch_prefix)TARGET_CC := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)gcc
-$(combo_2nd_arch_prefix)TARGET_CXX := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)g++
-$(combo_2nd_arch_prefix)TARGET_AR := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ar
-$(combo_2nd_arch_prefix)TARGET_OBJCOPY := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)objcopy
-$(combo_2nd_arch_prefix)TARGET_LD := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ld
-$(combo_2nd_arch_prefix)TARGET_READELF := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)readelf
-$(combo_2nd_arch_prefix)TARGET_STRIP := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)strip
-$(combo_2nd_arch_prefix)TARGET_NM := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
 
-$(combo_2nd_arch_prefix)TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
-TARGET_mips_CFLAGS :=	-O2 \
-			-fomit-frame-pointer \
-			-fno-strict-aliasing    \
-			-funswitch-loops
-
-# Set FORCE_MIPS_DEBUGGING to "true" in your buildspec.mk
-# or in your environment to gdb debugging easier.
-# Don't forget to do a clean build.
-ifeq ($(FORCE_MIPS_DEBUGGING),true)
-  TARGET_mips_CFLAGS += -fno-omit-frame-pointer
-endif
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += \
-			$(TARGET_mips_CFLAGS) \
-			-U__unix -U__unix__ -Umips \
-			-ffunction-sections \
-			-fdata-sections \
-			-funwind-tables \
-			-fstack-protector-strong \
-			-Wa,--noexecstack \
-			-Werror=format-security \
-			-D_FORTIFY_SOURCE=2 \
-			-no-canonical-prefixes \
-			-fno-canonical-system-headers \
-			$(arch_variant_cflags) \
-
-ifneq ($(ARCH_MIPS_PAGE_SHIFT),)
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -DPAGE_SHIFT=$(ARCH_MIPS_PAGE_SHIFT)
-endif
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += \
-			-Wl,-z,noexecstack \
-			-Wl,-z,relro \
-			-Wl,-z,now \
-			-Wl,--build-id=md5 \
-			-Wl,--warn-shared-textrel \
-			-Wl,--fatal-warnings \
-			-Wl,--no-undefined-version \
-			$(arch_variant_ldflags)
-
-# Disable transitive dependency library symbol resolving.
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,--allow-shlib-undefined
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
-
-# More flags/options can be added here
-$(combo_2nd_arch_prefix)TARGET_RELEASE_CFLAGS := \
-			-DNDEBUG \
-			-g \
-			-Wstrict-aliasing=2 \
-			-fgcse-after-reload \
-			-frerun-cse-after-loop \
-			-frename-registers
-
-libc_root := bionic/libc
-libm_root := bionic/libm
-
-
-## on some hosts, the target cross-compiler is not available so do not run this command
-ifneq ($(wildcard $($(combo_2nd_arch_prefix)TARGET_CC)),)
-# We compile with the global cflags to ensure that
-# any flags which affect libgcc are correctly taken
-# into account.
-$(combo_2nd_arch_prefix)TARGET_LIBGCC := \
-  $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-file-name=libgcc.a)
-$(combo_2nd_arch_prefix)TARGET_LIBATOMIC := \
-  $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-file-name=libatomic.a)
-LIBGCC_EH := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) -print-file-name=libgcc_eh.a)
-ifneq ($(LIBGCC_EH),libgcc_eh.a)
-  $(combo_2nd_arch_prefix)TARGET_LIBGCC += $(LIBGCC_EH)
-endif
-$(combo_2nd_arch_prefix)TARGET_LIBGCOV := $(shell $($(combo_2nd_arch_prefix)TARGET_CC) $($(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \
-        --print-file-name=libgcov.a)
-endif
-
-KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi
-KERNEL_HEADERS_COMMON += $(libc_root)/kernel/common
-KERNEL_HEADERS_ARCH   := $(libc_root)/kernel/uapi/asm-mips # mips covers both mips and mips64.
-KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
-
-$(combo_2nd_arch_prefix)TARGET_C_INCLUDES := \
-	$(libc_root)/arch-mips/include \
-	$(libc_root)/include \
-	$(KERNEL_HEADERS) \
-	$(libm_root)/include \
-	$(libm_root)/include/mips \
-
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_STATIC_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_DYNAMIC_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
-$(combo_2nd_arch_prefix)TARGET_CRTEND_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
-
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_SO_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
-$(combo_2nd_arch_prefix)TARGET_CRTEND_SO_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
-
 $(combo_2nd_arch_prefix)TARGET_PACK_MODULE_RELOCATIONS := true
 
 $(combo_2nd_arch_prefix)TARGET_LINKER := /system/bin/linker
diff --git a/core/combo/TARGET_linux-mips64.mk b/core/combo/TARGET_linux-mips64.mk
index 3e1f61a..b498d1f 100644
--- a/core/combo/TARGET_linux-mips64.mk
+++ b/core/combo/TARGET_linux-mips64.mk
@@ -33,15 +33,6 @@
 TARGET_ARCH_VARIANT := mips64r6
 endif
 
-# Decouple NDK library selection with platform compiler version
-TARGET_NDK_GCC_VERSION := 4.9
-
-ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-TARGET_GCC_VERSION := 4.9
-else
-TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
-endif
-
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
 $(error Unknown MIPS architecture variant: $(TARGET_ARCH_VARIANT))
@@ -50,130 +41,10 @@
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 include $(BUILD_SYSTEM)/combo/fdo.mk
 
-# You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
-TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mips64el-linux-android-$(TARGET_GCC_VERSION)
-TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/mips64el-linux-android-
-endif
-
-TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc
-TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++
-TARGET_AR := $(TARGET_TOOLS_PREFIX)ar
-TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy
-TARGET_LD := $(TARGET_TOOLS_PREFIX)ld
-TARGET_READELF := $(TARGET_TOOLS_PREFIX)readelf
-TARGET_STRIP := $(TARGET_TOOLS_PREFIX)strip
-TARGET_NM := $(TARGET_TOOLS_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
 
-TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
-TARGET_mips_CFLAGS :=	-O2 \
-			-fomit-frame-pointer \
-			-fno-strict-aliasing    \
-			-funswitch-loops
-
-# Set FORCE_MIPS_DEBUGGING to "true" in your buildspec.mk
-# or in your environment to gdb debugging easier.
-# Don't forget to do a clean build.
-ifeq ($(FORCE_MIPS_DEBUGGING),true)
-  TARGET_mips_CFLAGS += -fno-omit-frame-pointer
-endif
-
-TARGET_GLOBAL_CFLAGS += \
-			$(TARGET_mips_CFLAGS) \
-			-U__unix -U__unix__ -Umips \
-			-ffunction-sections \
-			-fdata-sections \
-			-funwind-tables \
-			-fstack-protector-strong \
-			-Wa,--noexecstack \
-			-Werror=format-security \
-			-D_FORTIFY_SOURCE=2 \
-			-no-canonical-prefixes \
-			-fno-canonical-system-headers \
-			$(arch_variant_cflags) \
-
-# Help catch common 32/64-bit errors.
-TARGET_GLOBAL_CFLAGS += \
-    -Werror=pointer-to-int-cast \
-    -Werror=int-to-pointer-cast \
-    -Werror=implicit-function-declaration \
-
-ifneq ($(ARCH_MIPS_PAGE_SHIFT),)
-TARGET_GLOBAL_CFLAGS += -DPAGE_SHIFT=$(ARCH_MIPS_PAGE_SHIFT)
-endif
-
-TARGET_GLOBAL_LDFLAGS += \
-			-Wl,-z,noexecstack \
-			-Wl,-z,relro \
-			-Wl,-z,now \
-			-Wl,--build-id=md5 \
-			-Wl,--warn-shared-textrel \
-			-Wl,--fatal-warnings \
-			-Wl,--no-undefined-version \
-			$(arch_variant_ldflags)
-
-# Disable transitive dependency library symbol resolving.
-TARGET_GLOBAL_LDFLAGS += -Wl,--allow-shlib-undefined
-
-TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
-
-# More flags/options can be added here
-TARGET_RELEASE_CFLAGS := \
-			-DNDEBUG \
-			-g \
-			-Wstrict-aliasing=2 \
-			-fgcse-after-reload \
-			-frerun-cse-after-loop \
-			-frename-registers
-
-libc_root := bionic/libc
-libm_root := bionic/libm
-
-
-## on some hosts, the target cross-compiler is not available so do not run this command
-ifneq ($(wildcard $(TARGET_CC)),)
-# We compile with the global cflags to ensure that
-# any flags which affect libgcc are correctly taken
-# into account.
-TARGET_LIBGCC := \
-  $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) -print-file-name=libgcc.a)
-TARGET_LIBATOMIC := \
-  $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) -print-file-name=libatomic.a)
-LIBGCC_EH := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) -print-file-name=libgcc_eh.a)
-ifneq ($(LIBGCC_EH),libgcc_eh.a)
-  TARGET_LIBGCC += $(LIBGCC_EH)
-endif
-TARGET_LIBGCOV := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \
-        --print-file-name=libgcov.a)
-endif
-
-KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi
-KERNEL_HEADERS_COMMON += $(libc_root)/kernel/common
-KERNEL_HEADERS_ARCH   := $(libc_root)/kernel/uapi/asm-mips
-# TODO: perhaps use $(libc_root)/kernel/uapi/asm-$(TARGET_ARCH) instead of asm-mips ?
-KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
-
-TARGET_C_INCLUDES := \
-	$(libc_root)/arch-mips64/include \
-	$(libc_root)/include \
-	$(KERNEL_HEADERS) \
-	$(libm_root)/include \
-	$(libm_root)/include/mips \
-
-# TODO: perhaps use $(libm_root)/include/mips64 instead of mips ?
-
-TARGET_CRTBEGIN_STATIC_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
-TARGET_CRTBEGIN_DYNAMIC_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
-TARGET_CRTEND_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
-
-TARGET_CRTBEGIN_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
-TARGET_CRTEND_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
-
 TARGET_PACK_MODULE_RELOCATIONS := true
 
 TARGET_LINKER := /system/bin/linker64
diff --git a/core/combo/TARGET_linux-x86.mk b/core/combo/TARGET_linux-x86.mk
index 558ec3b..2c4614b 100644
--- a/core/combo/TARGET_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -22,15 +22,6 @@
 TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := x86
 endif
 
-# Decouple NDK library selection with platform compiler version
-$(combo_2nd_arch_prefix)TARGET_NDK_GCC_VERSION := 4.9
-
-ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := 4.9
-else
-$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
-endif
-
 # Include the arch-variant-specific configuration file.
 # Its role is to define various ARCH_X86_HAVE_XXX feature macros,
 # plus initial values for TARGET_GLOBAL_CFLAGS
@@ -43,108 +34,10 @@
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 include $(BUILD_SYSTEM)/combo/fdo.mk
 
-# You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)),)
-$(combo_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/x86_64-linux-android-$($(combo_2nd_arch_prefix)TARGET_GCC_VERSION)
-$(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX := $($(combo_2nd_arch_prefix)TARGET_TOOLCHAIN_ROOT)/bin/x86_64-linux-android-
-endif
-
-$(combo_2nd_arch_prefix)TARGET_CC := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)gcc
-$(combo_2nd_arch_prefix)TARGET_CXX := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)g++
-$(combo_2nd_arch_prefix)TARGET_AR := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ar
-$(combo_2nd_arch_prefix)TARGET_OBJCOPY := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)objcopy
-$(combo_2nd_arch_prefix)TARGET_LD := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ld
-$(combo_2nd_arch_prefix)TARGET_READELF := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)readelf
-$(combo_2nd_arch_prefix)TARGET_STRIP := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)strip
-$(combo_2nd_arch_prefix)TARGET_NM := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
 
-ifneq ($(wildcard $($(combo_2nd_arch_prefix)TARGET_CC)),)
-$(combo_2nd_arch_prefix)TARGET_LIBGCC := \
-	$(shell $($(combo_2nd_arch_prefix)TARGET_CC) -m32 -print-file-name=libgcc.a)
-$(combo_2nd_arch_prefix)TARGET_LIBATOMIC := \
-	$(shell $($(combo_2nd_arch_prefix)TARGET_CC) -m32 -print-file-name=libatomic.a)
-$(combo_2nd_arch_prefix)TARGET_LIBGCOV := \
-	$(shell $($(combo_2nd_arch_prefix)TARGET_CC) -m32 -print-file-name=libgcov.a)
-endif
-
-$(combo_2nd_arch_prefix)TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
-libc_root := bionic/libc
-libm_root := bionic/libm
-
-KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi
-KERNEL_HEADERS_COMMON += $(libc_root)/kernel/common
-KERNEL_HEADERS_ARCH   := $(libc_root)/kernel/uapi/asm-x86 # x86 covers both x86 and x86_64.
-KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += \
-			-O2 \
-			-Wa,--noexecstack \
-			-Werror=format-security \
-			-D_FORTIFY_SOURCE=2 \
-			-Wstrict-aliasing=2 \
-			-ffunction-sections \
-			-finline-functions \
-			-finline-limit=300 \
-			-fno-short-enums \
-			-fstrict-aliasing \
-			-funswitch-loops \
-			-funwind-tables \
-			-fstack-protector-strong \
-			-m32 \
-			-no-canonical-prefixes \
-			-fno-canonical-system-headers \
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += $(arch_variant_cflags)
-
-ifeq ($(ARCH_X86_HAVE_SSSE3),true)   # yes, really SSSE3, not SSE3!
-    $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -DUSE_SSSE3 -mssse3
-endif
-ifeq ($(ARCH_X86_HAVE_SSE4),true)
-    $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -msse4
-endif
-ifeq ($(ARCH_X86_HAVE_SSE4_1),true)
-    $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -msse4.1
-endif
-ifeq ($(ARCH_X86_HAVE_SSE4_2),true)
-    $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -msse4.2
-endif
-ifeq ($(ARCH_X86_HAVE_AVX),true)
-    $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -mavx
-endif
-ifeq ($(ARCH_X86_HAVE_AES_NI),true)
-    $(combo_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS += -maes
-endif
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -m32
-
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,-z,noexecstack
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,-z,relro -Wl,-z,now
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,--build-id=md5
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,--warn-shared-textrel
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,--fatal-warnings
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,--gc-sections
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,--hash-style=gnu
-$(combo_2nd_arch_prefix)TARGET_GLOBAL_LDFLAGS += -Wl,--no-undefined-version
-
-$(combo_2nd_arch_prefix)TARGET_C_INCLUDES := \
-	$(libc_root)/arch-x86/include \
-	$(libc_root)/include \
-	$(KERNEL_HEADERS) \
-	$(libm_root)/include \
-	$(libm_root)/include/i387 \
-
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_STATIC_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_DYNAMIC_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
-$(combo_2nd_arch_prefix)TARGET_CRTEND_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
-
-$(combo_2nd_arch_prefix)TARGET_CRTBEGIN_SO_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
-$(combo_2nd_arch_prefix)TARGET_CRTEND_SO_O := $($(combo_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
-
 $(combo_2nd_arch_prefix)TARGET_PACK_MODULE_RELOCATIONS := true
 
 $(combo_2nd_arch_prefix)TARGET_LINKER := /system/bin/linker
diff --git a/core/combo/TARGET_linux-x86_64.mk b/core/combo/TARGET_linux-x86_64.mk
index 12166ec..d2172d6 100644
--- a/core/combo/TARGET_linux-x86_64.mk
+++ b/core/combo/TARGET_linux-x86_64.mk
@@ -22,15 +22,6 @@
 TARGET_ARCH_VARIANT := x86_64
 endif
 
-# Decouple NDK library selection with platform compiler version
-TARGET_NDK_GCC_VERSION := 4.9
-
-ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-TARGET_GCC_VERSION := 4.9
-else
-TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
-endif
-
 # Include the arch-variant-specific configuration file.
 # Its role is to define various ARCH_X86_HAVE_XXX feature macros,
 # plus initial values for TARGET_GLOBAL_CFLAGS
@@ -43,117 +34,10 @@
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 include $(BUILD_SYSTEM)/combo/fdo.mk
 
-# You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
-TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/x86_64-linux-android-$(TARGET_GCC_VERSION)
-TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/x86_64-linux-android-
-endif
-
-TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc
-TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++
-TARGET_AR := $(TARGET_TOOLS_PREFIX)ar
-TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy
-TARGET_LD := $(TARGET_TOOLS_PREFIX)ld
-TARGET_READELF := $(TARGET_TOOLS_PREFIX)readelf
-TARGET_STRIP := $(TARGET_TOOLS_PREFIX)strip
-TARGET_NM := $(TARGET_TOOLS_PREFIX)nm
-
 define $(combo_var_prefix)transform-shared-lib-to-toc
 $(call _gen_toc_command_for_elf,$(1),$(2))
 endef
 
-ifneq ($(wildcard $(TARGET_CC)),)
-TARGET_LIBGCC := \
-	$(shell $(TARGET_CC) -m64 -print-file-name=libgcc.a)
-TARGET_LIBATOMIC := \
-	$(shell $(TARGET_CC) -m64 -print-file-name=libatomic.a)
-TARGET_LIBGCOV := \
-	$(shell $(TARGET_CC) -m64 -print-file-name=libgcov.a)
-endif
-
-TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
-libc_root := bionic/libc
-libm_root := bionic/libm
-
-KERNEL_HEADERS_COMMON := $(libc_root)/kernel/uapi
-KERNEL_HEADERS_COMMON += $(libc_root)/kernel/common
-KERNEL_HEADERS_ARCH   := $(libc_root)/kernel/uapi/asm-x86 # x86 covers both x86 and x86_64.
-KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
-
-TARGET_GLOBAL_CFLAGS += \
-			-O2 \
-			-Wa,--noexecstack \
-			-Werror=format-security \
-			-D_FORTIFY_SOURCE=2 \
-			-Wstrict-aliasing=2 \
-			-ffunction-sections \
-			-finline-functions \
-			-finline-limit=300 \
-			-fno-short-enums \
-			-fstrict-aliasing \
-			-funswitch-loops \
-			-funwind-tables \
-			-fstack-protector-strong \
-			-m64 \
-			-no-canonical-prefixes \
-			-fno-canonical-system-headers
-
-# Help catch common 32/64-bit errors.
-TARGET_GLOBAL_CFLAGS += \
-    -Werror=pointer-to-int-cast \
-    -Werror=int-to-pointer-cast \
-    -Werror=implicit-function-declaration \
-
-TARGET_GLOBAL_CFLAGS += $(arch_variant_cflags)
-
-ifeq ($(ARCH_X86_HAVE_SSSE3),true)   # yes, really SSSE3, not SSE3!
-    TARGET_GLOBAL_CFLAGS += -DUSE_SSSE3 -mssse3
-endif
-ifeq ($(ARCH_X86_HAVE_SSE4),true)
-    TARGET_GLOBAL_CFLAGS += -msse4
-endif
-ifeq ($(ARCH_X86_HAVE_SSE4_1),true)
-    TARGET_GLOBAL_CFLAGS += -msse4.1
-endif
-ifeq ($(ARCH_X86_HAVE_SSE4_2),true)
-    TARGET_GLOBAL_CFLAGS += -msse4.2
-endif
-ifeq ($(ARCH_X86_HAVE_POPCNT),true)
-    TARGET_GLOBAL_CFLAGS += -mpopcnt
-endif
-ifeq ($(ARCH_X86_HAVE_AVX),true)
-    TARGET_GLOBAL_CFLAGS += -mavx
-endif
-ifeq ($(ARCH_X86_HAVE_AES_NI),true)
-    TARGET_GLOBAL_CFLAGS += -maes
-endif
-
-TARGET_GLOBAL_LDFLAGS += -m64
-
-TARGET_GLOBAL_LDFLAGS += -Wl,-z,noexecstack
-TARGET_GLOBAL_LDFLAGS += -Wl,-z,relro -Wl,-z,now
-TARGET_GLOBAL_LDFLAGS += -Wl,--build-id=md5
-TARGET_GLOBAL_LDFLAGS += -Wl,--warn-shared-textrel
-TARGET_GLOBAL_LDFLAGS += -Wl,--fatal-warnings
-TARGET_GLOBAL_LDFLAGS += -Wl,--gc-sections
-TARGET_GLOBAL_LDFLAGS += -Wl,--hash-style=gnu
-TARGET_GLOBAL_LDFLAGS += -Wl,--no-undefined-version
-
-TARGET_C_INCLUDES := \
-	$(libc_root)/arch-x86_64/include \
-	$(libc_root)/include \
-	$(KERNEL_HEADERS) \
-	$(libm_root)/include \
-	$(libm_root)/include/amd64 \
-
-TARGET_CRTBEGIN_STATIC_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
-TARGET_CRTBEGIN_DYNAMIC_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
-TARGET_CRTEND_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
-
-TARGET_CRTBEGIN_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
-TARGET_CRTEND_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
-
 TARGET_LINKER := /system/bin/linker64
 
 TARGET_GLOBAL_YASM_FLAGS := -f elf64 -m amd64
diff --git a/core/combo/arch/arm/armv5te.mk b/core/combo/arch/arm/armv5te.mk
index 88e57b7..bd75695 100644
--- a/core/combo/arch/arm/armv5te.mk
+++ b/core/combo/arch/arm/armv5te.mk
@@ -2,14 +2,3 @@
 # Generating binaries for the ARMv5TE architecture and higher
 #
 
-# Note: Hard coding the 'tune' value here is probably not ideal,
-# and a better solution should be found in the future.
-#
-arch_variant_cflags := \
-    -march=armv5te \
-    -mtune=xscale  \
-    -D__ARM_ARCH_5__ \
-    -D__ARM_ARCH_5T__ \
-    -D__ARM_ARCH_5E__ \
-    -D__ARM_ARCH_5TE__
-
diff --git a/core/combo/arch/arm/armv7-a-neon.mk b/core/combo/arch/arm/armv7-a-neon.mk
index 5d5b050..01d2235 100644
--- a/core/combo/arch/arm/armv7-a-neon.mk
+++ b/core/combo/arch/arm/armv7-a-neon.mk
@@ -5,50 +5,3 @@
 ARCH_ARM_HAVE_VFP               := true
 ARCH_ARM_HAVE_VFP_D32           := true
 ARCH_ARM_HAVE_NEON              := true
-
-local_arch_has_lpae := false
-
-ifneq (,$(filter cortex-a15 krait denver,$(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)))
-	# TODO: krait is not a cortex-a15, we set the variant to cortex-a15 so that
-	#       hardware divide operations are generated. This should be removed and a
-	#       krait CPU variant added to GCC. For clang we specify -mcpu for krait in
-	#       core/clang/arm.mk.
-	arch_variant_cflags := -mcpu=cortex-a15
-
-	local_arch_has_lpae := true
-	arch_variant_ldflags := \
-		-Wl,--no-fix-cortex-a8
-else
-ifeq ($(strip $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)),cortex-a8)
-	arch_variant_cflags := -mcpu=cortex-a8
-	arch_variant_ldflags := \
-		-Wl,--fix-cortex-a8
-else
-ifneq (,$(filter cortex-a7 cortex-a53 cortex-a53.a57,$(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)))
-	arch_variant_cflags := -mcpu=cortex-a7
-
-	local_arch_has_lpae := true
-	arch_variant_ldflags := \
-		-Wl,--no-fix-cortex-a8
-else
-	arch_variant_cflags := -march=armv7-a
-	# Generic ARM might be a Cortex A8 -- better safe than sorry
-	arch_variant_ldflags := \
-		-Wl,--fix-cortex-a8
-endif
-endif
-endif
-
-ifeq (true,$(local_arch_has_lpae))
-	# Fake an ARM compiler flag as these processors support LPAE which GCC/clang
-	# don't advertise.
-	# TODO This is a hack and we need to add it for each processor that supports LPAE until some
-	# better solution comes around. See Bug 27340895
-	arch_variant_cflags += -D__ARM_FEATURE_LPAE=1
-endif
-
-local_arch_has_lpae :=
-
-arch_variant_cflags += \
-    -mfloat-abi=softfp \
-    -mfpu=neon
diff --git a/core/combo/arch/arm/armv7-a.mk b/core/combo/arch/arm/armv7-a.mk
index 4a51977..0c2f04d 100644
--- a/core/combo/arch/arm/armv7-a.mk
+++ b/core/combo/arch/arm/armv7-a.mk
@@ -3,14 +3,3 @@
 #
 ARCH_ARM_HAVE_ARMV7A            := true
 ARCH_ARM_HAVE_VFP               := true
-
-# Note: Hard coding the 'tune' value here is probably not ideal,
-# and a better solution should be found in the future.
-#
-arch_variant_cflags := \
-    -march=armv7-a \
-    -mfloat-abi=softfp \
-    -mfpu=vfpv3-d16
-
-arch_variant_ldflags := \
-	-Wl,--fix-cortex-a8
diff --git a/core/combo/arch/arm64/armv8-a.mk b/core/combo/arch/arm64/armv8-a.mk
index 5e27e5a..e69de29 100644
--- a/core/combo/arch/arm64/armv8-a.mk
+++ b/core/combo/arch/arm64/armv8-a.mk
@@ -1,5 +0,0 @@
-ifneq (,$(filter cortex-a53,$(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)))
-	arch_variant_cflags := -mcpu=cortex-a53
-else
-	arch_variant_cflags :=
-endif
diff --git a/core/combo/arch/mips/mips32-fp.mk b/core/combo/arch/mips/mips32-fp.mk
index 912ff63..4b09bc1 100644
--- a/core/combo/arch/mips/mips32-fp.mk
+++ b/core/combo/arch/mips/mips32-fp.mk
@@ -3,11 +3,3 @@
 
 ARCH_MIPS_HAS_FPU	:=true
 ARCH_HAVE_ALIGNED_DOUBLES :=true
-arch_variant_cflags := \
-    -mips32 \
-    -mfp32 \
-    -modd-spreg \
-    -mno-synci
-
-arch_variant_ldflags := \
-    -Wl,-melf32ltsmip
diff --git a/core/combo/arch/mips/mips32r2-fp-xburst.mk b/core/combo/arch/mips/mips32r2-fp-xburst.mk
index 09b3bc2..83fb12e 100644
--- a/core/combo/arch/mips/mips32r2-fp-xburst.mk
+++ b/core/combo/arch/mips/mips32r2-fp-xburst.mk
@@ -4,13 +4,3 @@
 
 ARCH_MIPS_HAS_FPU :=true
 ARCH_HAVE_ALIGNED_DOUBLES :=true
-arch_variant_cflags := \
-    -mips32r2 \
-    -mfp32 \
-    -modd-spreg \
-    -mno-fused-madd \
-    -Wa,-mmxu \
-    -mno-synci
-
-arch_variant_ldflags := \
-    -Wl,-melf32ltsmip
diff --git a/core/combo/arch/mips/mips32r2-fp.mk b/core/combo/arch/mips/mips32r2-fp.mk
index 9acb018..97c14c3 100644
--- a/core/combo/arch/mips/mips32r2-fp.mk
+++ b/core/combo/arch/mips/mips32r2-fp.mk
@@ -3,11 +3,3 @@
 
 ARCH_MIPS_HAS_FPU	:=true
 ARCH_HAVE_ALIGNED_DOUBLES :=true
-arch_variant_cflags := \
-    -mips32r2 \
-    -mfp32 \
-    -modd-spreg \
-    -msynci
-
-arch_variant_ldflags := \
-    -Wl,-melf32ltsmip
diff --git a/core/combo/arch/mips/mips32r2dsp-fp.mk b/core/combo/arch/mips/mips32r2dsp-fp.mk
index c4b49b6..522b6b9 100644
--- a/core/combo/arch/mips/mips32r2dsp-fp.mk
+++ b/core/combo/arch/mips/mips32r2dsp-fp.mk
@@ -5,12 +5,3 @@
 ARCH_MIPS_DSP_REV	:=1
 ARCH_MIPS_HAS_FPU       :=true
 ARCH_HAVE_ALIGNED_DOUBLES :=true
-arch_variant_cflags := \
-    -mips32r2 \
-    -mfp32 \
-    -modd-spreg \
-    -mdsp \
-    -msynci
-
-arch_variant_ldflags := \
-    -Wl,-melf32ltsmip
diff --git a/core/combo/arch/mips/mips32r2dspr2-fp.mk b/core/combo/arch/mips/mips32r2dspr2-fp.mk
index 8b05ffc..886d378 100644
--- a/core/combo/arch/mips/mips32r2dspr2-fp.mk
+++ b/core/combo/arch/mips/mips32r2dspr2-fp.mk
@@ -5,12 +5,3 @@
 ARCH_MIPS_DSP_REV	:=2
 ARCH_MIPS_HAS_FPU       :=true
 ARCH_HAVE_ALIGNED_DOUBLES :=true
-arch_variant_cflags := \
-    -mips32r2 \
-    -mfp32 \
-    -modd-spreg \
-    -mdspr2 \
-    -msynci
-
-arch_variant_ldflags := \
-    -Wl,-melf32ltsmip
diff --git a/core/combo/arch/mips/mips32r6.mk b/core/combo/arch/mips/mips32r6.mk
index 315aa60..7bc6cac 100644
--- a/core/combo/arch/mips/mips32r6.mk
+++ b/core/combo/arch/mips/mips32r6.mk
@@ -2,11 +2,3 @@
 # Generating binaries for MIPS32R6/hard-float/little-endian
 
 ARCH_MIPS_REV6 := true
-arch_variant_cflags := \
-    -mips32r6 \
-    -mfp64 \
-    -mno-odd-spreg \
-    -msynci
-
-arch_variant_ldflags := \
-    -Wl,-melf32ltsmip
diff --git a/core/combo/arch/mips64/mips64r2.mk b/core/combo/arch/mips64/mips64r2.mk
index c5710d0..54aa387 100644
--- a/core/combo/arch/mips64/mips64r2.mk
+++ b/core/combo/arch/mips64/mips64r2.mk
@@ -4,7 +4,3 @@
 
 ARCH_MIPS_HAS_FPU	:=true
 ARCH_HAVE_ALIGNED_DOUBLES :=true
-arch_variant_cflags := \
-    -mips64r2 \
-    -msynci
-
diff --git a/core/combo/arch/mips64/mips64r6.mk b/core/combo/arch/mips64/mips64r6.mk
index 443de20..42d6c9e 100644
--- a/core/combo/arch/mips64/mips64r6.mk
+++ b/core/combo/arch/mips64/mips64r6.mk
@@ -1,7 +1,3 @@
 # Configuration for Android on mips64r6.
 
-ARCH_MIPS_REV6 := true
-arch_variant_cflags := \
-    -mips64r6 \
-    -msynci
-
+ARCH_MIPS64_REV6 := true
diff --git a/core/combo/arch/x86/atom.mk b/core/combo/arch/x86/atom.mk
index 3800350..d313a9a 100644
--- a/core/combo/arch/x86/atom.mk
+++ b/core/combo/arch/x86/atom.mk
@@ -7,9 +7,3 @@
 ARCH_X86_HAVE_SSSE3 := true
 ARCH_X86_HAVE_MOVBE := true
 ARCH_X86_HAVE_POPCNT := false   # popcnt is not supported by current Atom CPUs
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=atom \
-	-mfpmath=sse \
-
diff --git a/core/combo/arch/x86/haswell.mk b/core/combo/arch/x86/haswell.mk
index b3922c0..50c27b4 100644
--- a/core/combo/arch/x86/haswell.mk
+++ b/core/combo/arch/x86/haswell.mk
@@ -9,9 +9,3 @@
 ARCH_X86_HAVE_AVX    := true
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := true
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=core-avx2 \
-	-mfpmath=sse \
-
diff --git a/core/combo/arch/x86/ivybridge.mk b/core/combo/arch/x86/ivybridge.mk
index c9fc33b..44035d8 100644
--- a/core/combo/arch/x86/ivybridge.mk
+++ b/core/combo/arch/x86/ivybridge.mk
@@ -9,9 +9,3 @@
 ARCH_X86_HAVE_AVX    := true
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := false
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=core-avx-i \
-	-mfpmath=sse \
-
diff --git a/core/combo/arch/x86/sandybridge.mk b/core/combo/arch/x86/sandybridge.mk
index bca5953..a4c1bd9 100644
--- a/core/combo/arch/x86/sandybridge.mk
+++ b/core/combo/arch/x86/sandybridge.mk
@@ -5,13 +5,7 @@
 ARCH_X86_HAVE_SSE4   := true
 ARCH_X86_HAVE_SSE4_1 := true
 ARCH_X86_HAVE_SSE4_2 := true
-ARCH_X86_HAVE_AES_NI := true
-ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AES_NI := false
+ARCH_X86_HAVE_AVX    := false
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := false
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=corei7-avx \
-	-mfpmath=sse \
-
diff --git a/core/combo/arch/x86/silvermont.mk b/core/combo/arch/x86/silvermont.mk
index d064b1d..70b718c 100644
--- a/core/combo/arch/x86/silvermont.mk
+++ b/core/combo/arch/x86/silvermont.mk
@@ -11,9 +11,3 @@
 ARCH_X86_HAVE_AES_NI := true
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := true
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=slm \
-	-mfpmath=sse \
-
diff --git a/core/combo/arch/x86/x86.mk b/core/combo/arch/x86/x86.mk
index f070426..a55cc7a 100644
--- a/core/combo/arch/x86/x86.mk
+++ b/core/combo/arch/x86/x86.mk
@@ -11,9 +11,3 @@
 ARCH_X86_HAVE_SSSE3 := false
 ARCH_X86_HAVE_MOVBE := false
 ARCH_X86_HAVE_POPCNT := false
-
-
-# Some intrinsic functions used by libcxx only exist for prescott or newer CPUs.
-arch_variant_cflags := \
-    -march=prescott \
-
diff --git a/core/combo/arch/x86/x86_64.mk b/core/combo/arch/x86/x86_64.mk
new file mode 100644
index 0000000..fc2a087
--- /dev/null
+++ b/core/combo/arch/x86/x86_64.mk
@@ -0,0 +1,12 @@
+# This file is used as the second (32-bit) architecture when building a generic
+# x86_64 64-bit platform image. (full_x86_64-eng / sdk_x86_64-eng)
+#
+# The generic 'x86' variant cannot be used, since it resets some flags used
+# by the 'x86_64' variant.
+
+ARCH_X86_HAVE_SSSE3 := true
+ARCH_X86_HAVE_MOVBE := false # Only supported on Atom.
+ARCH_X86_HAVE_POPCNT := true
+ARCH_X86_HAVE_SSE4 := true
+ARCH_X86_HAVE_SSE4_1 := true
+ARCH_X86_HAVE_SSE4_2 := true
diff --git a/core/combo/arch/x86_64/haswell.mk b/core/combo/arch/x86_64/haswell.mk
index 6067eee..f9c6ebd 100644
--- a/core/combo/arch/x86_64/haswell.mk
+++ b/core/combo/arch/x86_64/haswell.mk
@@ -9,7 +9,3 @@
 ARCH_X86_HAVE_AVX    := true
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := true
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=core-avx2
diff --git a/core/combo/arch/x86_64/ivybridge.mk b/core/combo/arch/x86_64/ivybridge.mk
index 90e23a9..69011d6 100644
--- a/core/combo/arch/x86_64/ivybridge.mk
+++ b/core/combo/arch/x86_64/ivybridge.mk
@@ -9,7 +9,3 @@
 ARCH_X86_HAVE_AVX    := true
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := false
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=core-avx-i
diff --git a/core/combo/arch/x86_64/sandybridge.mk b/core/combo/arch/x86_64/sandybridge.mk
index 865548c..2092d19 100644
--- a/core/combo/arch/x86_64/sandybridge.mk
+++ b/core/combo/arch/x86_64/sandybridge.mk
@@ -5,11 +5,7 @@
 ARCH_X86_HAVE_SSE4   := true
 ARCH_X86_HAVE_SSE4_1 := true
 ARCH_X86_HAVE_SSE4_2 := true
-ARCH_X86_HAVE_AES_NI := true
-ARCH_X86_HAVE_AVX    := true
+ARCH_X86_HAVE_AES_NI := false
+ARCH_X86_HAVE_AVX    := false
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := false
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=corei7-avx
diff --git a/core/combo/arch/x86_64/silvermont.mk b/core/combo/arch/x86_64/silvermont.mk
index 6c953a3..70b718c 100644
--- a/core/combo/arch/x86_64/silvermont.mk
+++ b/core/combo/arch/x86_64/silvermont.mk
@@ -11,7 +11,3 @@
 ARCH_X86_HAVE_AES_NI := true
 ARCH_X86_HAVE_POPCNT := true
 ARCH_X86_HAVE_MOVBE  := true
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-	-march=slm \
diff --git a/core/combo/arch/x86_64/x86_64.mk b/core/combo/arch/x86_64/x86_64.mk
index 08dd9cd..26a9d0f 100755
--- a/core/combo/arch/x86_64/x86_64.mk
+++ b/core/combo/arch/x86_64/x86_64.mk
@@ -11,8 +11,3 @@
 ARCH_X86_HAVE_SSE4 := true
 ARCH_X86_HAVE_SSE4_1 := true
 ARCH_X86_HAVE_SSE4_2 := true
-
-
-# CFLAGS for this arch
-arch_variant_cflags := \
-    -march=x86-64
diff --git a/core/combo/javac.mk b/core/combo/javac.mk
index 7f66ea8..9042d83 100644
--- a/core/combo/javac.mk
+++ b/core/combo/javac.mk
@@ -9,11 +9,6 @@
 #   COMMON_JAVAC -- Java compiler command with common arguments
 #
 
-ifndef ANDROID_COMPILE_WITH_JACK
-# Defines if compilation with jack is enabled by default.
-ANDROID_COMPILE_WITH_JACK := true
-endif
-
 common_jdk_flags := -Xmaxerrs 9999999
 
 # Use the indexer wrapper to index the codebase instead of the javac compiler
diff --git a/core/combo/mac_version.mk b/core/combo/mac_version.mk
deleted file mode 100644
index 51394c6..0000000
--- a/core/combo/mac_version.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# Detect Mac OS X and SDK versions.
-# Output variables:
-#   build_mac_version
-#   mac_sdk_version
-#   mac_sdk_root
-#   gcc_darwin_version
-
-ifndef build_mac_version
-
-build_mac_version := $(shell sw_vers -productVersion)
-
-mac_sdk_versions_supported :=  10.8 10.9 10.10 10.11
-ifneq ($(strip $(MAC_SDK_VERSION)),)
-mac_sdk_version := $(MAC_SDK_VERSION)
-ifeq ($(filter $(mac_sdk_version),$(mac_sdk_versions_supported)),)
-$(warning ****************************************************************)
-$(warning * MAC_SDK_VERSION $(MAC_SDK_VERSION) isn't one of the supported $(mac_sdk_versions_supported))
-$(warning ****************************************************************)
-$(error Stop.)
-endif
-else
-mac_sdk_versions_installed := $(shell xcodebuild -showsdks | grep macosx | sed -e "s/.*macosx//g")
-mac_sdk_version := $(firstword $(filter $(mac_sdk_versions_installed), $(mac_sdk_versions_supported)))
-ifeq ($(mac_sdk_version),)
-mac_sdk_version := $(firstword $(mac_sdk_versions_supported))
-$(warning none of the installed SDKs ($mac_sdk_versions_installed) match supported versions ($(mac_sdk_versions_supported)), trying $(mac_sdk_version))
-endif
-endif
-
-mac_sdk_path := $(shell xcode-select -print-path)
-# try /Applications/Xcode*.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.?.sdk
-#  or /Volume/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.?.sdk
-mac_sdk_root := $(mac_sdk_path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$(mac_sdk_version).sdk
-ifeq ($(wildcard $(mac_sdk_root)),)
-# try legacy /Developer/SDKs/MacOSX10.?.sdk
-$(warning no SDK $(mac_sdk_version) at $(mac_sdk_root), trying legacy dir)
-mac_sdk_root := /Developer/SDKs/MacOSX$(mac_sdk_version).sdk
-endif
-ifeq ($(wildcard $(mac_sdk_root)),)
-$(warning *****************************************************)
-$(warning * Can not find SDK $(mac_sdk_version) at $(mac_sdk_root))
-$(warning *****************************************************)
-$(error Stop.)
-endif
-
-ifeq ($(mac_sdk_version),10.6)
-  gcc_darwin_version := 10
-else
-  gcc_darwin_version := 11
-endif
-
-endif  # ifndef build_mac_version
diff --git a/core/combo/select.mk b/core/combo/select.mk
index df12e7e..5e181b9 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -28,21 +28,8 @@
 
 # Set reasonable defaults for the various variables
 
-$(combo_var_prefix)CC := $(CC)
-$(combo_var_prefix)CXX := $(CXX)
-$(combo_var_prefix)AR := $(AR)
-$(combo_var_prefix)STRIP := $(STRIP)
-
-$(combo_var_prefix)GLOBAL_CFLAGS := -fno-exceptions -Wno-multichar
-$(combo_var_prefix)RELEASE_CFLAGS := -O2 -g -fno-strict-aliasing
-$(combo_var_prefix)GLOBAL_CPPFLAGS :=
-$(combo_var_prefix)GLOBAL_LDFLAGS :=
 $(combo_var_prefix)GLOBAL_ARFLAGS := crsPD
-$(combo_var_prefix)GLOBAL_LD_DIRS :=
 
-$(combo_var_prefix)EXECUTABLE_SUFFIX :=
-$(combo_var_prefix)SHLIB_SUFFIX := .so
-$(combo_var_prefix)JNILIB_SUFFIX := $($(combo_var_prefix)SHLIB_SUFFIX)
 $(combo_var_prefix)STATIC_LIB_SUFFIX := .a
 
 # Now include the combo for this specific target.
diff --git a/core/config.mk b/core/config.mk
index 94c880f..da4784f 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -40,25 +40,6 @@
 $(error Please remove --color=always from your  $$GREP_OPTIONS)
 endif
 
-# Standard source directories.
-SRC_DOCS:= $(TOPDIR)docs
-# TODO: Enforce some kind of layering; only add include paths
-#       when a module links against a particular library.
-# TODO: See if we can remove most of these from the global list.
-SRC_HEADERS := \
-	$(TOPDIR)system/core/include \
-	$(TOPDIR)system/media/audio/include \
-	$(TOPDIR)hardware/libhardware/include \
-	$(TOPDIR)hardware/libhardware_legacy/include \
-	$(TOPDIR)hardware/ril/include \
-	$(TOPDIR)libnativehelper/include \
-	$(TOPDIR)frameworks/native/include \
-	$(TOPDIR)frameworks/native/opengl/include \
-	$(TOPDIR)frameworks/av/include \
-	$(TOPDIR)frameworks/base/include
-SRC_HOST_HEADERS:=$(TOPDIR)tools/include
-SRC_LIBRARIES:= $(TOPDIR)libs
-SRC_SERVERS:= $(TOPDIR)servers
 SRC_TARGET_DIR := $(TOPDIR)build/target
 SRC_API_DIR := $(TOPDIR)prebuilts/sdk/api
 SRC_SYSTEM_API_DIR := $(TOPDIR)prebuilts/sdk/system-api
@@ -80,6 +61,8 @@
 BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
 BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
 BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
+BUILD_AUX_STATIC_LIBRARY:= $(BUILD_SYSTEM)/aux_static_library.mk
+BUILD_AUX_EXECUTABLE:= $(BUILD_SYSTEM)/aux_executable.mk
 BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
 BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
 BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
@@ -197,8 +180,8 @@
 #     etc.
 #
 # NOTE: These directories MUST contain post-processed headers using the
-# bionic/libc/kernel/clean_header.py tool. Additionally, the original kernel
-# headers must also be checked in, but in a different subdirectory. By
+# bionic/libc/kernel/tools/clean_header.py tool. Additionally, the original
+# kernel headers must also be checked in, but in a different subdirectory. By
 # convention, the originals should be checked into original-kernel-headers
 # directory of the same parent dir. For example,
 #     device/samsung/tuna/kernel-headers            <----- post-processed
@@ -283,9 +266,14 @@
 include $(BUILD_SYSTEM)/combo/select.mk
 endif
 
+ifndef KATI
 include $(BUILD_SYSTEM)/ccache.mk
 include $(BUILD_SYSTEM)/goma.mk
 
+export CC_WRAPPER
+export CXX_WRAPPER
+endif
+
 ifdef TARGET_PREFER_32_BIT
 TARGET_PREFER_32_BIT_APPS := true
 TARGET_PREFER_32_BIT_EXECUTABLES := true
@@ -339,26 +327,35 @@
 TARGET_CPU_ABI_LIST_32_BIT := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST_32_BIT)))
 TARGET_CPU_ABI_LIST_64_BIT := $(subst $(space),$(comma),$(strip $(TARGET_CPU_ABI_LIST_64_BIT)))
 
-# Compute TARGET_TOOLCHAIN_ROOT from TARGET_TOOLS_PREFIX
-# if only TARGET_TOOLS_PREFIX is passed to the make command.
-ifndef TARGET_TOOLCHAIN_ROOT
-TARGET_TOOLCHAIN_ROOT := $(patsubst %/, %, $(dir $(TARGET_TOOLS_PREFIX)))
-TARGET_TOOLCHAIN_ROOT := $(patsubst %/, %, $(dir $(TARGET_TOOLCHAIN_ROOT)))
-TARGET_TOOLCHAIN_ROOT := $(wildcard $(TARGET_TOOLCHAIN_ROOT))
+# GCC version selection
+TARGET_GCC_VERSION := 4.9
+ifdef TARGET_2ND_ARCH
+2ND_TARGET_GCC_VERSION := 4.9
 endif
 
-# Normalize WITH_STATIC_ANALYZER and WITH_SYNTAX_CHECK
+# Normalize WITH_STATIC_ANALYZER
 ifeq ($(strip $(WITH_STATIC_ANALYZER)),0)
   WITH_STATIC_ANALYZER :=
 endif
-ifeq ($(strip $(WITH_SYNTAX_CHECK)),0)
-  WITH_SYNTAX_CHECK :=
-endif
 
 # define clang/llvm versions and base directory.
 include $(BUILD_SYSTEM)/clang/versions.mk
 
-# Disable WITH_STATIC_ANALYZER and WITH_SYNTAX_CHECK if tool can't be found
+# Unset WITH_TIDY_ONLY if global WITH_TIDY_ONLY is not true nor 1.
+ifeq (,$(filter 1 true,$(WITH_TIDY_ONLY)))
+  WITH_TIDY_ONLY :=
+endif
+
+PATH_TO_CLANG_TIDY := \
+    $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/bin/clang-tidy
+ifeq ($(wildcard $(PATH_TO_CLANG_TIDY)),)
+  ifneq (,$(filter 1 true,$(WITH_TIDY)))
+    $(warning *** Disable WITH_TIDY because $(PATH_TO_CLANG_TIDY) does not exist)
+  endif
+  PATH_TO_CLANG_TIDY :=
+endif
+
+# Disable WITH_STATIC_ANALYZER if tool can't be found
 SYNTAX_TOOLS_PREFIX := \
     $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/tools/scan-build/libexec
 ifneq ($(strip $(WITH_STATIC_ANALYZER)),)
@@ -368,14 +365,6 @@
   endif
 endif
 
-# WITH_STATIC_ANALYZER trumps WITH_SYNTAX_CHECK
-ifneq ($(strip $(WITH_STATIC_ANALYZER)),)
-  ifneq ($(strip $(WITH_SYNTAX_CHECK)),)
-    $(warning *** Disable WITH_SYNTAX_CHECK in the presence of static analyzer WITH_STATIC_ANALYZER)
-    WITH_SYNTAX_CHECK :=
-  endif
-endif
-
 # Pick a Java compiler.
 include $(BUILD_SYSTEM)/combo/javac.mk
 
@@ -454,8 +443,9 @@
 #
 # Tools that are prebuilts for TARGET_BUILD_APPS
 #
+prebuilt_sdk_tools := prebuilts/sdk/tools
+prebuilt_sdk_tools_bin := $(prebuilt_sdk_tools)/$(HOST_OS)/bin
 
-ACP := $(HOST_OUT_EXECUTABLES)/acp
 AIDL := $(HOST_OUT_EXECUTABLES)/aidl
 AAPT := $(HOST_OUT_EXECUTABLES)/aapt
 AAPT2 := $(HOST_OUT_EXECUTABLES)/aapt2
@@ -468,14 +458,22 @@
 DX := $(HOST_OUT_EXECUTABLES)/dx
 MAINDEXCLASSES := $(HOST_OUT_EXECUTABLES)/mainDexClasses
 
+SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
+ZIP2ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/zip2zip
+
+# Always use prebuilts for ckati and makeparallel
+prebuilt_build_tools := prebuilts/build-tools
+prebuilt_build_tools_bin := $(prebuilt_build_tools)/$(HOST_PREBUILT_TAG)/bin
+ACP := $(prebuilt_build_tools_bin)/acp
+CKATI := $(prebuilt_build_tools_bin)/ckati
+IJAR := $(prebuilt_build_tools_bin)/ijar
+MAKEPARALLEL := $(prebuilt_build_tools_bin)/makeparallel
+ZIPTIME := $(prebuilt_build_tools_bin)/ziptime
+
 USE_PREBUILT_SDK_TOOLS_IN_PLACE := true
 
 # Override the definitions above for unbundled and PDK builds
 ifneq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
-prebuilt_sdk_tools := prebuilts/sdk/tools
-prebuilt_sdk_tools_bin := $(prebuilt_sdk_tools)/$(HOST_OS)/bin
-
-ACP := $(prebuilt_sdk_tools_bin)/acp
 AIDL := $(prebuilt_sdk_tools_bin)/aidl
 AAPT := $(prebuilt_sdk_tools_bin)/aapt
 AAPT2 := $(prebuilt_sdk_tools_bin)/aapt2
@@ -493,6 +491,8 @@
 BCC_COMPAT := $(prebuilt_sdk_tools_bin)/bcc_compat
 endif # TARGET_BUILD_PDK
 endif # TARGET_BUILD_APPS || TARGET_BUILD_PDK
+prebuilt_sdk_tools :=
+prebuilt_sdk_tools_bin :=
 
 
 # ---------------------------------------------------------------
@@ -507,6 +507,7 @@
 BISON_PKGDATADIR := $(PWD)/external/bison/data
 BISON := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/bison/bison
 YACC := $(BISON) -d
+BISON_DATA := $(wildcard external/bison/data/* external/bison/data/*/*)
 
 YASM := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/yasm/yasm
 
@@ -519,6 +520,10 @@
 BREAKPAD_GENERATE_SYMBOLS := false
 endif
 PROTOC := $(HOST_OUT_EXECUTABLES)/aprotoc$(HOST_EXECUTABLE_SUFFIX)
+NANOPB_SRCS := external/nanopb-c/generator/protoc-gen-nanopb \
+    $(wildcard external/nanopb-c/generator/*.py \
+               external/nanopb-c/generator/google/*.py \
+               external/nanopb-c/generator/proto/*.py)
 VTSC := $(HOST_OUT_EXECUTABLES)/vtsc$(HOST_EXECUTABLE_SUFFIX)
 DBUS_GENERATOR := $(HOST_OUT_EXECUTABLES)/dbus-binding-generator
 MKBOOTFS := $(HOST_OUT_EXECUTABLES)/mkbootfs$(HOST_EXECUTABLE_SUFFIX)
@@ -528,6 +533,16 @@
 else
 MKBOOTIMG := $(BOARD_CUSTOM_MKBOOTIMG)
 endif
+ifeq (,$(strip $(BOARD_CUSTOM_BPTTOOL)))
+BPTTOOL := $(HOST_OUT_EXECUTABLES)/bpttool$(HOST_EXECUTABLE_SUFFIX)
+else
+BPTTOOL := $(BOARD_CUSTOM_BPTTOOL)
+endif
+ifeq (,$(strip $(BOARD_CUSTOM_AVBTOOL)))
+AVBTOOL := $(HOST_OUT_EXECUTABLES)/avbtool$(HOST_EXECUTABLE_SUFFIX)
+else
+AVBTOOL := $(BOARD_CUSTOM_AVBTOOL)
+endif
 APICHECK := $(HOST_OUT_EXECUTABLES)/apicheck$(HOST_EXECUTABLE_SUFFIX)
 FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
 MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/make_ext4fs$(HOST_EXECUTABLE_SUFFIX)
@@ -542,26 +557,23 @@
 E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)
 MKTARBALL := build/tools/mktarball.sh
 TUNE2FS := $(HOST_OUT_EXECUTABLES)/tune2fs$(HOST_EXECUTABLE_SUFFIX)
-E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)
 JARJAR := $(HOST_OUT_JAVA_LIBRARIES)/jarjar.jar
 DATA_BINDING_COMPILER := $(HOST_OUT_JAVA_LIBRARIES)/databinding-compiler.jar
+FAT16COPY := build/tools/fat16copy.py
+CHECK_LINK_TYPE := build/tools/check_link_type.py
 
-ifeq ($(ANDROID_COMPILE_WITH_JACK),true)
-DEFAULT_JACK_ENABLED:=full
-else
-DEFAULT_JACK_ENABLED:=
-endif
 ifneq ($(ANDROID_JACK_EXTRA_ARGS),)
+JACK_DEFAULT_ARGS :=
 DEFAULT_JACK_EXTRA_ARGS := $(ANDROID_JACK_EXTRA_ARGS)
 else
-DEFAULT_JACK_EXTRA_ARGS := @$(BUILD_SYSTEM)/jack-default.args
+JACK_DEFAULT_ARGS := $(BUILD_SYSTEM)/jack-default.args
+DEFAULT_JACK_EXTRA_ARGS := @$(JACK_DEFAULT_ARGS)
 endif
-# Turn off jack warnings by default.
-DEFAULT_JACK_EXTRA_ARGS += --verbose error
 
 PROGUARD := external/proguard/bin/proguard.sh
 JAVATAGS := build/tools/java-event-log-tags.py
-RMTYPEDEFS := $(HOST_OUT_EXECUTABLES)/rmtypedefs
+MERGETAGS := build/tools/merge-event-log-tags.py
+BUILD_IMAGE_SRCS := $(wildcard build/tools/releasetools/*.py)
 APPEND2SIMG := $(HOST_OUT_EXECUTABLES)/append2simg
 VERITY_SIGNER := $(HOST_OUT_EXECUTABLES)/verity_signer
 BUILD_VERITY_TREE := $(HOST_OUT_EXECUTABLES)/build_verity_tree
@@ -570,13 +582,6 @@
 VBOOT_SIGNER := prebuilts/misc/scripts/vboot_signer/vboot_signer.sh
 FEC := $(HOST_OUT_EXECUTABLES)/fec
 
-ifndef TARGET_BUILD_APPS
-ZIPTIME := $(HOST_OUT_EXECUTABLES)/ziptime$(HOST_EXECUTABLE_SUFFIX)
-endif
-
-# ijar converts a .jar file to a smaller .jar file which only has its
-# interfaces.
-IJAR := $(HOST_OUT_EXECUTABLES)/ijar$(BUILD_EXECUTABLE_SUFFIX)
 DEXDUMP := $(HOST_OUT_EXECUTABLES)/dexdump2$(BUILD_EXECUTABLE_SUFFIX)
 
 # relocation packer
@@ -631,152 +636,53 @@
 # Set up final options.
 # ###############################################################
 
-ifneq ($(COMMON_GLOBAL_CFLAGS)$(COMMON_GLOBAL_CPPFLAGS),)
-$(warning COMMON_GLOBAL_C(PP)FLAGS changed)
-$(info *** Device configurations are no longer allowed to change the global flags.)
-$(info *** COMMON_GLOBAL_CFLAGS: $(COMMON_GLOBAL_CFLAGS))
-$(info *** COMMON_GLOBAL_CPPFLAGS: $(COMMON_GLOBAL_CPPFLAGS))
-$(error bailing...)
-endif
-
-# These can be changed to modify both host and device modules.
-COMMON_GLOBAL_CFLAGS:= -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith
-COMMON_RELEASE_CFLAGS:= -DNDEBUG -UDEBUG
-
-# Force gcc to always output color diagnostics.  Ninja will strip the ANSI
-# color codes if it is not running in a terminal.
-ifdef BUILDING_WITH_NINJA
-COMMON_GLOBAL_CFLAGS += -fdiagnostics-color
-endif
-
-COMMON_GLOBAL_CPPFLAGS:= -Wsign-promo
-COMMON_RELEASE_CPPFLAGS:=
-
 GLOBAL_CFLAGS_NO_OVERRIDE := \
     -Werror=int-to-pointer-cast \
     -Werror=pointer-to-int-cast \
 
 GLOBAL_CLANG_CFLAGS_NO_OVERRIDE := \
     -Werror=address-of-temporary \
-    -Werror=null-dereference \
     -Werror=return-type \
+    # Bug: http://b/29823425 Disable -Wnull-dereference until the new cases
+    # detected by this warning in Clang r271374 are fixed.
+    #-Werror=null-dereference \
 
 GLOBAL_CPPFLAGS_NO_OVERRIDE :=
 
-# list of flags to turn specific warnings in to errors
-TARGET_ERROR_FLAGS := -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Werror=date-time
-
 # We run gcc/clang with PWD=/proc/self/cwd to remove the $TOP
 # from the debug output. That way two builds in two different
 # directories will create the same output.
 # /proc doesn't exist on Darwin.
 ifeq ($(HOST_OS),linux)
 RELATIVE_PWD := PWD=/proc/self/cwd
-# Remove this useless prefix from the debug output.
-COMMON_GLOBAL_CFLAGS += -fdebug-prefix-map=/proc/self/cwd=
 else
 RELATIVE_PWD :=
 endif
 
-# Allow the C/C++ macros __DATE__ and __TIME__ to be set to the
-# build date and time, so that a build may be repeated.
-# Write the date and time to a file so that the command line
-# doesn't change every time, which would cause ninja to rebuild
-# the files.
-$(shell mkdir -p $(OUT_DIR) && \
-    $(DATE) "+%b %_d %Y" > $(OUT_DIR)/build_c_date.txt && \
-    $(DATE) +%T > $(OUT_DIR)/build_c_time.txt)
-BUILD_DATETIME_C_DATE := $$(cat $(OUT_DIR)/build_c_date.txt)
-BUILD_DATETIME_C_TIME := $$(cat $(OUT_DIR)/build_c_time.txt)
-ifeq ($(OVERRIDE_C_DATE_TIME),true)
-COMMON_GLOBAL_CFLAGS += -Wno-builtin-macro-redefined -D__DATE__="\"$(BUILD_DATETIME_C_DATE)\"" -D__TIME__=\"$(BUILD_DATETIME_C_TIME)\"
-endif
-
-HOST_GLOBAL_CFLAGS += $(COMMON_GLOBAL_CFLAGS)
-HOST_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)
-
-HOST_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
-HOST_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)
-
-TARGET_GLOBAL_CFLAGS += $(COMMON_GLOBAL_CFLAGS)
-TARGET_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)
-
-TARGET_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
-TARGET_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)
-
-HOST_GLOBAL_LD_DIRS += -L$(HOST_OUT_INTERMEDIATE_LIBRARIES)
-TARGET_GLOBAL_LD_DIRS += -L$(TARGET_OUT_INTERMEDIATE_LIBRARIES)
-
-HOST_PROJECT_INCLUDES:= $(SRC_HEADERS) $(SRC_HOST_HEADERS) $(HOST_OUT_HEADERS)
-TARGET_PROJECT_INCLUDES:= $(SRC_HEADERS) $(TARGET_OUT_HEADERS) \
+HOST_PROJECT_INCLUDES :=
+HOST_PROJECT_SYSTEM_INCLUDES := $(HOST_OUT_HEADERS)
+TARGET_PROJECT_INCLUDES :=
+TARGET_PROJECT_SYSTEM_INCLUDES := $(TARGET_OUT_HEADERS) \
 		$(TARGET_DEVICE_KERNEL_HEADERS) $(TARGET_BOARD_KERNEL_HEADERS) \
 		$(TARGET_PRODUCT_KERNEL_HEADERS)
 
-# Many host compilers don't support these flags, so we have to make
-# sure to only specify them for the target compilers checked in to
-# the source tree.
-TARGET_GLOBAL_CFLAGS += $(TARGET_ERROR_FLAGS)
-
-HOST_GLOBAL_CFLAGS += $(HOST_RELEASE_CFLAGS)
-HOST_GLOBAL_CPPFLAGS += $(HOST_RELEASE_CPPFLAGS)
-
-TARGET_GLOBAL_CFLAGS += $(TARGET_RELEASE_CFLAGS)
-TARGET_GLOBAL_CPPFLAGS += $(TARGET_RELEASE_CPPFLAGS)
-
 ifdef TARGET_2ND_ARCH
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CFLAGS += $(COMMON_GLOBAL_CFLAGS)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LD_DIRS += -L$($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_PROJECT_INCLUDES := $(TARGET_PROJECT_INCLUDES)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CFLAGS += $(TARGET_ERROR_FLAGS)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CFLAGS += $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_RELEASE_CFLAGS)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CPPFLAGS += $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_RELEASE_CPPFLAGS)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_PROJECT_SYSTEM_INCLUDES := $(TARGET_PROJECT_SYSTEM_INCLUDES)
 endif
 
 ifdef HOST_2ND_ARCH
-$(HOST_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_CFLAGS += $(COMMON_GLOBAL_CFLAGS)
-$(HOST_2ND_ARCH_VAR_PREFIX)HOST_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)
-$(HOST_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
-$(HOST_2ND_ARCH_VAR_PREFIX)HOST_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)
-$(HOST_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_LD_DIRS += -L$($(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES)
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_PROJECT_INCLUDES := $(HOST_PROJECT_INCLUDES)
-$(HOST_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_CFLAGS += $($(HOST_2ND_ARCH_VAR_PREFIX)HOST_RELEASE_CFLAGS)
-$(HOST_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_CPPFLAGS += $($(HOST_2ND_ARCH_VAR_PREFIX)HOST_RELEASE_CPPFLAGS)
+$(HOST_2ND_ARCH_VAR_PREFIX)HOST_PROJECT_SYSTEM_INCLUDES := $(HOST_PROJECT_SYSTEM_INCLUDES)
 endif
 
 ifdef HOST_CROSS_OS
-HOST_CROSS_GLOBAL_CFLAGS += $(filter-out $(HOST_CROSS_UNKNOWN_CFLAGS),$(COMMON_GLOBAL_CFLAGS))
-HOST_CROSS_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)
-HOST_CROSS_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
-HOST_CROSS_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)
-HOST_CROSS_GLOBAL_LD_DIRS += -L$(HOST_CROSS_OUT_INTERMEDIATE_LIBRARIES)
-HOST_CROSS_PROJECT_INCLUDES:= $(SRC_HEADERS) $(SRC_HOST_HEADERS) $(HOST_CROSS_OUT_HEADERS)
-HOST_CROSS_GLOBAL_CFLAGS += $(HOST_CROSS_RELEASE_CFLAGS)
-HOST_CROSS_GLOBAL_CPPFLAGS += $(HOST_CROSS_RELEASE_CPPFLAGS)
+HOST_CROSS_PROJECT_INCLUDES :=
+HOST_CROSS_PROJECT_SYSTEM_INCLUDES := $(HOST_CROSS_OUT_HEADERS)
 
 ifdef HOST_CROSS_2ND_ARCH
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_GLOBAL_CFLAGS += $(filter-out $($(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_UNKNOWN_CFLAGS),$(COMMON_GLOBAL_CFLAGS))
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_RELEASE_CFLAGS += $(COMMON_RELEASE_CFLAGS)
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_GLOBAL_CPPFLAGS += $(COMMON_GLOBAL_CPPFLAGS)
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_RELEASE_CPPFLAGS += $(COMMON_RELEASE_CPPFLAGS)
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_GLOBAL_LD_DIRS += -L$($(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATE_LIBRARIES)
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_PROJECT_INCLUDES:= $(SRC_HEADERS) $(SRC_HOST_HEADERS) $($(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_HEADERS)
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_GLOBAL_CFLAGS += $($(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_RELEASE_CFLAGS)
-$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_GLOBAL_CPPFLAGS += $($(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_RELEASE_CPPFLAGS)
-endif
-endif
-
-ifdef BRILLO
-# Add a C define that identifies Brillo targets. __BRILLO__ should only be used
-# to differentiate between Brillo and non-Brillo-but-Android environments. Use
-# __ANDROID__ instead to test if something is being built in an Android-derived
-# environment (including Brillo) as opposed to an entirely different
-# environment (e.g. Chrome OS).
-TARGET_GLOBAL_CFLAGS += -D__BRILLO__
-ifdef TARGET_2ND_ARCH
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_CFLAGS += -D__BRILLO__
+$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_PROJECT_INCLUDES:= $(HOST_CROSS_PROJECT_INCLUDES)
+$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_PROJECT_SYSTEM_INCLUDES:= $(HOST_CROSS_PROJECT_SYSTEM_INCLUDES)
 endif
 endif
 
@@ -867,4 +773,14 @@
 RSCOMPAT_32BIT_ONLY_API_LEVELS := 8 9 10 11 12 13 14 15 16 17 18 19 20
 RSCOMPAT_NO_USAGEIO_API_LEVELS := 8 9 10 11 12 13
 
+NDK_PREBUILT_SHARED_LIBRARIES := android c dl EGL GLESv1_CM GLESv2 GLESv3 jnigraphics log mediandk m OpenMAXAL OpenSLES stdc++ vulkan z
+
+ifeq ($(JAVA_NOT_REQUIRED),true)
+# Remove java and tools from our path so that we make sure nobody uses them.
+unexport ANDROID_JAVA_HOME
+unexport JAVA_HOME
+export ANDROID_BUILD_PATHS:=$(abspath $(BUILD_SYSTEM)/no_java_path):$(ANDROID_BUILD_PATHS)
+export PATH:=$(abspath $(BUILD_SYSTEM)/no_java_path):$(PATH)
+endif
+
 include $(BUILD_SYSTEM)/dumpvar.mk
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 6e96880..2e14fef 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -19,14 +19,39 @@
   endif
 endif
 
-# The sanitizer specified by the environment wins over the module.
 ifneq ($(my_global_sanitize),)
-  my_sanitize := $(my_global_sanitize)
+  my_sanitize := $(my_global_sanitize) $(my_sanitize)
+endif
+
+# The sanitizer specified in the product configuration wins over the previous.
+ifneq ($(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG),)
+  my_sanitize := $(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG)
+  ifeq ($(my_sanitize),never)
+    my_sanitize :=
+  endif
+endif
+
+# Add a filter point for 32-bit vs 64-bit sanitization (to lighten the burden).
+SANITIZE_ARCH ?= 32 64
+ifeq ($(filter $(SANITIZE_ARCH),$(my_32_64_bit_suffix)),)
+  my_sanitize :=
+endif
+
+# Add a filter point based on module owner (to lighten the burden). The format is a space- or
+# colon-separated list of owner names.
+ifneq (,$(SANITIZE_NEVER_BY_OWNER))
+  ifneq (,$(LOCAL_MODULE_OWNER))
+    ifneq (,$(filter $(LOCAL_MODULE_OWNER),$(subst :, ,$(SANITIZE_NEVER_BY_OWNER))))
+      $(warning Not sanitizing $(LOCAL_MODULE) based on module owner.)
+      my_sanitize :=
+    endif
+  endif
 endif
 
 # Don't apply sanitizers to NDK code.
 ifdef LOCAL_SDK_VERSION
   my_sanitize :=
+  my_global_sanitize :=
 endif
 
 # Never always wins.
@@ -34,6 +59,11 @@
   my_sanitize :=
 endif
 
+my_nosanitize = $(strip $(LOCAL_NOSANITIZE))
+ifneq ($(my_nosanitize),)
+  my_sanitize := $(filter-out $(my_nosanitize),$(my_sanitize))
+endif
+
 # TSAN is not supported on 32-bit architectures. For non-multilib cases, make
 # its use an error. For multilib cases, don't use it for the 32-bit case.
 ifneq ($(filter thread,$(my_sanitize)),)
@@ -46,21 +76,23 @@
   endif
 endif
 
+ifneq ($(filter safe-stack,$(my_sanitize)),)
+  ifeq ($(my_32_64_bit_suffix),32)
+    my_sanitize := $(filter-out safe-stack,$(my_sanitize))
+  endif
+endif
+
 # Undefined symbols can occur if a non-sanitized library links
 # sanitized static libraries. That's OK, because the executable
 # always depends on the ASan runtime library, which defines these
 # symbols.
-ifneq ($(strip $(SANITIZE_TARGET)),)
+ifneq ($(filter address thread,$(strip $(SANITIZE_TARGET))),)
   ifndef LOCAL_IS_HOST_MODULE
     ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
       ifeq ($(my_sanitize),)
         my_allow_undefined_symbols := true
       endif
     endif
-    # Workaround for a bug in AddressSanitizer that breaks stack unwinding.
-    # https://code.google.com/p/address-sanitizer/issues/detail?id=387
-    # Revert when external/compiler-rt is updated past r236014.
-    LOCAL_PACK_MODULE_RELOCATIONS := false
   endif
 endif
 
@@ -92,18 +124,22 @@
     my_ldflags += -fsanitize=$(fsanitize_arg)
     my_ldlibs += -lrt -ldl
   else
-    ifeq ($(filter address,$(my_sanitize)),)
-      my_cflags += -fsanitize-trap=all
-      my_cflags += -ftrap-function=abort
+    my_cflags += -fsanitize-trap=all
+    my_cflags += -ftrap-function=abort
+    ifneq ($(filter address thread,$(my_sanitize)),)
+      my_cflags += -fno-sanitize-trap=address,thread
+      my_shared_libraries += libdl
     endif
-    my_shared_libraries += libdl
   endif
 endif
 
-ifneq ($(filter address,$(my_sanitize)),)
-  # Frame pointer based unwinder in ASan requires ARM frame setup.
-  LOCAL_ARM_MODE := arm
-  my_cflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS)
+ifneq ($(filter cfi,$(my_sanitize)),)
+  my_cflags += -flto -fsanitize-cfi-cross-dso -fvisibility=default
+  my_ldflags += -flto -fsanitize-cfi-cross-dso -fsanitize=cfi -Wl,-plugin-opt,O1 -Wl,-export-dynamic-symbol=__cfi_check
+endif
+
+# If local or global modules need ASAN, add linker flags.
+ifneq ($(filter address,$(my_global_sanitize) $(my_sanitize)),)
   my_ldflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS)
   ifdef LOCAL_IS_HOST_MODULE
     # -nodefaultlibs (provided with libc++) prevents the driver from linking
@@ -111,16 +147,38 @@
     my_ldlibs += -lm -lpthread
     my_ldflags += -Wl,--no-as-needed
   else
-    my_cflags += -mllvm -asan-globals=0
+    # Add asan libraries unless LOCAL_MODULE is the asan library.
     # ASan runtime library must be the first in the link order.
-    my_shared_libraries := $($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
-                           $(my_shared_libraries) \
-                           $(ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES)
-    my_static_libraries += $(ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES)
+    ifeq (,$(filter $(LOCAL_MODULE),$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_RUNTIME_LIBRARY)))
+      my_shared_libraries := $($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+                             $(my_shared_libraries)
+    endif
+    ifeq (,$(filter $(LOCAL_MODULE),$(ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES)))
+      my_static_libraries += $(ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES)
+    endif
 
-    my_linker := $($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER)
-    # Make sure linker_asan get installed.
-    $(LOCAL_INSTALLED_MODULE) : | $(PRODUCT_OUT)$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER)
+    # Do not add unnecessary dependency in shared libraries.
+    ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
+      my_ldflags += -Wl,--as-needed
+    endif
+
+    ifeq ($(LOCAL_MODULE_CLASS),EXECUTABLES)
+      ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
+        my_linker := $($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER)
+        # Make sure linker_asan get installed.
+        $(LOCAL_INSTALLED_MODULE) : | $(PRODUCT_OUT)$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_LINKER)
+      endif
+    endif
+  endif
+endif
+
+# If local module needs ASAN, add compiler flags.
+ifneq ($(filter address,$(my_sanitize)),)
+  # Frame pointer based unwinder in ASan requires ARM frame setup.
+  LOCAL_ARM_MODE := arm
+  my_cflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS)
+  ifndef LOCAL_IS_HOST_MODULE
+    my_cflags += -mllvm -asan-globals=0
   endif
 endif
 
@@ -134,3 +192,13 @@
   recover_arg := $(subst $(space),$(comma),$(LOCAL_SANITIZE_RECOVER)),
   my_cflags += -fsanitize-recover=$(recover_arg)
 endif
+
+ifneq ($(strip $(LOCAL_SANITIZE_DIAG)),)
+  notrap_arg := $(subst $(space),$(comma),$(LOCAL_SANITIZE_DIAG)),
+  my_cflags += -fno-sanitize-trap=$(notrap_arg)
+  # Diagnostic requires a runtime library, unless ASan or TSan are also enabled.
+  ifeq ($(filter address thread,$(my_sanitize)),)
+    # Does not have to be the first DT_NEEDED unlike ASan.
+    my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_RUNTIME_LIBRARY)
+  endif
+endif
diff --git a/core/configure_local_jack.mk b/core/configure_local_jack.mk
index 2270c88..446bab7 100644
--- a/core/configure_local_jack.mk
+++ b/core/configure_local_jack.mk
@@ -21,16 +21,9 @@
 LOCAL_JACK_ENABLED := $(strip $(LOCAL_JACK_ENABLED))
 LOCAL_MODULE := $(strip $(LOCAL_MODULE))
 
-ifneq ($(LOCAL_JACK_ENABLED),full)
-ifneq ($(LOCAL_JACK_ENABLED),incremental)
-ifdef LOCAL_JACK_ENABLED
-ifneq ($(LOCAL_JACK_ENABLED),disabled)
+ifeq ($(filter full incremental,$(LOCAL_JACK_ENABLED)),)
 $(error $(LOCAL_PATH): invalid LOCAL_JACK_ENABLED "$(LOCAL_JACK_ENABLED)" for $(LOCAL_MODULE))
 endif
-endif
-LOCAL_JACK_ENABLED :=
-endif
-endif
 
 ifdef $(LOCAL_MODULE).JACK_VERSION
 LOCAL_JACK_VERSION := $($(LOCAL_MODULE).JACK_VERSION)
diff --git a/core/copy_headers.mk b/core/copy_headers.mk
index 7d5a5d9..417a76c 100644
--- a/core/copy_headers.mk
+++ b/core/copy_headers.mk
@@ -1,6 +1,7 @@
 ###########################################################
 ## Copy headers to the install tree
 ###########################################################
+$(call record-module-type,COPY_HEADERS)
 ifneq ($(strip $(LOCAL_IS_HOST_MODULE)),)
   my_prefix := HOST_
 else
diff --git a/core/cxx_stl_setup.mk b/core/cxx_stl_setup.mk
index 37be1f7..fd9c442 100644
--- a/core/cxx_stl_setup.mk
+++ b/core/cxx_stl_setup.mk
@@ -70,6 +70,7 @@
     endif
 endif
 
+my_cxx_ldlibs :=
 ifneq ($(filter $(my_cxx_stl),libc++ libc++_static),)
     my_cflags += -D_USING_LIBCXX
 
@@ -89,7 +90,7 @@
         my_cppflags += -nostdinc++
         my_ldflags += -nodefaultlibs
         my_ldlibs += -lpthread -lm
-        my_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
+        my_cxx_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
     else
         ifeq (arm,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
             my_static_libraries += libunwind_llvm
@@ -105,18 +106,16 @@
 else ifeq ($(my_cxx_stl),ndk)
     # Using an NDK STL. Handled in binary.mk.
 else ifeq ($(my_cxx_stl),libstdc++)
-    # Using bionic's basic libstdc++. Not actually an STL. Only around until the
-    # tree is in good enough shape to not need it.
     ifndef LOCAL_IS_HOST_MODULE
-        my_c_includes += bionic/libstdc++/include
-        my_system_shared_libraries += libstdc++
+        $(error $(LOCAL_PATH): $(LOCAL_MODULE): libstdc++ is not supported for device modules)
+    else ifneq ($($(my_prefix)OS),windows)
+        $(error $(LOCAL_PATH): $(LOCAL_MODULE): libstdc++ is not supported on $($(my_prefix)OS))
     endif
-    # Host builds will use GNU libstdc++.
 else ifeq ($(my_cxx_stl),none)
     ifdef LOCAL_IS_HOST_MODULE
         my_cppflags += -nostdinc++
         my_ldflags += -nodefaultlibs
-        my_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
+        my_cxx_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
     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 b9ef4d5..83f7efc 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -55,10 +55,6 @@
 # its sub-variables.)
 ALL_MODULE_NAME_TAGS:=
 
-# Full paths to all prebuilt files that will be copied
-# (used to make the dependency on acp)
-ALL_PREBUILT:=
-
 # Full path to all files that are made by some tool
 ALL_GENERATED_SOURCES:=
 
@@ -96,9 +92,13 @@
 
 # Display names for various build targets
 TARGET_DISPLAY := target
+AUX_DISPLAY := aux
 HOST_DISPLAY := host
 HOST_CROSS_DISPLAY := host cross
 
+# All installed initrc files
+ALL_INIT_RC_INSTALLED_PAIRS :=
+
 ###########################################################
 ## Debugging; prints a variable list to stdout
 ###########################################################
@@ -123,6 +123,15 @@
 $(filter true, $(1))
 endef
 
+###########################################################
+## Rule for touching GCNO files.
+###########################################################
+define gcno-touch-rule
+$(2): $(1)
+	touch -c $$@
+endef
+
+###########################################################
 
 ###########################################################
 ## Retrieve the directory of the current makefile
@@ -133,7 +142,6 @@
 define my-dir
 $(strip \
   $(eval LOCAL_MODULE_MAKEFILE := $$(lastword $$(MAKEFILE_LIST))) \
-  $(eval LOCAL_MODULE_MAKEFILE_DEP := $(if $(BUILDING_WITH_NINJA),,$$(LOCAL_MODULE_MAKEFILE))) \
   $(if $(filter $(BUILD_SYSTEM)/% $(OUT_DIR)/%,$(LOCAL_MODULE_MAKEFILE)), \
     $(error my-dir must be called before including any other makefile.) \
    , \
@@ -142,28 +150,13 @@
  )
 endef
 
-###########################################################
-## Remove any makefiles that are being handled by soong
-###########################################################
-ifeq ($(USE_SOONG),true)
-define filter-soong-makefiles
-$(foreach mk,$(1),\
-  $(if $(wildcard $(patsubst %/Android.mk,%/Android.bp,$(mk))),\
-    $(info skipping $(mk) ...),\
-    $(mk)))
-endef
-else
-define filter-soong-makefiles
-$(1)
-endef
-endif
 
 ###########################################################
 ## Retrieve a list of all makefiles immediately below some directory
 ###########################################################
 
 define all-makefiles-under
-$(sort $(call filter-soong-makefiles,$(wildcard $(1)/*/Android.mk)))
+$(wildcard $(1)/*/Android.mk)
 endef
 
 ###########################################################
@@ -174,9 +167,8 @@
 # $(1): directory to search under
 # Ignores $(1)/Android.mk
 define first-makefiles-under
-$(call filter-soong-makefiles,\
-  $(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) \
-        --mindepth=2 $(1) Android.mk))
+$(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) \
+        --mindepth=2 $(addprefix --dir=,$(1)) Android.mk)
 endef
 
 ###########################################################
@@ -196,8 +188,7 @@
 
 # $(1): List of directories to look for under this directory
 define all-named-subdir-makefiles
-$(sort $(call filter-soong-makefiles,\
-  $(wildcard $(addsuffix /Android.mk, $(addprefix $(call my-dir)/,$(1))))))
+$(wildcard $(addsuffix /Android.mk, $(addprefix $(call my-dir)/,$(1))))
 endef
 
 ###########################################################
@@ -425,7 +416,7 @@
 
 define find-subdir-assets
 $(sort $(if $(1),$(patsubst ./%,%, \
-	$(shell if [ -d $(1) ] ; then cd $(1) ; find -L ./ -not -name '.*' -and -type f -and -not -type l ; fi)), \
+	$(shell if [ -d $(1) ] ; then cd $(1) ; find -L ./ -not -name '.*' -and -type f ; fi)), \
 	$(warning Empty argument supplied to find-subdir-assets) \
 ))
 endef
@@ -493,6 +484,28 @@
 $(if $(1),$(call reverse-list,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
 endef
 
+define def-host-aux-target
+$(eval _idf_val_:=$(if $(strip $(LOCAL_IS_HOST_MODULE)),HOST,$(if $(strip $(LOCAL_IS_AUX_MODULE)),AUX,))) \
+$(_idf_val_)
+endef
+
+###########################################################
+## Returns correct _idfPrefix from the list:
+##   { HOST, HOST_CROSS, AUX, TARGET }
+###########################################################
+# the following rules checked in order:
+# ($1 is in {AUX, HOST_CROSS} => $1;
+# ($1 is empty) => TARGET;
+# ($2 is not empty) => HOST_CROSS;
+# => HOST;
+define find-idf-prefix
+$(strip \
+    $(eval _idf_pfx_:=$(strip $(filter AUX HOST_CROSS,$(1)))) \
+    $(eval _idf_pfx_:=$(if $(strip $(1)),$(if $(_idf_pfx_),$(_idf_pfx_),$(if $(strip $(2)),HOST_CROSS,HOST)),TARGET)) \
+    $(_idf_pfx_)
+)
+endef
+
 ###########################################################
 ## The intermediates directory.  Where object files go for
 ## a given target.  We could technically get away without
@@ -503,7 +516,7 @@
 
 # $(1): target class, like "APPS"
 # $(2): target name, like "NotePad"
-# $(3): if non-empty, this is a HOST target.
+# $(3): { HOST, HOST_CROSS, AUX, <empty (TARGET)>, <other non-empty (HOST)> }
 # $(4): if non-empty, force the intermediates to be COMMON
 # $(5): if non-empty, force the intermediates to be for the 2nd arch
 # $(6): if non-empty, force the intermediates to be for the host cross os
@@ -515,7 +528,7 @@
     $(eval _idfName := $(strip $(2))) \
     $(if $(_idfName),, \
         $(error $(LOCAL_PATH): Name not defined in call to intermediates-dir-for)) \
-    $(eval _idfPrefix := $(if $(strip $(3)),$(if $(strip $(6)),HOST_CROSS,HOST),TARGET)) \
+    $(eval _idfPrefix := $(call find-idf-prefix,$(3),$(6))) \
     $(eval _idf2ndArchPrefix := $(if $(strip $(5)),$(TARGET_2ND_ARCH_VAR_PREFIX))) \
     $(if $(filter $(_idfPrefix)-$(_idfClass),$(COMMON_MODULE_CLASSES))$(4), \
         $(eval _idfIntBase := $($(_idfPrefix)_OUT_COMMON_INTERMEDIATES)) \
@@ -540,7 +553,7 @@
         $(error $(LOCAL_PATH): LOCAL_MODULE_CLASS not defined before call to local-intermediates-dir)) \
     $(if $(strip $(LOCAL_MODULE)),, \
         $(error $(LOCAL_PATH): LOCAL_MODULE not defined before call to local-intermediates-dir)) \
-    $(call intermediates-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(LOCAL_IS_HOST_MODULE),$(1),$(2),$(3)) \
+    $(call intermediates-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(call def-host-aux-target),$(1),$(2),$(3)) \
 )
 endef
 
@@ -555,7 +568,7 @@
 
 # $(1): target class, like "APPS"
 # $(2): target name, like "NotePad"
-# $(3): if non-empty, this is a HOST target.
+# $(3): { HOST, HOST_CROSS, AUX, <empty (TARGET)>, <other non-empty (HOST)> }
 # $(4): if non-empty, force the generated sources to be COMMON
 define generated-sources-dir-for
 $(strip \
@@ -565,7 +578,7 @@
     $(eval _idfName := $(strip $(2))) \
     $(if $(_idfName),, \
         $(error $(LOCAL_PATH): Name not defined in call to generated-sources-dir-for)) \
-    $(eval _idfPrefix := $(if $(strip $(3)),HOST,TARGET)) \
+    $(eval _idfPrefix := $(call find-idf-prefix,$(3),)) \
     $(if $(filter $(_idfPrefix)-$(_idfClass),$(COMMON_MODULE_CLASSES))$(4), \
         $(eval _idfIntBase := $($(_idfPrefix)_OUT_COMMON_GEN)) \
       , \
@@ -585,30 +598,11 @@
         $(error $(LOCAL_PATH): LOCAL_MODULE_CLASS not defined before call to local-generated-sources-dir)) \
     $(if $(strip $(LOCAL_MODULE)),, \
         $(error $(LOCAL_PATH): LOCAL_MODULE not defined before call to local-generated-sources-dir)) \
-    $(call generated-sources-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(LOCAL_IS_HOST_MODULE),$(1)) \
+    $(call generated-sources-dir-for,$(LOCAL_MODULE_CLASS),$(LOCAL_MODULE),$(call def-host-aux-target),$(1)) \
 )
 endef
 
 ###########################################################
-## Convert "path/to/libXXX.so" to "-lXXX".
-## Any "path/to/libXXX.a" elements pass through unchanged.
-###########################################################
-
-define normalize-libraries
-$(foreach so,$(filter %.so,$(1)),-l$(patsubst lib%.so,%,$(notdir $(so))))\
-$(filter-out %.so,$(1))
-endef
-
-# TODO: change users to call the common version.
-define normalize-host-libraries
-$(call normalize-libraries,$(1))
-endef
-
-define normalize-target-libraries
-$(call normalize-libraries,$(1))
-endef
-
-###########################################################
 ## Convert a list of short module names (e.g., "framework", "Browser")
 ## into the list of files that are built for those modules.
 ## NOTE: this won't return reliable results until after all
@@ -723,12 +717,6 @@
 $(foreach lib,$(1),$(call _jack-lib-full-classes,$(lib),$(2)))
 endef
 
-# $(1): library name list
-# $(2): Non-empty if IS_HOST_MODULE
-define jack-lib-deps
-$(call jack-lib-files,$(1),$(2))
-endef
-
 ###########################################################
 ## Run rot13 on a string
 ## $(1): the string.  Must be one line.
@@ -761,6 +749,13 @@
 endef
 
 ###########################################################
+## Convert "a b c" into "a,b,c"
+###########################################################
+define normalize-comma-list
+$(subst $(space),$(comma),$(strip $(1)))
+endef
+
+###########################################################
 ## Read the word out of a colon-separated list of words.
 ## This has the same behavior as the built-in function
 ## $(word n,str).
@@ -850,6 +845,20 @@
 
 
 ###########################################################
+## Color-coded warnings and errors in build rules
+##
+## $(1): message to print
+###########################################################
+define echo-warning
+echo -e "\e[1;35mwarning:\e[0m \e[1m" $(1) "\e[0m\n"
+endef
+
+define echo-error
+echo -e "\e[1;31merror:\e[0m \e[1m" $(1) "\e[0m\n"
+endef
+
+
+###########################################################
 ## Package filtering
 ###########################################################
 
@@ -918,15 +927,9 @@
 ###########################################################
 # $(1): the .P file
 # $(2): the main build target
-ifeq ($(BUILDING_WITH_NINJA),true)
 define include-depfile
 $(eval $(2) : .KATI_DEPFILE := $1)
 endef
-else
-define include-depfile
-$(eval -include $1)
-endef
-endif
 
 # $(1): object files
 define include-depfiles-for-objs
@@ -1091,6 +1094,19 @@
     $< $(PRIVATE_HEADER_OUTPUT_DIR) $@
 endef
 
+## Given a .aidl file path, generate the rule to compile it a .java file
+# $(1): a .aidl source file
+# $(2): a directory to place the generated .java files in
+# $(3): name of a variable to add the path to the generated source file to
+#
+# You must call this with $(eval).
+define define-aidl-java-rule
+define-aidl-java-rule-src := $(patsubst %.aidl,%.java,$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define-aidl-java-rule-src) : $(LOCAL_PATH)/$(1) $(AIDL)
+	$$(transform-aidl-to-java)
+$(3) += $$(define-aidl-java-rule-src)
+endef
+
 ## Given a .aidl file path generate the rule to compile it a .cpp file.
 # $(1): a .aidl source file
 # $(2): a directory to place the generated .cpp files in
@@ -1136,7 +1152,7 @@
 define transform-logtags-to-java
 @mkdir -p $(dir $@)
 @echo "logtags: $@ <= $<"
-$(hide) $(JAVATAGS) -o $@ $^
+$(hide) $(JAVATAGS) -o $@ $< $(PRIVATE_MERGED_TAG)
 endef
 
 
@@ -1169,6 +1185,9 @@
 	$(addprefix --proto_path=, $(PRIVATE_PROTO_INCLUDES)) \
 	$(PRIVATE_PROTOC_FLAGS) \
 	$<
+@# aprotoc outputs only .cc. Rename it to .cpp if necessary.
+$(if $(PRIVATE_RENAME_CPP_EXT),\
+  $(hide) mv $(basename $@).cc $@)
 endef
 
 
@@ -1196,22 +1215,27 @@
 	$(filter %.dbus-xml,$^)
 endef
 
+###########################################################
+## Helper to set include paths form transform-*-to-o
+###########################################################
+define c-includes
+$(addprefix -I , $(PRIVATE_C_INCLUDES)) \
+$$(cat $(PRIVATE_IMPORT_INCLUDES))\
+$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),,\
+    $(addprefix -I ,\
+        $(filter-out $(PRIVATE_C_INCLUDES), \
+            $(PRIVATE_GLOBAL_C_INCLUDES))) \
+    $(addprefix -isystem ,\
+        $(filter-out $(PRIVATE_C_INCLUDES), \
+            $(PRIVATE_GLOBAL_C_SYSTEM_INCLUDES))))
+endef
 
 ###########################################################
 ## Commands for running gcc to compile a C++ file
 ###########################################################
 
-define transform-cpp-to-o
-@echo "target $(PRIVATE_ARM_MODE) C++: $(PRIVATE_MODULE) <= $<"
-@mkdir -p $(dir $@)
-$(hide) $(RELATIVE_PWD) $(PRIVATE_CXX) \
-	$(addprefix -I , $(PRIVATE_C_INCLUDES)) \
-	$(shell cat $(PRIVATE_IMPORT_INCLUDES)) \
-	$(addprefix -isystem ,\
-	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
-	        $(filter-out $(PRIVATE_C_INCLUDES), \
-	            $(PRIVATE_TARGET_PROJECT_INCLUDES) \
-	            $(PRIVATE_TARGET_C_INCLUDES)))) \
+define transform-cpp-to-o-compiler-args
+	$(c-includes) \
 	-c \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 	    $(PRIVATE_TARGET_GLOBAL_CFLAGS) \
@@ -1223,54 +1247,88 @@
 	$(PRIVATE_CPPFLAGS) \
 	$(PRIVATE_DEBUG_CFLAGS) \
 	$(PRIVATE_CFLAGS_NO_OVERRIDE) \
-	$(PRIVATE_CPPFLAGS_NO_OVERRIDE) \
-	-MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
-$(transform-d-to-p)
+	$(PRIVATE_CPPFLAGS_NO_OVERRIDE)
 endef
 
+define clang-tidy-cpp
+$(hide) $(PATH_TO_CLANG_TIDY) $(PRIVATE_TIDY_FLAGS) \
+  -checks=$(PRIVATE_TIDY_CHECKS) \
+  $< -- $(transform-cpp-to-o-compiler-args)
+endef
+
+ifneq (,$(filter 1 true,$(WITH_TIDY_ONLY)))
+define transform-cpp-to-o
+$(if $(PRIVATE_TIDY_CHECKS),
+  @echo "$($(PRIVATE_PREFIX)DISPLAY) tidy $(PRIVATE_ARM_MODE) C++: $<"
+  $(clang-tidy-cpp))
+endef
+else
+define transform-cpp-to-o
+@echo "$($(PRIVATE_PREFIX)DISPLAY) $(PRIVATE_ARM_MODE) C++: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
+$(if $(PRIVATE_TIDY_CHECKS),$(clang-tidy-cpp))
+$(hide) $(RELATIVE_PWD) $(PRIVATE_CXX) \
+  $(transform-cpp-to-o-compiler-args) \
+  -MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
+$(hide) $(transform-d-to-p)
+endef
+endif
+
 
 ###########################################################
 ## Commands for running gcc to compile a C file
 ###########################################################
 
 # $(1): extra flags
-define transform-c-or-s-to-o-no-deps
-@mkdir -p $(dir $@)
-$(hide) $(RELATIVE_PWD) $(PRIVATE_CC) \
-	$(addprefix -I , $(PRIVATE_C_INCLUDES)) \
-	$(shell cat $(PRIVATE_IMPORT_INCLUDES)) \
-	$(addprefix -isystem ,\
-	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
-	        $(filter-out $(PRIVATE_C_INCLUDES), \
-	            $(PRIVATE_TARGET_PROJECT_INCLUDES) \
-	            $(PRIVATE_TARGET_C_INCLUDES)))) \
+define transform-c-or-s-to-o-compiler-args
+	$(c-includes) \
 	-c \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 	    $(PRIVATE_TARGET_GLOBAL_CFLAGS) \
 	    $(PRIVATE_TARGET_GLOBAL_CONLYFLAGS) \
 	    $(PRIVATE_ARM_CFLAGS) \
 	 ) \
-	 $(1) \
-	-MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
+	 $(1)
 endef
 
-define transform-c-to-o-no-deps
-@echo "target $(PRIVATE_ARM_MODE) C: $(PRIVATE_MODULE) <= $<"
-$(call transform-c-or-s-to-o-no-deps, \
-    $(PRIVATE_CFLAGS) \
-    $(PRIVATE_CONLYFLAGS) \
-    $(PRIVATE_DEBUG_CFLAGS) \
-    $(PRIVATE_CFLAGS_NO_OVERRIDE))
+define transform-c-to-o-compiler-args
+$(call transform-c-or-s-to-o-compiler-args, \
+  $(PRIVATE_CFLAGS) \
+  $(PRIVATE_CONLYFLAGS) \
+  $(PRIVATE_DEBUG_CFLAGS) \
+  $(PRIVATE_CFLAGS_NO_OVERRIDE))
 endef
 
+define clang-tidy-c
+$(hide) $(PATH_TO_CLANG_TIDY) $(PRIVATE_TIDY_FLAGS) \
+  -checks=$(PRIVATE_TIDY_CHECKS) \
+  $< -- $(transform-c-to-o-compiler-args)
+endef
+
+ifneq (,$(filter 1 true,$(WITH_TIDY_ONLY)))
+define transform-c-to-o
+$(if $(PRIVATE_TIDY_CHECKS),
+  @echo "$($(PRIVATE_PREFIX)DISPLAY) tidy $(PRIVATE_ARM_MODE) C: $<"
+  $(clang-tidy-c))
+endef
+else
+define transform-c-to-o
+@echo "$($(PRIVATE_PREFIX)DISPLAY) $(PRIVATE_ARM_MODE) C: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
+$(if $(PRIVATE_TIDY_CHECKS),$(clang-tidy-c))
+$(hide) $(RELATIVE_PWD) $(PRIVATE_CC) \
+  $(transform-c-to-o-compiler-args) \
+  -MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
+$(hide) $(transform-d-to-p)
+endef
+endif
+
 define transform-s-to-o-no-deps
-@echo "target asm: $(PRIVATE_MODULE) <= $<"
-$(call transform-c-or-s-to-o-no-deps, $(PRIVATE_ASFLAGS))
-endef
-
-define transform-c-to-o
-$(transform-c-to-o-no-deps)
-$(transform-d-to-p)
+@echo "$($(PRIVATE_PREFIX)DISPLAY) asm: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
+$(RELATIVE_PWD) $(PRIVATE_CC) \
+  $(call transform-c-or-s-to-o-compiler-args, $(PRIVATE_ASFLAGS)) \
+  -MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
 endef
 
 define transform-s-to-o
@@ -1295,7 +1353,7 @@
 ###########################################################
 
 define transform-m-to-o-no-deps
-@echo "target ObjC: $(PRIVATE_MODULE) <= $<"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) ObjC: $(PRIVATE_MODULE) <= $<"
 $(call transform-c-or-s-to-o-no-deps, $(PRIVATE_CFLAGS) $(PRIVATE_DEBUG_CFLAGS))
 endef
 
@@ -1308,17 +1366,8 @@
 ## Commands for running gcc to compile a host C++ file
 ###########################################################
 
-define transform-host-cpp-to-o
-@echo "$($(PRIVATE_PREFIX)DISPLAY) C++: $(PRIVATE_MODULE) <= $<"
-@mkdir -p $(dir $@)
-$(hide) $(RELATIVE_PWD) $(PRIVATE_CXX) \
-	$(addprefix -I , $(PRIVATE_C_INCLUDES)) \
-	$(shell cat $(PRIVATE_IMPORT_INCLUDES)) \
-	$(addprefix -isystem ,\
-	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
-	        $(filter-out $(PRIVATE_C_INCLUDES), \
-	            $($(PRIVATE_PREFIX)PROJECT_INCLUDES) \
-	            $(PRIVATE_HOST_C_INCLUDES)))) \
+define transform-host-cpp-to-o-compiler-args
+	$(c-includes) \
 	-c \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 	    $(PRIVATE_HOST_GLOBAL_CFLAGS) \
@@ -1328,52 +1377,91 @@
 	$(PRIVATE_CPPFLAGS) \
 	$(PRIVATE_DEBUG_CFLAGS) \
 	$(PRIVATE_CFLAGS_NO_OVERRIDE) \
-	$(PRIVATE_CPPFLAGS_NO_OVERRIDE) \
-	-MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
-$(transform-d-to-p)
+	$(PRIVATE_CPPFLAGS_NO_OVERRIDE)
 endef
 
+define clang-tidy-host-cpp
+$(hide) $(PATH_TO_CLANG_TIDY) $(PRIVATE_TIDY_FLAGS) \
+  -checks=$(PRIVATE_TIDY_CHECKS) \
+  $< -- $(transform-host-cpp-to-o-compiler-args)
+endef
+
+ifneq (,$(filter 1 true,$(WITH_TIDY_ONLY)))
+define transform-host-cpp-to-o
+$(if $(PRIVATE_TIDY_CHECKS),
+  @echo "tidy $($(PRIVATE_PREFIX)DISPLAY) C++: $<"
+  $(clang-tidy-host-cpp))
+endef
+else
+define transform-host-cpp-to-o
+@echo "$($(PRIVATE_PREFIX)DISPLAY) C++: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
+$(if $(PRIVATE_TIDY_CHECKS),$(clang-tidy-host-cpp))
+$(hide) $(RELATIVE_PWD) $(PRIVATE_CXX) \
+  $(transform-host-cpp-to-o-compiler-args) \
+  -MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
+$(hide) $(transform-d-to-p)
+endef
+endif
+
 
 ###########################################################
 ## Commands for running gcc to compile a host C file
 ###########################################################
 
-# $(1): extra flags
-define transform-host-c-or-s-to-o-no-deps
-@mkdir -p $(dir $@)
-$(hide) $(RELATIVE_PWD) $(PRIVATE_CC) \
-	$(addprefix -I , $(PRIVATE_C_INCLUDES)) \
-	$(shell cat $(PRIVATE_IMPORT_INCLUDES)) \
-	$(addprefix -isystem ,\
-	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
-	        $(filter-out $(PRIVATE_C_INCLUDES), \
-	            $($(PRIVATE_PREFIX)PROJECT_INCLUDES) \
-	            $(PRIVATE_HOST_C_INCLUDES)))) \
+define transform-host-c-or-s-to-o-common-args
+	$(c-includes) \
 	-c \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 	    $(PRIVATE_HOST_GLOBAL_CFLAGS) \
 	    $(PRIVATE_HOST_GLOBAL_CONLYFLAGS) \
-	 ) \
-	$(1) \
-	$(PRIVATE_CFLAGS_NO_OVERRIDE) \
-	-MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
+	 )
 endef
 
-define transform-host-c-to-o-no-deps
-@echo "$($(PRIVATE_PREFIX)DISPLAY) C: $(PRIVATE_MODULE) <= $<"
-$(call transform-host-c-or-s-to-o-no-deps, $(PRIVATE_CFLAGS) $(PRIVATE_CONLYFLAGS) $(PRIVATE_DEBUG_CFLAGS))
+# $(1): extra flags
+define transform-host-c-or-s-to-o-no-deps
+@mkdir -p $(dir $@)
+$(hide) $(RELATIVE_PWD) $(PRIVATE_CC) \
+  $(transform-host-c-or-s-to-o-common-args) \
+  $(1) \
+  -MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
 endef
 
+define transform-host-c-to-o-compiler-args
+  $(transform-host-c-or-s-to-o-common-args) \
+  $(PRIVATE_CFLAGS) $(PRIVATE_CONLYFLAGS) \
+  $(PRIVATE_DEBUG_CFLAGS) $(PRIVATE_CFLAGS_NO_OVERRIDE)
+endef
+
+define clang-tidy-host-c
+$(hide) $(PATH_TO_CLANG_TIDY) $(PRIVATE_TIDY_FLAGS) \
+  -checks=$(PRIVATE_TIDY_CHECKS) \
+  $< -- $(transform-host-c-to-o-compiler-args)
+endef
+
+ifneq (,$(filter 1 true,$(WITH_TIDY_ONLY)))
+define transform-host-c-to-o
+$(if $(PRIVATE_TIDY_CHECKS),
+  @echo "tidy $($(PRIVATE_PREFIX)DISPLAY) C: $<"
+  $(clang-tidy-host-c))
+endef
+else
+define transform-host-c-to-o
+@echo "$($(PRIVATE_PREFIX)DISPLAY) C: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
+$(if $(PRIVATE_TIDY_CHECKS), $(clang-tidy-host-c))
+$(hide) $(RELATIVE_PWD) $(PRIVATE_CC) \
+  $(transform-host-c-to-o-compiler-args) \
+  -MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
+$(hide) $(transform-d-to-p)
+endef
+endif
+
 define transform-host-s-to-o-no-deps
 @echo "$($(PRIVATE_PREFIX)DISPLAY) asm: $(PRIVATE_MODULE) <= $<"
 $(call transform-host-c-or-s-to-o-no-deps, $(PRIVATE_ASFLAGS))
 endef
 
-define transform-host-c-to-o
-$(transform-host-c-to-o-no-deps)
-$(transform-d-to-p)
-endef
-
 define transform-host-s-to-o
 $(transform-host-s-to-o-no-deps)
 $(transform-d-to-p)
@@ -1385,7 +1473,7 @@
 
 define transform-host-m-to-o-no-deps
 @echo "$($(PRIVATE_PREFIX)DISPLAY) ObjC: $(PRIVATE_MODULE) <= $<"
-$(call transform-host-c-or-s-to-o-no-deps, $(PRIVATE_CFLAGS) $(PRIVATE_DEBUG_CFLAGS))
+$(call transform-host-c-or-s-to-o-no-deps, $(PRIVATE_CFLAGS) $(PRIVATE_DEBUG_CFLAGS) $(PRIVATE_CFLAGS_NO_OVERRIDE))
 endef
 
 define transform-host-m-to-o
@@ -1524,7 +1612,7 @@
 # Explicitly delete the archive first so that ar doesn't
 # try to add to an existing archive.
 define transform-o-to-static-lib
-@echo "target StaticLib: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) StaticLib: $(PRIVATE_MODULE) ($@)"
 @mkdir -p $(dir $@)
 @rm -f $@
 $(extract-and-include-target-whole-static-libs)
@@ -1533,6 +1621,89 @@
     $(PRIVATE_ARFLAGS) $@,$(PRIVATE_ALL_OBJECTS))
 endef
 
+# $(1): the full path of the source static library.
+define _extract-and-include-single-aux-whole-static-lib
+$(hide) ldir=$(PRIVATE_INTERMEDIATES_DIR)/WHOLE/$(basename $(notdir $(1)))_objs;\
+    rm -rf $$ldir; \
+    mkdir -p $$ldir; \
+    cp $(1) $$ldir; \
+    lib_to_include=$$ldir/$(notdir $(1)); \
+    filelist=; \
+    subdir=0; \
+    for f in `$(PRIVATE_AR) t $(1)`; do \
+        if [ -e $$ldir/$$f ]; then \
+            mkdir $$ldir/$$subdir; \
+            ext=$$subdir/; \
+            subdir=$$((subdir+1)); \
+            $(PRIVATE_AR) m $$lib_to_include $$f; \
+        else \
+            ext=; \
+        fi; \
+        $(PRIVATE_AR) p $$lib_to_include $$f > $$ldir/$$ext$$f; \
+        filelist="$$filelist $$ldir/$$ext$$f"; \
+    done ; \
+    $(PRIVATE_AR) $(AUX_GLOBAL_ARFLAGS) \
+        $(PRIVATE_ARFLAGS) $@ $$filelist
+
+endef
+
+define extract-and-include-aux-whole-static-libs
+$(call extract-and-include-whole-static-libs-first, $(firstword $(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)))
+$(foreach lib,$(wordlist 2,999,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)), \
+    $(call _extract-and-include-single-aux-whole-static-lib, $(lib)))
+endef
+
+# Explicitly delete the archive first so that ar doesn't
+# try to add to an existing archive.
+define transform-o-to-aux-static-lib
+@echo "$($(PRIVATE_PREFIX)DISPLAY) StaticLib: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
+@rm -f $@
+$(extract-and-include-aux-whole-static-libs)
+$(call split-long-arguments,$(PRIVATE_AR) \
+    $(AUX_GLOBAL_ARFLAGS) \
+    $(PRIVATE_ARFLAGS) $@,$(PRIVATE_ALL_OBJECTS))
+endef
+
+define transform-o-to-aux-executable-inner
+$(hide) $(PRIVATE_CXX) -pie \
+	-Bdynamic \
+	-Wl,--gc-sections \
+	$(PRIVATE_ALL_OBJECTS) \
+	-Wl,--whole-archive \
+	$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
+	-Wl,--no-whole-archive \
+	$(PRIVATE_ALL_STATIC_LIBRARIES) \
+	$(PRIVATE_LDFLAGS) \
+	-o $@
+endef
+
+define transform-o-to-aux-executable
+@echo "$(AUX_DISPLAY) Executable: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
+$(transform-o-to-aux-executable-inner)
+endef
+
+define transform-o-to-aux-static-executable-inner
+$(hide) $(PRIVATE_CXX) \
+	-Bstatic \
+	-Wl,--gc-sections \
+	$(PRIVATE_ALL_OBJECTS) \
+	-Wl,--whole-archive \
+	$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
+	-Wl,--no-whole-archive \
+	$(PRIVATE_ALL_STATIC_LIBRARIES) \
+	$(PRIVATE_LDFLAGS) \
+	-Wl,-Map=$(@).map \
+	-o $@
+endef
+
+define transform-o-to-aux-static-executable
+@echo "$(AUX_DISPLAY) StaticExecutable: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
+$(transform-o-to-aux-static-executable-inner)
+endef
+
 ###########################################################
 ## Commands for running host ar
 ###########################################################
@@ -1569,6 +1740,23 @@
     $(call _extract-and-include-single-host-whole-static-lib, $(lib)))
 endef
 
+ifeq ($(HOST_OS),darwin)
+# On Darwin the host ar fails if there is nothing to add to .a at all.
+# We work around by adding a dummy.o and then deleting it.
+define create-dummy.o-if-no-objs
+$(if $(PRIVATE_ALL_OBJECTS),,$(hide) touch $(dir $@)dummy.o)
+endef
+
+define get-dummy.o-if-no-objs
+$(if $(PRIVATE_ALL_OBJECTS),,$(dir $@)dummy.o)
+endef
+
+define delete-dummy.o-if-no-objs
+$(if $(PRIVATE_ALL_OBJECTS),,$(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)AR) d $@ $(dir $@)dummy.o \
+  && rm -f $(dir $@)dummy.o)
+endef
+endif  # HOST_OS is darwin
+
 # Explicitly delete the archive first so that ar doesn't
 # try to add to an existing archive.
 define transform-host-o-to-static-lib
@@ -1576,9 +1764,11 @@
 @mkdir -p $(dir $@)
 @rm -f $@
 $(extract-and-include-host-whole-static-libs)
+$(create-dummy.o-if-no-objs)
 $(call split-long-arguments,$($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)AR) \
     $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)GLOBAL_ARFLAGS) \
-    $(PRIVATE_ARFLAGS) $@,$(PRIVATE_ALL_OBJECTS))
+    $(PRIVATE_ARFLAGS) $@,$(PRIVATE_ALL_OBJECTS) $(get-dummy.o-if-no-objs))
+$(delete-dummy.o-if-no-objs)
 endef
 
 
@@ -1595,21 +1785,20 @@
 	-Wl,-rpath,\$$ORIGIN/../$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OUT_SHARED_LIBRARIES)) \
 	-Wl,-rpath,\$$ORIGIN/$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OUT_SHARED_LIBRARIES)) \
 	-shared -Wl,-soname,$(notdir $@) \
-	$($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)GLOBAL_LD_DIRS) \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 	   $(PRIVATE_HOST_GLOBAL_LDFLAGS) \
 	) \
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
-	$(call normalize-host-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
 	-Wl,--no-whole-archive \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
-	$(call normalize-host-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_STATIC_LIBRARIES) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),-lgcov) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_HOST_LIBPROFILE_RT)) \
-	$(call normalize-host-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+	$(PRIVATE_ALL_SHARED_LIBRARIES) \
 	-o $@ \
 	$(PRIVATE_LDLIBS)
 endef
@@ -1641,24 +1830,24 @@
 	$(PRIVATE_TARGET_CRTBEGIN_SO_O) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
 	-Wl,--no-whole-archive \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_STATIC_LIBRARIES) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_COVERAGE_LIB)) \
 	$(PRIVATE_TARGET_LIBATOMIC) \
 	$(PRIVATE_TARGET_LIBGCC) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
+	$(PRIVATE_ALL_SHARED_LIBRARIES) \
+	-o $@ \
 	$(PRIVATE_TARGET_CRTEND_SO_O) \
 	$(PRIVATE_LDLIBS)
 endef
 
 define transform-o-to-shared-lib
-@echo "target SharedLib: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) SharedLib: $(PRIVATE_MODULE) ($@)"
 @mkdir -p $(dir $@)
 $(transform-o-to-shared-lib-inner)
 endef
@@ -1673,14 +1862,31 @@
 endif
 
 define transform-to-stripped
-@echo "target Strip: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Strip: $(PRIVATE_MODULE) ($@)"
 @mkdir -p $(dir $@)
 $(hide) $(PRIVATE_STRIP) --strip-all $< -o $@ \
   $(if $(PRIVATE_NO_DEBUGLINK),,$(TARGET_STRIP_EXTRA))
 endef
 
+define transform-to-stripped-keep-mini-debug-info
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Strip (mini debug info): $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
+$(hide) $(PRIVATE_NM) -D $< --format=posix --defined-only | awk '{ print $$1 }' | sort >$@.dynsyms
+$(hide) $(PRIVATE_NM) $< --format=posix --defined-only | awk '{ if ($$2 == "T" || $$2 == "t" || $$2 == "D") print $$1 }' | sort >$@.funcsyms
+$(hide) comm -13 $@.dynsyms $@.funcsyms >$@.keep_symbols
+$(hide) $(PRIVATE_OBJCOPY) --only-keep-debug $< $@.debug
+$(hide) $(PRIVATE_OBJCOPY) --rename-section .debug_frame=saved_debug_frame $@.debug $@.mini_debuginfo
+$(hide) $(PRIVATE_OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$@.keep_symbols $@.mini_debuginfo
+$(hide) $(PRIVATE_OBJCOPY) --rename-section saved_debug_frame=.debug_frame $@.mini_debuginfo
+$(hide) $(PRIVATE_STRIP) --strip-all -R .comment $< -o $@
+$(hide) rm -f $@.mini_debuginfo.xz
+$(hide) xz $@.mini_debuginfo
+$(hide) $(PRIVATE_OBJCOPY) --add-section .gnu_debugdata=$@.mini_debuginfo.xz $@
+$(hide) rm -f $@.dynsyms $@.funcsyms $@.keep_symbols $@.debug $@.mini_debuginfo.xz
+endef
+
 define transform-to-stripped-keep-symbols
-@echo "target Strip (keep symbols): $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Strip (keep symbols): $(PRIVATE_MODULE) ($@)"
 @mkdir -p $(dir $@)
 $(hide) $(PRIVATE_OBJCOPY) \
     `$(PRIVATE_READELF) -S $< | awk '/.debug_/ {print "-R " $$2}' | xargs` \
@@ -1692,7 +1898,7 @@
 ###########################################################
 
 define pack-elf-relocations
-@echo "target Pack Relocations: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Pack Relocations: $(PRIVATE_MODULE) ($@)"
 $(copy-file-to-target)
 $(hide) $(RELOCATION_PACKER) $@
 endef
@@ -1712,24 +1918,24 @@
 	$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
 	-Wl,--no-whole-archive \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_STATIC_LIBRARIES) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_COVERAGE_LIB)) \
 	$(PRIVATE_TARGET_LIBATOMIC) \
 	$(PRIVATE_TARGET_LIBGCC) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
+	$(PRIVATE_ALL_SHARED_LIBRARIES) \
+	-o $@ \
 	$(PRIVATE_TARGET_CRTEND_O) \
 	$(PRIVATE_LDLIBS)
 endef
 
 define transform-o-to-executable
-@echo "target Executable: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Executable: $(PRIVATE_MODULE) ($@)"
 @mkdir -p $(dir $@)
 $(transform-o-to-executable-inner)
 endef
@@ -1757,22 +1963,22 @@
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
 	-Wl,--no-whole-archive \
-	$(call normalize-target-libraries,$(filter-out %libcompiler_rt.a,$(filter-out %libc_nomalloc.a,$(filter-out %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))))) \
+	$(filter-out %libcompiler_rt.a,$(filter-out %libc_nomalloc.a,$(filter-out %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES)))) \
 	-Wl,--start-group \
-	$(call normalize-target-libraries,$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \
-	$(call normalize-target-libraries,$(filter %libc_nomalloc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \
+	$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+	$(filter %libc_nomalloc.a,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_COVERAGE_LIB)) \
 	$(PRIVATE_TARGET_LIBATOMIC) \
-	$(call normalize-target-libraries,$(filter %libcompiler_rt.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \
+	$(filter %libcompiler_rt.a,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(PRIVATE_TARGET_LIBGCC) \
 	-Wl,--end-group \
 	$(PRIVATE_TARGET_CRTEND_O)
 endef
 
 define transform-o-to-static-executable
-@echo "target StaticExecutable: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) StaticExecutable: $(PRIVATE_MODULE) ($@)"
 @mkdir -p $(dir $@)
 $(transform-o-to-static-executable-inner)
 endef
@@ -1796,18 +2002,17 @@
 $(hide) $(PRIVATE_CXX) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
-	$(call normalize-host-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES) \
 	-Wl,--no-whole-archive \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
-	$(call normalize-host-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+	$(PRIVATE_ALL_STATIC_LIBRARIES) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),-lgcov) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_HOST_LIBPROFILE_RT)) \
-	$(call normalize-host-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+	$(PRIVATE_ALL_SHARED_LIBRARIES) \
 	-Wl,-rpath-link=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OUT_INTERMEDIATE_LIBRARIES) \
-	-Wl,-rpath,\$$ORIGIN/../$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OUT_SHARED_LIBRARIES)) \
-	-Wl,-rpath,\$$ORIGIN/$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)OUT_SHARED_LIBRARIES)) \
-	$($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)GLOBAL_LD_DIRS) \
+	$(foreach path,$(PRIVATE_RPATHS), \
+	  -Wl,-rpath,\$$ORIGIN/$(path)) \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 		$(PRIVATE_HOST_GLOBAL_LDFLAGS) \
 	) \
@@ -2068,7 +2273,6 @@
 $(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) rm -rf \
     $(foreach pkg, $(PRIVATE_JAR_EXCLUDE_PACKAGES), \
         $(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))))
-$(if $(PRIVATE_RMTYPEDEFS), $(hide) $(RMTYPEDEFS) -v $(PRIVATE_CLASS_INTERMEDIATES_DIR))
 $(if $(PRIVATE_JAR_MANIFEST), \
     $(hide) sed -e "s/%BUILD_NUMBER%/$(BUILD_NUMBER_FROM_FILE)/" \
             $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \
@@ -2079,7 +2283,7 @@
 endef
 
 define transform-java-to-classes.jar
-@echo "target Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
 $(call compile-java,$(TARGET_JAVAC),$(PRIVATE_BOOTCLASSPATH))
 endef
 
@@ -2126,8 +2330,11 @@
     $(if $(PRIVATE_RMTYPEDEFS), \
         -D jack.android.remove-typedef="true") \
     $(addprefix --classpath ,$(strip \
-        $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES) $(PRIVATE_ALL_JACK_LIBRARIES)))) \
+        $(call normalize-path-list,$(PRIVATE_JACK_SHARED_LIBRARIES)))) \
     $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
+    $(addprefix --pluginpath ,$(strip \
+         $(call normalize-path-list,$(PRIVATE_JACK_PLUGIN_PATH)))) \
+    $(if $(PRIVATE_JACK_PLUGIN),--plugin $(call normalize-comma-list,$(PRIVATE_JACK_PLUGIN))) \
     $(if $(PRIVATE_EXTRA_JAR_ARGS),--import-resource $@.res.tmp) \
     -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
     -D jack.import.resource.policy=keep-first \
@@ -2167,11 +2374,10 @@
 $(hide) tr ' ' '\n' < $@.java-source-list \
     | sort -u > $@.java-source-list-uniq
 $(hide) if [ -s $@.java-source-list-uniq ] ; then \
-	$(call call-jack,$(PRIVATE_JACK_EXTRA_ARGS)) \
+	$(call call-jack) \
 	    $(strip $(PRIVATE_JACK_FLAGS)) \
-	    $(strip $(PRIVATE_JACK_DEBUG_FLAGS)) \
 	    $(addprefix --classpath ,$(strip \
-	        $(call normalize-path-list,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES)) $(PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES) $(PRIVATE_ALL_JACK_LIBRARIES)))) \
+	        $(call normalize-path-list,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES)) $(PRIVATE_JACK_SHARED_LIBRARIES)))) \
 	    -D jack.import.resource.policy=keep-first \
 	    -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
 	    -D jack.import.type.policy=keep-first \
@@ -2188,6 +2394,9 @@
 	$(hide) find $@.tmpjill.res -iname "*.class" -delete
 	$(hide) $(call call-jack) \
 	    $(PRIVATE_JACK_FLAGS) \
+	    $(addprefix --pluginpath ,$(strip \
+                $(call normalize-path-list,$(PRIVATE_JACK_PLUGIN_PATH)))) \
+	    $(if $(PRIVATE_JACK_PLUGIN),--plugin $(call normalize-comma-list,$(PRIVATE_JACK_PLUGIN))) \
         -D jack.import.resource.policy=keep-first \
         -D jack.import.type.policy=keep-first \
         -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
@@ -2200,9 +2409,7 @@
 # Moves $1.tmp to $1 if necessary. This is designed to be used with
 # .KATI_RESTAT. For kati, this function doesn't update the timestamp
 # of $1 when $1.tmp is identical to $1 so that ninja won't rebuild
-# targets which depend on $1. For GNU make, this function simply
-# copies $1.tmp to $1.
-ifeq ($(BUILDING_WITH_NINJA),true)
+# targets which depend on $1.
 define commit-change-for-toc
 $(hide) if cmp -s $1.tmp $1 ; then \
  rm $1.tmp ; \
@@ -2210,12 +2417,6 @@
  mv $1.tmp $1 ; \
 fi
 endef
-else
-define commit-change-for-toc
-@# make doesn't support restat. We always update .toc files so the dependents will always be updated too.
-$(hide) mv $1.tmp $1
-endef
-endif
 
 ## Rule to create a table of contents from a .jar file.
 ## Must be called with $(eval).
@@ -2243,7 +2444,7 @@
 $1/classes.dex.toc: PRIVATE_INPUT_DEX_FILES := $1/classes*.dex
 $1/classes.dex.toc: $1/classes.dex $(DEXDUMP)
 	@echo Generating TOC: $$@
-	$(hide) $(DEXDUMP) -l xml $$(PRIVATE_INPUT_DEX_FILES) > $$@.tmp
+	$(hide) ANDROID_LOG_TAGS="*:e" $(DEXDUMP) -l xml $$(PRIVATE_INPUT_DEX_FILES) > $$@.tmp
 	$$(call commit-change-for-toc,$$@)
 endef
 
@@ -2301,8 +2502,11 @@
     $(if $(NO_OPTIMIZE_DX), \
         -D jack.dex.optimize="false") \
     $(addprefix --classpath ,$(strip \
-        $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES) $(PRIVATE_ALL_JACK_LIBRARIES)))) \
+        $(call normalize-path-list,$(PRIVATE_JACK_SHARED_LIBRARIES)))) \
     $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
+    $(addprefix --pluginpath ,$(strip \
+        $(call normalize-path-list,$(PRIVATE_JACK_PLUGIN_PATH)))) \
+    $(if $(PRIVATE_JACK_PLUGIN),--plugin $(call normalize-comma-list,$(PRIVATE_JACK_PLUGIN))) \
     $(if $(PRIVATE_EXTRA_JAR_ARGS),--import-resource $@.res.tmp) \
     -D jack.import.resource.policy=keep-first \
     -D jack.import.type.policy=keep-first \
@@ -2346,17 +2550,6 @@
 $(call create-empty-package-at,$@)
 endef
 
-# Copy an arhchive file and delete any class files and empty folders inside.
-# $(1): the source archive file.
-# $(2): the destination archive file.
-define initialize-package-file
-@mkdir -p $(dir $(2))
-$(hide) cp -f $(1) $(2)
-$(hide) zip -qd $(2) "*.class" \
-    $(if $(strip $(PRIVATE_DONT_DELETE_JAR_DIRS)),,"*/") \
-    || true # Ignore the error when nothing to delete.
-endef
-
 #TODO: we kinda want to build different asset packages for
 #      different configurations, then combine them later (or something).
 #      Per-locale, etc.
@@ -2492,11 +2685,9 @@
 
 # Remove dynamic timestamps from packages
 #
-ifndef TARGET_BUILD_APPS
 define remove-timestamps-from-package
 $(hide) $(ZIPTIME) $@
 endef
-endif
 
 # Uncompress shared libraries embedded in an apk.
 #
@@ -2510,19 +2701,6 @@
   fi
 endef
 
-define install-dex-debug
-$(hide) if [ -f "$(PRIVATE_INTERMEDIATES_DIR)/classes.dex" ]; then \
-	    mkdir -p $(TOP)/dalvik/DEBUG-FILES; \
-	    $(ACP) $(PRIVATE_INTERMEDIATES_DIR)/classes.dex \
-		$(TOP)/dalvik/DEBUG-FILES/$(PRIVATE_MODULE).dex; \
-	fi
-$(hide) if [ -f "$(PRIVATE_INTERMEDIATES_DIR)/classes.lst" ]; then \
-	    mkdir -p $(TOP)/dalvik/DEBUG-FILES; \
-	    $(ACP) $(PRIVATE_INTERMEDIATES_DIR)/classes.lst \
-		$(TOP)/dalvik/DEBUG-FILES/$(PRIVATE_MODULE).lst; \
-	fi
-endef
-
 # TODO(joeo): If we can ever upgrade to post 3.81 make and get the
 # new prebuilt rules to work, we should change this to copy the
 # resources to the out directory and then copy the resources.
@@ -2551,7 +2729,7 @@
 # $(1): source file
 # $(2): destination file
 define copy-one-file
-$(2): $(1) | $(ACP)
+$(2): $(1)
 	@echo "Copy: $$@"
 	$$(copy-file-to-target)
 endef
@@ -2572,7 +2750,7 @@
 # $(1): source file
 # $(2): destination file, must end with .xml.
 define copy-xml-file-checked
-$(2): $(1) | $(ACP)
+$(2): $(1)
 	@echo "Copy xml: $$@"
 	$(hide) xmllint $$< >/dev/null  # Don't print the xml file to stdout.
 	$$(copy-file-to-target)
@@ -2587,24 +2765,29 @@
 # Copy a single file from one place to another,
 # preserving permissions and overwriting any existing
 # file.
-# We disable the "-t" option for acp cannot handle
-# high resolution timestamp correctly on file systems like ext4.
-# Therefore copy-file-to-target is the same as copy-file-to-new-target.
+# When we used acp, it could not handle high resolution timestamps
+# on file systems like ext4. Because of that, '-t' option was disabled
+# and copy-file-to-target was identical to copy-file-to-new-target.
+# Keep the behavior until we audit and ensure that switching this back
+# won't break anything.
 define copy-file-to-target
 @mkdir -p $(dir $@)
-$(hide) $(ACP) -fp $< $@
+$(hide) rm -f $@
+$(hide) cp $< $@
 endef
 
 # The same as copy-file-to-target, but use the local
 # cp command instead of acp.
 define copy-file-to-target-with-cp
 @mkdir -p $(dir $@)
-$(hide) cp -fp $< $@
+$(hide) rm -f $@
+$(hide) cp -p $< $@
 endef
 
 # The same as copy-file-to-target, but use the zipalign tool to do so.
 define copy-file-to-target-with-zipalign
 @mkdir -p $(dir $@)
+$(hide) rm -f $@
 $(hide) $(ZIPALIGN) -f 4 $< $@
 endef
 
@@ -2612,6 +2795,7 @@
 # comments (for config files and such).
 define copy-file-to-target-strip-comments
 @mkdir -p $(dir $@)
+$(hide) rm -f $@
 $(hide) sed -e 's/#.*$$//' -e 's/[ \t]*$$//' -e '/^$$/d' < $< > $@
 endef
 
@@ -2619,31 +2803,33 @@
 # the old modification time.
 define copy-file-to-new-target
 @mkdir -p $(dir $@)
-$(hide) $(ACP) -fp $< $@
+$(hide) rm -f $@
+$(hide) cp $< $@
 endef
 
 # The same as copy-file-to-new-target, but use the local
 # cp command instead of acp.
 define copy-file-to-new-target-with-cp
 @mkdir -p $(dir $@)
-$(hide) cp -f $< $@
+$(hide) rm -f $@
+$(hide) cp $< $@
 endef
 
 # Copy a prebuilt file to a target location.
 define transform-prebuilt-to-target
-@echo "$(if $(PRIVATE_IS_HOST_MODULE),host,target) Prebuilt: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Prebuilt: $(PRIVATE_MODULE) ($@)"
 $(copy-file-to-target)
 endef
 
 # Copy a prebuilt file to a target location, using zipalign on it.
 define transform-prebuilt-to-target-with-zipalign
-@echo "$(if $(PRIVATE_IS_HOST_MODULE),host,target) Prebuilt APK: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Prebuilt APK: $(PRIVATE_MODULE) ($@)"
 $(copy-file-to-target-with-zipalign)
 endef
 
 # Copy a prebuilt file to a target location, stripping "# comment" comments.
 define transform-prebuilt-to-target-strip-comments
-@echo "$(if $(PRIVATE_IS_HOST_MODULE),host,target) Prebuilt: $(PRIVATE_MODULE) ($@)"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Prebuilt: $(PRIVATE_MODULE) ($@)"
 $(copy-file-to-target-strip-comments)
 endef
 
@@ -2658,6 +2844,23 @@
   $(hide) mkdir -p $(dir $(3)/$(s)); cp -Rf $(t) $(3)/$(s)$(newline))
 endef
 
+# Define a rule to create a symlink to a file.
+# $(1): full path to source
+# $(2): source (may be relative)
+# $(3): full path to destination
+define symlink-file
+$(eval $(_symlink-file))
+endef
+
+# Order-only dependency because make/ninja will follow the link when checking
+# the timestamp, so the file must exist
+define _symlink-file
+$(3): | $(1)
+	@echo "Symlink: $$@ -> $(2)"
+	@mkdir -p $(dir $$@)
+	@rm -rf $$@
+	$(hide) ln -sf $(2) $$@
+endef
 
 ###########################################################
 ## Commands to call Proguard
@@ -2673,7 +2876,7 @@
 ###########################################################
 
 define transform-generated-source
-@echo "target Generated: $(PRIVATE_MODULE) <= $<"
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Generated: $(PRIVATE_MODULE) <= $<"
 @mkdir -p $(dir $@)
 $(hide) $(PRIVATE_CUSTOM_TOOL)
 endef
@@ -2755,7 +2958,7 @@
 endef
 define add-radio-file-internal
 INSTALLED_RADIOIMAGE_TARGET += $$(PRODUCT_OUT)/$(2)
-$$(PRODUCT_OUT)/$(2) : $$(LOCAL_PATH)/$(1) | $$(ACP)
+$$(PRODUCT_OUT)/$(2) : $$(LOCAL_PATH)/$(1)
 	$$(transform-prebuilt-to-target)
 endef
 
@@ -2770,7 +2973,7 @@
 define add-radio-file-checked-internal
 INSTALLED_RADIOIMAGE_TARGET += $$(PRODUCT_OUT)/$(2)
 BOARD_INFO_CHECK += $(3):$(LOCAL_PATH)/$(1)
-$$(PRODUCT_OUT)/$(2) : $$(LOCAL_PATH)/$(1) | $$(ACP)
+$$(PRODUCT_OUT)/$(2) : $$(LOCAL_PATH)/$(1)
 	$$(transform-prebuilt-to-target)
 endef
 
@@ -2886,6 +3089,86 @@
   $(if $(filter $(TARGET_2ND_ARCH),$(1)),$(TARGET_2ND_ARCH),$(if $(1),none))))
 endef
 
+# ###############################################################
+# Set up statistics gathering
+# ###############################################################
+STATS.MODULE_TYPE := \
+  HOST_STATIC_LIBRARY \
+  HOST_SHARED_LIBRARY \
+  STATIC_LIBRARY \
+  SHARED_LIBRARY \
+  EXECUTABLE \
+  HOST_EXECUTABLE \
+  PACKAGE \
+  PHONY_PACKAGE \
+  HOST_PREBUILT \
+  PREBUILT \
+  MULTI_PREBUILT \
+  JAVA_LIBRARY \
+  STATIC_JAVA_LIBRARY \
+  HOST_JAVA_LIBRARY \
+  DROIDDOC \
+  COPY_HEADERS \
+  NATIVE_TEST \
+  NATIVE_BENCHMARK \
+  HOST_NATIVE_TEST \
+  FUZZ_TEST \
+  HOST_FUZZ_TEST \
+  STATIC_TEST_LIBRARY \
+  HOST_STATIC_TEST_LIBRARY \
+  NOTICE_FILE \
+  HOST_DALVIK_JAVA_LIBRARY \
+  HOST_DALVIK_STATIC_JAVA_LIBRARY \
+  base_rules
+
+$(foreach $(s),$(STATS.MODULE_TYPE),$(eval STATS.MODULE_TYPE.$(s) :=))
+define record-module-type
+$(strip $(if $(LOCAL_RECORDED_MODULE_TYPE),,
+  $(if $(filter-out $(SOONG_ANDROID_MK),$(LOCAL_MODULE_MAKEFILE)),
+    $(if $(filter $(1),$(STATS.MODULE_TYPE)),
+      $(eval LOCAL_RECORDED_MODULE_TYPE := true)
+        $(eval STATS.MODULE_TYPE.$(1) += 1),
+      $(error Invalid module type: $(1))))))
+endef
+
+###########################################################
+# Link type checking
+###########################################################
+define check-link-type
+$(hide) mkdir -p $(dir $@) && rm -f $@
+$(hide) $(CHECK_LINK_TYPE) --makefile $(PRIVATE_MAKEFILE) --module $(PRIVATE_MODULE) \
+  --type "$(PRIVATE_LINK_TYPE)" $(addprefix --allowed ,$(PRIVATE_ALLOWED_TYPES)) \
+  $(addprefix --warn ,$(PRIVATE_WARN_TYPES)) $(PRIVATE_DEPS)
+$(hide) echo "$(PRIVATE_LINK_TYPE)" >$@
+endef
+
+define link-type-partitions
+ifndef LOCAL_IS_HOST_MODULE
+ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
+ifneq ($(filter $(TARGET_OUT_VENDOR)/%,$(my_module_path)),)
+$(1): PRIVATE_LINK_TYPE += partition:vendor
+$(1): PRIVATE_WARN_TYPES += partition:data
+$(1): PRIVATE_ALLOWED_TYPES += partition:vendor partition:oem partition:odm
+else ifneq ($(filter $(TARGET_OUT_OEM)/%,$(my_module_path)),)
+$(1): PRIVATE_LINK_TYPE += partition:oem
+$(1): PRIVATE_WARN_TYPES += partition:data
+$(1): PRIVATE_ALLOWED_TYPES += partition:vendor partition:oem partition:odm
+else ifneq ($(filter $(TARGET_OUT_ODM)/%,$(my_module_path)),)
+$(1): PRIVATE_LINK_TYPE += partition:odm
+$(1): PRIVATE_WARN_TYPES += partition:data
+$(1): PRIVATE_ALLOWED_TYPES += partition:vendor partition:oem partition:odm
+else ifneq ($(filter $(TARGET_OUT_DATA)/%,$(my_module_path)),)
+$(1): PRIVATE_LINK_TYPE += partition:data
+$(1): PRIVATE_ALLOWED_TYPES += partition:data partition:vendor partition:oem partition:odm
+else
+$(1): PRIVATE_WARN_TYPES += partition:vendor partition:oem partition:odm partition:data
+endif
+else # uninstallable module
+$(1): PRIVATE_ALLOWED_TYPES += partition:vendor partition:oem partition:odm partition:data
+endif
+endif
+endef
+
 ###########################################################
 ## Other includes
 ###########################################################
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index d182dc0..fa8bb19 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -57,7 +57,7 @@
 _dbj_jar_no_dex := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(1)_nodex.jar
 _dbj_src_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,$(1),,COMMON)/javalib.jar
 
-$$(_dbj_jar_no_dex) : $$(_dbj_src_jar) | $(ACP)
+$$(_dbj_jar_no_dex) : $$(_dbj_src_jar)
 	$$(call copy-file-to-target)
 ifneq ($(DEX_PREOPT_DEFAULT),nostripping)
 	$$(call dexpreopt-remove-classes.dex,$$@)
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 9410c3c..5a2f07f 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -75,17 +75,19 @@
 # is converted into to boot.art (to match the legacy assumption that boot.art
 # exists), and the rest are converted to boot-<name>.art.
 # In addition, each .art file has an associated .oat file.
-LIBART_TARGET_BOOT_ART_EXTRA_FILES := $(foreach jar,$(wordlist 2,999,$(LIBART_TARGET_BOOT_JARS)),boot-$(jar).art boot-$(jar).oat)
-LIBART_TARGET_BOOT_ART_EXTRA_FILES += boot.oat
+LIBART_TARGET_BOOT_ART_EXTRA_FILES := $(foreach jar,$(wordlist 2,999,$(LIBART_TARGET_BOOT_JARS)),boot-$(jar).art boot-$(jar).oat boot-$(jar).vdex)
+LIBART_TARGET_BOOT_ART_EXTRA_FILES += boot.oat boot.vdex
 
 my_2nd_arch_prefix :=
 include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
 
+ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
 ifdef TARGET_2ND_ARCH
 my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
 include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
 my_2nd_arch_prefix :=
 endif
+endif
 
 
 ########################################################################
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 4e486d5..0966bd5 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -41,8 +41,11 @@
 endif
 
 built_odex :=
+built_vdex :=
 installed_odex :=
+installed_vdex :=
 built_installed_odex :=
+built_installed_vdex :=
 ifdef LOCAL_DEX_PREOPT
 dexpreopt_boot_jar_module := $(filter $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE))
 ifdef dexpreopt_boot_jar_module
@@ -68,10 +71,12 @@
 # #################################################
 # Odex for the 2nd arch
 ifdef TARGET_2ND_ARCH
+ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
 ifneq (first,$(my_module_multilib))
 my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
 include $(BUILD_SYSTEM)/setup_one_odex.mk
 endif  # my_module_multilib is not first.
+endif  # TARGET_TRANSLATE_2ND_ARCH not true
 endif  # TARGET_2ND_ARCH
 # #################################################
 else  # must be APPS
@@ -89,7 +94,9 @@
 endif  # boot jar
 
 built_odex := $(strip $(built_odex))
+built_vdex := $(strip $(built_vdex))
 installed_odex := $(strip $(installed_odex))
+installed_vdex := $(strip $(installed_vdex))
 
 ifdef built_odex
 ifndef LOCAL_DEX_PREOPT_FLAGS
@@ -101,18 +108,25 @@
 
 $(built_odex): PRIVATE_DEX_PREOPT_FLAGS := $(LOCAL_DEX_PREOPT_FLAGS)
 
+$(built_vdex): $(built_odex)
+
 # Use pattern rule - we may have multiple installed odex files.
 # Ugly syntax - See the definition get-odex-file-path.
 $(installed_odex) : $(dir $(LOCAL_INSTALLED_MODULE))%$(notdir $(word 1,$(installed_odex))) \
-                  : $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_odex))) \
-    | $(ACP)
+                  : $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_odex)))
+	@echo "Install: $@"
+	$(copy-file-to-target)
+$(installed_vdex) : $(dir $(LOCAL_INSTALLED_MODULE))%$(notdir $(word 1,$(installed_vdex))) \
+                  : $(dir $(LOCAL_BUILT_MODULE))%$(notdir $(word 1,$(built_vdex)))
 	@echo "Install: $@"
 	$(copy-file-to-target)
 endif
 
 # Add the installed_odex to the list of installed files for this module.
 ALL_MODULES.$(my_register_name).INSTALLED += $(installed_odex)
+ALL_MODULES.$(my_register_name).INSTALLED += $(installed_vdex)
 ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_odex)
+ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_vdex)
 
 # Record dex-preopt config.
 DEXPREOPT.$(LOCAL_MODULE).DEX_PREOPT := $(LOCAL_DEX_PREOPT)
@@ -127,7 +141,7 @@
   $(DEXPREOPT.MODULES.$(LOCAL_MODULE_CLASS)) $(LOCAL_MODULE))
 
 
-# Make sure to install the .odex when you run "make <module_name>"
-$(my_register_name): $(installed_odex)
+# Make sure to install the .odex and .vdex when you run "make <module_name>"
+$(my_all_targets): $(installed_odex) $(installed_vdex)
 
 endif # LOCAL_DEX_PREOPT
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
index 6bae25d..bcc5c18 100644
--- a/core/dpi_specific_apk.mk
+++ b/core/dpi_specific_apk.mk
@@ -5,6 +5,7 @@
 dpi_apk_name := $(LOCAL_MODULE)_$(my_dpi)
 dpi_intermediate := $(call intermediates-dir-for,APPS,$(dpi_apk_name))
 built_dpi_apk := $(dpi_intermediate)/package.apk
+additional_certificates := $(foreach c,$(LOCAL_ADDITIONAL_CERTIFICATES), $(c).x509.pem $(c).pk8)
 
 # Set up all the target-specific variables.
 $(built_dpi_apk): PRIVATE_MODULE := $(dpi_apk_name)
@@ -27,18 +28,12 @@
 $(built_dpi_apk): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abis)
 $(built_dpi_apk): PRIVATE_PRIVATE_KEY := $(private_key)
 $(built_dpi_apk): PRIVATE_CERTIFICATE := $(certificate)
-$(built_dpi_apk): PRIVATE_ADDITIONAL_CERTIFICATES := $(foreach c,\
-    $(LOCAL_ADDITIONAL_CERTIFICATES), $(c).x509.pem $(c).pk8)
+$(built_dpi_apk): $(additional_certificates)
+$(built_dpi_apk): PRIVATE_ADDITIONAL_CERTIFICATES := $(additional_certificates)
 
-$(built_dpi_apk): PRIVATE_SOURCE_ARCHIVE :=
 ifneq ($(full_classes_jar),)
-$(built_dpi_apk): PRIVATE_DEX_FILE := $(built_dex)
-ifndef LOCAL_JACK_ENABLED
-# Use the jarjar processed arhive as the initial package file.
-$(built_dpi_apk): PRIVATE_SOURCE_ARCHIVE := $(full_classes_jarjar_jar)
-else
 $(built_dpi_apk): PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
-endif # LOCAL_JACK_ENABLED
+$(built_dpi_apk): PRIVATE_DEX_FILE := $(built_dex)
 $(built_dpi_apk): $(built_dex)
 else
 $(built_dpi_apk): PRIVATE_DEX_FILE :=
@@ -51,9 +46,7 @@
 $(built_dpi_apk) : $(AAPT)
 $(built_dpi_apk) : $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)
 	@echo "target Package: $(PRIVATE_MODULE) ($@)"
-	$(if $(PRIVATE_SOURCE_ARCHIVE),\
-	  $(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@),\
-	  $(create-empty-package))
+	$(create-empty-package)
 	$(add-assets-to-package)
 ifneq ($(jni_shared_libraries),)
 	$(add-jni-shared-libs-to-package)
@@ -63,10 +56,8 @@
 	$(if $(PRIVATE_EXTRA_JAR_ARGS),$(call add-java-resources-to,$@))
 else
 	$(add-dex-to-package)
-ifdef LOCAL_JACK_ENABLED
 	$(add-carried-jack-resources)
 endif
-endif
 	$(sign-package)
 
 # Set up global variables to register this apk to the higher-level dependency graph.
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index f143579..a70ab03 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -14,6 +14,7 @@
 # limitations under the License.
 #
 
+$(call record-module-type,DROIDDOC)
 ##
 ##
 ## Common to both droiddoc and javadoc
@@ -165,7 +166,6 @@
         $(droiddoc) \
         $(html_dir_files) \
         $(full_java_lib_deps) \
-        $(LOCAL_MODULE_MAKEFILE_DEP) \
         $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	@echo Docs droiddoc: $(PRIVATE_OUT_DIR)
 	$(hide) mkdir -p $(dir $@)
diff --git a/core/dumpvar.mk b/core/dumpvar.mk
index 1bd4777..74ea3ff 100644
--- a/core/dumpvar.mk
+++ b/core/dumpvar.mk
@@ -22,7 +22,8 @@
   HOST_CROSS_2ND_ARCH \
   HOST_BUILD_TYPE \
   BUILD_ID \
-  OUT_DIR
+  OUT_DIR \
+  AUX_OS_VARIANT_LIST
 
 ifeq ($(TARGET_BUILD_PDK),true)
 print_build_config_vars += \
@@ -35,10 +36,15 @@
 # what to add to the path given the config we have chosen.
 ifeq ($(CALLED_FROM_SETUP),true)
 
-ifneq ($(filter /%,$(HOST_OUT_EXECUTABLES)),)
-ABP:=$(HOST_OUT_EXECUTABLES)
+ifneq ($(filter /%,$(SOONG_HOST_OUT_EXECUTABLES)),)
+ABP := $(SOONG_HOST_OUT_EXECUTABLES)
 else
-ABP:=$(PWD)/$(HOST_OUT_EXECUTABLES)
+ABP := $(PWD)/$(SOONG_HOST_OUT_EXECUTABLES)
+endif
+ifneq ($(filter /%,$(HOST_OUT_EXECUTABLES)),)
+ABP := $(ABP):$(HOST_OUT_EXECUTABLES)
+else
+ABP := $(ABP):$(PWD)/$(HOST_OUT_EXECUTABLES)
 endif
 
 ANDROID_BUILD_PATHS := $(ABP)
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index 91fd271..579338e 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -58,7 +58,7 @@
 # Do not pack relocations for executables. Because packing results in
 # non-zero p_vaddr which causes kernel to load executables to lower
 # address (starting at 0x8000) http://b/20665974
-ifeq ($(LOCAL_MODULE_CLASS),EXECUTABLES)
+ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
   my_pack_module_relocations := false
 endif
 
@@ -69,10 +69,10 @@
 
 ifeq (true,$(my_pack_module_relocations))
 # Pack relocations
-$(relocation_packer_output): $(relocation_packer_input) | $(ACP)
+$(relocation_packer_output): $(relocation_packer_input)
 	$(pack-elf-relocations)
 else
-$(relocation_packer_output): $(relocation_packer_input) | $(ACP)
+$(relocation_packer_output): $(relocation_packer_input)
 	@echo "target Unpacked: $(PRIVATE_MODULE) ($@)"
 	$(copy-file-to-target)
 endif
@@ -87,7 +87,7 @@
 endif
 symbolic_input := $(relocation_packer_output)
 symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
-$(symbolic_output) : $(symbolic_input) | $(ACP)
+$(symbolic_output) : $(symbolic_input)
 	@echo "target Symbolic: $(PRIVATE_MODULE) ($@)"
 	$(copy-file-to-target)
 
@@ -116,11 +116,21 @@
   $(LOCAL_STRIP_MODULE_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) \
   $(LOCAL_STRIP_MODULE))
 ifeq ($(my_strip_module),)
+  my_strip_module := mini-debug-info
+endif
+
+ifeq ($(my_strip_module),mini-debug-info)
+# Don't use mini-debug-info on mips (both 32-bit and 64-bit). objcopy checks that all
+# SH_MIPS_DWARF sections having name prefix .debug_ or .zdebug_, so there seems no easy
+# way using objcopy to remove all debug sections except .debug_frame on mips.
+ifneq ($(filter mips mips64,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
   my_strip_module := true
 endif
+endif
 
 $(strip_output): PRIVATE_STRIP := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_STRIP)
 $(strip_output): PRIVATE_OBJCOPY := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJCOPY)
+$(strip_output): PRIVATE_NM := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_NM)
 $(strip_output): PRIVATE_READELF := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_READELF)
 ifeq ($(my_strip_module),no_debuglink)
 $(strip_output): PRIVATE_NO_DEBUGLINK := true
@@ -128,7 +138,11 @@
 $(strip_output): PRIVATE_NO_DEBUGLINK :=
 endif
 
-ifneq ($(filter true no_debuglink,$(my_strip_module)),)
+ifeq ($(my_strip_module),mini-debug-info)
+# Strip the binary, but keep debug frames and symbol table in a compressed .gnu_debugdata section.
+$(strip_output): $(strip_input) | $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_STRIP) $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJCOPY) $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_NM)
+	$(transform-to-stripped-keep-mini-debug-info)
+else ifneq ($(filter true no_debuglink,$(my_strip_module)),)
 # Strip the binary
 $(strip_output): $(strip_input) | $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_STRIP)
 	$(transform-to-stripped)
@@ -148,18 +162,9 @@
 else
 # Don't strip the binary, just copy it.  We can't skip this step
 # because a copy of the binary must appear at LOCAL_BUILT_MODULE.
-#
-# If the binary we're copying is acp or a prerequisite,
-# use cp(1) instead.
-ifneq ($(LOCAL_ACP_UNAVAILABLE),true)
-$(strip_output): $(strip_input) | $(ACP)
-	@echo "target Unstripped: $(PRIVATE_MODULE) ($@)"
-	$(copy-file-to-target)
-else
 $(strip_output): $(strip_input)
 	@echo "target Unstripped: $(PRIVATE_MODULE) ($@)"
-	$(copy-file-to-target-with-cp)
-endif
+	$(copy-file-to-target)
 endif # my_strip_module
 
 $(cleantarget): PRIVATE_CLEAN_FILES += \
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 0a72603..8794c8a 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -20,7 +20,7 @@
 # people who haven't re-run those will have to do so before they
 # can build.  Make sure to also update the corresponding value in
 # buildspec.mk.default and envsetup.sh.
-CORRECT_BUILD_ENV_SEQUENCE_NUMBER := 10
+CORRECT_BUILD_ENV_SEQUENCE_NUMBER := 12
 
 # ---------------------------------------------------------------
 # The product defaults to generic on hardware
@@ -65,6 +65,7 @@
 HOST_CROSS_OS := windows
 HOST_CROSS_ARCH := x86
 HOST_CROSS_2ND_ARCH := x86_64
+2ND_HOST_CROSS_IS_64_BIT := true
 endif
 
 ifeq ($(HOST_OS),)
@@ -77,7 +78,7 @@
   HOST_2ND_ARCH := x86
   HOST_IS_64_BIT := true
 else
-ifneq (,$(findstring x86,$(UNAME)))
+ifneq (,$(findstring i686,$(UNAME))$(findstring x86,$(UNAME)))
 $(error Building on a 32-bit x86 host is not supported: $(UNAME)!)
 endif
 endif
@@ -172,6 +173,19 @@
 $(error TARGET_COPY_OUT_VENDOR must be either 'vendor' or 'system/vendor', seeing '$(TARGET_COPY_OUT_VENDOR)'.)
 endif
 PRODUCT_COPY_FILES := $(subst $(_vendor_path_placeholder),$(TARGET_COPY_OUT_VENDOR),$(PRODUCT_COPY_FILES))
+
+BOARD_USES_VENDORIMAGE :=
+ifdef BOARD_PREBUILT_VENDORIMAGE
+BOARD_USES_VENDORIMAGE := true
+endif
+ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+BOARD_USES_VENDORIMAGE := true
+endif
+ifeq ($(TARGET_COPY_OUT_VENDOR),vendor)
+BOARD_USES_VENDORIMAGE := true
+else ifdef BOARD_USES_VENDORIMAGE
+$(error TARGET_COPY_OUT_VENDOR must be set to 'vendor' to use a vendor image)
+endif
 ###########################################
 
 
@@ -203,6 +217,8 @@
 endif
 endif
 
+SOONG_OUT_DIR := $(OUT_DIR)/soong
+
 DEBUG_OUT_DIR := $(OUT_DIR)/debug
 
 # Move the host or target under the debug/ directory
@@ -219,6 +235,7 @@
 HOST_OUT_release := $(HOST_OUT_ROOT_release)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
 HOST_OUT_debug := $(HOST_OUT_ROOT_debug)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
 HOST_OUT := $(HOST_OUT_$(HOST_BUILD_TYPE))
+SOONG_HOST_OUT := $(SOONG_OUT_DIR)/host/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
 # TODO: remove
 BUILD_OUT := $(HOST_OUT)
 
@@ -236,15 +253,20 @@
 OUT_DOCS := $(TARGET_COMMON_OUT_ROOT)/docs
 
 BUILD_OUT_EXECUTABLES := $(BUILD_OUT)/bin
+SOONG_HOST_OUT_EXECUTABLES := $(SOONG_HOST_OUT)/bin
 
 HOST_OUT_EXECUTABLES := $(HOST_OUT)/bin
 HOST_OUT_SHARED_LIBRARIES := $(HOST_OUT)/lib64
 HOST_OUT_RENDERSCRIPT_BITCODE := $(HOST_OUT_SHARED_LIBRARIES)
 HOST_OUT_JAVA_LIBRARIES := $(HOST_OUT)/framework
 HOST_OUT_SDK_ADDON := $(HOST_OUT)/sdk_addon
+HOST_OUT_NATIVE_TESTS := $(HOST_OUT)/nativetest64
+HOST_OUT_COVERAGE := $(HOST_OUT)/coverage
 
 HOST_CROSS_OUT_EXECUTABLES := $(HOST_CROSS_OUT)/bin
 HOST_CROSS_OUT_SHARED_LIBRARIES := $(HOST_CROSS_OUT)/lib
+HOST_CROSS_OUT_NATIVE_TESTS := $(HOST_CROSS_OUT)/nativetest
+HOST_CROSS_OUT_COVERAGE := $(HOST_CROSS_OUT)/coverage
 
 HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj
 HOST_OUT_HEADERS := $(HOST_OUT_INTERMEDIATES)/include
@@ -253,6 +275,9 @@
 HOST_OUT_COMMON_INTERMEDIATES := $(HOST_COMMON_OUT_ROOT)/obj
 HOST_OUT_FAKE := $(HOST_OUT)/fake_packages
 
+# Nano environment config
+include $(BUILD_SYSTEM)/aux_config.mk
+
 HOST_CROSS_OUT_INTERMEDIATES := $(HOST_CROSS_OUT)/obj
 HOST_CROSS_OUT_HEADERS := $(HOST_CROSS_OUT_INTERMEDIATES)/include
 HOST_CROSS_OUT_INTERMEDIATE_LIBRARIES := $(HOST_CROSS_OUT_INTERMEDIATES)/lib
@@ -271,14 +296,11 @@
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES := $(HOST_OUT)/lib
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_EXECUTABLES := $(HOST_OUT_EXECUTABLES)
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_JAVA_LIBRARIES := $(HOST_OUT_JAVA_LIBRARIES)
+$(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_NATIVE_TESTS := $(HOST_OUT)/nativetest
 
 # The default host library path.
 # It always points to the path where we build libraries in the default bitness.
-ifeq ($(HOST_PREFER_32_BIT),true)
-HOST_LIBRARY_PATH := $($(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)
-else
 HOST_LIBRARY_PATH := $(HOST_OUT_SHARED_LIBRARIES)
-endif
 
 # Out for HOST_CROSS_2ND_ARCH
 HOST_CROSS_2ND_ARCH_VAR_PREFIX := 2ND_
@@ -287,6 +309,7 @@
 $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATE_LIBRARIES := $($(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_INTERMEDIATES)/lib
 $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_SHARED_LIBRARIES := $(HOST_CROSS_OUT)/lib64
 $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_EXECUTABLES := $(HOST_CROSS_OUT_EXECUTABLES)
+$(HOST_CROSS_2ND_ARCH_VAR_PREFIX)HOST_CROSS_OUT_NATIVE_TESTS := $(HOST_CROSS_OUT)/nativetest64
 
 TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj
 TARGET_OUT_HEADERS := $(TARGET_OUT_INTERMEDIATES)/include
@@ -324,10 +347,19 @@
 
 # Out for TARGET_2ND_ARCH
 TARGET_2ND_ARCH_VAR_PREFIX := $(HOST_2ND_ARCH_VAR_PREFIX)
+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
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj_$(TARGET_2ND_ARCH)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATES)/lib
+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)
@@ -353,8 +385,13 @@
 $(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)
+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
+endif
 
 TARGET_OUT_CACHE := $(PRODUCT_OUT)/cache
 
@@ -374,10 +411,15 @@
 endif
 TARGET_OUT_VENDOR_JAVA_LIBRARIES := $(TARGET_OUT_VENDOR)/framework
 TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR)/app
+TARGET_OUT_VENDOR_APPS_PRIVILEGED := $(TARGET_OUT_VENDOR)/priv-app
 TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc
 
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR_EXECUTABLES)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib
+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_APPS := $(TARGET_OUT_VENDOR_APPS)
 
 TARGET_OUT_OEM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_OEM)
@@ -393,7 +435,11 @@
 TARGET_OUT_OEM_ETC := $(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)
 
 TARGET_OUT_ODM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ODM)
@@ -407,7 +453,11 @@
 TARGET_OUT_ODM_ETC := $(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)/lib/$(TARGET_2ND_ARCH)
+else
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib
+endif
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS := $(TARGET_OUT_ODM_APPS)
 
 TARGET_OUT_BREAKPAD := $(PRODUCT_OUT)/breakpad
@@ -419,6 +469,7 @@
 TARGET_ROOT_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)
 TARGET_ROOT_OUT_SBIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/sbin
 TARGET_ROOT_OUT_BIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/bin
+TARGET_OUT_COVERAGE := $(PRODUCT_OUT)/coverage
 
 TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT)
 TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin
@@ -439,7 +490,7 @@
 TARGET_INSTALLER_SYSTEM_OUT := $(TARGET_INSTALLER_OUT)/root/system
 
 COMMON_MODULE_CLASSES := TARGET-NOTICE_FILES HOST-NOTICE_FILES HOST-JAVA_LIBRARIES
-PER_ARCH_MODULE_CLASSES := SHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP RENDERSCRIPT_BITCODE
+PER_ARCH_MODULE_CLASSES := SHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP RENDERSCRIPT_BITCODE NATIVE_TESTS
 
 ifeq (,$(strip $(DIST_DIR)))
   DIST_DIR := $(OUT_DIR)/dist
@@ -452,3 +503,9 @@
 ifeq ($(USE_CLANG_PLATFORM_BUILD),)
 USE_CLANG_PLATFORM_BUILD := true
 endif
+
+ifneq ($(USE_CLANG_PLATFORM_BUILD),true)
+ifneq ($(USE_CLANG_PLATFORM_BUILD),false)
+$(error USE_CLANG_PLATFORM_BUILD must be true or false)
+endif
+endif
diff --git a/core/executable.mk b/core/executable.mk
index e22ea0e..f1b2462 100644
--- a/core/executable.mk
+++ b/core/executable.mk
@@ -16,17 +16,29 @@
 endif
 
 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
 
 ifeq ($(my_module_multilib),both)
+ifneq ($(LOCAL_MODULE_CLASS),NATIVE_TESTS)
 ifeq ($(LOCAL_MODULE_PATH_32)$(LOCAL_MODULE_STEM_32),)
 $(error $(LOCAL_PATH): LOCAL_MODULE_STEM_32 or LOCAL_MODULE_PATH_32 is required for LOCAL_MULTILIB := both for module $(LOCAL_MODULE))
 endif
 ifeq ($(LOCAL_MODULE_PATH_64)$(LOCAL_MODULE_STEM_64),)
 $(error $(LOCAL_PATH): LOCAL_MODULE_STEM_64 or LOCAL_MODULE_PATH_64 is required for LOCAL_MULTILIB := both for module $(LOCAL_MODULE))
 endif
+endif
 else #!LOCAL_MULTILIB == both
 LOCAL_NO_2ND_ARCH_MODULE_SUFFIX := true
 endif
diff --git a/core/executable_internal.mk b/core/executable_internal.mk
index febea98..593f9f4 100644
--- a/core/executable_internal.mk
+++ b/core/executable_internal.mk
@@ -34,21 +34,21 @@
 endif
 
 # Define PRIVATE_ variables from global vars
-my_target_global_ld_dirs := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LD_DIRS)
+my_target_global_ld_dirs :=
 ifeq ($(LOCAL_NO_LIBGCC),true)
 my_target_libgcc :=
 else
-my_target_libgcc := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCC)
+my_target_libgcc := $(call intermediates-dir-for,STATIC_LIBRARIES,libgcc,,,$(LOCAL_2ND_ARCH_VAR_PREFIX))/libgcc.a
 endif
-my_target_libatomic := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBATOMIC)
+my_target_libatomic := $(call intermediates-dir-for,STATIC_LIBRARIES,libatomic,,,$(LOCAL_2ND_ARCH_VAR_PREFIX))/libatomic.a
 ifeq ($(LOCAL_NO_CRT),true)
 my_target_crtbegin_dynamic_o :=
 my_target_crtbegin_static_o :=
 my_target_crtend_o :=
 else
-my_target_crtbegin_dynamic_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CRTBEGIN_DYNAMIC_O)
-my_target_crtbegin_static_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CRTBEGIN_STATIC_O)
-my_target_crtend_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CRTEND_O)
+my_target_crtbegin_dynamic_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
+my_target_crtbegin_static_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
+my_target_crtend_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_android.o
 endif
 ifdef LOCAL_SDK_VERSION
 # Make sure the prebuilt NDK paths are put ahead of the TARGET_GLOBAL_LD_DIRS,
@@ -73,11 +73,11 @@
 $(linked_module): PRIVATE_POST_LINK_CMD := $(LOCAL_POST_LINK_CMD)
 
 ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
-$(linked_module): $(my_target_crtbegin_static_o) $(all_objects) $(all_libraries) $(my_target_crtend_o)
+$(linked_module): $(my_target_crtbegin_static_o) $(all_objects) $(all_libraries) $(my_target_crtend_o) $(my_target_libgcc) $(my_target_libatomic)
 	$(transform-o-to-static-executable)
 	$(PRIVATE_POST_LINK_CMD)
 else
-$(linked_module): $(my_target_crtbegin_dynamic_o) $(all_objects) $(all_libraries) $(my_target_crtend_o)
+$(linked_module): $(my_target_crtbegin_dynamic_o) $(all_objects) $(all_libraries) $(my_target_crtend_o) $(my_target_libgcc) $(my_target_libatomic)
 	$(transform-o-to-executable)
 	$(PRIVATE_POST_LINK_CMD)
 endif
diff --git a/core/executable_prefer_symlink.mk b/core/executable_prefer_symlink.mk
index 931550f..9b9814e 100644
--- a/core/executable_prefer_symlink.mk
+++ b/core/executable_prefer_symlink.mk
@@ -10,43 +10,33 @@
 # et al. since those variables make no sense in that context.
 ifneq ($(LOCAL_IS_HOST_MODULE),true)
   my_symlink := $(addprefix $(TARGET_OUT)/bin/, $(LOCAL_MODULE))
+  my_src_binary_name :=
   ifeq ($(TARGET_IS_64_BIT),true)
     ifeq ($(TARGET_SUPPORTS_64_BIT_APPS)|$(TARGET_SUPPORTS_32_BIT_APPS),true|true)
       # We support both 32 and 64 bit apps, so we will have to
       # base our decision on whether the target prefers one or the
       # other.
       ifeq ($(TARGET_PREFER_32_BIT_APPS),true)
-        $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32)
+        my_src_binary_name := $(LOCAL_MODULE_STEM_32)
       else
-        $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_64)
+        my_src_binary_name := $(LOCAL_MODULE_STEM_64)
       endif
     else ifeq ($(TARGET_SUPPORTS_64_BIT_APPS),true)
       # We support only 64 bit apps.
-      $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_64)
+      my_src_binary_name := $(LOCAL_MODULE_STEM_64)
     else
       # We support only 32 bit apps.
-      $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32)
+      my_src_binary_name := $(LOCAL_MODULE_STEM_32)
     endif
   else
-    $(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32)
+    my_src_binary_name := $(LOCAL_MODULE_STEM_32)
   endif
 else
   my_symlink := $(addprefix $(HOST_OUT)/bin/, $(LOCAL_MODULE))
-  ifneq ($(HOST_PREFER_32_BIT),true)
-$(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_64)
-  else
-$(my_symlink): PRIVATE_SRC_BINARY_NAME := $(LOCAL_MODULE_STEM_32)
-  endif
+  my_src_binary_name := $(LOCAL_MODULE_STEM_64)
 endif
 
-# $(my_symlink) doesn't need to depend on $(PRIVATE_SRC_BINARY_NAME): we can generate symlink to nonexistent file.
-# If you add the dependency, make would compare the timestamp of a file against that of its symlink:
-# they are always equal, because make follows symlink.
-$(my_symlink): $(LOCAL_MODULE_MAKEFILE_DEP)
-	@echo "Symlink: $@ -> $(PRIVATE_SRC_BINARY_NAME)"
-	@mkdir -p $(dir $@)
-	@rm -rf $@
-	$(hide) ln -sf $(PRIVATE_SRC_BINARY_NAME) $@
+$(call symlink-file,$(my_module_path)/$(my_src_binary_name),$(my_src_binary_name),$(my_symlink))
 
 # We need this so that the installed files could be picked up based on the
 # local module name
diff --git a/core/fuzz_test.mk b/core/fuzz_test.mk
index fc582b3..f6d6e9a 100644
--- a/core/fuzz_test.mk
+++ b/core/fuzz_test.mk
@@ -2,6 +2,7 @@
 ## A thin wrapper around BUILD_EXECUTABLE
 ## Common flags for fuzz tests are added.
 ###########################################
+$(call record-module-type,FUZZ_TEST)
 
 ifdef LOCAL_SDK_VERSION
     $(error $(LOCAL_PATH): $(LOCAL_MODULE): NDK fuzz tests are not supported.)
@@ -22,8 +23,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)/$(LOCAL_MODULE)
-LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+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
diff --git a/core/goma.mk b/core/goma.mk
index 6535b3e..4e8318a 100644
--- a/core/goma.mk
+++ b/core/goma.mk
@@ -14,18 +14,11 @@
 # limitations under the License.
 #
 
+# Used by the compiler wrapper, but should only be set by gomacc
+unexport GOMACC_PATH
+
 # Notice: this works only with Google's Goma build infrastructure.
 ifneq ($(filter-out false,$(USE_GOMA)),)
-  # Check if USE_NINJA is not false because GNU make won't work well
-  # with goma. Note this file is evaluated twice, once by GNU make and
-  # once by kati with USE_NINJA=false. We do this check in the former
-  # pass.
-  ifndef KATI
-    ifeq ($(USE_NINJA),false)
-      $(error USE_GOMA=true is not compatible with USE_NINJA=false)
-    endif
-  endif
-
   # Goma requires a lot of processes and file descriptors.
   ifeq ($(shell echo $$(($$(ulimit -u) < 2500 || $$(ulimit -n) < 16000))),1)
     $(warning Max user processes and/or open files are insufficient)
@@ -56,11 +49,9 @@
   # gomacc can start goma client's daemon process automatically, but
   # it is safer and faster to start up it beforehand. We run this as a
   # background process so this won't slow down the build.
-  # We use "ensure_start" command when the compiler_proxy is already
-  # running and uses GOMA_HERMETIC=error flag. The compiler_proxy will
-  # restart otherwise.
-  # TODO(hamaji): Remove this condition after http://b/25676777 is fixed.
-  $(shell ( if ( curl http://localhost:$$($(GOMA_CC) port)/flagz | grep GOMA_HERMETIC=error ); then cmd=ensure_start; else cmd=restart; fi; GOMA_HERMETIC=error $(goma_ctl) $${cmd} ) &> /dev/null &)
+  ifndef NOSTART_GOMA
+    $(shell ( $(goma_ctl) ensure_start ) &> /dev/null &)
+  endif
 
   goma_ctl :=
   goma_dir :=
diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk
index 83047d4..64b610e 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+$(call record-module-type,HOST_DALVIK_JAVA_LIBRARY)
 
 #
 # Rules for building a host dalvik java library. These libraries
@@ -23,36 +24,34 @@
 ifeq ($(HOST_OS),linux)
 USE_CORE_LIB_BOOTCLASSPATH := true
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
 #######################################
 include $(BUILD_SYSTEM)/host_java_library_common.mk
 #######################################
-
-ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-  LOCAL_JAVA_LIBRARIES += core-oj-hostdex core-libart-hostdex
+ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
+  # For static library, $(LOCAL_BUILT_MODULE) is $(full_classes_jack).
+  LOCAL_BUILT_MODULE_STEM := classes.jack
 endif
 
-full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar
-full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
-full_classes_jar := $(intermediates.COMMON)/classes.jar
+ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
+  LOCAL_JAVA_LIBRARIES :=  core-oj-hostdex core-libart-hostdex $(LOCAL_JAVA_LIBRARIES)
+endif
+
 full_classes_jack := $(intermediates.COMMON)/classes.jack
 jack_check_timestamp := $(intermediates.COMMON)/jack.check.timestamp
 built_dex := $(intermediates.COMMON)/classes.dex
 
 LOCAL_INTERMEDIATE_TARGETS += \
-    $(full_classes_compiled_jar) \
-    $(full_classes_jarjar_jar) \
     $(full_classes_jack) \
-    $(full_classes_jar) \
     $(jack_check_timestamp) \
     $(built_dex)
 
 # See comment in java.mk
 ifndef LOCAL_CHECKED_MODULE
-ifdef LOCAL_JACK_ENABLED
 LOCAL_CHECKED_MODULE := $(jack_check_timestamp)
-else
-LOCAL_CHECKED_MODULE := $(full_classes_compiled_jar)
-endif
 endif
 
 #######################################
@@ -64,80 +63,34 @@
 
 include $(BUILD_SYSTEM)/java_common.mk
 
-# The layers file allows you to enforce a layering between java packages.
-# Run build/tools/java-layers.py for more details.
-layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE))
-
 $(cleantarget): PRIVATE_CLEAN_FILES += $(intermediates.COMMON)
 
-$(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file)
-$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JAVACFLAGS)
-$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES :=
-$(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES :=
-$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES :=
-$(full_classes_compiled_jar): \
-        $(java_sources) \
-        $(java_resource_sources) \
-        $(full_java_lib_deps) \
-        $(jar_manifest_file) \
-        $(proto_java_sources_file_stamp) \
-        $(LOCAL_MODULE_MAKEFILE_DEP) \
-        $(LOCAL_ADDITIONAL_DEPENDENCIES)
-	$(transform-host-java-to-package)
-
-# Run jarjar if necessary, otherwise just copy the file.
-ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
-$(full_classes_jarjar_jar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
-$(full_classes_jarjar_jar): $(full_classes_compiled_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
-	@echo JarJar: $@
-	$(hide) java -jar $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
-else
-$(full_classes_jarjar_jar): $(full_classes_compiled_jar) | $(ACP)
-	@echo Copying: $@
-	$(hide) $(ACP) -fp $< $@
-endif
-
-$(full_classes_jar): $(full_classes_jarjar_jar) | $(ACP)
-	@echo Copying: $@
-	$(hide) $(ACP) -fp $< $@
-
-ifndef LOCAL_JACK_ENABLED
-
-$(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE := $(built_dex)
-$(LOCAL_BUILT_MODULE): PRIVATE_SOURCE_ARCHIVE := $(full_classes_jarjar_jar)
-$(LOCAL_BUILT_MODULE): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
-$(LOCAL_BUILT_MODULE): $(built_dex) $(java_resource_sources)
-	@echo "Host Jar: $(PRIVATE_MODULE) ($@)"
-	$(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@)
-	$(add-dex-to-package)
-
-else # LOCAL_JACK_ENABLED
 $(LOCAL_INTERMEDIATE_TARGETS): \
-	PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
+  PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
 
 ifeq ($(LOCAL_JACK_ENABLED),incremental)
 $(LOCAL_INTERMEDIATE_TARGETS): \
-	PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-incremental
+  PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-incremental
 else
 $(LOCAL_INTERMEDIATE_TARGETS): \
-	PRIVATE_JACK_INCREMENTAL_DIR :=
+  PRIVATE_JACK_INCREMENTAL_DIR :=
 endif
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_FLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JACK_FLAGS)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VERSION := $(LOCAL_JACK_VERSION)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_MIN_SDK_VERSION := $(PLATFORM_JACK_MIN_SDK_VERSION)
 
 jack_all_deps := $(java_sources) $(java_resource_sources) $(full_jack_deps) \
-        $(jar_manifest_file) $(proto_java_sources_file_stamp) $(LOCAL_MODULE_MAKEFILE_DEP) \
-        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JACK)
+        $(jar_manifest_file) $(proto_java_sources_file_stamp) \
+        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(NORMALIZE_PATH) $(JACK_DEFAULT_ARGS) $(JACK)
+
+ifneq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
 $(built_dex): PRIVATE_CLASSES_JACK := $(full_classes_jack)
-$(built_dex): $(jack_all_deps) | setup-jack-server
+$(built_dex): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
+$(built_dex): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
+$(built_dex): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
 	@echo Building with Jack: $@
 	$(jack-java-to-dex)
 
-$(jack_check_timestamp): $(jack_all_deps) | setup-jack-server
-	@echo Checking build with Jack: $@
-	$(jack-check-java)
-
 # $(full_classes_jack) is just by-product of $(built_dex).
 # The dummy command was added because, without it, make misses the fact the $(built_dex) also
 # change $(full_classes_jack).
@@ -151,7 +104,18 @@
 	$(add-dex-to-package)
 	$(add-carried-jack-resources)
 
-endif # LOCAL_JACK_ENABLED
+else  # LOCAL_IS_STATIC_JAVA_LIBRARY
+$(full_classes_jack): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
+$(full_classes_jack): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
+$(full_classes_jack): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
+	@echo Building with Jack: $@
+	$(java-to-jack)
+
+endif  # LOCAL_IS_STATIC_JAVA_LIBRARY
+
+$(jack_check_timestamp): $(jack_all_deps) | setup-jack-server
+	@echo Checking build with Jack: $@
+	$(jack-check-java)
 
 USE_CORE_LIB_BOOTCLASSPATH :=
 
diff --git a/core/host_dalvik_static_java_library.mk b/core/host_dalvik_static_java_library.mk
index c296be3..78faf73 100644
--- a/core/host_dalvik_static_java_library.mk
+++ b/core/host_dalvik_static_java_library.mk
@@ -13,48 +13,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+$(call record-module-type,HOST_DALVIK_STATIC_JAVA_LIBRARY)
 
 #
 # Rules for building a host dalvik static java library.
 # These libraries will be compiled against libcore and not the host
 # JRE.
 #
-ifeq ($(HOST_OS),linux)
-
 LOCAL_UNINSTALLABLE_MODULE := true
 LOCAL_IS_STATIC_JAVA_LIBRARY := true
-USE_CORE_LIB_BOOTCLASSPATH := true
-LOCAL_JAVA_LIBRARIES += core-oj-hostdex core-libart-hostdex
 
-intermediates.COMMON := $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE),true,COMMON,)
-full_classes_jack := $(intermediates.COMMON)/classes.jack
-LOCAL_INTERMEDIATE_TARGETS += \
-    $(full_classes_jack)
+include $(BUILD_SYSTEM)/host_dalvik_java_library.mk
 
-include $(BUILD_SYSTEM)/host_java_library.mk
-# proguard is not supported
-# *.proto files are not supported
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_FLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JACK_FLAGS)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VERSION := $(LOCAL_JACK_VERSION)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_MIN_SDK_VERSION := $(PLATFORM_JACK_MIN_SDK_VERSION)
-
-$(full_classes_jack): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
-$(full_classes_jack): \
-	PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
-ifeq ($(LOCAL_JACK_ENABLED),incremental)
-$(full_classes_jack): \
-	PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-incremental
-else
-$(full_classes_jack): \
-	PRIVATE_JACK_INCREMENTAL_DIR :=
-endif
-$(full_classes_jack): $(java_sources) $(java_resource_sources) $(full_jack_deps) \
-        $(jar_manifest_file) $(layers_file) $(LOCAL_MODULE_MAKEFILE_DEP) \
-        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(LOCAL_JARJAR_RULES) \
-        $(JACK) | setup-jack-server
-	@echo Building with Jack: $@
-	$(java-to-jack)
-
-USE_CORE_LIB_BOOTCLASSPATH :=
 LOCAL_IS_STATIC_JAVA_LIBRARY :=
-endif
diff --git a/core/host_executable.mk b/core/host_executable.mk
index 6f19bd1..1480c2c 100644
--- a/core/host_executable.mk
+++ b/core/host_executable.mk
@@ -1,3 +1,4 @@
+$(call record-module-type,HOST_EXECUTABLE)
 LOCAL_IS_HOST_MODULE := true
 my_prefix := HOST_
 LOCAL_HOST_PREFIX :=
@@ -5,26 +6,24 @@
 
 ifndef LOCAL_MODULE_HOST_ARCH
 ifndef my_module_multilib
-ifeq ($(HOST_PREFER_32_BIT),true)
-my_module_multilib := 32
-else
 # By default we only build host module for the first arch.
 my_module_multilib := first
 endif
 endif
-endif
 
 ifeq ($(LOCAL_NO_FPIE),)
 LOCAL_LDFLAGS += $(HOST_FPIE_FLAGS)
 endif
 
 ifeq ($(my_module_multilib),both)
+ifneq ($(LOCAL_MODULE_CLASS),NATIVE_TESTS)
 ifeq ($(LOCAL_MODULE_PATH_32)$(LOCAL_MODULE_STEM_32),)
 $(error $(LOCAL_PATH): LOCAL_MODULE_STEM_32 or LOCAL_MODULE_PATH_32 is required for LOCAL_MULTILIB := both for module $(LOCAL_MODULE))
 endif
 ifeq ($(LOCAL_MODULE_PATH_64)$(LOCAL_MODULE_STEM_64),)
 $(error $(LOCAL_PATH): LOCAL_MODULE_STEM_64 or LOCAL_MODULE_PATH_64 is required for LOCAL_MULTILIB := both for module $(LOCAL_MODULE))
 endif
+endif
 else #!LOCAL_MULTILIB == both
 LOCAL_NO_2ND_ARCH_MODULE_SUFFIX := true
 endif
diff --git a/core/host_executable_internal.mk b/core/host_executable_internal.mk
index b682ffd..19200fd 100644
--- a/core/host_executable_internal.mk
+++ b/core/host_executable_internal.mk
@@ -29,6 +29,14 @@
 my_host_libprofile_rt := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)LIBPROFILE_RT)
 $(LOCAL_BUILT_MODULE): PRIVATE_HOST_LIBPROFILE_RT := $(my_host_libprofile_rt)
 
+my_libdir := $(notdir $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT_SHARED_LIBRARIES))
+ifeq ($(LOCAL_MODULE_CLASS),NATIVE_TESTS)
+$(LOCAL_BUILT_MODULE): PRIVATE_RPATHS := ../../$(my_libdir)
+else
+$(LOCAL_BUILT_MODULE): PRIVATE_RPATHS := ../$(my_libdir) $(my_libdir)
+endif
+my_libdir :=
+
 $(LOCAL_BUILT_MODULE): $(all_objects) $(all_libraries)
 	$(transform-host-o-to-executable)
 
diff --git a/core/host_fuzz_test.mk b/core/host_fuzz_test.mk
index cc7baad..1c9eed2 100644
--- a/core/host_fuzz_test.mk
+++ b/core/host_fuzz_test.mk
@@ -2,6 +2,7 @@
 ## A thin wrapper around BUILD_HOST_EXECUTABLE
 ## Common flags for host fuzz tests are added.
 ################################################
+$(call record-module-type,HOST_FUZZ_TEST)
 
 LOCAL_CFLAGS += -fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp
 LOCAL_STATIC_LIBRARIES += libLLVMFuzzer
diff --git a/core/host_java_library.mk b/core/host_java_library.mk
index 97079fd..cc26d7c 100644
--- a/core/host_java_library.mk
+++ b/core/host_java_library.mk
@@ -14,6 +14,8 @@
 # limitations under the License.
 #
 
+$(call record-module-type,HOST_JAVA_LIBRARY)
+
 #
 # Standard rules for building a host java library.
 #
@@ -66,10 +68,13 @@
         $(full_java_lib_deps) \
         $(jar_manifest_file) \
         $(proto_java_sources_file_stamp) \
-        $(LOCAL_MODULE_MAKEFILE_DEP) \
+        $(NORMALIZE_PATH) \
         $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	$(transform-host-java-to-package)
 
+javac-check : $(full_classes_compiled_jar)
+javac-check-$(LOCAL_MODULE) : $(full_classes_compiled_jar)
+
 # Run jarjar if necessary, otherwise just copy the file.
 ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
 $(full_classes_jarjar_jar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
@@ -97,13 +102,12 @@
 $(full_classes_emma_jar) : $(full_classes_jarjar_jar) | $(EMMA_JAR)
 	$(transform-classes.jar-to-emma)
 
-$(built_javalib_jar) : $(full_classes_emma_jar)
+$(LOCAL_BUILT_MODULE) : $(full_classes_emma_jar)
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 
 else # LOCAL_EMMA_INSTRUMENT
-$(built_javalib_jar): $(full_classes_jarjar_jar) | $(ACP)
+$(LOCAL_BUILT_MODULE) : $(full_classes_jarjar_jar) | $(ACP)
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 endif # LOCAL_EMMA_INSTRUMENT
-
diff --git a/core/host_java_library_common.mk b/core/host_java_library_common.mk
index 35a6e28..8df4b37 100644
--- a/core/host_java_library_common.mk
+++ b/core/host_java_library_common.mk
@@ -26,19 +26,6 @@
 intermediates := $(call local-intermediates-dir)
 intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
-built_javalib_jar := $(intermediates)/javalib.jar
-
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
-ifdef LOCAL_JACK_ENABLED
-ifdef LOCAL_IS_STATIC_JAVA_LIBRARY
-LOCAL_BUILT_MODULE_STEM := classes.jack
-LOCAL_INTERMEDIATE_TARGETS += $(built_javalib_jar)
-endif
-endif
-
 # base_rules.mk looks at this
 all_res_assets :=
 
@@ -61,4 +48,3 @@
 
 LOCAL_INTERMEDIATE_SOURCE_DIR := $(intermediates.COMMON)/src
 LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES))
-
diff --git a/core/host_native_test.mk b/core/host_native_test.mk
index 7cba1ae..aa05bb3 100644
--- a/core/host_native_test.mk
+++ b/core/host_native_test.mk
@@ -2,25 +2,22 @@
 ## A thin wrapper around BUILD_HOST_EXECUTABLE
 ## Common flags for host native tests are added.
 ################################################
+$(call record-module-type,HOST_NATIVE_TEST)
+
+ifdef LOCAL_MODULE_CLASS
+ifneq ($(LOCAL_MODULE_CLASS),NATIVE_TESTS)
+$(error $(LOCAL_PATH): LOCAL_MODULE_CLASS must be NATIVE_TESTS with BUILD_HOST_NATIVE_TEST)
+endif
+endif
+
+LOCAL_MODULE_CLASS := NATIVE_TESTS
 
 include $(BUILD_SYSTEM)/host_test_internal.mk
 
-needs_symlink :=
 ifndef LOCAL_MULTILIB
-  ifndef LOCAL_32_BIT_ONLY
-    LOCAL_MULTILIB := both
-
-    ifeq (,$(LOCAL_MODULE_STEM_32)$(LOCAL_MODULE_STEM_64))
-      LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-      LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-      needs_symlink := true
-    endif
-  endif
+ifndef LOCAL_32_BIT_ONLY
+LOCAL_MULTILIB := both
+endif
 endif
 
 include $(BUILD_HOST_EXECUTABLE)
-
-ifdef needs_symlink
-include $(BUILD_SYSTEM)/executable_prefer_symlink.mk
-needs_symlink :=
-endif
diff --git a/core/host_prebuilt.mk b/core/host_prebuilt.mk
index 7baab69..79f3ffa 100644
--- a/core/host_prebuilt.mk
+++ b/core/host_prebuilt.mk
@@ -14,5 +14,6 @@
 # limitations under the License.
 #
 
+$(call record-module-type,HOST_PREBUILT)
 LOCAL_IS_HOST_MODULE := true
 include $(BUILD_MULTI_PREBUILT)
diff --git a/core/host_shared_library.mk b/core/host_shared_library.mk
index 2e0c9f1c..5da7913 100644
--- a/core/host_shared_library.mk
+++ b/core/host_shared_library.mk
@@ -1,3 +1,4 @@
+$(call record-module-type,HOST_SHARED_LIBRARY)
 LOCAL_IS_HOST_MODULE := true
 my_prefix := HOST_
 LOCAL_HOST_PREFIX :=
@@ -5,14 +6,10 @@
 
 ifndef LOCAL_MODULE_HOST_ARCH
 ifndef my_module_multilib
-ifeq ($(HOST_PREFER_32_BIT),true)
-my_module_multilib := 32
-else
 # libraries default to building for both architecturess
 my_module_multilib := both
 endif
 endif
-endif
 
 LOCAL_2ND_ARCH_VAR_PREFIX :=
 include $(BUILD_SYSTEM)/module_arch_supported.mk
diff --git a/core/host_shared_library_internal.mk b/core/host_shared_library_internal.mk
index 272e76f..bfbde21 100644
--- a/core/host_shared_library_internal.mk
+++ b/core/host_shared_library_internal.mk
@@ -44,7 +44,6 @@
 $(LOCAL_BUILT_MODULE): \
         $(all_objects) \
         $(all_libraries) \
-        $(LOCAL_MODULE_MAKEFILE_DEP) \
         $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	$(transform-host-o-to-shared-lib)
 
diff --git a/core/host_shared_test_lib.mk b/core/host_shared_test_lib.mk
index 1eb9b26..ed7e23a 100644
--- a/core/host_shared_test_lib.mk
+++ b/core/host_shared_test_lib.mk
@@ -1,8 +1 @@
-##################################################
-## A thin wrapper around BUILD_HOST_SHARED_LIBRARY
-## Common flags for host native tests are added.
-##################################################
-
-include $(BUILD_SYSTEM)/host_test_internal.mk
-
-include $(BUILD_HOST_SHARED_LIBRARY)
+$(error BUILD_HOST_SHARED_TEST_LIBRARY is obsolete)
diff --git a/core/host_static_library.mk b/core/host_static_library.mk
index 068c702..aa0421e 100644
--- a/core/host_static_library.mk
+++ b/core/host_static_library.mk
@@ -1,3 +1,4 @@
+$(call record-module-type,HOST_STATIC_LIBRARY)
 LOCAL_IS_HOST_MODULE := true
 my_prefix := HOST_
 LOCAL_HOST_PREFIX :=
@@ -5,14 +6,10 @@
 
 ifndef LOCAL_MODULE_HOST_ARCH
 ifndef my_module_multilib
-ifeq ($(HOST_PREFER_32_BIT),true)
-my_module_multilib := 32
-else
 # libraries default to building for both architecturess
 my_module_multilib := both
 endif
 endif
-endif
 
 LOCAL_2ND_ARCH_VAR_PREFIX :=
 include $(BUILD_SYSTEM)/module_arch_supported.mk
diff --git a/core/host_static_test_lib.mk b/core/host_static_test_lib.mk
index 5423dc6..a24cd62 100644
--- a/core/host_static_test_lib.mk
+++ b/core/host_static_test_lib.mk
@@ -2,6 +2,7 @@
 ## A thin wrapper around BUILD_HOST_STATIC_LIBRARY
 ## Common flags for host native tests are added.
 ##################################################
+$(call record-module-type,HOST_STATIC_TEST_LIBRARY)
 
 include $(BUILD_SYSTEM)/host_test_internal.mk
 
diff --git a/core/host_test_internal.mk b/core/host_test_internal.mk
index 7f6aff0..473815b 100644
--- a/core/host_test_internal.mk
+++ b/core/host_test_internal.mk
@@ -5,10 +5,25 @@
 LOCAL_CFLAGS_windows += -DGTEST_OS_WINDOWS
 LOCAL_CFLAGS_linux += -DGTEST_OS_LINUX
 LOCAL_LDLIBS_linux += -lpthread
-LOCAL_CFLAGS_darwin += -DGTEST_OS_LINUX
+LOCAL_CFLAGS_darwin += -DGTEST_OS_MAC
 LOCAL_LDLIBS_darwin += -lpthread
 
 LOCAL_CFLAGS += -DGTEST_HAS_STD_STRING -O0 -g
-LOCAL_C_INCLUDES +=  external/gtest/include
 
 LOCAL_STATIC_LIBRARIES += libgtest_main_host libgtest_host
+
+ifdef LOCAL_MODULE_PATH
+$(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH when building test $(LOCAL_MODULE))
+endif
+
+ifdef LOCAL_MODULE_PATH_32
+$(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH_32 when building test $(LOCAL_MODULE))
+endif
+
+ifdef LOCAL_MODULE_PATH_64
+$(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH_64 when building test $(LOCAL_MODULE))
+endif
+
+ifndef LOCAL_MODULE_RELATIVE_PATH
+LOCAL_MODULE_RELATIVE_PATH := $(LOCAL_MODULE)
+endif
diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk
index 27b9697..14cc384 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -32,10 +32,10 @@
 endif
 ifeq (stlport_shared,$(LOCAL_NDK_STL_VARIANT))
 my_jni_shared_libraries += \
-    $(HISTORICAL_NDK_VERSIONS_ROOT)/current/sources/cxx-stl/stlport/libs/$(TARGET_$(my_2nd_arch_prefix)CPU_ABI)/libstlport_shared.so
+    $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources/cxx-stl/stlport/libs/$(TARGET_$(my_2nd_arch_prefix)CPU_ABI)/libstlport_shared.so
 else ifeq (c++_shared,$(LOCAL_NDK_STL_VARIANT))
 my_jni_shared_libraries += \
-    $(HISTORICAL_NDK_VERSIONS_ROOT)/current/sources/cxx-stl/llvm-libc++/libs/$(TARGET_$(my_2nd_arch_prefix)CPU_ABI)/libc++_shared.so
+    $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources/cxx-stl/llvm-libc++/libs/$(TARGET_$(my_2nd_arch_prefix)CPU_ABI)/libc++_shared.so
 endif
 
 # Set the abi directory used by the local JNI shared libraries.
@@ -98,3 +98,33 @@
 endif  # my_embed_jni
 endif  # inner my_prebuilt_jni_libs
 endif  # outer my_prebuilt_jni_libs
+
+# Verify that all included libraries are built against the NDK
+ifneq ($(strip $(LOCAL_JNI_SHARED_LIBRARIES)),)
+my_link_type := $(call intermediates-dir-for,APPS,$(LOCAL_MODULE))/$(my_2nd_arch_prefix)jni_link_type
+all_link_types: $(my_link_type)
+my_link_type_deps := $(strip \
+  $(foreach l,$(LOCAL_JNI_SHARED_LIBRARIES),\
+    $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),,,$(my_2nd_arch_prefix))/link_type))
+ifneq ($(LOCAL_SDK_VERSION),)
+$(my_link_type): PRIVATE_LINK_TYPE := app:sdk
+$(my_link_type): PRIVATE_WARN_TYPES := native:platform
+$(my_link_type): PRIVATE_ALLOWED_TYPES := native:ndk
+else
+$(my_link_type): PRIVATE_LINK_TYPE := app:platform
+$(my_link_type): PRIVATE_WARN_TYPES :=
+$(my_link_type): PRIVATE_ALLOWED_TYPES := native:ndk native:platform
+endif
+$(eval $(call link-type-partitions,$(my_link_type)))
+$(my_link_type): PRIVATE_DEPS := $(my_link_type_deps)
+$(my_link_type): PRIVATE_MODULE := $(LOCAL_MODULE)
+$(my_link_type): PRIVATE_MAKEFILE := $(LOCAL_MODULE_MAKEFILE)
+$(my_link_type): $(my_link_type_deps) $(CHECK_LINK_TYPE)
+	@echo Check JNI module types: $@
+	$(check-link-type)
+
+$(LOCAL_BUILT_MODULE): | $(my_link_type)
+
+my_link_type :=
+my_link_type_deps :=
+endif
diff --git a/core/jack-default.args b/core/jack-default.args
index 8d70a82..bcc3235 100644
--- a/core/jack-default.args
+++ b/core/jack-default.args
@@ -2,4 +2,5 @@
 -D sched.runner.thread.kind=fixed
 -D sched.runner.thread.fixed.count=4
 --sanity-checks off
--D jack.reporter.level.file=error=--,warning=-
\ No newline at end of file
+-D jack.reporter.level.file=error=--,warning=-
+--verbose error
\ No newline at end of file
diff --git a/core/java.mk b/core/java.mk
index 2602daf..9199f7c 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -96,34 +96,14 @@
 intermediates := $(call local-intermediates-dir)
 intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
-# Choose leaf name for the compiled jar file.
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-full_classes_compiled_jar_leaf := classes-no-debug-var.jar
-built_dex_intermediate_leaf := no-local
-else
-full_classes_compiled_jar_leaf := classes-full-debug.jar
-built_dex_intermediate_leaf := with-local
-endif
-
 ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
 LOCAL_PROGUARD_ENABLED :=
 endif
 
-ifdef LOCAL_PROGUARD_ENABLED
-proguard_jar_leaf := proguard.classes.jar
-else
-proguard_jar_leaf := noproguard.classes.jar
-endif
-
-full_classes_compiled_jar := $(intermediates.COMMON)/$(full_classes_compiled_jar_leaf)
-jarjar_leaf := classes-jarjar.jar
-full_classes_jarjar_jar := $(intermediates.COMMON)/$(jarjar_leaf)
-emma_intermediates_dir := $(intermediates.COMMON)/emma_out
-# emma is hardcoded to use the leaf name of its input for the output file --
-# only the output directory can be changed
-full_classes_emma_jar := $(emma_intermediates_dir)/lib/$(jarjar_leaf)
-full_classes_proguard_jar := $(intermediates.COMMON)/$(proguard_jar_leaf)
-built_dex_intermediate := $(intermediates.COMMON)/$(built_dex_intermediate_leaf)/classes.dex
+full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar
+full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
+full_classes_proguard_jar := $(intermediates.COMMON)/proguard.classes.jar
+built_dex_intermediate := $(intermediates.COMMON)/dex-dir/classes.dex
 full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar
 
 ifeq ($(LOCAL_MODULE_CLASS)$(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),APPS)
@@ -143,7 +123,6 @@
 LOCAL_INTERMEDIATE_TARGETS += \
     $(full_classes_compiled_jar) \
     $(full_classes_jarjar_jar) \
-    $(full_classes_emma_jar) \
     $(full_classes_jar) \
     $(full_classes_proguard_jar) \
     $(built_dex_intermediate) \
@@ -306,10 +285,9 @@
 ## AIDL: Compile .aidl files to .java
 ###########################################################
 aidl_sources := $(filter %.aidl,$(LOCAL_SRC_FILES))
+aidl_java_sources :=
 
 ifneq ($(strip $(aidl_sources)),)
-aidl_java_sources := $(patsubst %.aidl,%.java,$(addprefix $(intermediates.COMMON)/src/, $(aidl_sources)))
-aidl_sources := $(addprefix $(LOCAL_PATH)/, $(aidl_sources))
 
 aidl_preprocess_import :=
 ifdef LOCAL_SDK_VERSION
@@ -323,20 +301,17 @@
 # build against the platform.
 LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
 endif # LOCAL_SDK_VERSION
-$(aidl_java_sources): PRIVATE_AIDL_FLAGS := -b $(addprefix -p,$(aidl_preprocess_import)) -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
 
-$(aidl_java_sources): $(intermediates.COMMON)/src/%.java: \
-        $(LOCAL_PATH)/%.aidl \
-        $(LOCAL_MODULE_MAKEFILE_DEP) \
-        $(LOCAL_ADDITIONAL_DEPENDENCIES) \
-        $(AIDL) \
-        $(aidl_preprocess_import)
-	$(transform-aidl-to-java)
+$(foreach s,$(aidl_sources),\
+    $(eval $(call define-aidl-java-rule,$(s),$(intermediates.COMMON),aidl_java_sources)))
 $(foreach java,$(aidl_java_sources), \
     $(call include-depfile,$(java:%.java=%.P),$(java)))
 
-else
-aidl_java_sources :=
+$(aidl_java_sources) : $(LOCAL_ADDITIONAL_DEPENDENCIES) $(aidl_preprocess_import)
+
+$(aidl_java_sources): PRIVATE_AIDL_FLAGS := -b $(addprefix -p,$(aidl_preprocess_import)) -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
+$(aidl_java_sources): PRIVATE_MODULE := $(LOCAL_MODULE)
+
 endif
 
 ##########################################
@@ -347,11 +322,7 @@
 # command line.
 ifndef LOCAL_CHECKED_MODULE
 ifdef full_classes_jar
-ifdef LOCAL_JACK_ENABLED
 LOCAL_CHECKED_MODULE := $(jack_check_timestamp)
-else
-LOCAL_CHECKED_MODULE := $(full_classes_compiled_jar)
-endif
 endif
 endif
 
@@ -367,7 +338,8 @@
 logtags_java_sources := $(patsubst %.logtags,%.java,$(addprefix $(intermediates.COMMON)/src/, $(logtags_sources)))
 logtags_sources := $(addprefix $(LOCAL_PATH)/, $(logtags_sources))
 
-$(logtags_java_sources): $(intermediates.COMMON)/src/%.java: $(LOCAL_PATH)/%.logtags $(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txt
+$(logtags_java_sources): PRIVATE_MERGED_TAG := $(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txt
+$(logtags_java_sources): $(intermediates.COMMON)/src/%.java: $(LOCAL_PATH)/%.logtags $(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txt $(JAVATAGS) build/tools/event_log_tags.py
 	$(transform-logtags-to-java)
 
 else
@@ -422,10 +394,6 @@
 $(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file)
 $(full_classes_compiled_jar): PRIVATE_WARNINGS_ENABLE := $(LOCAL_WARNINGS_ENABLE)
 
-ifdef LOCAL_RMTYPEDEFS
-$(full_classes_compiled_jar): | $(RMTYPEDEFS)
-endif
-
 # Compile the java files to a .jar file.
 # This intentionally depends on java_sources, not all_java_sources.
 # Deps for generated source files must be handled separately,
@@ -443,10 +411,13 @@
         $(layers_file) \
         $(RenderScript_file_stamp) \
         $(proto_java_sources_file_stamp) \
-        $(LOCAL_MODULE_MAKEFILE_DEP) \
+        $(NORMALIZE_PATH) \
         $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	$(transform-java-to-classes.jar)
 
+javac-check : $(full_classes_compiled_jar)
+javac-check-$(LOCAL_MODULE) : $(full_classes_compiled_jar)
+
 # Run jarjar if necessary, otherwise just copy the file.
 ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
 $(full_classes_jarjar_jar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
@@ -459,30 +430,8 @@
 	$(hide) $(ACP) -fp $< $@
 endif
 
-full_classes_jar_source := $(full_classes_jarjar_jar)
-ifndef LOCAL_JACK_ENABLED
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILE := $(intermediates.COMMON)/coverage.emma.ignore
-$(full_classes_emma_jar): PRIVATE_EMMA_INTERMEDIATES_DIR := $(emma_intermediates_dir)
-# module level coverage filter can be defined using LOCAL_EMMA_COVERAGE_FILTER
-# in Android.mk
-ifdef LOCAL_EMMA_COVERAGE_FILTER
-$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILTER := $(LOCAL_EMMA_COVERAGE_FILTER)
-else
-# by default, avoid applying emma instrumentation onto emma classes itself,
-# otherwise there will be exceptions thrown
-$(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILTER := *,-emma,-emmarun,-com.vladium.*
-endif
-# this rule will generate both $(PRIVATE_EMMA_COVERAGE_FILE) and
-# $(full_classes_emma_jar)
-$(full_classes_emma_jar): $(full_classes_jarjar_jar) | $(EMMA_JAR)
-	$(transform-classes.jar-to-emma)
-full_classes_jar_source := $(full_classes_emma_jar)
-endif
-endif
-
 # Keep a copy of the jar just before proguard processing.
-$(full_classes_jar): $(full_classes_jar_source) | $(ACP)
+$(full_classes_jar): $(full_classes_jarjar_jar) | $(ACP)
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 
@@ -525,22 +474,25 @@
 
 common_proguard_flags := -forceprocessing
 
+common_proguard_flag_files :=
 ifeq ($(filter nosystem,$(LOCAL_PROGUARD_ENABLED)),)
-common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.flags
+common_proguard_flag_files += $(BUILD_SYSTEM)/proguard.flags
 ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-ifdef LOCAL_JACK_ENABLED
-common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.jacoco.flags
-else
-common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.emma.flags
-endif # LOCAL_JACK_ENABLED
+common_proguard_flag_files += $(BUILD_SYSTEM)/proguard.jacoco.flags
 endif
 # If this is a test package, add proguard keep flags for tests.
 ifneq ($(LOCAL_INSTRUMENTATION_FOR)$(filter tests,$(LOCAL_MODULE_TAGS)),)
-common_proguard_flags += -include $(BUILD_SYSTEM)/proguard_tests.flags
+common_proguard_flag_files += $(BUILD_SYSTEM)/proguard_tests.flags
 ifeq ($(filter shrinktests,$(LOCAL_PROGUARD_ENABLED)),)
 common_proguard_flags += -dontshrink # don't shrink tests by default
 endif # shrinktests
 endif # test package
+ifneq ($(common_proguard_flag_files),)
+common_proguard_flags += $(addprefix -include , $(common_proguard_flag_files))
+# This is included from $(BUILD_SYSTEM)/proguard.flags
+common_proguard_flag_files += $(BUILD_SYSTEM)/proguard_basic_keeps.flags
+endif
+
 ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)
 # By default no obfuscation
 common_proguard_flags += -dontobfuscate
@@ -566,10 +518,9 @@
     -applymapping $(link_instr_intermediates_dir.COMMON)/proguard_dictionary \
     -verbose \
     $(legacy_proguard_flags)
-ifdef LOCAL_JACK_ENABLED
+
 jack_proguard_flags += -applymapping $(link_instr_intermediates_dir.COMMON)/jack_dictionary
 full_jack_deps += $(link_instr_intermediates_dir.COMMON)/jack_dictionary
-endif
 
 # Sometimes (test + main app) uses different keep rules from the main app -
 # apply the main app's dictionary anyway.
@@ -592,40 +543,21 @@
 endif
 $(full_classes_proguard_jar): PRIVATE_EXTRA_INPUT_JAR := $(extra_input_jar)
 $(full_classes_proguard_jar): PRIVATE_PROGUARD_FLAGS := $(legacy_proguard_flags) $(common_proguard_flags) $(LOCAL_PROGUARD_FLAGS)
-$(full_classes_proguard_jar) : $(full_classes_jar) $(extra_input_jar) $(my_support_library_sdk_raise) $(proguard_flag_files) | $(ACP) $(PROGUARD)
+$(full_classes_proguard_jar) : $(full_classes_jar) $(extra_input_jar) $(my_support_library_sdk_raise) $(common_proguard_flag_files) $(proguard_flag_files) | $(PROGUARD)
 	$(call transform-jar-to-proguard)
 
 else  # LOCAL_PROGUARD_ENABLED not defined
-$(full_classes_proguard_jar) : $(full_classes_jar)
+$(full_classes_proguard_jar) : $(full_classes_jar) | $(ACP)
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 
 endif # LOCAL_PROGUARD_ENABLED defined
 
-ifndef LOCAL_JACK_ENABLED
-# Override PRIVATE_INTERMEDIATES_DIR so that install-dex-debug
-# will work even when intermediates != intermediates.COMMON.
-$(built_dex_intermediate): PRIVATE_INTERMEDIATES_DIR := $(intermediates.COMMON)
-$(built_dex_intermediate): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
-# If you instrument class files that have local variable debug information in
-# them emma does not correctly maintain the local variable table.
-# This will cause an error when you try to convert the class files for Android.
-# The workaround here is to build different dex file here based on emma switch
-# then later copy into classes.dex. When emma is on, dx is run with --no-locals
-# option to remove local variable information
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-$(built_dex_intermediate): PRIVATE_DX_FLAGS += --no-locals
-endif
-endif # LOCAL_JACK_ENABLED is disabled
-
 $(built_dex): $(built_dex_intermediate) | $(ACP)
 	@echo Copying: $@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) rm -f $(dir $@)/classes*.dex
 	$(hide) $(ACP) -fp $(dir $<)/classes*.dex $(dir $@)
-ifneq ($(GENERATE_DEX_DEBUG),)
-	$(install-dex-debug)
-endif
 
 findbugs_xml := $(intermediates.COMMON)/findbugs.xml
 $(findbugs_xml): PRIVATE_AUXCLASSPATH := $(addprefix -auxclasspath ,$(strip \
@@ -653,7 +585,6 @@
 
 endif  # full_classes_jar is defined
 
-ifdef LOCAL_JACK_ENABLED
 $(LOCAL_INTERMEDIATE_TARGETS): \
 	PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
 ifeq ($(LOCAL_JACK_ENABLED),incremental)
@@ -694,16 +625,19 @@
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VERSION := $(LOCAL_JACK_VERSION)
 
 jack_all_deps := $(java_sources) $(java_resource_sources) $(full_jack_deps) \
-        $(jar_manifest_file) $(layers_file) $(RenderScript_file_stamp) $(proguard_flag_files) \
+        $(jar_manifest_file) $(layers_file) $(RenderScript_file_stamp) \
+        $(common_proguard_flag_files) $(proguard_flag_files) \
         $(proto_java_sources_file_stamp) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(LOCAL_JARJAR_RULES) \
-        $(LOCAL_MODULE_MAKEFILE_DEP) $(JACK)
+        $(NORMALIZE_PATH) $(JACK_DEFAULT_ARGS) $(JACK)
 
 $(jack_check_timestamp): $(jack_all_deps) | setup-jack-server
 	@echo Checking build with Jack: $@
 	$(jack-check-java)
 
 ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
-$(full_classes_jack): $(jack_all_deps) | setup-jack-server
+$(full_classes_jack): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
+$(full_classes_jack): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
+$(full_classes_jack): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
 	@echo Building with Jack: $@
 	$(java-to-jack)
 
@@ -716,6 +650,8 @@
 $(built_dex_intermediate): PRIVATE_CLASSES_JACK := $(full_classes_jack)
 
 ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
+LOCAL_JACK_PLUGIN_PATH += $(HOST_OUT_JAVA_LIBRARIES)/jack-coverage-plugin.jar
+LOCAL_JACK_PLUGIN += com.android.jack.coverage.CodeCoverage
 $(built_dex_intermediate): PRIVATE_JACK_COVERAGE_OPTIONS := \
     -D jack.coverage=true \
     -D jack.coverage.metadata.file=$(intermediates.COMMON)/coverage.em \
@@ -726,7 +662,9 @@
 $(built_dex_intermediate): PRIVATE_JACK_COVERAGE_OPTIONS :=
 endif
 
-$(built_dex_intermediate): $(jack_all_deps) | setup-jack-server
+$(built_dex_intermediate): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
+$(built_dex_intermediate): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
+$(built_dex_intermediate): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
 	@echo Building with Jack: $@
 	$(jack-java-to-dex)
 
@@ -740,10 +678,11 @@
 
 endif #LOCAL_IS_STATIC_JAVA_LIBRARY
 
+$(noshrob_classes_jack): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
+$(noshrob_classes_jack): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
 $(noshrob_classes_jack): PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-noshrob-rsc
 $(noshrob_classes_jack): PRIVATE_JACK_PROGUARD_FLAGS :=
-$(noshrob_classes_jack): $(jack_all_deps) | setup-jack-server
+$(noshrob_classes_jack): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
 	@echo Building with Jack: $@
 	$(java-to-jack)
 endif  # full_classes_jar is defined
-endif # LOCAL_JACK_ENABLED
diff --git a/core/java_common.mk b/core/java_common.mk
index 9b7d10f..1119a37 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -19,7 +19,12 @@
   ifneq (,$(filter $(LOCAL_SDK_VERSION), $(private_sdk_versions_without_any_java_18_support)))
     LOCAL_JAVA_LANGUAGE_VERSION := 1.7
   else
-    LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+    # This retains 1.7 for ART build bots only. http://b/27583810
+    ifeq (,$(LEGACY_USE_JAVA7))
+      LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+    else
+      LOCAL_JAVA_LANGUAGE_VERSION := 1.7
+    endif
   endif
 endif
 LOCAL_JAVACFLAGS += -source $(LOCAL_JAVA_LANGUAGE_VERSION) -target $(LOCAL_JAVA_LANGUAGE_VERSION)
@@ -128,6 +133,15 @@
   extra_jar_args :=
 endif # java_resource_file_groups
 
+#####################################
+## Warn if there is unrecognized file in LOCAL_SRC_FILES.
+my_unknown_src_files := $(filter-out \
+  %.java %.aidl %.proto %.logtags %.fs %.rs, \
+  $(LOCAL_SRC_FILES) $(LOCAL_INTERMEDIATE_SOURCES) $(LOCAL_GENERATED_SOURCES))
+ifneq ($(my_unknown_src_files),)
+$(warning $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Unused source files: $(my_unknown_src_files))
+endif
+
 ######################################
 ## PRIVATE java vars
 # LOCAL_SOURCE_FILES_ALL_GENERATED is set only if the module does not have static source files,
@@ -305,7 +319,6 @@
 ###########################################################
 # JACK
 ###########################################################
-ifdef LOCAL_JACK_ENABLED
 ifdef need_compile_java
 
 LOCAL_JACK_FLAGS += -D jack.java.source.version=$(LOCAL_JAVA_LANGUAGE_VERSION)
@@ -317,54 +330,16 @@
 
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JACK_LIBRARIES := $(full_static_jack_libs)
 
-ifndef LOCAL_IS_HOST_MODULE
-ifeq ($(LOCAL_SDK_VERSION),)
-ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-my_bootclasspath :=
-else
-my_bootclasspath := $(call jack-lib-files,core-oj core-libart)
-endif
-else  # LOCAL_SDK_VERSION
-ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current)
-# LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS.
-my_bootclasspath := $(call jack-lib-files,android_stubs_current)
-else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current)
-my_bootclasspath := $(call jack-lib-files,android_system_stubs_current)
-else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
-my_bootclasspath := $(call jack-lib-files,android_test_stubs_current)
-else
-my_bootclasspath :=$(call jack-lib-files,sdk_v$(LOCAL_SDK_VERSION))
-endif # current, system_current, or test_current
-endif # LOCAL_SDK_VERSION
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(my_bootclasspath)
-
 full_shared_jack_libs := $(call jack-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
-full_jack_deps := $(call jack-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_jack_deps := $(full_shared_jack_libs)
+
+ifndef LOCAL_IS_HOST_MODULE
 # Turn off .toc optimization for apps build as we cannot build dexdump.
 ifeq (,$(TARGET_BUILD_APPS))
 full_jack_deps := $(patsubst %.jack, %.dex.toc, $(full_jack_deps))
 endif
-
-else # LOCAL_IS_HOST_MODULE
-
-ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
-ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-my_bootclasspath :=
-else
-my_bootclasspath := $(call jack-lib-files,core-oj-hostdex core-libart-hostdex,$(LOCAL_IS_HOST_MODULE))
-endif
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(my_bootclasspath)
-# Compiling against the final jack library. If we want to add support for obfuscated library
-# we'll need to change that to compile against the not obfuscated jack library.
-full_shared_jack_libs := $(call jack-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
-full_jack_deps := $(call jack-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
-else
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES :=
-full_shared_jack_libs := $(call jack-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
-full_jack_deps := $(full_shared_jack_libs)
-endif # USE_CORE_LIB_BOOTCLASSPATH
 endif # !LOCAL_IS_HOST_MODULE
-full_jack_libs := $(full_shared_jack_libs) $(full_static_jack_libs) $(LOCAL_JACK_CLASSPATH)
+full_shared_jack_libs += $(LOCAL_JACK_CLASSPATH)
 full_jack_deps += $(full_static_jack_libs) $(LOCAL_JACK_CLASSPATH)
 
 ifndef LOCAL_IS_HOST_MODULE
@@ -378,7 +353,6 @@
 
   # link against the jar with full original names (before proguard processing).
   full_shared_jack_libs += $(link_apk_jack_libraries)
-  full_jack_libs += $(link_apk_jack_libraries)
   full_jack_deps += $(link_apk_jack_libraries)
 endif
 
@@ -388,14 +362,51 @@
 ifdef LOCAL_INSTRUMENTATION_FOR
    # link against the jar with full original names (before proguard processing).
    link_instr_classes_jack := $(link_instr_intermediates_dir.COMMON)/classes.noshrob.jack
-   full_jack_libs += $(link_instr_classes_jack)
+   full_shared_jack_libs += $(link_instr_classes_jack)
    full_jack_deps += $(link_instr_classes_jack)
 endif  # LOCAL_INSTRUMENTATION_FOR
 endif  # !LOCAL_IS_HOST_MODULE
 
 # Propagate local configuration options to this target.
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_JACK_LIBRARIES:= $(full_jack_libs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_SHARED_LIBRARIES:= $(full_shared_jack_libs)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
 
 endif  # need_compile_java
-endif # LOCAL_JACK_ENABLED
+
+
+###########################################################
+# Verify that all libraries are safe to use
+###########################################################
+ifndef LOCAL_IS_HOST_MODULE
+my_link_type := $(intermediates.COMMON)/link_type
+all_link_types: $(my_link_type)
+my_link_type_deps := $(strip \
+  $(foreach lib,$(LOCAL_STATIC_JAVA_LIBRARIES),\
+    $(call intermediates-dir-for, \
+      JAVA_LIBRARIES,$(lib),,COMMON)/link_type) \
+  $(foreach lib,$(apk_libraries), \
+    $(call intermediates-dir-for, \
+      APPS,$(lib),,COMMON)/link_type))
+ifeq ($(LOCAL_SDK_VERSION),system_current)
+$(my_link_type): PRIVATE_LINK_TYPE := java:system
+$(my_link_type): PRIVATE_WARN_TYPES := java:platform
+$(my_link_type): PRIVATE_ALLOWED_TYPES := java:sdk java:system
+else ifneq ($(LOCAL_SDK_VERSION),)
+$(my_link_type): PRIVATE_LINK_TYPE := java:sdk
+$(my_link_type): PRIVATE_WARN_TYPES := java:system java:platform
+$(my_link_type): PRIVATE_ALLOWED_TYPES := java:sdk
+else
+$(my_link_type): PRIVATE_LINK_TYPE := java:platform
+$(my_link_type): PRIVATE_WARN_TYPES :=
+$(my_link_type): PRIVATE_ALLOWED_TYPES := java:sdk java:system java:platform
+endif
+$(eval $(call link-type-partitions,$(my_link_type)))
+$(my_link_type): PRIVATE_DEPS := $(my_link_type_deps)
+$(my_link_type): PRIVATE_MODULE := $(LOCAL_MODULE)
+$(my_link_type): PRIVATE_MAKEFILE := $(LOCAL_MODULE_MAKEFILE)
+$(my_link_type): $(my_link_type_deps) $(CHECK_LINK_TYPE)
+	@echo Check Java library module types: $@
+	$(check-link-type)
+
+$(LOCAL_BUILT_MODULE): $(my_link_type)
+endif  # !LOCAL_IS_HOST_MODULE
diff --git a/core/java_library.mk b/core/java_library.mk
index 81a4a6a..b132fa6 100644
--- a/core/java_library.mk
+++ b/core/java_library.mk
@@ -2,6 +2,7 @@
 ## Standard rules for building a java library.
 ##
 ###########################################################
+$(call record-module-type,JAVA_LIBRARY)
 
 ifdef LOCAL_IS_HOST_MODULE
 $(error $(LOCAL_PATH): Host java libraries must use BUILD_HOST_JAVA_LIBRARY)
@@ -28,11 +29,9 @@
 include $(BUILD_SYSTEM)/configure_local_jack.mk
 #################################
 
-ifdef LOCAL_JACK_ENABLED
 ifdef LOCAL_IS_STATIC_JAVA_LIBRARY
 LOCAL_BUILT_MODULE_STEM := classes.jack
 endif
-endif
 
 intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
@@ -47,12 +46,8 @@
 ifeq (true,$(EMMA_INSTRUMENT))
 ifeq (true,$(LOCAL_EMMA_INSTRUMENT))
 ifeq (true,$(EMMA_INSTRUMENT_STATIC))
-ifdef LOCAL_JACK_ENABLED
 # Jack supports coverage with Jacoco
 LOCAL_STATIC_JAVA_LIBRARIES += jacocoagent
-else
-LOCAL_STATIC_JAVA_LIBRARIES += emma
-endif # LOCAL_JACK_ENABLED
 endif # LOCAL_EMMA_INSTRUMENT
 endif # EMMA_INSTRUMENT_STATIC
 else
@@ -66,44 +61,28 @@
 ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
 # No dex; all we want are the .class files with resources.
 $(common_javalib.jar) : $(java_resource_sources)
-ifdef LOCAL_PROGUARD_ENABLED
-$(common_javalib.jar) : $(full_classes_proguard_jar)
-else
 $(common_javalib.jar) : $(full_classes_jar)
-endif
 	@echo "target Static Jar: $(PRIVATE_MODULE) ($@)"
 	$(copy-file-to-target)
 
-ifdef LOCAL_JACK_ENABLED
 $(LOCAL_BUILT_MODULE) : $(full_classes_jack)
-else
-$(LOCAL_BUILT_MODULE) : $(common_javalib.jar)
-endif
 	$(copy-file-to-target)
 
 else # !LOCAL_IS_STATIC_JAVA_LIBRARY
 
 $(common_javalib.jar): PRIVATE_DEX_FILE := $(built_dex)
-$(common_javalib.jar): PRIVATE_SOURCE_ARCHIVE := $(full_classes_jarjar_jar)
-$(common_javalib.jar): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
 $(common_javalib.jar) : $(built_dex) $(java_resource_sources) | $(ZIPTIME)
 	@echo "target Jar: $(PRIVATE_MODULE) ($@)"
-ifdef LOCAL_JACK_ENABLED
 	$(create-empty-package)
-else
-	$(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@)
-endif
 	$(add-dex-to-package)
-ifdef LOCAL_JACK_ENABLED
 	$(add-carried-jack-resources)
-endif
 	$(remove-timestamps-from-package)
 
 ifdef LOCAL_DEX_PREOPT
 ifneq ($(dexpreopt_boot_jar_module),) # boot jar
 # boot jar's rules are defined in dex_preopt.mk
 dexpreopted_boot_jar := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(dexpreopt_boot_jar_module)_nodex.jar
-$(LOCAL_BUILT_MODULE) : $(dexpreopted_boot_jar) | $(ACP)
+$(LOCAL_BUILT_MODULE) : $(dexpreopted_boot_jar)
 	$(call copy-file-to-target)
 
 # For libart boot jars, we don't have .odex files.
@@ -114,7 +93,7 @@
 	@echo "Dexpreopt Jar: $(PRIVATE_MODULE) ($@)"
 	$(call dexpreopt-one-file,$<,$@)
 
-$(LOCAL_BUILT_MODULE) : $(common_javalib.jar) | $(ACP)
+$(LOCAL_BUILT_MODULE) : $(common_javalib.jar)
 	$(call copy-file-to-target)
 ifneq (nostripping,$(LOCAL_DEX_PREOPT))
 	$(call dexpreopt-remove-classes.dex,$@)
@@ -123,7 +102,7 @@
 endif # ! boot jar
 
 else # LOCAL_DEX_PREOPT
-$(LOCAL_BUILT_MODULE) : $(common_javalib.jar) | $(ACP)
+$(LOCAL_BUILT_MODULE) : $(common_javalib.jar)
 	$(call copy-file-to-target)
 
 endif # LOCAL_DEX_PREOPT
diff --git a/core/legacy_prebuilts.mk b/core/legacy_prebuilts.mk
deleted file mode 100644
index f4633d0..0000000
--- a/core/legacy_prebuilts.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# This is the list of modules grandfathered to use ALL_PREBUILT
-
-# DO NOT ADD ANY NEW MODULE TO THIS FILE
-#
-# ALL_PREBUILT modules are hard to control and audit and we don't want
-# to add any new such module in the system
-
-GRANDFATHERED_ALL_PREBUILT := \
-	bmgr \
-	ime \
-	input \
-	monkey \
-	pm \
-	RFFspeed_501.bmd \
-	RFFstd_501.bmd \
-	svc
diff --git a/core/main.mk b/core/main.mk
index 651ba98..fee2995 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -57,9 +57,6 @@
 
 BUILD_SYSTEM := $(TOPDIR)build/core
 
-# Ensure JAVA_NOT_REQUIRED is not set externally.
-JAVA_NOT_REQUIRED := false
-
 # This is the default target.  It must be the first declared target.
 .PHONY: droid
 DEFAULT_GOAL := droid
@@ -80,10 +77,12 @@
     stnod systemtarball-nodeps \
     userdataimage-nodeps userdatatarball-nodeps \
     cacheimage-nodeps \
+    bptimage-nodeps \
     vendorimage-nodeps \
     ramdisk-nodeps \
     bootimage-nodeps \
     recoveryimage-nodeps \
+    vbmetaimage-nodeps \
     product-graph dump-products
 
 ifneq ($(filter $(dont_bother_goals), $(MAKECMDGOALS)),)
@@ -99,22 +98,17 @@
 # and host information.
 include $(BUILD_SYSTEM)/config.mk
 
-relaunch_with_ninja :=
-ifneq ($(USE_NINJA),false)
-ifndef BUILDING_WITH_NINJA
-relaunch_with_ninja := true
-endif
+ifndef KATI
+ifdef USE_NINJA
+$(warning USE_NINJA is ignored. Ninja is always used.)
 endif
 
-ifeq ($(relaunch_with_ninja),true)
 # Mark this is a ninja build.
 $(shell mkdir -p $(OUT_DIR) && touch $(OUT_DIR)/ninja_build)
 include build/core/ninja.mk
-else # !relaunch_with_ninja
-ifndef BUILDING_WITH_NINJA
-# Remove ninja build mark if it exists.
-$(shell rm -f $(OUT_DIR)/ninja_build)
-endif
+else # KATI
+
+include $(SOONG_MAKEVARS_MK)
 
 # Write the build number to a file so it can be read back in
 # without changing the command line every time.  Avoids rebuilds
@@ -145,8 +139,9 @@
 -include vendor/google/build/config.mk
 
 VERSION_CHECK_SEQUENCE_NUMBER := 6
+JAVA_NOT_REQUIRED_CHECKED :=
 -include $(OUT_DIR)/versions_checked.mk
-ifneq ($(VERSION_CHECK_SEQUENCE_NUMBER),$(VERSIONS_CHECKED))
+ifneq ($(VERSION_CHECK_SEQUENCE_NUMBER)$(JAVA_NOT_REQUIRED),$(VERSIONS_CHECKED)$(JAVA_NOT_REQUIRED_CHECKED))
 
 $(info Checking build tools versions...)
 
@@ -177,7 +172,7 @@
 $(error Directory names containing spaces not supported)
 endif
 
-ifeq ($(JAVA_NOT_REQUIRED), false)
+ifneq ($(JAVA_NOT_REQUIRED),true)
 java_version_str := $(shell unset _JAVA_OPTIONS && java -version 2>&1)
 javac_version_str := $(shell unset _JAVA_OPTIONS && javac -version 2>&1)
 
@@ -279,6 +274,8 @@
         > $(OUT_DIR)/versions_checked.mk)
 $(shell echo 'BUILD_EMULATOR ?= $(BUILD_EMULATOR)' \
         >> $(OUT_DIR)/versions_checked.mk)
+$(shell echo 'JAVA_NOT_REQUIRED_CHECKED := $(JAVA_NOT_REQUIRED)' \
+        >> $(OUT_DIR)/versions_checked.mk)
 endif
 
 # These are the modifier targets that don't do anything themselves, but
@@ -456,6 +453,9 @@
 $(error The 'sdk' target may not be specified with any other targets)
 endif
 
+# AUX dependencies are already added by now; remove triggers from the MAKECMDGOALS
+MAKECMDGOALS := $(strip $(filter-out AUX-%,$(MAKECMDGOALS)))
+
 # TODO: this should be eng I think.  Since the sdk is built from the eng
 # variant.
 tags_to_install := debug eng
@@ -501,7 +501,6 @@
 #
 # Typical build; include any Android.mk files we can find.
 #
-subdirs := $(TOP)
 
 FULL_BUILD := true
 
@@ -515,7 +514,7 @@
 ifneq ($(ONE_SHOT_MAKEFILE),)
 # We've probably been invoked by the "mm" shell function
 # with a subdirectory's makefile.
-include $(ONE_SHOT_MAKEFILE)
+include $(SOONG_ANDROID_MK) $(wildcard $(ONE_SHOT_MAKEFILE))
 # Change CUSTOM_MODULES to include only modules that were
 # defined by this makefile; this will install all of those
 # modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE
@@ -529,11 +528,28 @@
 NOTICE-TARGET-%: ;
 
 # A helper goal printing out install paths
-.PHONY: GET-INSTALL-PATH
-GET-INSTALL-PATH:
-	@echo "Install paths for modules in $(ONE_SHOT_MAKEFILE):"
-	@$(foreach m, $(ALL_MODULES), $(if $(ALL_MODULES.$(m).INSTALLED), \
-		echo 'INSTALL-PATH: $(m) $(ALL_MODULES.$(m).INSTALLED)';))
+define register_module_install_path
+.PHONY: GET-MODULE-INSTALL-PATH-$(1)
+GET-MODULE-INSTALL-PATH-$(1):
+	echo 'INSTALL-PATH: $(1) $(ALL_MODULES.$(1).INSTALLED)'
+endef
+
+SORTED_ALL_MODULES := $(sort $(ALL_MODULES))
+UNIQUE_ALL_MODULES :=
+$(foreach m,$(SORTED_ALL_MODULES),\
+    $(if $(call streq,$(m),$(lastword $(UNIQUE_ALL_MODULES))),,\
+        $(eval UNIQUE_ALL_MODULES += $(m))))
+SORTED_ALL_MODULES :=
+
+$(foreach mod,$(UNIQUE_ALL_MODULES),$(if $(ALL_MODULES.$(mod).INSTALLED),\
+    $(eval $(call register_module_install_path,$(mod)))\
+    $(foreach path,$(ALL_MODULES.$(mod).PATH),\
+        $(eval my_path_prefix := GET-INSTALL-PATH-IN)\
+        $(foreach component,$(subst /,$(space),$(path)),\
+            $(eval my_path_prefix := $$(my_path_prefix)-$$(component))\
+            $(eval .PHONY: $$(my_path_prefix))\
+            $(eval $$(my_path_prefix): GET-MODULE-INSTALL-PATH-$(mod))))))
+UNIQUE_ALL_MODULES :=
 
 else # ONE_SHOT_MAKEFILE
 
@@ -542,16 +558,9 @@
 # Include all of the makefiles in the system
 #
 
-# Can't use first-makefiles-under here because
-# --mindepth=2 makes the prunes not work.
-subdir_makefiles := \
-	$(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) $(subdirs) Android.mk)
+subdir_makefiles := $(SOONG_ANDROID_MK) $(call first-makefiles-under,$(TOP))
 
-ifeq ($(USE_SOONG),true)
-subdir_makefiles := $(SOONG_ANDROID_MK) $(call filter-soong-makefiles,$(subdir_makefiles))
-endif
-
-$(foreach mk, $(subdir_makefiles),$(info including $(mk) ...)$(eval include $(mk)))
+$(foreach mk,$(subdir_makefiles),$(info including $(mk) ...)$(eval include $(mk)))
 
 ifdef PDK_FUSION_PLATFORM_ZIP
 # Bring in the PDK platform.zip modules.
@@ -569,22 +578,6 @@
   $(call assert-product-vars, __STASHED)
 endif
 
-include $(BUILD_SYSTEM)/legacy_prebuilts.mk
-ifneq ($(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),)
-  $(warning *** Some files have been added to ALL_PREBUILT.)
-  $(warning *)
-  $(warning * ALL_PREBUILT is a deprecated mechanism that)
-  $(warning * should not be used for new files.)
-  $(warning * As an alternative, use PRODUCT_COPY_FILES in)
-  $(warning * the appropriate product definition.)
-  $(warning * build/target/product/core.mk is the product)
-  $(warning * definition used in all products.)
-  $(warning *)
-  $(foreach bad_prebuilt,$(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),$(warning * unexpected $(bad_prebuilt) in ALL_PREBUILT))
-  $(warning *)
-  $(error ALL_PREBUILT contains unexpected files)
-endif
-
 # -------------------------------------------------------------------
 # All module makefiles have been included at this point.
 # -------------------------------------------------------------------
@@ -612,19 +605,33 @@
 #
 # 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
-$(strip $(foreach m,$(1),\
+$(sort $(foreach m,$(1),\
   $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\
-    $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX))))
+    $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX))\
+  $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\
+    $(m)$(HOST_2ND_ARCH_MODULE_SUFFIX))\
+    ))
 endef
 # Get a list of corresponding 32-bit module names, if one exists;
 # otherwise return the original module name
 define get-32-bit-modules-if-we-can
-$(strip $(foreach m,$(1),\
-  $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),\
-    $(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX),
-    $(m))))
+$(sort $(foreach m,$(1),\
+  $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS)$(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),\
+    $(if $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).CLASS),$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX)) \
+    $(if $(ALL_MODULES.$(m)$(HOST_2ND_ARCH_MODULE_SUFFIX).CLASS),$(m)$(HOST_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
 
 # If a module is for a cross host os, the required modules must be for
 # that OS too.
@@ -639,7 +646,7 @@
       $(eval r := $(addprefix host_cross_,$(r))))\
     $(if $(ALL_MODULES.$(m).FOR_2ND_ARCH),\
       $(eval r_r := $(call get-32-bit-modules-if-we-can,$(r))),\
-      $(if $(filter EXECUTABLES SHARED_LIBRARIES,$(ALL_MODULES.$(m).CLASS)),\
+      $(if $(filter EXECUTABLES SHARED_LIBRARIES NATIVE_TESTS,$(ALL_MODULES.$(m).CLASS)),\
         $(eval r_r := $(r)),\
         $(eval r_r := $(r) $(call get-32-bit-modules,$(r)))\
        )\
@@ -658,11 +665,11 @@
   $(if $(r), \
     $(eval r := $(call module-installed-files,$(r))) \
     $(eval t_m := $(filter $(TARGET_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
-    $(eval h_m := $(filter $(HOST_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
-    $(eval hc_m := $(filter $(HOST_CROSS_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
+    $(eval h_m := $(filter $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
+    $(eval hc_m := $(filter $(HOST_CROSS_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
     $(eval t_r := $(filter $(TARGET_OUT_ROOT)/%, $(r))) \
-    $(eval h_r := $(filter $(HOST_OUT_ROOT)/%, $(r))) \
-    $(eval hc_r := $(filter $(HOST_CROSS_OUT_ROOT)/%, $(r))) \
+    $(eval h_r := $(filter $(HOST_OUT)/%, $(r))) \
+    $(eval hc_r := $(filter $(HOST_CROSS_OUT)/%, $(r))) \
     $(eval t_m := $(filter-out $(t_r), $(t_m))) \
     $(eval h_m := $(filter-out $(h_r), $(h_m))) \
     $(eval hc_m := $(filter-out $(hc_r), $(hc_m))) \
@@ -690,9 +697,10 @@
   $(eval p := $(subst :,$(space),$(m)))\
   $(eval mod := $(firstword $(p)))\
   $(eval deps := $(subst $(comma),$(space),$(lastword $(p))))\
+  $(eval root := $(1)OUT$(if $(call streq,$(1),TARGET_),_ROOT))\
   $(if $(2),$(eval deps := $(addsuffix $($(1)2ND_ARCH_MODULE_SUFFIX),$(deps))))\
   $(if $(3),$(eval deps := $(addprefix host_cross_,$(deps))))\
-  $(eval r := $(filter $($(1)OUT)/%,$(call module-installed-files,\
+  $(eval r := $(filter $($(root))/%,$(call module-installed-files,\
     $(deps))))\
   $(eval $(call add-required-deps,$(word 2,$(p)),$(r)))\
   $(eval ALL_MODULES.$(mod).REQUIRED += $(deps)))
@@ -875,9 +883,6 @@
 # This is used to to get the ordering right, you can also use these,
 # but they're considered undocumented, so don't complain if their
 # behavior changes.
-.PHONY: prebuilt
-prebuilt: $(ALL_PREBUILT)
-
 # An internal target that depends on all copied headers
 # (see copy_headers.make).  Other targets that need the
 # headers to be copied first can depend on this target.
@@ -888,17 +893,15 @@
 
 # All the droid stuff, in directories
 .PHONY: files
-files: prebuilt \
-        $(modules_to_install) \
-        $(INSTALLED_ANDROID_INFO_TXT_TARGET)
+files: $(modules_to_install) \
+       $(INSTALLED_ANDROID_INFO_TXT_TARGET)
 
 # -------------------------------------------------------------------
 
 .PHONY: checkbuild
 checkbuild: $(modules_to_check) droid_targets
-ifeq ($(USE_SOONG),true)
 checkbuild: checkbuild-soong
-endif
+
 ifeq (true,$(ANDROID_BUILD_EVERYTHING_BY_DEFAULT))
 droid: checkbuild
 endif
@@ -925,26 +928,20 @@
 .PHONY: cacheimage
 cacheimage: $(INSTALLED_CACHEIMAGE_TARGET)
 
+.PHONY: bptimage
+bptimage: $(INSTALLED_BPTIMAGE_TARGET)
+
 .PHONY: vendorimage
 vendorimage: $(INSTALLED_VENDORIMAGE_TARGET)
 
 .PHONY: bootimage
 bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
 
-# phony target that include any targets in $(ALL_MODULES)
-.PHONY: all_modules
-ifndef BUILD_MODULES_IN_PATHS
-all_modules: $(ALL_MODULES)
-else
-# BUILD_MODULES_IN_PATHS is a list of paths relative to the top of the tree
-build_modules_in_paths := $(patsubst ./%,%,$(BUILD_MODULES_IN_PATHS))
-module_path_patterns := $(foreach p, $(build_modules_in_paths),\
-    $(if $(filter %/,$(p)),$(p)%,$(p)/%))
-my_all_modules := $(sort $(foreach m, $(ALL_MODULES),$(if $(filter\
-    $(module_path_patterns), $(addsuffix /,$(ALL_MODULES.$(m).PATH))),$(m))))
-all_modules: $(my_all_modules)
-endif
+.PHONY: vbmetaimage
+vbmetaimage: $(INSTALLED_VBMETAIMAGE_TARGET)
 
+.PHONY: auxiliary
+auxiliary: $(INSTALLED_AUX_TARGETS)
 
 # Build files and then package it into the rom formats
 .PHONY: droidcore
@@ -952,8 +949,10 @@
 	systemimage \
 	$(INSTALLED_BOOTIMAGE_TARGET) \
 	$(INSTALLED_RECOVERYIMAGE_TARGET) \
+	$(INSTALLED_VBMETAIMAGE_TARGET) \
 	$(INSTALLED_USERDATAIMAGE_TARGET) \
 	$(INSTALLED_CACHEIMAGE_TARGET) \
+	$(INSTALLED_BPTIMAGE_TARGET) \
 	$(INSTALLED_VENDORIMAGE_TARGET) \
 	$(INSTALLED_FILES_FILE) \
 	$(INSTALLED_FILES_FILE_VENDOR)
@@ -995,6 +994,9 @@
   $(SYMBOLS_ZIP) : $(apps_only_installed_files)
   $(call dist-for-goals,apps_only, $(SYMBOLS_ZIP))
 
+  $(COVERAGE_ZIP) : $(apps_only_installed_files)
+  $(call dist-for-goals,apps_only, $(COVERAGE_ZIP))
+
 .PHONY: apps_only
 apps_only: $(unbundled_build_modules)
 
@@ -1015,6 +1017,7 @@
     $(INTERNAL_OTA_PACKAGE_TARGET) \
     $(BUILT_OTATOOLS_PACKAGE) \
     $(SYMBOLS_ZIP) \
+    $(COVERAGE_ZIP) \
     $(INSTALLED_FILES_FILE) \
     $(INSTALLED_FILES_FILE_VENDOR) \
     $(INSTALLED_BUILD_PROP_TARGET) \
@@ -1057,6 +1060,7 @@
 $(call dist-for-goals,sdk win_sdk, \
     $(ALL_SDK_TARGETS) \
     $(SYMBOLS_ZIP) \
+    $(COVERAGE_ZIP) \
     $(INSTALLED_BUILD_PROP_TARGET) \
 )
 
@@ -1075,6 +1079,9 @@
 target-native-tests : native-target-tests
 tests : host-tests target-tests
 
+# Phony target to run all java compilations that use javac instead of jack.
+.PHONY: javac-check
+
 # To catch more build breakage, check build tests modules in eng and userdebug builds.
 ifneq ($(ANDROID_NO_TEST_CHECK),true)
 ifneq ($(TARGET_BUILD_PDK),true)
@@ -1093,7 +1100,7 @@
 $(foreach module,$(sample_MODULES),$(eval $(call \
         copy-one-file,$(module),$(sample_APKS_DEST_PATH)/$(notdir $(module)))))
 sample_ADDITIONAL_INSTALLED := \
-        $(filter-out $(modules_to_install) $(modules_to_check) $(ALL_PREBUILT),$(sample_MODULES))
+        $(filter-out $(modules_to_install) $(modules_to_check),$(sample_MODULES))
 samplecode: $(sample_APKS_COLLECTION)
 	@echo "Collect sample code apks: $^"
 	# remove apks that are not intended to be installed.
@@ -1127,4 +1134,15 @@
 .PHONY: nothing
 nothing:
 	@echo Successfully read the makefiles.
-endif # !relaunch_with_ninja
+
+.PHONY: tidy_only
+tidy_only:
+	@echo Successfully make tidy_only.
+
+ndk: $(SOONG_OUT_DIR)/ndk.timestamp
+.PHONY: ndk
+
+.PHONY: all_link_types
+all_link_types:
+
+endif # KATI
diff --git a/core/multi_prebuilt.mk b/core/multi_prebuilt.mk
index ed2fed6..77c57ab 100644
--- a/core/multi_prebuilt.mk
+++ b/core/multi_prebuilt.mk
@@ -14,6 +14,7 @@
 # limitations under the License.
 #
 
+$(call record-module-type,MULTI_PREBUILT)
 ifneq ($(LOCAL_MODULE)$(LOCAL_MODULE_CLASS),)
 $(error $(LOCAL_PATH): LOCAL_MODULE or LOCAL_MODULE_CLASS not needed by \
   BUILD_MULTI_PREBUILT, use BUILD_PREBUILT instead!)
diff --git a/core/native_benchmark.mk b/core/native_benchmark.mk
index ac37701..e73bcad 100644
--- a/core/native_benchmark.mk
+++ b/core/native_benchmark.mk
@@ -2,6 +2,7 @@
 ## A thin wrapper around BUILD_EXECUTABLE
 ## Common flags for native benchmarks are added.
 ###########################################
+$(call record-module-type,NATIVE_BENCHMARK)
 
 LOCAL_STATIC_LIBRARIES += libgoogle-benchmark
 
diff --git a/core/native_test.mk b/core/native_test.mk
index 93b7e1a..8b49fbd 100644
--- a/core/native_test.mk
+++ b/core/native_test.mk
@@ -2,6 +2,15 @@
 ## A thin wrapper around BUILD_EXECUTABLE
 ## Common flags for native tests are added.
 ###########################################
+$(call record-module-type,NATIVE_TEST)
+
+ifdef LOCAL_MODULE_CLASS
+ifneq ($(LOCAL_MODULE_CLASS),NATIVE_TESTS)
+$(error $(LOCAL_PATH): LOCAL_MODULE_CLASS must be NATIVE_TESTS with BUILD_HOST_NATIVE_TEST)
+endif
+endif
+
+LOCAL_MODULE_CLASS := NATIVE_TESTS
 
 include $(BUILD_SYSTEM)/target_test_internal.mk
 
diff --git a/core/ninja.mk b/core/ninja.mk
index 9d0ff9a..f3aa70e 100644
--- a/core/ninja.mk
+++ b/core/ninja.mk
@@ -1,15 +1,6 @@
-NINJA ?= prebuilts/ninja/$(HOST_PREBUILT_TAG)/ninja
+NINJA ?= prebuilts/build-tools/$(HOST_PREBUILT_TAG)/bin/ninja
 
-ifeq ($(USE_SOONG),true)
-USE_SOONG_FOR_KATI := true
-endif
-
-ifeq ($(USE_SOONG_FOR_KATI),true)
 include $(BUILD_SYSTEM)/soong.mk
-else
-KATI ?= $(HOST_OUT_EXECUTABLES)/ckati
-MAKEPARALLEL ?= $(HOST_OUT_EXECUTABLES)/makeparallel
-endif
 
 KATI_OUTPUT_PATTERNS := $(OUT_DIR)/build%.ninja $(OUT_DIR)/ninja%.sh
 
@@ -26,7 +17,9 @@
 	DUMP_% \
 	ECLIPSE-% \
 	PRODUCT-% \
+	AUX-% \
 	boottarball-nodeps \
+	brillo_tests \
 	btnod \
 	build-art% \
 	build_kernel-nodeps \
@@ -70,7 +63,7 @@
 -include vendor/google/build/ninja_config.mk
 
 # Any Android goals that need to be built.
-ANDROID_GOALS := $(filter-out $(KATI_OUTPUT_PATTERNS) $(KATI) $(MAKEPARALLEL),\
+ANDROID_GOALS := $(filter-out $(KATI_OUTPUT_PATTERNS) $(CKATI) $(MAKEPARALLEL),\
     $(sort $(ORIGINAL_MAKECMDGOALS) $(MAKECMDGOALS)))
 # Goals we need to pass to Ninja.
 NINJA_GOALS := $(filter-out $(NINJA_EXCLUDE_GOALS), $(ANDROID_GOALS))
@@ -88,9 +81,6 @@
 ifneq ($(ONE_SHOT_MAKEFILE),)
 KATI_NINJA_SUFFIX := $(KATI_NINJA_SUFFIX)-mmm-$(call replace_space_and_slash,$(ONE_SHOT_MAKEFILE))
 endif
-ifneq ($(BUILD_MODULES_IN_PATHS),)
-KATI_NINJA_SUFFIX := $(KATI_NINJA_SUFFIX)-mmma-$(call replace_space_and_slash,$(BUILD_MODULES_IN_PATHS))
-endif
 
 my_checksum_suffix :=
 my_ninja_suffix_too_long := $(filter 1, $(shell v='$(KATI_NINJA_SUFFIX)' && echo $$(($${$(pound)v} > 64))))
@@ -111,34 +101,46 @@
 endif
 
 ifeq (,$(NINJA_STATUS))
-NINJA_STATUS := [%p %s/%t]$(space)
+NINJA_STATUS := [%p %f/%t]$(space)
 endif
 
+NINJA_EXTRA_ARGS :=
+
 ifneq (,$(filter showcommands,$(ORIGINAL_MAKECMDGOALS)))
-NINJA_ARGS += "-v"
+NINJA_EXTRA_ARGS += "-v"
 endif
 
-ifdef USE_GOMA
+# Make multiple rules to generate the same target an error instead of
+# proceeding with undefined behavior.
+NINJA_EXTRA_ARGS += -w dupbuild=err
+
+ifneq ($(filter-out false,$(USE_GOMA)),)
 KATI_MAKEPARALLEL := $(MAKEPARALLEL)
 # Ninja runs remote jobs (i.e., commands which contain gomacc) with
 # this parallelism. Note the parallelism of all other jobs is still
 # limited by the -j flag passed to GNU make.
 NINJA_REMOTE_NUM_JOBS ?= 500
-NINJA_ARGS += -j$(NINJA_REMOTE_NUM_JOBS)
+NINJA_EXTRA_ARGS += -j$(NINJA_REMOTE_NUM_JOBS)
 else
 NINJA_MAKEPARALLEL := $(MAKEPARALLEL) --ninja
+
+# We never want Kati to see MAKEFLAGS, as forcefully overriding variables is
+# terrible. The variables in MAKEFLAGS are still available in the environment,
+# so if part of the build wants input from the user, it should be explicitly
+# checking for an environment variable or using ?=
+#
+# makeparallel already clears MAKEFLAGS, so it's not necessary in the GOMA case
+KATI_MAKEPARALLEL := MAKEFLAGS=
 endif
 
-ifeq ($(USE_SOONG),true)
+NINJA_ARGS += $(NINJA_EXTRA_ARGS)
+
 COMBINED_BUILD_NINJA := $(OUT_DIR)/combined$(KATI_NINJA_SUFFIX).ninja
 
-$(COMBINED_BUILD_NINJA): $(KATI_BUILD_NINJA) $(SOONG_ANDROID_MK)
+$(COMBINED_BUILD_NINJA): $(KATI_BUILD_NINJA)
 	$(hide) echo "builddir = $(OUT_DIR)" > $(COMBINED_BUILD_NINJA)
-	$(hide) echo "subninja $(SOONG_BUILD_NINJA)" >> $(COMBINED_BUILD_NINJA)
-	$(hide) echo "subninja $(KATI_BUILD_NINJA)" >> $(COMBINED_BUILD_NINJA)
-else
-COMBINED_BUILD_NINJA := $(KATI_BUILD_NINJA)
-endif
+	$(hide) echo "include $(KATI_BUILD_NINJA)" >> $(COMBINED_BUILD_NINJA)
+	$(hide) echo "include $(SOONG_BUILD_NINJA)" >> $(COMBINED_BUILD_NINJA)
 
 $(sort $(DEFAULT_GOAL) $(ANDROID_GOALS)) : ninja_wrapper
 	@#empty
@@ -159,34 +161,9 @@
 ifeq ($(KATI_EMULATE_FIND),false)
   KATI_FIND_EMULATOR :=
 endif
-$(KATI_BUILD_NINJA): $(KATI) $(MAKEPARALLEL) $(DUMMY_OUT_MKS) $(SOONG_ANDROID_MK) FORCE
+$(KATI_BUILD_NINJA): $(CKATI) $(MAKEPARALLEL) $(DUMMY_OUT_MKS) run_soong FORCE
 	@echo Running kati to generate build$(KATI_NINJA_SUFFIX).ninja...
-	+$(hide) $(KATI_MAKEPARALLEL) $(KATI) --ninja --ninja_dir=$(OUT_DIR) --ninja_suffix=$(KATI_NINJA_SUFFIX) --regen --ignore_dirty=$(OUT_DIR)/% --no_ignore_dirty=$(SOONG_ANDROID_MK) --ignore_optional_include=$(OUT_DIR)/%.P --detect_android_echo $(KATI_FIND_EMULATOR) -f build/core/main.mk $(KATI_GOALS) --gen_all_targets BUILDING_WITH_NINJA=true SOONG_ANDROID_MK=$(SOONG_ANDROID_MK)
-
-ifneq ($(USE_SOONG_FOR_KATI),true)
-KATI_CXX := $(CLANG_CXX) $(CLANG_HOST_GLOBAL_CFLAGS) $(CLANG_HOST_GLOBAL_CPPFLAGS)
-KATI_LD := $(CLANG_CXX) $(CLANG_HOST_GLOBAL_LDFLAGS)
-# Build static ckati. Unfortunately Mac OS X doesn't officially support static exectuables.
-ifeq ($(BUILD_OS),linux)
-# We need everything in libpthread.a otherwise C++11's threading library will be disabled.
-KATI_LD += -static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl
-endif
-
-KATI_INTERMEDIATES_PATH := $(HOST_OUT_INTERMEDIATES)/EXECUTABLES/ckati_intermediates
-KATI_BIN_PATH := $(HOST_OUT_EXECUTABLES)
-include build/kati/Makefile.ckati
-
-MAKEPARALLEL_CXX := $(CLANG_CXX) $(CLANG_HOST_GLOBAL_CFLAGS) $(CLANG_HOST_GLOBAL_CPPFLAGS)
-MAKEPARALLEL_LD := $(CLANG_CXX) $(CLANG_HOST_GLOBAL_LDFLAGS)
-# Build static makeparallel. Unfortunately Mac OS X doesn't officially support static exectuables.
-ifeq ($(BUILD_OS),linux)
-MAKEPARALLEL_LD += -static
-endif
-
-MAKEPARALLEL_INTERMEDIATES_PATH := $(HOST_OUT_INTERMEDIATES)/EXECUTABLES/makeparallel_intermediates
-MAKEPARALLEL_BIN_PATH := $(HOST_OUT_EXECUTABLES)
-include build/tools/makeparallel/Makefile
-endif
+	+$(hide) $(KATI_MAKEPARALLEL) $(CKATI) --ninja --ninja_dir=$(OUT_DIR) --ninja_suffix=$(KATI_NINJA_SUFFIX) --regen --ignore_dirty=$(OUT_DIR)/% --no_ignore_dirty=$(SOONG_OUT_DIR)/%.mk --ignore_optional_include=$(OUT_DIR)/%.P --detect_android_echo $(KATI_FIND_EMULATOR) -f build/core/main.mk $(KATI_GOALS) --gen_all_targets BUILDING_WITH_NINJA=true SOONG_ANDROID_MK=$(SOONG_ANDROID_MK) SOONG_MAKEVARS_MK=$(SOONG_MAKEVARS_MK)
 
 .PHONY: FORCE
 FORCE:
diff --git a/core/no_java_path/jar b/core/no_java_path/jar
new file mode 120000
index 0000000..8586397
--- /dev/null
+++ b/core/no_java_path/jar
@@ -0,0 +1 @@
+java
\ No newline at end of file
diff --git a/core/no_java_path/jarsigner b/core/no_java_path/jarsigner
new file mode 120000
index 0000000..8586397
--- /dev/null
+++ b/core/no_java_path/jarsigner
@@ -0,0 +1 @@
+java
\ No newline at end of file
diff --git a/core/no_java_path/java b/core/no_java_path/java
new file mode 100755
index 0000000..f3422f3
--- /dev/null
+++ b/core/no_java_path/java
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+echo "Error: JAVA_NOT_REQUIRED=true, $(basename $0) is unavailable." 1>&2
+exit 1
diff --git a/core/no_java_path/javac b/core/no_java_path/javac
new file mode 120000
index 0000000..8586397
--- /dev/null
+++ b/core/no_java_path/javac
@@ -0,0 +1 @@
+java
\ No newline at end of file
diff --git a/core/no_java_path/keytool b/core/no_java_path/keytool
new file mode 120000
index 0000000..8586397
--- /dev/null
+++ b/core/no_java_path/keytool
@@ -0,0 +1 @@
+java
\ No newline at end of file
diff --git a/core/notice_files.mk b/core/notice_files.mk
index e7f8974..f0013c2 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -1,6 +1,7 @@
 ###########################################################
 ## Track NOTICE files
 ###########################################################
+$(call record-module-type,NOTICE_FILE)
 
 ifneq ($(LOCAL_NOTICE_FILE),)
 notice_file:=$(strip $(LOCAL_NOTICE_FILE))
diff --git a/core/package.mk b/core/package.mk
index 78b65db..4fe058d 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -2,6 +2,12 @@
 # TARGET_ARCH and TARGET_2ND_ARCH.
 # To build it for TARGET_2ND_ARCH in a 64bit product, use "LOCAL_MULTILIB := 32".
 
+$(call record-module-type,PACKAGE)
+
+ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
+LOCAL_MULTILIB := first
+endif
+
 my_prefix := TARGET_
 include $(BUILD_SYSTEM)/multilib.mk
 
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 551f18e..af1d2a5 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -209,12 +209,10 @@
 endif # !custom
 LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
 
-ifdef LOCAL_JACK_ENABLED
 ifndef LOCAL_JACK_PROGUARD_FLAGS
     LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
 endif
 LOCAL_JACK_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_JACK_PROGUARD_FLAGS)
-endif # LOCAL_JACK_ENABLED
 
 ifeq (true,$(EMMA_INSTRUMENT))
 ifndef LOCAL_EMMA_INSTRUMENT
@@ -227,52 +225,35 @@
 LOCAL_EMMA_INSTRUMENT := false
 endif # EMMA_INSTRUMENT is true
 
-ifeq (true,$(LOCAL_EMMA_INSTRUMENT))
-ifeq (true,$(EMMA_INSTRUMENT_STATIC))
-ifdef LOCAL_JACK_ENABLED
-# Jack supports coverage with Jacoco
 ifneq ($(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),)
 # Only add jacocoagent if the package contains some java code
+ifeq (true,$(LOCAL_EMMA_INSTRUMENT))
+ifeq (true,$(EMMA_INSTRUMENT_STATIC))
+# Jack supports coverage with Jacoco
 LOCAL_STATIC_JAVA_LIBRARIES += jacocoagent
-endif # Contains java code
-else
-LOCAL_STATIC_JAVA_LIBRARIES += emma
-endif # LOCAL_JACK_ENABLED
-else
+else  # ! EMMA_INSTRUMENT_STATIC
 ifdef LOCAL_SDK_VERSION
 ifdef TARGET_BUILD_APPS
 # In unbundled build, merge the coverage library into the apk.
-ifdef LOCAL_JACK_ENABLED
 # Jack supports coverage with Jacoco
-ifneq ($(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),)
-# Only add jacocoagent if the package contains some java code
 LOCAL_STATIC_JAVA_LIBRARIES += jacocoagent
 # Exclude jacoco classes from proguard
 LOCAL_PROGUARD_FLAGS += -include $(BUILD_SYSTEM)/proguard.jacoco.flags
 LOCAL_JACK_PROGUARD_FLAGS += -include $(BUILD_SYSTEM)/proguard.jacoco.flags
-endif # Contains java code
-else
-LOCAL_STATIC_JAVA_LIBRARIES += emma
-endif # LOCAL_JACK_ENABLED
-else
+else # ! TARGET_BUILD_APPS
 # If build against the SDK in full build, core.jar is not used
 # so coverage classes are not present.
-ifdef LOCAL_JACK_ENABLED
 # Jack needs jacoco on the classpath but we do not want it to be in
 # the final apk. While it is a static library, we add it to the
 # LOCAL_JAVA_LIBRARIES which are only present on the classpath.
 # Note: we have nothing to do for proguard since jacoco will be
 # on the classpath only, thus not modified during the compilation.
 LOCAL_JAVA_LIBRARIES += jacocoagent
-else
-# We have to use prebuilt emma.jar to make Proguard happy;
-# Otherwise emma classes are included in core.jar.
-LOCAL_PROGUARD_FLAGS += -libraryjars $(EMMA_JAR)
-endif # LOCAL_JACK_ENABLED
-endif # full build
+endif # TARGET_BUILD_APPS
 endif # LOCAL_SDK_VERSION
-endif # EMMA_INSTRUMENT_STATIC
+endif # ! EMMA_INSTRUMENT_STATIC
 endif # LOCAL_EMMA_INSTRUMENT
+endif # Contains java code
 
 rs_compatibility_jni_libs :=
 
@@ -393,30 +374,13 @@
 
 endif  # LOCAL_USE_AAPT2
 
+# Make sure to generate R.java before compiling.
 # Other modules should depend on the BUILT module if
 # they want to use this module's R.java file.
-$(LOCAL_BUILT_MODULE): $(R_file_stamp)
-
-ifdef LOCAL_JACK_ENABLED
-ifneq ($(built_dex_intermediate),)
-$(built_dex_intermediate): $(R_file_stamp)
-endif
-ifneq ($(noshrob_classes_jack),)
-$(noshrob_classes_jack): $(R_file_stamp)
-endif
-ifneq ($(full_classes_jack),)
-$(full_classes_jack): $(R_file_stamp)
-$(jack_check_timestamp): $(R_file_stamp)
-endif
-endif # LOCAL_JACK_ENABLED
-
-ifneq ($(full_classes_jar),)
-# If full_classes_jar is non-empty, we're building sources.
-# If we're building sources, the initial javac step (which
-# produces full_classes_compiled_jar) needs to ensure the
-# R.java and Manifest.java files have been generated first.
-$(full_classes_compiled_jar): $(R_file_stamp)
-endif
+$(LOCAL_BUILT_MODULE) \
+$(full_classes_compiled_jar) \
+$(built_dex_intermediate) $(noshrob_classes_jack) $(full_classes_jack) $(jack_check_timestamp) \
+  :  $(R_file_stamp)
 
 endif  # need_compile_res
 
@@ -462,12 +426,9 @@
 
 ifneq ($(full_classes_jar),)
 $(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE := $(built_dex)
-# Use the jarjar processed arhive as the initial package file.
-$(LOCAL_BUILT_MODULE): PRIVATE_SOURCE_ARCHIVE := $(full_classes_jarjar_jar)
 $(LOCAL_BUILT_MODULE): $(built_dex)
 else
 $(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE :=
-$(LOCAL_BUILT_MODULE): PRIVATE_SOURCE_ARCHIVE :=
 endif # full_classes_jar
 
 include $(BUILD_SYSTEM)/install_jni_libs.mk
@@ -494,6 +455,7 @@
 endif
 private_key := $(LOCAL_CERTIFICATE).pk8
 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_PRIVATE_KEY := $(private_key)
@@ -502,8 +464,8 @@
 PACKAGES.$(LOCAL_PACKAGE_NAME).PRIVATE_KEY := $(private_key)
 PACKAGES.$(LOCAL_PACKAGE_NAME).CERTIFICATE := $(certificate)
 
-$(LOCAL_BUILT_MODULE): PRIVATE_ADDITIONAL_CERTIFICATES := $(foreach c,\
-    $(LOCAL_ADDITIONAL_CERTIFICATES), $(c).x509.pem $(c).pk8)
+$(LOCAL_BUILT_MODULE): $(additional_certificates)
+$(LOCAL_BUILT_MODULE): PRIVATE_ADDITIONAL_CERTIFICATES := $(additional_certificates)
 
 # Define the rule to build the actual package.
 # PRIVATE_JNI_SHARED_LIBRARIES is a list of <abi>:<path_of_built_lib>.
@@ -525,7 +487,6 @@
     $(my_res_package) $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := $(PRODUCT_AAPT_PREF_CONFIG)
 endif
 endif
-$(LOCAL_BUILT_MODULE): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
 $(LOCAL_BUILT_MODULE) : $(jni_shared_libraries)
 ifdef LOCAL_USE_AAPT2
 $(LOCAL_BUILT_MODULE): PRIVATE_RES_PACKAGE := $(my_res_package)
@@ -535,22 +496,9 @@
 endif
 	@echo "target Package: $(PRIVATE_MODULE) ($@)"
 ifdef LOCAL_USE_AAPT2
-ifdef LOCAL_JACK_ENABLED
 	$(call copy-file-to-new-target)
-else
-	@# TODO: implement merge-two-packages.
-	$(if $(PRIVATE_SOURCE_ARCHIVE),\
-	  $(call merge-two-packages,$(PRIVATE_RES_PACKAGE) $(PRIVATE_SOURCE_ARCHIVE),$@),
-	  $(call copy-file-to-new-target))
-endif
-else  # LOCAL_USE_AAPT2
-ifdef LOCAL_JACK_ENABLED
+else  # ! LOCAL_USE_AAPT2
 	$(create-empty-package)
-else
-	$(if $(PRIVATE_SOURCE_ARCHIVE),\
-	  $(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@),\
-	  $(create-empty-package))
-endif
 	$(add-assets-to-package)
 endif  # LOCAL_USE_AAPT2
 ifneq ($(jni_shared_libraries),)
@@ -562,9 +510,7 @@
 else  # full_classes_jar
 	$(add-dex-to-package)
 endif  # full_classes_jar
-ifdef LOCAL_JACK_ENABLED
 	$(add-carried-jack-resources)
-endif
 ifdef LOCAL_DEX_PREOPT
 ifneq ($(BUILD_PLATFORM_ZIP),)
 	@# Keep a copy of apk with classes.dex unstripped
@@ -623,7 +569,7 @@
 	$(sign-package)
 
 # Rules to install the splits
-$(installed_apk_splits) : $(my_module_path)/$(LOCAL_MODULE)_%.apk : $(built_module_path)/package_%.apk | $(ACP)
+$(installed_apk_splits) : $(my_module_path)/$(LOCAL_MODULE)_%.apk : $(built_module_path)/package_%.apk
 	@echo "Install: $@"
 	$(copy-file-to-new-target)
 
@@ -633,7 +579,7 @@
   $(foreach s,$(my_split_suffixes),$(built_module_path)/package_$(s).apk:$(my_module_path)/$(LOCAL_MODULE)_$(s).apk)
 
 # Make sure to install the splits when you run "make <module_name>".
-$(my_register_name): $(installed_apk_splits)
+$(my_all_targets): $(installed_apk_splits)
 
 ifdef LOCAL_COMPATIBILITY_SUITE
 cts_testcase_file := $(foreach s,$(my_split_suffixes),$(COMPATIBILITY_TESTCASES_OUT_$(LOCAL_COMPATIBILITY_SUITE))/$(LOCAL_MODULE)_$(s).apk)
@@ -644,16 +590,13 @@
   $(COMPATIBILITY.$(LOCAL_COMPATIBILITY_SUITE).FILES) \
   $(cts_testcase_file)
 
-$(my_register_name) : $(cts_testcase_file)
+$(my_all_targets) : $(cts_testcase_file)
 endif # LOCAL_COMPATIBILITY_SUITE
 endif # LOCAL_PACKAGE_SPLITS
 
 # Save information about this package
 PACKAGES.$(LOCAL_PACKAGE_NAME).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
 PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources)
-ifdef package_resource_overlays
-PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_OVERLAYS := $(package_resource_overlays)
-endif
 
 PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME)
 
diff --git a/core/pathmap.mk b/core/pathmap.mk
index 9b5a7db..13b3fe4 100644
--- a/core/pathmap.mk
+++ b/core/pathmap.mk
@@ -49,8 +49,7 @@
     audio-route:system/media/audio_route/include \
     wilhelm:frameworks/wilhelm/include \
     wilhelm-ut:frameworks/wilhelm/src/ut \
-    mediandk:frameworks/av/media/ndk/ \
-    speex:external/speex/include
+    mediandk:frameworks/av/media/ndk/
 
 #
 # Returns the path to the requested module's include directory,
diff --git a/core/phony_package.mk b/core/phony_package.mk
index 866b13c..578d629 100644
--- a/core/phony_package.mk
+++ b/core/phony_package.mk
@@ -1,3 +1,4 @@
+$(call record-module-type,PHONY_PACKAGE)
 ifneq ($(strip $(LOCAL_SRC_FILES)),)
 $(error LOCAL_SRC_FILES are not allowed for phony packages)
 endif
@@ -7,7 +8,7 @@
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
-$(LOCAL_BUILT_MODULE): $(LOCAL_MODULE_MAKEFILE_DEP) $(LOCAL_ADDITIONAL_DEPENDENCIES)
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	$(hide) echo "Fake: $@"
 	$(hide) mkdir -p $(dir $@)
 	$(hide) touch $@
diff --git a/core/post_clean.mk b/core/post_clean.mk
index f08abff..d7e8322 100644
--- a/core/post_clean.mk
+++ b/core/post_clean.mk
@@ -16,44 +16,6 @@
 # This file must be included after all Android.mks have been loaded.
 
 #######################################################
-# Checks the current build configurations against the previous build,
-# clean artifacts in TARGET_COMMON_OUT_ROOT if necessary.
-# If a package's resource overlay has been changed, its R class needs to be
-# regenerated.
-previous_package_overlay_config := $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/previous_overlays.txt
-current_package_overlay_config := $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/current_overlays.txt
-current_all_packages_config := $(dir $(current_package_overlay_config))current_packages.txt
-
-$(shell rm -rf $(current_package_overlay_config) \
-    && mkdir -p $(dir $(current_package_overlay_config)) \
-    && touch $(current_package_overlay_config))
-$(shell echo '$(PACKAGES)' > $(current_all_packages_config))
-$(foreach p, $(PACKAGES), $(if $(PACKAGES.$(p).RESOURCE_OVERLAYS), \
-  $(shell echo '$(p)' '$(PACKAGES.$(p).RESOURCE_OVERLAYS)' >> $(current_package_overlay_config))))
-
-ifneq (,$(wildcard $(previous_package_overlay_config)))
-packages_overlay_changed := $(shell build/tools/diff_package_overlays.py \
-    $(current_all_packages_config) $(current_package_overlay_config) \
-    $(previous_package_overlay_config))
-ifneq (,$(packages_overlay_changed))
-overlay_cleanup_cmd := $(strip rm -rf $(foreach p, $(packages_overlay_changed),\
-    $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/$(p)_intermediates))
-$(info *** Overlay change detected, clean shared intermediate files...)
-$(info *** $(overlay_cleanup_cmd))
-$(shell $(overlay_cleanup_cmd))
-overlay_cleanup_cmd :=
-endif
-packages_overlay_changed :=
-endif
-
-# Now current becomes previous.
-$(shell mv -f $(current_package_overlay_config) $(previous_package_overlay_config))
-
-previous_package_overlay_config :=
-current_package_overlay_config :=
-current_all_packages_config :=
-
-#######################################################
 # Check if we need to delete obsolete generated java files.
 # When an aidl/proto/etc file gets deleted (or renamed), the generated java file is obsolete.
 previous_gen_java_config := $(TARGET_OUT_COMMON_INTERMEDIATES)/previous_gen_java_config.mk
diff --git a/core/prebuilt.mk b/core/prebuilt.mk
index 428922b..5831e24 100644
--- a/core/prebuilt.mk
+++ b/core/prebuilt.mk
@@ -5,12 +5,20 @@
 ## None.
 ##
 ###########################################################
+$(call record-module-type,PREBUILT)
 
 ifdef LOCAL_IS_HOST_MODULE
   my_prefix := HOST_
   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,$(LOCAL_MODULE_CLASS)),)
+      LOCAL_MULTILIB := first
+    endif
+  endif
 endif
 
 include $(BUILD_SYSTEM)/multilib.mk
@@ -52,7 +60,7 @@
 
 ifdef LOCAL_IS_HOST_MODULE
 ifdef HOST_CROSS_OS
-ifneq (,$(filter EXECUTABLES STATIC_LIBRARIES SHARED_LIBRARIES,$(LOCAL_MODULE_CLASS)))
+ifneq (,$(filter EXECUTABLES STATIC_LIBRARIES SHARED_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)))
 my_prefix := HOST_CROSS_
 LOCAL_HOST_PREFIX := $(my_prefix)
 include $(BUILD_SYSTEM)/module_arch_supported.mk
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index ee68427..af59756 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -46,9 +46,18 @@
   $(LOCAL_PACK_MODULE_RELOCATIONS))
 
 ifeq (SHARED_LIBRARIES,$(LOCAL_MODULE_CLASS))
-  # Put the built targets of all shared libraries in a common directory
-  # to simplify the link line.
-  OVERRIDE_BUILT_MODULE_PATH := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT_INTERMEDIATE_LIBRARIES)
+  # LOCAL_COPY_TO_INTERMEDIATE_LIBRARIES indicates that this prebuilt should be
+  # installed to the common directory of libraries. This is needed for the NDK
+  # shared libraries built by soong, as we build many different versions of each
+  # library (one for each API level). Since they all have the same basename,
+  # they'd clobber each other (as well as any platform libraries by the same
+  # name).
+  ifneq ($(LOCAL_COPY_TO_INTERMEDIATE_LIBRARIES),false)
+    # Put the built targets of all shared libraries in a common directory
+    # to simplify the link line.
+    OVERRIDE_BUILT_MODULE_PATH :=  \
+        $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT_INTERMEDIATE_LIBRARIES)
+  endif
   ifeq ($(LOCAL_IS_HOST_MODULE)$(my_strip_module),)
     # Strip but not try to add debuglink
     my_strip_module := no_debuglink
@@ -70,6 +79,12 @@
   prebuilt_module_is_a_library :=
 endif
 
+ifeq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+ifeq ($(prebuilt_module_is_a_library),true)
+SOONG_ALREADY_CONV := $(SOONG_ALREADY_CONV) $(LOCAL_MODULE)
+endif
+endif
+
 # Don't install static libraries by default.
 ifndef LOCAL_UNINSTALLABLE_MODULE
 ifeq (STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS))
@@ -88,11 +103,11 @@
 LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk
 endif
 
-ifneq ($(filter true no_debuglink,$(my_strip_module) $(my_pack_module_relocations)),)
+ifneq ($(filter true keep_symbols no_debuglink mini-debug-info,$(my_strip_module) $(my_pack_module_relocations)),)
   ifdef LOCAL_IS_HOST_MODULE
     $(error Cannot strip/pack host module LOCAL_PATH=$(LOCAL_PATH))
   endif
-  ifeq ($(filter SHARED_LIBRARIES EXECUTABLES,$(LOCAL_MODULE_CLASS)),)
+  ifeq ($(filter SHARED_LIBRARIES EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
     $(error Can strip/pack only shared libraries or executables LOCAL_PATH=$(LOCAL_PATH))
   endif
   ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),)
@@ -111,7 +126,7 @@
 ifdef prebuilt_module_is_a_library
 export_includes := $(intermediates)/export_includes
 $(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDE_DIRS)
-$(export_includes) : $(LOCAL_MODULE_MAKEFILE_DEP)
+$(export_includes): $(LOCAL_EXPORT_C_INCLUDE_DEPS)
 	@echo Export includes file: $< -- $@
 	$(hide) mkdir -p $(dir $@) && rm -f $@
 ifdef LOCAL_EXPORT_C_INCLUDE_DIRS
@@ -122,7 +137,15 @@
 	$(hide) touch $@
 endif
 
-$(LOCAL_BUILT_MODULE) : | $(intermediates)/export_includes
+my_link_type := $(intermediates)/link_type
+$(my_link_type): PRIVATE_LINK_TYPE := native:$(if $(LOCAL_SDK_VERSION),ndk,platform)
+$(eval $(call link-type-partitions,$(my_link_type)))
+$(my_link_type):
+	@echo Check module type: $@
+	$(hide) mkdir -p $(dir $@) && rm -f $@
+	$(hide) echo "$(PRIVATE_LINK_TYPE)" >$@
+
+$(LOCAL_BUILT_MODULE) : | $(export_includes) $(my_link_type)
 endif  # prebuilt_module_is_a_library
 
 # The real dependency will be added after all Android.mks are loaded and the install paths
@@ -149,6 +172,16 @@
 # "my_strip_module not true" because otherwise the rules are defined in dynamic_binary.mk.
 endif  # my_strip_module not true
 
+# Coverage information is needed when static lib is a dependency of another
+# coverage-enabled module.
+ifeq (STATIC_LIBRARIES, $(LOCAL_MODULE_CLASS))
+GCNO_ARCHIVE := $(LOCAL_MODULE).gcnodir
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_OBJECTS :=
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_WHOLE_STATIC_LIBRARIES :=
+$(intermediates)/$(GCNO_ARCHIVE) :
+	$(transform-o-to-static-lib)
+endif
+
 ifeq ($(LOCAL_MODULE_CLASS),APPS)
 PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
 
@@ -178,6 +211,7 @@
   LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
   PACKAGES.$(LOCAL_MODULE).EXTERNAL_KEY := 1
 
+  $(built_module) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
   $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
   $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
 endif
@@ -204,6 +238,7 @@
   PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
   PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
 
+  $(built_module) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
   $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
   $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
 endif
@@ -221,7 +256,7 @@
 #######################################
 ifneq ($(LOCAL_REPLACE_PREBUILT_APK_INSTALLED),)
 # There is a replacement for the prebuilt .apk we can install without any processing.
-$(built_module) : $(LOCAL_REPLACE_PREBUILT_APK_INSTALLED) | $(ACP)
+$(built_module) : $(LOCAL_REPLACE_PREBUILT_APK_INSTALLED)
 	$(transform-prebuilt-to-target)
 
 else  # ! LOCAL_REPLACE_PREBUILT_APK_INSTALLED
@@ -239,7 +274,7 @@
 endif
 $(built_module): PRIVATE_EMBEDDED_JNI_LIBS := $(embedded_prebuilt_jni_libs)
 
-$(built_module) : $(my_prebuilt_src_file) | $(ACP) $(ZIPALIGN) $(SIGNAPK_JAR) $(AAPT)
+$(built_module) : $(my_prebuilt_src_file) | $(ZIPALIGN) $(SIGNAPK_JAR) $(AAPT)
 	$(transform-prebuilt-to-target)
 	$(uncompress-shared-libs)
 ifdef LOCAL_DEX_PREOPT
@@ -283,14 +318,15 @@
 endif
 my_src_dir := $(LOCAL_PATH)/$(my_src_dir)
 
+$(built_apk_splits) : $(LOCAL_CERTIFICATE).pk8 $(LOCAL_CERTIFICATE).x509.pem
 $(built_apk_splits) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
 $(built_apk_splits) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
-$(built_apk_splits) : $(built_module_path)/%.apk : $(my_src_dir)/%.apk | $(ACP) $(AAPT)
+$(built_apk_splits) : $(built_module_path)/%.apk : $(my_src_dir)/%.apk | $(AAPT)
 	$(copy-file-to-new-target)
 	$(sign-package)
 
 # Rules to install the split apks.
-$(installed_apk_splits) : $(my_module_path)/%.apk : $(built_module_path)/%.apk | $(ACP)
+$(installed_apk_splits) : $(my_module_path)/%.apk : $(built_module_path)/%.apk
 	@echo "Install: $@"
 	$(copy-file-to-new-target)
 
@@ -300,7 +336,7 @@
   $(foreach s,$(LOCAL_PACKAGE_SPLITS),$(built_module_path)/$(notdir $(s)):$(my_module_path)/$(notdir $(s)))
 
 # Make sure to install the splits when you run "make <module_name>".
-$(my_register_name): $(installed_apk_splits)
+$(my_all_targets): $(installed_apk_splits)
 
 endif # LOCAL_PACKAGE_SPLITS
 
@@ -315,7 +351,7 @@
 ifneq ($(dexpreopt_boot_jar_module),) # boot jar
 # boot jar's rules are defined in dex_preopt.mk
 dexpreopted_boot_jar := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(dexpreopt_boot_jar_module)_nodex.jar
-$(built_module) : $(dexpreopted_boot_jar) | $(ACP)
+$(built_module) : $(dexpreopted_boot_jar)
 	$(call copy-file-to-target)
 
 # For libart boot jars, we don't have .odex files.
@@ -326,36 +362,26 @@
 	@echo "Dexpreopt Jar: $(PRIVATE_MODULE) ($@)"
 	$(call dexpreopt-one-file,$<,$@)
 
-$(built_module) : $(my_prebuilt_src_file) | $(ACP)
+$(built_module) : $(my_prebuilt_src_file)
 	$(call copy-file-to-target)
 ifneq (nostripping,$(LOCAL_DEX_PREOPT))
 	$(call dexpreopt-remove-classes.dex,$@)
 endif
 endif # boot jar
 else # ! LOCAL_DEX_PREOPT
-$(built_module) : $(my_prebuilt_src_file) | $(ACP)
+$(built_module) : $(my_prebuilt_src_file)
 	$(call copy-file-to-target)
 endif # LOCAL_DEX_PREOPT
 
 else  # ! prebuilt_module_is_dex_javalib
+$(built_module) : $(my_prebuilt_src_file)
 ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),)
-$(built_module) : $(my_prebuilt_src_file)
 	$(transform-prebuilt-to-target-strip-comments)
-ifeq ($(LOCAL_MODULE_CLASS),EXECUTABLES)
-	$(hide) chmod +x $@
-endif
-else ifneq ($(LOCAL_ACP_UNAVAILABLE),true)
-$(built_module) : $(my_prebuilt_src_file) | $(ACP)
-	$(transform-prebuilt-to-target)
-ifeq ($(LOCAL_MODULE_CLASS),EXECUTABLES)
-	$(hide) chmod +x $@
-endif
 else
-$(built_module) : $(my_prebuilt_src_file)
-	$(copy-file-to-target-with-cp)
-ifeq ($(LOCAL_MODULE_CLASS),EXECUTABLES)
-	$(hide) chmod +x $@
+	$(transform-prebuilt-to-target)
 endif
+ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+	$(hide) chmod +x $@
 endif
 endif # ! prebuilt_module_is_dex_javalib
 endif # LOCAL_MODULE_CLASS != APPS
@@ -370,9 +396,24 @@
 
 $(common_classes_jar) $(common_javalib_jar): PRIVATE_MODULE := $(LOCAL_MODULE)
 
+my_link_type := $(intermediates.COMMON)/link_type
+ifeq ($(LOCAL_SDK_VERSION),system_current)
+$(my_link_type): PRIVATE_LINK_TYPE := java:system
+else ifneq ($(LOCAL_SDK_VERSION),)
+$(my_link_type): PRIVATE_LINK_TYPE := java:sdk
+else
+$(my_link_type): PRIVATE_LINK_TYPE := java:platform
+endif
+$(eval $(call link-type-partitions,$(my_link_type)))
+$(my_link_type):
+	@echo Check module type: $@
+	$(hide) mkdir -p $(dir $@) && rm -f $@
+	$(hide) echo "$(PRIVATE_LINK_TYPE)" >$@
+$(LOCAL_BUILT_MODULE): $(my_link_type)
+
 ifeq ($(prebuilt_module_is_dex_javalib),true)
 # For prebuilt shared Java library we don't have classes.jar.
-$(common_javalib_jar) : $(my_src_jar) | $(ACP)
+$(common_javalib_jar) : $(my_src_jar)
 	$(transform-prebuilt-to-target)
 
 else  # ! prebuilt_module_is_dex_javalib
@@ -390,10 +431,10 @@
 
 endif
 
-$(common_classes_jar) : $(my_src_jar) | $(ACP)
+$(common_classes_jar) : $(my_src_jar)
 	$(transform-prebuilt-to-target)
 
-$(common_javalib_jar) : $(common_classes_jar) | $(ACP)
+$(common_javalib_jar) : $(common_classes_jar)
 	$(transform-prebuilt-to-target)
 
 $(call define-jar-to-toc-rule, $(common_classes_jar))
@@ -435,15 +476,15 @@
 endif # LOCAL_IS_HOST_MODULE is not set
 
 ifneq ($(prebuilt_module_is_dex_javalib),true)
-ifneq ($(LOCAL_JILL_FLAGS),)
-$(error LOCAL_JILL_FLAGS is not supported any more, please use jack options in LOCAL_JACK_FLAGS instead)
-endif
 
 # We may be building classes.jack from a host jar for host dalvik Java library.
 $(intermediates.COMMON)/classes.jack : PRIVATE_JACK_FLAGS:=$(LOCAL_JACK_FLAGS)
-$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_MIN_SDK_VERSION := 1
-$(intermediates.COMMON)/classes.jack : $(my_src_jar) $(LOCAL_MODULE_MAKEFILE_DEP) \
-        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JACK) | setup-jack-server
+$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_MIN_SDK_VERSION := $(if $(strip $(LOCAL_MIN_SDK_VERSION)),$(LOCAL_MIN_SDK_VERSION),1)
+$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
+$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
+$(intermediates.COMMON)/classes.jack : $(LOCAL_JACK_PLUGIN_PATH) $(my_src_jar) \
+        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JACK_DEFAULT_ARGS) $(JACK) \
+        | setup-jack-server
 	$(transform-jar-to-jack)
 
 # Update timestamps of .toc files for prebuilts so dependents will be
@@ -454,6 +495,6 @@
 endif # ! prebuilt_module_is_dex_javalib
 endif # JAVA_LIBRARIES
 
-$(built_module) : $(LOCAL_MODULE_MAKEFILE_DEP) $(LOCAL_ADDITIONAL_DEPENDENCIES)
+$(built_module) : $(LOCAL_ADDITIONAL_DEPENDENCIES)
 
 my_prebuilt_src_file :=
diff --git a/core/product.mk b/core/product.mk
index 94cc2e3..ad9b022 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -120,9 +120,13 @@
     PRODUCT_DEX_PREOPT_MODULE_CONFIGS \
     PRODUCT_DEX_PREOPT_DEFAULT_FLAGS \
     PRODUCT_DEX_PREOPT_BOOT_FLAGS \
+    PRODUCT_SANITIZER_MODULE_CONFIGS \
     PRODUCT_SYSTEM_BASE_FS_PATH \
     PRODUCT_VENDOR_BASE_FS_PATH \
     PRODUCT_SHIPPING_API_LEVEL \
+    VENDOR_PRODUCT_RESTRICT_VENDOR_FILES \
+    VENDOR_EXCEPTION_MODULES \
+    VENDOR_EXCEPTION_PATHS \
 
 
 
@@ -333,3 +337,14 @@
 $(eval PRODUCT_DEX_PREOPT_MODULE_CONFIGS += \
   $(foreach m,$(1),$(m)=$(_c)))
 endef
+
+# whitespace placeholder when we record module's sanitizer config.
+_PSMC_SP_PLACE_HOLDER := |@SP@|
+# Set up sanitizer config for a module.
+# $(1) list of module names
+# $(2) the modules' sanitizer config
+define add-product-sanitizer-module-config
+$(eval _c := $(subst $(space),$(_PSMC_SP_PLACE_HOLDER),$(strip $(2))))\
+$(eval PRODUCT_SANITIZER_MODULE_CONFIGS += \
+  $(foreach m,$(1),$(m)=$(_c)))
+endef
diff --git a/core/product_config.mk b/core/product_config.mk
index ed38bc8..0d4ced3 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -392,7 +392,7 @@
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
 PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
-# Resolve and setup per-module dex-preopot configs.
+# Resolve and setup per-module dex-preopt configs.
 PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
     $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_MODULE_CONFIGS))
 # If a module has multiple setups, the first takes precedence.
@@ -405,3 +405,17 @@
     $(eval cf := $(subst $(_PDPMC_SP_PLACE_HOLDER),$(space),$(cf)))\
     $(eval DEXPREOPT.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
 _pdpmc_modules :=
+
+# Resolve and setup per-module sanitizer configs.
+PRODUCT_SANITIZER_MODULE_CONFIGS := \
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SANITIZER_MODULE_CONFIGS))
+# If a module has multiple setups, the first takes precedence.
+_psmc_modules :=
+$(foreach c,$(PRODUCT_SANITIZER_MODULE_CONFIGS),\
+  $(eval m := $(firstword $(subst =,$(space),$(c))))\
+  $(if $(filter $(_psmc_modules),$(m)),,\
+    $(eval _psmc_modules += $(m))\
+    $(eval cf := $(patsubst $(m)=%,%,$(c)))\
+    $(eval cf := $(subst $(_PSMC_SP_PLACE_HOLDER),$(space),$(cf)))\
+    $(eval SANITIZER.$(TARGET_PRODUCT).$(m).CONFIG := $(cf))))
+_psmc_modules :=
diff --git a/core/setup_one_odex.mk b/core/setup_one_odex.mk
index ec8a28a..40dbb55 100644
--- a/core/setup_one_odex.mk
+++ b/core/setup_one_odex.mk
@@ -35,5 +35,10 @@
 my_installed_odex := $(call get-odex-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(LOCAL_INSTALLED_MODULE))
 
 built_odex += $(my_built_odex)
+built_vdex += $(patsubst %.odex,%.vdex,$(my_built_odex))
+
 installed_odex += $(my_installed_odex)
+installed_vdex += $(patsubst %.odex,%.vdex,$(my_installed_odex))
+
 built_installed_odex += $(my_built_odex):$(my_installed_odex)
+built_installed_vdex += $(my_built_vdex):$(my_installed_vdex)
diff --git a/core/shared_library.mk b/core/shared_library.mk
index 2f48341..a15b1a6 100644
--- a/core/shared_library.mk
+++ b/core/shared_library.mk
@@ -1,3 +1,4 @@
+$(call record-module-type,SHARED_LIBRARY)
 my_prefix := TARGET_
 include $(BUILD_SYSTEM)/multilib.mk
 
diff --git a/core/shared_library_internal.mk b/core/shared_library_internal.mk
index b9a5e3e..05886fa 100644
--- a/core/shared_library_internal.mk
+++ b/core/shared_library_internal.mk
@@ -39,19 +39,19 @@
 include $(BUILD_SYSTEM)/dynamic_binary.mk
 
 # Define PRIVATE_ variables from global vars
-my_target_global_ld_dirs := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LD_DIRS)
+my_target_global_ld_dirs :=
 ifeq ($(LOCAL_NO_LIBGCC),true)
 my_target_libgcc :=
 else
-my_target_libgcc := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCC)
+my_target_libgcc := $(call intermediates-dir-for,STATIC_LIBRARIES,libgcc,,,$(LOCAL_2ND_ARCH_VAR_PREFIX))/libgcc.a
 endif
-my_target_libatomic := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBATOMIC)
+my_target_libatomic := $(call intermediates-dir-for,STATIC_LIBRARIES,libatomic,,,$(LOCAL_2ND_ARCH_VAR_PREFIX))/libatomic.a
 ifeq ($(LOCAL_NO_CRT),true)
 my_target_crtbegin_so_o :=
 my_target_crtend_so_o :=
 else
-my_target_crtbegin_so_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CRTBEGIN_SO_O)
-my_target_crtend_so_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CRTEND_SO_O)
+my_target_crtbegin_so_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
+my_target_crtend_so_o := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
 endif
 ifdef LOCAL_SDK_VERSION
 # Make sure the prebuilt NDK paths are put ahead of the TARGET_GLOBAL_LD_DIRS,
@@ -76,8 +76,37 @@
         $(all_libraries) \
         $(my_target_crtbegin_so_o) \
         $(my_target_crtend_so_o) \
-        $(LOCAL_MODULE_MAKEFILE_DEP) \
+        $(my_target_libgcc) \
+        $(my_target_libatomic) \
         $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	$(transform-o-to-shared-lib)
 
+ifeq ($(my_native_coverage),true)
+gcno_suffix := .gcnodir
+
+built_whole_gcno_libraries := \
+    $(foreach lib,$(my_whole_static_libraries), \
+      $(call intermediates-dir-for, \
+        STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX), \
+        $(my_host_cross))/$(lib)$(gcno_suffix))
+
+built_static_gcno_libraries := \
+    $(foreach lib,$(my_static_libraries), \
+      $(call intermediates-dir-for, \
+        STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX), \
+        $(my_host_cross))/$(lib)$(gcno_suffix))
+
+GCNO_ARCHIVE := $(LOCAL_MODULE)$(gcno_suffix)
+
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_OBJECTS := $(strip $(LOCAL_GCNO_FILES))
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_WHOLE_STATIC_LIBRARIES := $(strip $(built_whole_gcno_libraries)) $(strip $(built_static_gcno_libraries))
+$(intermediates)/$(GCNO_ARCHIVE) : $(LOCAL_GCNO_FILES) $(built_whole_gcno_libraries) $(built_static_gcno_libraries)
+	$(transform-o-to-static-lib)
+
+$($(my_prefix)OUT_COVERAGE)/$(GCNO_ARCHIVE) : $(intermediates)/$(GCNO_ARCHIVE)
+	$(copy-file-to-target)
+
+$(LOCAL_BUILT_MODULE): $($(my_prefix)OUT_COVERAGE)/$(GCNO_ARCHIVE)
+endif
+
 endif  # skip_build_from_source
diff --git a/core/shared_test_lib.mk b/core/shared_test_lib.mk
index fbfdc9c..1ea9fe7 100644
--- a/core/shared_test_lib.mk
+++ b/core/shared_test_lib.mk
@@ -1,8 +1 @@
-#############################################
-## A thin wrapper around BUILD_SHARED_LIBRARY
-## Common flags for native tests are added.
-#############################################
-
-include $(BUILD_SYSTEM)/target_test_internal.mk
-
-include $(BUILD_SHARED_LIBRARY)
+$(error BUILD_SHARED_TEST_LIBRARY is obsolete)
diff --git a/core/soong.mk b/core/soong.mk
index 2463953..cd5eff4 100644
--- a/core/soong.mk
+++ b/core/soong.mk
@@ -1,14 +1,10 @@
-SOONG_OUT_DIR := $(OUT_DIR)/soong
-SOONG_HOST_EXECUTABLES := $(SOONG_OUT_DIR)/host/$(HOST_PREBUILT_TAG)/bin
-KATI := $(SOONG_HOST_EXECUTABLES)/ckati
-MAKEPARALLEL := $(SOONG_HOST_EXECUTABLES)/makeparallel
-
 SOONG := $(SOONG_OUT_DIR)/soong
 SOONG_BOOTSTRAP := $(SOONG_OUT_DIR)/.soong.bootstrap
 SOONG_BUILD_NINJA := $(SOONG_OUT_DIR)/build.ninja
-SOONG_ANDROID_MK := $(SOONG_OUT_DIR)/Android.mk
 SOONG_IN_MAKE := $(SOONG_OUT_DIR)/.soong.in_make
+SOONG_MAKEVARS_MK := $(SOONG_OUT_DIR)/make_vars-$(TARGET_PRODUCT).mk
 SOONG_VARIABLES := $(SOONG_OUT_DIR)/soong.variables
+SOONG_ANDROID_MK := $(SOONG_OUT_DIR)/Android-$(TARGET_PRODUCT).mk
 
 # We need to rebootstrap soong if SOONG_OUT_DIR or the reverse path from
 # SOONG_OUT_DIR to TOP changes
@@ -18,7 +14,7 @@
     SOONG_NEEDS_REBOOTSTRAP := FORCE
     $(warning soong_out_dir changed)
   endif
-  ifneq ($(strip $(shell build/soong/reverse_path.py $(SOONG_OUT_DIR))),$(strip $(shell source $(SOONG_BOOTSTRAP); echo $$SRCDIR_FROM_BUILDDIR)))
+  ifneq ($(strip $(shell build/soong/scripts/reverse_path.py $(SOONG_OUT_DIR))),$(strip $(shell source $(SOONG_BOOTSTRAP); echo $$SRCDIR_FROM_BUILDDIR)))
     SOONG_NEEDS_REBOOTSTRAP := FORCE
     $(warning reverse path changed)
   endif
@@ -29,6 +25,13 @@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) BUILDDIR=$(SOONG_OUT_DIR) ./bootstrap.bash
 
+BINDER32BIT :=
+ifneq ($(TARGET_USES_64_BIT_BINDER),true)
+ifneq ($(TARGET_IS_64_BIT),true)
+BINDER32BIT := true
+endif
+endif
+
 # Create soong.variables with copies of makefile settings.  Runs every build,
 # but only updates soong.variables if it changes
 SOONG_VARIABLES_TMP := $(SOONG_VARIABLES).$$$$
@@ -36,11 +39,22 @@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) (\
 	echo '{'; \
-	echo '    "Device_uses_jemalloc": $(if $(filter true,$(MALLOC_SVELTE)),false,true),'; \
-	echo '    "Device_uses_dlmalloc": $(if $(filter true,$(MALLOC_SVELTE)),true,false),'; \
+	echo '    "Make_suffix": "-$(TARGET_PRODUCT)",'; \
+	echo ''; \
 	echo '    "Platform_sdk_version": $(PLATFORM_SDK_VERSION),'; \
 	echo '    "Unbundled_build": $(if $(TARGET_BUILD_APPS),true,false),'; \
 	echo '    "Brillo": $(if $(BRILLO),true,false),'; \
+	echo '    "Malloc_not_svelte": $(if $(filter true,$(MALLOC_SVELTE)),false,true),'; \
+	echo '    "Allow_missing_dependencies": $(if $(TARGET_BUILD_APPS)$(filter true,$(SOONG_ALLOW_MISSING_DEPENDENCIES)),true,false),'; \
+	echo '    "SanitizeHost": [$(if $(SANITIZE_HOST),"$(subst $(space),"$(comma)",$(SANITIZE_HOST))")],'; \
+	echo '    "SanitizeDevice": [$(if $(SANITIZE_TARGET),"$(subst $(space),"$(comma)",$(SANITIZE_TARGET))")],'; \
+	echo '    "HostStaticBinaries": $(if $(strip $(BUILD_HOST_static)),true,false),'; \
+	echo '    "Cpusets": $(if $(strip $(ENABLE_CPUSETS)),true,false),'; \
+	echo '    "Schedboost": $(if $(strip $(ENABLE_SCHEDBOOST)),true,false),'; \
+	echo '    "Binder32bit": $(if $(BINDER32BIT),true,false),'; \
+	echo '    "DevicePrefer32BitExecutables": $(if $(filter true,$(TARGET_PREFER_32_BIT_EXECUTABLES)),true,false),'; \
+	echo '    "UseGoma": $(if $(filter-out false,$(USE_GOMA)),true,false),'; \
+	echo '    "Debuggable": $(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),true,false),'; \
 	echo ''; \
 	echo '    "DeviceName": "$(TARGET_DEVICE)",'; \
 	echo '    "DeviceArch": "$(TARGET_ARCH)",'; \
@@ -59,7 +73,8 @@
 	echo ''; \
 	echo '    "CrossHost": "$(HOST_CROSS_OS)",'; \
 	echo '    "CrossHostArch": "$(HOST_CROSS_ARCH)",'; \
-	echo '    "CrossHostSecondaryArch": "$(HOST_CROSS_2ND_ARCH)"'; \
+	echo '    "CrossHostSecondaryArch": "$(HOST_CROSS_2ND_ARCH)",'; \
+	echo '    "Safestack": $(if $(filter true,$(USE_SAFESTACK)),true,false)'; \
 	echo '}') > $(SOONG_VARIABLES_TMP); \
 	if ! cmp -s $(SOONG_VARIABLES_TMP) $(SOONG_VARIABLES); then \
 	  mv $(SOONG_VARIABLES_TMP) $(SOONG_VARIABLES); \
@@ -72,9 +87,8 @@
 	$(hide) mkdir -p $(dir $@)
 	$(hide) touch $@
 
-# Build an Android.mk listing all soong outputs as prebuilts
-$(SOONG_ANDROID_MK): $(SOONG_BOOTSTRAP) $(SOONG_VARIABLES) $(SOONG_IN_MAKE) FORCE
-	$(hide) $(SOONG) $(KATI) $(MAKEPARALLEL) $(NINJA_ARGS)
-
-$(KATI): $(SOONG_ANDROID_MK)
-$(MAKEPARALLEL): $(SOONG_ANDROID_MK)
+# Run Soong, this implicitly create an Android.mk listing all soong outputs as
+# prebuilts.
+.PHONY: run_soong
+run_soong: $(SOONG_BOOTSTRAP) $(SOONG_VARIABLES) $(SOONG_IN_MAKE) FORCE
+	$(hide) SKIP_NINJA=true $(SOONG)
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index 1279878..258c5f8 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -19,6 +19,7 @@
 # classpaths.  They can, however, be included wholesale in
 # other java modules.
 
+$(call record-module-type,STATIC_JAVA_LIBRARY)
 LOCAL_UNINSTALLABLE_MODULE := true
 LOCAL_IS_STATIC_JAVA_LIBRARY := true
 LOCAL_MODULE_CLASS := JAVA_LIBRARIES
@@ -74,12 +75,10 @@
 
 LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
 
-ifdef LOCAL_JACK_ENABLED
 ifndef LOCAL_JACK_PROGUARD_FLAGS
     LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
 endif
 LOCAL_JACK_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_JACK_PROGUARD_FLAGS)
-endif # LOCAL_JACK_ENABLED
 
 R_file_stamp := $(intermediates.COMMON)/src/R.stamp
 LOCAL_INTERMEDIATE_TARGETS += $(R_file_stamp)
@@ -165,13 +164,10 @@
 	$(hide) find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name R.java | xargs cat > $@
 endif  # LOCAL_USE_AAPT2
 
-$(LOCAL_BUILT_MODULE): $(R_file_stamp)
-ifdef LOCAL_JACK_ENABLED
-$(noshrob_classes_jack): $(R_file_stamp)
-$(full_classes_jack): $(R_file_stamp)
-$(jack_check_timestamp): $(R_file_stamp)
-endif # LOCAL_JACK_ENABLED
-$(full_classes_compiled_jar): $(R_file_stamp)
+$(LOCAL_BUILT_MODULE) \
+$(full_classes_compiled_jar) \
+$(noshrob_classes_jack) $(full_classes_jack) $(jack_check_timestamp) \
+  : $(R_file_stamp)
 
 # Rule to build AAR, archive including classes.jar, resource, etc.
 built_aar := $(intermediates.COMMON)/javalib.aar
diff --git a/core/static_library.mk b/core/static_library.mk
index a8ae399..25e5279 100644
--- a/core/static_library.mk
+++ b/core/static_library.mk
@@ -1,3 +1,4 @@
+$(call record-module-type,STATIC_LIBRARY)
 my_prefix := TARGET_
 include $(BUILD_SYSTEM)/multilib.mk
 
diff --git a/core/static_library_internal.mk b/core/static_library_internal.mk
index cabe823..6da6a75 100644
--- a/core/static_library_internal.mk
+++ b/core/static_library_internal.mk
@@ -20,14 +20,21 @@
 
 include $(BUILD_SYSTEM)/binary.mk
 
-ifeq ($(LOCAL_RAW_STATIC_LIBRARY),true)
-LOCAL_RAW_STATIC_LIBRARY:=
-$(all_objects) : PRIVATE_TARGET_PROJECT_INCLUDES :=
-$(all_objects) : PRIVATE_TARGET_C_INCLUDES :=
-$(all_objects) : PRIVATE_TARGET_GLOBAL_CFLAGS :=
-$(all_objects) : PRIVATE_TARGET_GLOBAL_CPPFLAGS :=
-endif
-
 $(LOCAL_BUILT_MODULE) : $(built_whole_libraries)
 $(LOCAL_BUILT_MODULE) : $(all_objects)
 	$(transform-o-to-static-lib)
+
+gcno_suffix := .gcnodir
+
+built_whole_gcno_libraries := \
+    $(foreach lib,$(my_whole_static_libraries), \
+      $(call intermediates-dir-for, \
+        STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX), \
+        $(my_host_cross))/$(lib)$(gcno_suffix))
+
+GCNO_ARCHIVE := $(LOCAL_MODULE)$(gcno_suffix)
+
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_OBJECTS := $(strip $(LOCAL_GCNO_FILES))
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_WHOLE_STATIC_LIBRARIES := $(strip $(built_whole_gcno_libraries))
+$(intermediates)/$(GCNO_ARCHIVE) : $(LOCAL_GCNO_FILES) $(built_whole_gcno_libraries)
+	$(transform-o-to-static-lib)
diff --git a/core/static_test_lib.mk b/core/static_test_lib.mk
index 9d0bcc8..a0e2970 100644
--- a/core/static_test_lib.mk
+++ b/core/static_test_lib.mk
@@ -2,6 +2,7 @@
 ## A thin wrapper around BUILD_STATIC_LIBRARY
 ## Common flags for native tests are added.
 #############################################
+$(call record-module-type,STATIC_TEST_LIBRARY)
 
 include $(BUILD_SYSTEM)/target_test_internal.mk
 
diff --git a/core/target_test_internal.mk b/core/target_test_internal.mk
index 4715fe8..2e65218 100644
--- a/core/target_test_internal.mk
+++ b/core/target_test_internal.mk
@@ -4,12 +4,21 @@
 
 LOCAL_CFLAGS += -DGTEST_OS_LINUX_ANDROID -DGTEST_HAS_STD_STRING
 
-LOCAL_C_INCLUDES += external/gtest/include
-
 ifndef LOCAL_SDK_VERSION
-LOCAL_STATIC_LIBRARIES += libgtest_main libgtest
+    LOCAL_STATIC_LIBRARIES += libgtest_main libgtest
 else
-LOCAL_STATIC_LIBRARIES += libgtest_main_ndk libgtest_ndk
+    ifneq (,$(filter c++_%,$(LOCAL_NDK_STL_VARIANT)))
+        my_ndk_gtest_suffix := _c++
+    else ifneq ($(filter stlport_,$(LOCAL_NDK_STL_VARIANT)),)
+        my_ndk_gtest_suffix := _stlport
+    else ifneq ($(filter gnustl_,$(LOCAL_NDK_STL_VARIANT)),)
+        my_ndk_gtest_suffix := _gnustl
+    else # system STL, use stlport
+        my_ndk_gtest_suffix := _stlport
+    endif
+    LOCAL_STATIC_LIBRARIES += \
+        libgtest_main_ndk$(my_ndk_gtest_suffix) \
+        libgtest_ndk$(my_ndk_gtest_suffix)
 endif
 
 ifdef LOCAL_MODULE_PATH
@@ -24,5 +33,6 @@
 $(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)/$(LOCAL_MODULE)
-LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+ifndef LOCAL_MODULE_RELATIVE_PATH
+LOCAL_MODULE_RELATIVE_PATH := $(LOCAL_MODULE)
+endif
diff --git a/core/tasks/check_boot_jars/package_whitelist.txt b/core/tasks/check_boot_jars/package_whitelist.txt
index 3cb6e28..601017b 100644
--- a/core/tasks/check_boot_jars/package_whitelist.txt
+++ b/core/tasks/check_boot_jars/package_whitelist.txt
@@ -8,6 +8,7 @@
 java\.io
 java\.lang
 java\.lang\.annotation
+java\.lang\.invoke
 java\.lang\.ref
 java\.lang\.reflect
 java\.math
@@ -61,10 +62,13 @@
 javax\.xml\.transform\.stream
 javax\.xml\.validation
 javax\.xml\.xpath
+jdk\.net
 org\.w3c\.dom
 org\.w3c\.dom\.ls
 org\.w3c\.dom\.traversal
 # OpenJdk internal implementation.
+sun\.invoke\.util
+sun\.invoke\.empty
 sun\.misc
 sun\.util.*
 sun\.text.*
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index 910c8b7..2a9c3d8 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -46,19 +46,43 @@
         widevine
 
 
-ifneq (,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES))
+_restrictions := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES))
 
-_vendor_check_modules := $(product_MODULES)
+ifneq (,$(_restrictions))
+ifneq (,$(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_PRODUCT_RESTRICT_VENDOR_FILES))
+$(error Error: cannot set both PRODUCT_RESTRICT_VENDOR_FILES and VENDOR_PRODUCT_RESTRICT_VENDOR_FILES)
+endif
+_vendor_exception_path_prefix :=
+_vendor_exception_modules :=
+else
+_restrictions := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_PRODUCT_RESTRICT_VENDOR_FILES))
+_vendor_exception_path_prefix := $(patsubst %, vendor/%/%, $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_EXCEPTION_PATHS))
+_vendor_exception_modules := $(PRODUCTS.$(INTERNAL_PRODUCT).VENDOR_EXCEPTION_MODULES)
+endif
+
+
+ifneq (,$(_restrictions))
+
+_vendor_check_modules := \
+$(foreach m, $(filter-out $(_vendor_exception_modules), $(product_MODULES)), \
+  $(if $(filter-out FAKE, $(ALL_MODULES.$(m).CLASS)),\
+    $(if $(filter vendor/%, $(ALL_MODULES.$(m).PATH)),\
+      $(if $(filter-out $(_vendor_exception_path_prefix), $(ALL_MODULES.$(m).PATH)),\
+        $(m)))))
 
 _vendor_module_owner_info :=
 # Restrict owners
-ifneq (,$(filter true owner all, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES)))
+ifneq (,$(filter true owner all, $(_restrictions)))
 
-ifneq (,$(filter vendor/%, $(PRODUCT_PACKAGE_OVERLAYS) $(DEVICE_PACKAGE_OVERLAYS)))
-$(error Error: Product "$(TARGET_PRODUCT)" cannot have overlay in vendor tree: \
+_vendor_package_overlays := $(filter-out $(_vendor_exception_path_prefix),\
     $(filter vendor/%, $(PRODUCT_PACKAGE_OVERLAYS) $(DEVICE_PACKAGE_OVERLAYS)))
+ifneq (,$(_vendor_package_overlays))
+$(error Error: Product "$(TARGET_PRODUCT)" cannot have overlay in vendor tree: $(_vendor_package_overlays))
 endif
-_vendor_check_copy_files := $(filter vendor/%, $(PRODUCT_COPY_FILES))
+_vendor_package_overlays :=
+
+_vendor_check_copy_files := $(filter-out $(_vendor_exception_path_prefix),\
+    $(filter vendor/%, $(PRODUCT_COPY_FILES)))
 ifneq (,$(_vendor_check_copy_files))
 $(foreach c, $(_vendor_check_copy_files), \
   $(if $(filter $(_vendor_owner_whitelist), $(call word-colon,3,$(c))),,\
@@ -68,28 +92,24 @@
 _vendor_check_copy_files :=
 
 $(foreach m, $(_vendor_check_modules), \
-  $(if $(filter vendor/%, $(ALL_MODULES.$(m).PATH)),\
-    $(if $(filter-out FAKE, $(ALL_MODULES.$(m).CLASS)),\
-      $(if $(filter $(_vendor_owner_whitelist), $(ALL_MODULES.$(m).OWNER)),,\
-        $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) with unknown owner \
-          "$(ALL_MODULES.$(m).OWNER)" in product "$(TARGET_PRODUCT)"))\
-      $(if $(ALL_MODULES.$(m).INSTALLED),\
-        $(eval _vendor_module_owner_info += $(patsubst $(PRODUCT_OUT)/%,%,$(ALL_MODULES.$(m).INSTALLED)):$(ALL_MODULES.$(m).OWNER))))))
+  $(if $(filter $(_vendor_owner_whitelist), $(ALL_MODULES.$(m).OWNER)),,\
+    $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) with unknown owner \
+      "$(ALL_MODULES.$(m).OWNER)" in product "$(TARGET_PRODUCT)"))\
+  $(if $(ALL_MODULES.$(m).INSTALLED),\
+    $(eval _vendor_module_owner_info += $(patsubst $(PRODUCT_OUT)/%,%,$(ALL_MODULES.$(m).INSTALLED)):$(ALL_MODULES.$(m).OWNER))))
 
 endif
 
 
 # Restrict paths
-ifneq (,$(filter path all, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_RESTRICT_VENDOR_FILES)))
+ifneq (,$(filter path all, $(_restrictions)))
 
 $(foreach m, $(_vendor_check_modules), \
-  $(if $(filter vendor/%, $(ALL_MODULES.$(m).PATH)),\
-    $(if $(filter-out FAKE, $(ALL_MODULES.$(m).CLASS)),\
-      $(if $(filter-out ,$(ALL_MODULES.$(m).INSTALLED)),\
-        $(if $(filter $(TARGET_OUT_VENDOR)/% $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED)),,\
-          $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) \
-            in product "$(TARGET_PRODUCT)" being installed to \
-            $(ALL_MODULES.$(m).INSTALLED) which is not in the vendor tree))))))
+  $(if $(filter-out ,$(ALL_MODULES.$(m).INSTALLED)),\
+    $(if $(filter $(TARGET_OUT_VENDOR)/% $(TARGET_OUT_ODM)/% $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED)),,\
+      $(error Error: vendor module "$(m)" in $(ALL_MODULES.$(m).PATH) \
+        in product "$(TARGET_PRODUCT)" being installed to \
+        $(ALL_MODULES.$(m).INSTALLED) which is not in the vendor tree or odm tree))))
 
 endif
 
@@ -112,4 +132,7 @@
 _vendor_module_owner_info_txt :=
 _vendor_module_owner_info :=
 _vendor_check_modules :=
+_vendor_exception_path_prefix :=
+_vendor_exception_modules :=
+_restrictions :=
 endif
diff --git a/envsetup.sh b/envsetup.sh
index 35df2d5..e919891 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -89,7 +89,7 @@
 {
     if [ "$BUILD_VAR_CACHE_READY" = "true" ]
     then
-        eval echo \"\${abs_var_cache_$1}\"
+        eval "echo \"\${abs_var_cache_$1}\""
     return
     fi
 
@@ -107,7 +107,7 @@
 {
     if [ "$BUILD_VAR_CACHE_READY" = "true" ]
     then
-        eval echo \"\${var_cache_$1}\"
+        eval "echo \"\${var_cache_$1}\""
     return
     fi
 
@@ -290,7 +290,7 @@
 
 function set_sequence_number()
 {
-    export BUILD_ENV_SEQUENCE_NUMBER=10
+    export BUILD_ENV_SEQUENCE_NUMBER=12
 }
 
 function settitle()
@@ -715,11 +715,18 @@
     local T="$1"
     test "$WITH_STATIC_ANALYZER" = "0" && unset WITH_STATIC_ANALYZER
     if [ -n "$WITH_STATIC_ANALYZER" ]; then
+        # Use scan-build to collect all static analyzer reports into directory
+        # /tmp/scan-build-yyyy-mm-dd-hhmmss-*
+        # The clang compiler passed by --use-analyzer here is not important.
+        # build/core/binary.mk will set CLANG_CXX and CLANG before calling
+        # c++-analyzer and ccc-analyzer.
+        local CLANG_VERSION=$(get_build_var LLVM_PREBUILTS_VERSION)
+        local BUILD_OS=$(get_build_var BUILD_OS)
+        local CLANG_DIR="$T/prebuilts/clang/host/${BUILD_OS}-x86/${CLANG_VERSION}"
         echo "\
-$T/prebuilts/misc/linux-x86/analyzer/tools/scan-build/scan-build \
---use-analyzer $T/prebuilts/misc/linux-x86/analyzer/bin/analyzer \
---status-bugs \
---top=$T"
+${CLANG_DIR}/tools/scan-build/bin/scan-build \
+--use-analyzer ${CLANG_DIR}/bin/clang \
+--status-bugs"
     fi
 }
 
@@ -742,7 +749,7 @@
     T=
     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
         T=`PWD= /bin/pwd`
-        if [ -f "$T/Android.mk" ]; then
+        if [ -f "$T/Android.mk" -o -f "$T/Android.bp" ]; then
             echo $T/Android.mk
             \cd $HERE
             return
@@ -782,11 +789,17 @@
             done
             if [ -n "$GET_INSTALL_PATH" ]; then
               MODULES=
-              ARGS=GET-INSTALL-PATH
+              ARGS=GET-INSTALL-PATH-IN-$(dirname ${M})
+              ARGS=${ARGS//\//-}
             else
-              MODULES=all_modules
+              MODULES=MODULES-IN-$(dirname ${M})
+              # Convert "/" to "-".
+              MODULES=${MODULES//\//-}
               ARGS=$@
             fi
+            if [ "1" = "${WITH_TIDY_ONLY}" -o "true" = "${WITH_TIDY_ONLY}" ]; then
+              MODULES=tidy_only
+            fi
             ONE_SHOT_MAKEFILE=$M $DRV make -C $T -f build/core/main.mk $MODULES $ARGS
         fi
     fi
@@ -799,28 +812,38 @@
     if [ "$T" ]; then
         local MAKEFILE=
         local MODULES=
+        local MODULES_IN_PATHS=
         local ARGS=
         local DIR TO_CHOP
+        local DIR_MODULES
         local GET_INSTALL_PATH=
+        local GET_INSTALL_PATHS=
         local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
         local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
         for DIR in $DIRS ; do
-            MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'`
-            if [ "$MODULES" = "" ]; then
-                MODULES=all_modules
-            fi
+            DIR_MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'`
             DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'`
-            if [ -f $DIR/Android.mk ]; then
+            # Remove the leading ./ and trailing / if any exists.
+            DIR=${DIR#./}
+            DIR=${DIR%/}
+            if [ -f $DIR/Android.mk -o -f $DIR/Android.bp ]; then
                 local TO_CHOP=`(\cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
                 local TO_CHOP=`expr $TO_CHOP + 1`
                 local START=`PWD= /bin/pwd`
-                local MFILE=`echo $START | cut -c${TO_CHOP}-`
-                if [ "$MFILE" = "" ] ; then
-                    MFILE=$DIR/Android.mk
+                local MDIR=`echo $START | cut -c${TO_CHOP}-`
+                if [ "$MDIR" = "" ] ; then
+                    MDIR=$DIR
                 else
-                    MFILE=$MFILE/$DIR/Android.mk
+                    MDIR=$MDIR/$DIR
                 fi
-                MAKEFILE="$MAKEFILE $MFILE"
+                MDIR=${MDIR%/.}
+                if [ "$DIR_MODULES" = "" ]; then
+                    MODULES_IN_PATHS="$MODULES_IN_PATHS MODULES-IN-$MDIR"
+                    GET_INSTALL_PATHS="$GET_INSTALL_PATHS GET-INSTALL-PATH-IN-$MDIR"
+                else
+                    MODULES="$MODULES $DIR_MODULES"
+                fi
+                MAKEFILE="$MAKEFILE $MDIR/Android.mk"
             else
                 case $DIR in
                   showcommands | snod | dist | *=*) ARGS="$ARGS $DIR";;
@@ -835,10 +858,17 @@
             fi
         done
         if [ -n "$GET_INSTALL_PATH" ]; then
-          ARGS=$GET_INSTALL_PATH
+          ARGS=${GET_INSTALL_PATHS//\//-}
           MODULES=
+          MODULES_IN_PATHS=
         fi
-        ONE_SHOT_MAKEFILE="$MAKEFILE" $DRV make -C $T -f build/core/main.mk $DASH_ARGS $MODULES $ARGS
+        if [ "1" = "${WITH_TIDY_ONLY}" -o "true" = "${WITH_TIDY_ONLY}" ]; then
+          MODULES=tidy_only
+          MODULES_IN_PATHS=
+        fi
+        # Convert "/" to "-".
+        MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}
+        ONE_SHOT_MAKEFILE="$MAKEFILE" $DRV make -C $T -f build/core/main.mk $DASH_ARGS $MODULES $MODULES_IN_PATHS $ARGS
     else
         echo "Couldn't locate the top of the tree.  Try setting TOP."
         return 1
@@ -856,8 +886,10 @@
       echo "Couldn't locate the top of the tree.  Try setting TOP."
       return 1
     fi
-    local MY_PWD=`PWD= /bin/pwd|sed 's:'$T'/::'`
-    local MODULES_IN_PATHS=MODULES-IN-$MY_PWD
+    local M=$(findmakefile)
+    # Remove the path to top as the makefilepath needs to be relative
+    local M=`echo $M|sed 's:'$T'/::'`
+    local MODULES_IN_PATHS=MODULES-IN-$(dirname ${M})
     # Convert "/" to "-".
     MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}
     $DRV make -C $T -f build/core/main.mk $@ $MODULES_IN_PATHS
@@ -909,7 +941,11 @@
 {
     T=$(gettop)
     if [ "$T" ]; then
-        \cd $(gettop)
+        if [ "$1" ]; then
+            \cd $(gettop)/$1
+        else
+            \cd $(gettop)
+        fi
     else
         echo "Couldn't locate the top of the tree.  Try setting TOP."
     fi
@@ -1022,7 +1058,7 @@
         return;
     fi;
     echo "Setting core limit for $PID to infinite...";
-    adb shell prlimit $PID 4 -1 -1
+    adb shell /system/bin/ulimit -p $PID -c unlimited
 }
 
 # core - send SIGV and pull the core for process
diff --git a/libs/host/Android.mk b/libs/host/Android.mk
deleted file mode 100644
index bc25e4b..0000000
--- a/libs/host/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    CopyFile.c
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_MODULE:= libhost
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CXX_STL := none
-
-# acp uses libhost, so we can't use
-# acp to install libhost.
-LOCAL_ACP_UNAVAILABLE:= true
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-# Include toolchain prebuilt modules if they exist.
--include $(TARGET_TOOLCHAIN_ROOT)/toolchain.mk
diff --git a/target/board/generic/sepolicy/file.te b/target/board/generic/sepolicy/file.te
index 6fad80a..9227f80 100644
--- a/target/board/generic/sepolicy/file.te
+++ b/target/board/generic/sepolicy/file.te
@@ -1 +1,2 @@
 type qemud_socket, file_type;
+type sysfs_writable, fs_type, sysfs_type, mlstrustedobject;
diff --git a/target/board/generic_mips64/BoardConfig.mk b/target/board/generic_mips64/BoardConfig.mk
index ebc1675..ed9c9b3 100644
--- a/target/board/generic_mips64/BoardConfig.mk
+++ b/target/board/generic_mips64/BoardConfig.mk
@@ -31,7 +31,10 @@
 TARGET_2ND_ARCH := mips
 ifeq (,$(TARGET_2ND_ARCH_VARIANT))
 ifeq ($(TARGET_ARCH_VARIANT),mips64r6)
-TARGET_2ND_ARCH_VARIANT :=  mips32r6
+# Imgtec builds use 32r6 arch variant with Imgtec-maintained prebuilts/ndk library:
+# TARGET_2ND_ARCH_VARIANT := mips32r6
+# Aosp builds lack full set of mips32r6 NDK prebuilts, so use 32r2 abi:
+TARGET_2ND_ARCH_VARIANT :=  mips32r2-fp
 else
 TARGET_2ND_ARCH_VARIANT :=  mips32r2-fp
 endif
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
index 553bec9..6958ba5 100755
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -13,7 +13,7 @@
 
 TARGET_2ND_CPU_ABI := x86
 TARGET_2ND_ARCH := x86
-TARGET_2ND_ARCH_VARIANT := x86
+TARGET_2ND_ARCH_VARIANT := x86_64
 
 TARGET_USES_64_BIT_BINDER := true
 
diff --git a/target/board/generic_x86_arm/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
new file mode 100644
index 0000000..6e2573e
--- /dev/null
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -0,0 +1,60 @@
+# Copyright (C) 2016 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.
+#
+
+# Configuration for generic_x86 + arm libraries needed by binary translation.
+
+# The generic product target doesn't have any hardware-specific pieces.
+TARGET_NO_BOOTLOADER := true
+TARGET_NO_KERNEL := true
+TARGET_CPU_ABI := x86
+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
+TARGET_2ND_CPU_VARIANT := generic
+
+# Tell the build system this isn't a typical 64bit+32bit multilib configuration.
+TARGET_TRANSLATE_2ND_ARCH := true
+
+# no hardware camera
+USE_CAMERA_STUB := true
+
+# Enable dex-preoptimization to speed up the first boot sequence
+# of an SDK AVD. Note that this operation only works on Linux for now
+ifeq ($(HOST_OS),linux)
+  ifeq ($(WITH_DEXPREOPT),)
+    WITH_DEXPREOPT := true
+  endif
+endif
+
+# Build OpenGLES emulation host and guest libraries
+BUILD_EMULATOR_OPENGL := true
+
+# Build and enable the OpenGL ES View renderer. When running on the emulator,
+# the GLES renderer disables itself if host GL acceleration isn't available.
+USE_OPENGL_RENDERER := true
+
+TARGET_USERIMAGES_USE_EXT4 := true
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1879048192  # 1.75 GB
+BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
+BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_FLASH_BLOCK_SIZE := 512
+TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
+
+BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 69edc72..42447f1 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -53,6 +53,7 @@
     $(LOCAL_DIR)/aosp_arm.mk \
     $(LOCAL_DIR)/full.mk \
     $(LOCAL_DIR)/aosp_x86.mk \
+    $(LOCAL_DIR)/aosp_x86_arm.mk \
     $(LOCAL_DIR)/full_x86.mk \
     $(LOCAL_DIR)/aosp_mips.mk \
     $(LOCAL_DIR)/full_mips.mk \
diff --git a/target/product/aosp_x86_arm.mk b/target/product/aosp_x86_arm.mk
new file mode 100644
index 0000000..85a2cf8
--- /dev/null
+++ b/target/product/aosp_x86_arm.mk
@@ -0,0 +1,42 @@
+#
+# Copyright 2016 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.
+#
+
+
+# aosp_x86 with arm libraries needed by binary translation.
+
+include $(SRC_TARGET_DIR)/product/full_x86.mk
+
+# arm libraries. This is the list of shared libraries included in the NDK.
+# Their dependency libraries will be automatically pulled in.
+PRODUCT_PACKAGES += \
+  libandroid_arm \
+  libc_arm \
+  libdl_arm \
+  libEGL_arm \
+  libGLESv1_CM_arm \
+  libGLESv2_arm \
+  libGLESv3_arm \
+  libjnigraphics_arm \
+  liblog_arm \
+  libm_arm \
+  libmediandk_arm \
+  libOpenMAXAL_arm \
+  libstdc++_arm \
+  libOpenSLES_arm \
+  libz_arm \
+
+PRODUCT_NAME := aosp_x86_arm
+PRODUCT_DEVICE := generic_x86_arm
diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk
index 009ca52..d19dcb2 100644
--- a/target/product/core_minimal.mk
+++ b/target/product/core_minimal.mk
@@ -68,6 +68,8 @@
     libfilterfw \
     libkeystore \
     libgatekeeper \
+    libwebviewchromium_loader \
+    libwebviewchromium_plat_support \
     libwilhelm \
     logd \
     make_ext4fs \
diff --git a/target/product/embedded.mk b/target/product/embedded.mk
index 55de3b9..5faf24f 100644
--- a/target/product/embedded.mk
+++ b/target/product/embedded.mk
@@ -32,6 +32,7 @@
     grep \
     gzip \
     healthd \
+    hwservicemanager \
     init \
     init.environ.rc \
     init.rc \
diff --git a/target/product/product_launched_with_l.mk b/target/product/product_launched_with_l.mk
index b86f424..8127bc3 100644
--- a/target/product/product_launched_with_l.mk
+++ b/target/product/product_launched_with_l.mk
@@ -1,2 +1,3 @@
 #PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
 PRODUCT_SHIPPING_API_LEVEL := 21
+
diff --git a/tools/acp/Android.bp b/tools/acp/Android.bp
new file mode 100644
index 0000000..faf2034
--- /dev/null
+++ b/tools/acp/Android.bp
@@ -0,0 +1,13 @@
+// Copyright 2005 The Android Open Source Project
+//
+// Custom version of cp.
+
+cc_binary_host {
+
+    srcs: ["acp.c"],
+
+    static_libs: ["libhost"],
+    name: "acp",
+    stl: "none",
+
+}
diff --git a/tools/acp/Android.mk b/tools/acp/Android.mk
deleted file mode 100644
index eec9c9d..0000000
--- a/tools/acp/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Custom version of cp.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    acp.c
-
-LOCAL_STATIC_LIBRARIES := libhost
-LOCAL_MODULE := acp
-LOCAL_ACP_UNAVAILABLE := true
-LOCAL_CXX_STL := none
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/atree/atree.cpp b/tools/atree/atree.cpp
index b134e01..7deca7e 100644
--- a/tools/atree/atree.cpp
+++ b/tools/atree/atree.cpp
@@ -92,7 +92,7 @@
 
 // Escape the filename so that it can be added to the makefile properly.
 static string
-escape_filename(const string name)
+escape_filename(const string& name)
 {
     ostringstream new_name;
     for (string::const_iterator iter = name.begin(); iter != name.end(); ++iter)
diff --git a/tools/brillo-clang-format b/tools/brillo-clang-format
new file mode 100644
index 0000000..a69d9d2
--- /dev/null
+++ b/tools/brillo-clang-format
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2016 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.
+#
+
+### DO NOT COPY THIS FILE TO YOUR PROJECT. ###
+
+#
+# This is the .clang-format file used by all Brillo projects, conforming to the
+# style guide defined by Brillo. To use this file create a *relative* symlink in
+# your project pointing to this file, as this repository is expected to be
+# present in all manifests.
+#
+# See go/brillo-c++-style for details about the style guide.
+#
+
+BasedOnStyle: Google
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+BinPackArguments: false
+BinPackParameters: false
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+PointerAlignment: Left
+TabWidth: 2
diff --git a/tools/check_link_type.py b/tools/check_link_type.py
new file mode 100755
index 0000000..40754ad
--- /dev/null
+++ b/tools/check_link_type.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 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.
+
+"""Utility to verify modules link against acceptable module types"""
+
+from __future__ import print_function
+import argparse
+import os
+import sys
+
+WARNING_MSG = ('\033[1m%(makefile)s: \033[35mwarning:\033[0m\033[1m '
+    '%(module)s (%(type)s) should not link to %(dep_name)s (%(dep_type)s)'
+    '\033[0m')
+ERROR_MSG = ('\033[1m%(makefile)s: \033[31merror:\033[0m\033[1m '
+    '%(module)s (%(type)s) should not link to %(dep_name)s (%(dep_type)s)'
+    '\033[0m')
+
+def parse_args():
+    """Parse commandline arguments."""
+    parser = argparse.ArgumentParser(description='Check link types')
+    parser.add_argument('--makefile', help='Makefile defining module')
+    parser.add_argument('--module', help='The module being checked')
+    parser.add_argument('--type', help='The link type of module')
+    parser.add_argument('--allowed', help='Allow deps to use these types',
+                        action='append', default=[], metavar='TYPE')
+    parser.add_argument('--warn', help='Warn if deps use these types',
+                        action='append', default=[], metavar='TYPE')
+    parser.add_argument('deps', help='The dependencies to check',
+                        metavar='DEP', nargs='*')
+    return parser.parse_args()
+
+def print_msg(msg, args, dep_name, dep_type):
+    """Print a warning or error message"""
+    print(msg % {
+          "makefile": args.makefile,
+          "module": args.module,
+          "type": args.type,
+          "dep_name": dep_name,
+          "dep_type": dep_type}, file=sys.stderr)
+
+def main():
+    """Program entry point."""
+    args = parse_args()
+
+    failed = False
+    for dep in args.deps:
+        dep_name = os.path.basename(os.path.dirname(dep))
+        if dep_name.endswith('_intermediates'):
+            dep_name = dep_name[:len(dep_name)-len('_intermediates')]
+
+        with open(dep, 'r') as dep_file:
+            dep_types = dep_file.read().strip().split(' ')
+
+        for dep_type in dep_types:
+            if dep_type in args.allowed:
+                continue
+            if dep_type in args.warn:
+                print_msg(WARNING_MSG, args, dep_name, dep_type)
+            else:
+                print_msg(ERROR_MSG, args, dep_name, dep_type)
+                failed = True
+
+    if failed:
+        sys.exit(1)
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/diff_package_overlays.py b/tools/diff_package_overlays.py
deleted file mode 100755
index 0e2c773..0000000
--- a/tools/diff_package_overlays.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2012 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Prints to stdout the package names that have overlay changes between
-current_overlays.txt and previous_overlays.txt.
-
-Usage: diff_package_overlays.py <current_packages.txt> <current_overlays.txt> <previous_overlays.txt>
-current_packages.txt contains all package names separated by space in the current build.
-This script modfies current_packages.txt if necessary: if there is a package in
-previous_overlays.txt but absent from current_packages.txt, we copy that line
-from previous_overlays.txt over to current_packages.txt. Usually that means we
-just don't care that package in the current build (for example we are switching
-from a full build to a partial build with mm/mmm), and we should carry on the
-previous overlay config so current_overlays.txt always reflects the current
-status of the entire tree.
-
-Format of current_overlays.txt and previous_overlays.txt:
-  <package_name> <resource_overlay> [resource_overlay ...]
-  <package_name> <resource_overlay> [resource_overlay ...]
-  ...
-"""
-
-import sys
-
-def main(argv):
-  if len(argv) != 4:
-    print >> sys.stderr, __doc__
-    sys.exit(1)
-
-  f = open(argv[1])
-  all_packages = set(f.read().split())
-  f.close()
-
-  def load_overlay_config(filename):
-    f = open(filename)
-    result = {}
-    for line in f:
-      line = line.strip()
-      if not line or line.startswith("#"):
-        continue
-      words = line.split()
-      result[words[0]] = " ".join(words[1:])
-    f.close()
-    return result
-
-  current_overlays = load_overlay_config(argv[2])
-  previous_overlays = load_overlay_config(argv[3])
-
-  result = []
-  carryon = []
-  for p in current_overlays:
-    if p not in previous_overlays:
-      result.append(p)
-    elif current_overlays[p] != previous_overlays[p]:
-      result.append(p)
-  for p in previous_overlays:
-    if p not in current_overlays:
-      if p in all_packages:
-        # overlay changed
-        result.append(p)
-      else:
-        # we don't build p in the current build.
-        carryon.append(p)
-
-  # Add carryon to the current overlay config file.
-  if carryon:
-    f = open(argv[2], "a")
-    for p in carryon:
-      f.write(p + " " + previous_overlays[p] + "\n")
-    f.close()
-
-  # Print out the package names that have overlay change.
-  for r in result:
-    print r
-
-if __name__ == "__main__":
-  main(sys.argv)
diff --git a/tools/fat16copy.py b/tools/fat16copy.py
new file mode 100755
index 0000000..1dd15b7
--- /dev/null
+++ b/tools/fat16copy.py
@@ -0,0 +1,789 @@
+#!/usr/bin/env python
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import sys
+import struct
+
+FAT_TABLE_START = 0x200
+DEL_MARKER = 0xe5
+ESCAPE_DEL_MARKER = 0x05
+
+ATTRIBUTE_READ_ONLY = 0x1
+ATTRIBUTE_HIDDEN = 0x2
+ATTRIBUTE_SYSTEM = 0x4
+ATTRIBUTE_VOLUME_LABEL = 0x8
+ATTRIBUTE_SUBDIRECTORY = 0x10
+ATTRIBUTE_ARCHIVE = 0x20
+ATTRIBUTE_DEVICE = 0x40
+
+LFN_ATTRIBUTES = \
+    ATTRIBUTE_VOLUME_LABEL | \
+    ATTRIBUTE_SYSTEM | \
+    ATTRIBUTE_HIDDEN | \
+    ATTRIBUTE_READ_ONLY
+LFN_ATTRIBUTES_BYTE = struct.pack("B", LFN_ATTRIBUTES)
+
+MAX_CLUSTER_ID = 0x7FFF
+
+def read_le_short(f):
+  "Read a little-endian 2-byte integer from the given file-like object"
+  return struct.unpack("<H", f.read(2))[0]
+
+def read_le_long(f):
+  "Read a little-endian 4-byte integer from the given file-like object"
+  return struct.unpack("<L", f.read(4))[0]
+
+def read_byte(f):
+  "Read a 1-byte integer from the given file-like object"
+  return struct.unpack("B", f.read(1))[0]
+
+def skip_bytes(f, n):
+  "Fast-forward the given file-like object by n bytes"
+  f.seek(n, os.SEEK_CUR)
+
+def skip_short(f):
+  "Fast-forward the given file-like object 2 bytes"
+  skip_bytes(f, 2)
+
+def skip_byte(f):
+  "Fast-forward the given file-like object 1 byte"
+  skip_bytes(f, 1)
+
+def rewind_bytes(f, n):
+  "Rewind the given file-like object n bytes"
+  skip_bytes(f, -n)
+
+def rewind_short(f):
+  "Rewind the given file-like object 2 bytes"
+  rewind_bytes(f, 2)
+
+class fake_file(object):
+  """
+  Interface for python file-like objects that we use to manipulate the image.
+  Inheritors must have an idx member which indicates the file pointer, and a
+  size member which indicates the total file size.
+  """
+
+  def seek(self, amount, direction=0):
+    "Implementation of seek from python's file-like object interface."
+    if direction == os.SEEK_CUR:
+      self.idx += amount
+    elif direction == os.SEEK_END:
+      self.idx = self.size - amount
+    else:
+      self.idx = amount
+
+    if self.idx < 0:
+      self.idx = 0
+    if self.idx > self.size:
+      self.idx = self.size
+
+class fat_file(fake_file):
+  """
+  A file inside of our fat image. The file may or may not have a dentry, and
+  if it does this object knows nothing about it. All we see is a valid cluster
+  chain.
+  """
+
+  def __init__(self, fs, cluster, size=None):
+    """
+    fs: The fat() object for the image this file resides in.
+    cluster: The first cluster of data for this file.
+    size: The size of this file. If not given, we use the total length of the
+          cluster chain that starts from the cluster argument.
+    """
+    self.fs = fs
+    self.start_cluster = cluster
+    self.size = size
+
+    if self.size is None:
+      self.size = fs.get_chain_size(cluster)
+
+    self.idx = 0
+
+  def read(self, size):
+    "Read method for pythonic file-like interface."
+    if self.idx + size > self.size:
+      size = self.size - self.idx
+    got = self.fs.read_file(self.start_cluster, self.idx, size)
+    self.idx += len(got)
+    return got
+
+  def write(self, data):
+    "Write method for pythonic file-like interface."
+    self.fs.write_file(self.start_cluster, self.idx, data)
+    self.idx += len(data)
+
+    if self.idx > self.size:
+      self.size = self.idx
+
+def shorten(name, index):
+  """
+  Create a file short name from the given long name (with the extension already
+  removed). The index argument gives a disambiguating integer to work into the
+  name to avoid collisions.
+  """
+  name = "".join(name.split('.')).upper()
+  postfix = "~" + str(index)
+  return name[:8 - len(postfix)] + postfix
+
+class fat_dir(object):
+  "A directory in our fat filesystem."
+
+  def __init__(self, backing):
+    """
+    backing: A file-like object from which we can read dentry info. Should have
+    an fs member allowing us to get to the underlying image.
+    """
+    self.backing = backing
+    self.dentries = []
+    to_read = self.backing.size / 32
+
+    self.backing.seek(0)
+
+    while to_read > 0:
+      (dent, consumed) = self.backing.fs.read_dentry(self.backing)
+      to_read -= consumed
+
+      if dent:
+        self.dentries.append(dent)
+
+  def __str__(self):
+    return "\n".join([str(x) for x in self.dentries]) + "\n"
+
+  def add_dentry(self, attributes, shortname, ext, longname, first_cluster,
+      size):
+    """
+    Add a new dentry to this directory.
+    attributes: Attribute flags for this dentry. See the ATTRIBUTE_ constants
+                above.
+    shortname: Short name of this file. Up to 8 characters, no dots.
+    ext: Extension for this file. Up to 3 characters, no dots.
+    longname: The long name for this file, with extension. Largely unrestricted.
+    first_cluster: The first cluster in the cluster chain holding the contents
+                   of this file.
+    size: The size of this file. Set to 0 for subdirectories.
+    """
+    new_dentry = dentry(self.backing.fs, attributes, shortname, ext,
+        longname, first_cluster, size)
+    new_dentry.commit(self.backing)
+    self.dentries.append(new_dentry)
+    return new_dentry
+
+  def make_short_name(self, name):
+    """
+    Given a long file name, return an 8.3 short name as a tuple. Name will be
+    engineered not to collide with other such names in this folder.
+    """
+    parts = name.rsplit('.', 1)
+
+    if len(parts) == 1:
+      parts.append('')
+
+    name = parts[0]
+    ext = parts[1].upper()
+
+    index = 1
+    shortened = shorten(name, index)
+
+    for dent in self.dentries:
+      assert dent.longname != name, "File must not exist"
+      if dent.shortname == shortened:
+        index += 1
+        shortened = shorten(name, index)
+
+    if len(name) <= 8 and len(ext) <= 3 and not '.' in name:
+      return (name.upper().ljust(8), ext.ljust(3))
+
+    return (shortened.ljust(8), ext[:3].ljust(3))
+
+  def new_file(self, name, data=None):
+    """
+    Add a new regular file to this directory.
+    name: The name of the new file.
+    data: The contents of the new file. Given as a file-like object.
+    """
+    size = 0
+    if data:
+      data.seek(0, os.SEEK_END)
+      size = data.tell()
+
+    chunk = self.backing.fs.allocate(size or 1)
+    (shortname, ext) = self.make_short_name(name)
+    self.add_dentry(0, shortname, ext, name, chunk, size)
+
+    if data is None:
+      return
+
+    data_file = fat_file(self.backing.fs, chunk, size)
+    data.seek(0)
+    data_file.write(data.read())
+
+  def new_subdirectory(self, name):
+    """
+    Create a new subdirectory of this directory with the given name.
+    Returns a fat_dir().
+    """
+    chunk = self.backing.fs.allocate(1)
+    (shortname, ext) = self.make_short_name(name)
+    new_dentry = dentry(self.backing.fs, ATTRIBUTE_SUBDIRECTORY,
+        shortname, ext, name, chunk, 0)
+    new_dentry.commit(self.backing)
+    return new_dentry.open_directory()
+
+def lfn_checksum(name_data):
+  """
+  Given the characters of an 8.3 file name (concatenated *without* the dot),
+  Compute a one-byte checksum which needs to appear in corresponding long file
+  name entries.
+  """
+  assert len(name_data) == 11, "Name data should be exactly 11 characters"
+  name_data = struct.unpack("B" * 11, name_data)
+
+  result = 0
+
+  for char in name_data:
+    last_bit = (result & 1) << 7
+    result = (result >> 1) | last_bit
+    result += char
+    result = result & 0xFF
+
+  return struct.pack("B", result)
+
+class dentry(object):
+  "A directory entry"
+  def __init__(self, fs, attributes, shortname, ext, longname,
+      first_cluster, size):
+    """
+    fs: The fat() object for the image we're stored in.
+    attributes: The attribute flags for this dentry. See the ATTRIBUTE_ flags
+                above.
+    shortname: The short name stored in this dentry. Up to 8 characters, no
+               dots.
+    ext: The file extension stored in this dentry. Up to 3 characters, no
+         dots.
+    longname: The long file name stored in this dentry.
+    first_cluster: The first cluster in the cluster chain backing the file
+                   this dentry points to.
+    size: Size of the file this dentry points to. 0 for subdirectories.
+    """
+    self.fs = fs
+    self.attributes = attributes
+    self.shortname = shortname
+    self.ext = ext
+    self.longname = longname
+    self.first_cluster = first_cluster
+    self.size = size
+
+  def name(self):
+    "A friendly text file name for this dentry."
+    if self.longname:
+      return self.longname
+
+    if not self.ext or len(self.ext) == 0:
+      return self.shortname
+
+    return self.shortname + "." + self.ext
+
+  def __str__(self):
+    return self.name() + " (" + str(self.size) + \
+      " bytes @ " + str(self.first_cluster) + ")"
+
+  def is_directory(self):
+    "Return whether this dentry points to a directory."
+    return (self.attributes & ATTRIBUTE_SUBDIRECTORY) != 0
+
+  def open_file(self):
+    "Open the target of this dentry if it is a regular file."
+    assert not self.is_directory(), "Cannot open directory as file"
+    return fat_file(self.fs, self.first_cluster, self.size)
+
+  def open_directory(self):
+    "Open the target of this dentry if it is a directory."
+    assert self.is_directory(), "Cannot open file as directory"
+    return fat_dir(fat_file(self.fs, self.first_cluster))
+
+  def longname_records(self, checksum):
+    """
+    Get the longname records necessary to store this dentry's long name,
+    packed as a series of 32-byte strings.
+    """
+    if self.longname is None:
+      return []
+    if len(self.longname) == 0:
+      return []
+
+    encoded_long_name = self.longname.encode('utf-16-le')
+    long_name_padding = "\0" * (26 - (len(encoded_long_name) % 26))
+    padded_long_name = encoded_long_name + long_name_padding
+
+    chunks = [padded_long_name[i:i+26] for i in range(0,
+      len(padded_long_name), 26)]
+    records = []
+    sequence_number = 1
+
+    for c in chunks:
+      sequence_byte = struct.pack("B", sequence_number)
+      sequence_number += 1
+      record = sequence_byte + c[:10] + LFN_ATTRIBUTES_BYTE + "\0" + \
+          checksum + c[10:22] + "\0\0" + c[22:]
+      records.append(record)
+
+    last = records.pop()
+    last_seq = struct.unpack("B", last[0])[0]
+    last_seq = last_seq | 0x40
+    last = struct.pack("B", last_seq) + last[1:]
+    records.append(last)
+    records.reverse()
+
+    return records
+
+  def commit(self, f):
+    """
+    Write this dentry into the given file-like object,
+    which is assumed to contain a FAT directory.
+    """
+    f.seek(0)
+    padded_short_name = self.shortname.ljust(8)
+    padded_ext = self.ext.ljust(3)
+    name_data = padded_short_name + padded_ext
+    longname_record_data = self.longname_records(lfn_checksum(name_data))
+    record = struct.pack("<11sBBBHHHHHHHL",
+        name_data,
+        self.attributes,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        self.first_cluster,
+        self.size)
+    entry = "".join(longname_record_data + [record])
+
+    record_count = len(longname_record_data) + 1
+
+    found_count = 0
+
+    while True:
+      record = f.read(32)
+
+      if record is None or len(record) != 32:
+        break
+
+      marker = struct.unpack("B", record[0])[0]
+
+      if marker == DEL_MARKER or marker == 0:
+        found_count += 1
+
+        if found_count == record_count:
+          break
+      else:
+        found_count = 0
+
+    if found_count != record_count:
+      f.write("\0" * self.fs.bytes_per_cluster)
+      f.seek(-self.fs.bytes_per_cluster, os.SEEK_CUR)
+    else:
+      f.seek(-(record_count * 32), os.SEEK_CUR)
+    f.write(entry)
+
+class root_dentry_file(fake_file):
+  """
+  File-like object for the root directory. The root directory isn't stored in a
+  normal file, so we can't use a normal fat_file object to create a view of it.
+  """
+  def __init__(self, fs):
+    self.fs = fs
+    self.idx = 0
+    self.size = fs.root_entries * 32
+
+  def read(self, count):
+    f = self.fs.f
+    f.seek(self.fs.data_start() + self.idx)
+
+    if self.idx + count > self.size:
+      count = self.size - self.idx
+
+    ret = f.read(count)
+    self.idx += len(ret)
+    return ret
+
+  def write(self, data):
+    f = self.fs.f
+    f.seek(self.fs.data_start() + self.idx)
+
+    if self.idx + len(data) > self.size:
+      data = data[:self.size - self.idx]
+
+    f.write(data)
+    self.idx += len(data)
+    if self.idx > self.size:
+      self.size = self.idx
+
+class fat(object):
+  "A FAT image"
+
+  def __init__(self, path):
+    """
+    path: Path to an image file containing a FAT file system.
+    """
+    f = open(path, "r+b")
+
+    self.f = f
+
+    f.seek(0xb)
+    bytes_per_sector = read_le_short(f)
+    sectors_per_cluster = read_byte(f)
+
+    self.bytes_per_cluster = bytes_per_sector * sectors_per_cluster
+
+    reserved_sectors = read_le_short(f)
+    assert reserved_sectors == 1, \
+        "Can only handle FAT with 1 reserved sector"
+
+    fat_count = read_byte(f)
+    assert fat_count == 2, "Can only handle FAT with 2 tables"
+
+    self.root_entries = read_le_short(f)
+
+    skip_short(f) # Image size. Sort of. Useless field.
+    skip_byte(f) # Media type. We don't care.
+
+    self.fat_size = read_le_short(f) * bytes_per_sector
+    self.root = fat_dir(root_dentry_file(self))
+
+  def data_start(self):
+    """
+    Index of the first byte after the FAT tables.
+    """
+    return FAT_TABLE_START + self.fat_size * 2
+
+  def get_chain_size(self, head_cluster):
+    """
+    Return how many total bytes are in the cluster chain rooted at the given
+    cluster.
+    """
+    if head_cluster == 0:
+      return 0
+
+    f = self.f
+    f.seek(FAT_TABLE_START + head_cluster * 2)
+
+    cluster_count = 0
+
+    while head_cluster <= MAX_CLUSTER_ID:
+      cluster_count += 1
+      head_cluster = read_le_short(f)
+      f.seek(FAT_TABLE_START + head_cluster * 2)
+
+    return cluster_count * self.bytes_per_cluster
+
+  def read_dentry(self, f=None):
+    """
+    Read and decode a dentry from the given file-like object at its current
+    seek position.
+    """
+    f = f or self.f
+    attributes = None
+
+    consumed = 1
+
+    lfn_entries = {}
+
+    while True:
+      skip_bytes(f, 11)
+      attributes = read_byte(f)
+      rewind_bytes(f, 12)
+
+      if attributes & LFN_ATTRIBUTES != LFN_ATTRIBUTES:
+        break
+
+      consumed += 1
+
+      seq = read_byte(f)
+      chars = f.read(10)
+      skip_bytes(f, 3) # Various hackish nonsense
+      chars += f.read(12)
+      skip_short(f) # Lots more nonsense
+      chars += f.read(4)
+
+      chars = unicode(chars, "utf-16-le").encode("utf-8")
+
+      lfn_entries[seq] = chars
+
+    ind = read_byte(f)
+
+    if ind == 0 or ind == DEL_MARKER:
+      skip_bytes(f, 31)
+      return (None, consumed)
+
+    if ind == ESCAPE_DEL_MARKER:
+      ind = DEL_MARKER
+
+    ind = str(unichr(ind))
+
+    if ind == '.':
+      skip_bytes(f, 31)
+      return (None, consumed)
+
+    shortname = ind + f.read(7).rstrip()
+    ext = f.read(3).rstrip()
+    skip_bytes(f, 15) # Assorted flags, ctime/atime/mtime, etc.
+    first_cluster = read_le_short(f)
+    size = read_le_long(f)
+
+    lfn = lfn_entries.items()
+    lfn.sort(key=lambda x: x[0])
+    lfn = reduce(lambda x, y: x + y[1], lfn, "")
+
+    if len(lfn) == 0:
+      lfn = None
+    else:
+      lfn = lfn.split('\0', 1)[0]
+
+    return (dentry(self, attributes, shortname, ext, lfn, first_cluster,
+      size), consumed)
+
+  def read_file(self, head_cluster, start_byte, size):
+    """
+    Read from a given FAT file.
+    head_cluster: The first cluster in the file.
+    start_byte: How many bytes in to the file to begin the read.
+    size: How many bytes to read.
+    """
+    f = self.f
+
+    assert size >= 0, "Can't read a negative amount"
+    if size == 0:
+      return ""
+
+    got_data = ""
+
+    while True:
+      size_now = size
+      if start_byte + size > self.bytes_per_cluster:
+        size_now = self.bytes_per_cluster - start_byte
+
+      if start_byte < self.bytes_per_cluster:
+        size -= size_now
+
+        cluster_bytes_from_root = (head_cluster - 2) * \
+            self.bytes_per_cluster
+        bytes_from_root = cluster_bytes_from_root + start_byte
+        bytes_from_data_start = bytes_from_root + self.root_entries * 32
+
+        f.seek(self.data_start() + bytes_from_data_start)
+        line = f.read(size_now)
+        got_data += line
+
+        if size == 0:
+          return got_data
+
+      start_byte -= self.bytes_per_cluster
+
+      if start_byte < 0:
+        start_byte = 0
+
+      f.seek(FAT_TABLE_START + head_cluster * 2)
+      assert head_cluster <= MAX_CLUSTER_ID, "Out-of-bounds read"
+      head_cluster = read_le_short(f)
+      assert head_cluster > 0, "Read free cluster"
+
+    return got_data
+
+  def write_cluster_entry(self, entry):
+    """
+    Write a cluster entry to the FAT table. Assumes our backing file is already
+    seeked to the correct entry in the first FAT table.
+    """
+    f = self.f
+    f.write(struct.pack("<H", entry))
+    skip_bytes(f, self.fat_size - 2)
+    f.write(struct.pack("<H", entry))
+    rewind_bytes(f, self.fat_size)
+
+  def allocate(self, amount):
+    """
+    Allocate a new cluster chain big enough to hold at least the given amount
+    of bytes.
+    """
+    f = self.f
+    f.seek(FAT_TABLE_START + 4)
+
+    current = None
+    current_size = 0
+    free_zones = {}
+
+    pos = 2
+    while pos < self.fat_size / 2:
+      data = read_le_short(f)
+
+      if data == 0 and current is not None:
+        current_size += 1
+      elif data == 0:
+        current = pos
+        current_size = 1
+      elif current is not None:
+        free_zones[current] = current_size
+        current = None
+
+      pos += 1
+
+    if current is not None:
+      free_zones[current] = current_size
+
+    free_zones = free_zones.items()
+    free_zones.sort(key=lambda x: x[1])
+
+    grabbed_zones = []
+    grabbed = 0
+
+    while grabbed < amount and len(free_zones) > 0:
+      zone = free_zones.pop()
+      grabbed += zone[1] * self.bytes_per_cluster
+      grabbed_zones.append(zone)
+
+    if grabbed < amount:
+      return None
+
+    excess = (grabbed - amount) / self.bytes_per_cluster
+
+    grabbed_zones[-1] = (grabbed_zones[-1][0],
+        grabbed_zones[-1][1] - excess)
+
+    out = None
+    grabbed_zones.reverse()
+
+    for cluster, size in grabbed_zones:
+      entries = range(cluster + 1, cluster + size)
+      entries.append(out or 0xFFFF)
+      out = cluster
+      f.seek(FAT_TABLE_START + cluster * 2)
+      for entry in entries:
+        self.write_cluster_entry(entry)
+
+    return out
+
+  def extend_cluster(self, cluster, amount):
+    """
+    Given a cluster which is the *last* cluster in a chain, extend it to hold
+    at least `amount` more bytes.
+    """
+    return_cluster = None
+    f = self.f
+
+    position = FAT_TABLE_START + cluster * 2
+    f.seek(position)
+
+    assert read_le_short(f) == 0xFFFF, "Extending from middle of chain"
+    rewind_short(f)
+
+    while position + 2 < FAT_TABLE_START + self.fat_size and amount > 0:
+      skip_short(f)
+      got = read_le_short(f)
+      rewind_short(f)
+      rewind_short(f)
+
+      if got != 0:
+        break
+
+      cluster += 1
+      return_cluster = return_cluster or cluster
+      position += 2
+      self.write_cluster_entry(cluster)
+
+    if amount < 0:
+      self.write_cluster_entry(0xFFFF)
+      return return_cluster
+
+    new_chunk = self.allocate(amount)
+    f.seek(FAT_TABLE_START + cluster * 2)
+    self.write_cluster_entry(new_chunk)
+
+    return return_cluster or new_chunk
+
+  def write_file(self, head_cluster, start_byte, data):
+    """
+    Write to a given FAT file.
+
+    head_cluster: The first cluster in the file.
+    start_byte: How many bytes in to the file to begin the write.
+    data: The data to write.
+    """
+    f = self.f
+
+    while True:
+      if start_byte < self.bytes_per_cluster:
+        to_write = data[:self.bytes_per_cluster - start_byte]
+        data = data[self.bytes_per_cluster - start_byte:]
+
+        cluster_bytes_from_root = (head_cluster - 2) * \
+            self.bytes_per_cluster
+        bytes_from_root = cluster_bytes_from_root + start_byte
+        bytes_from_data_start = bytes_from_root + self.root_entries * 32
+
+        f.seek(self.data_start() + bytes_from_data_start)
+        f.write(to_write)
+
+        if len(data) == 0:
+          return
+
+      start_byte -= self.bytes_per_cluster
+
+      if start_byte < 0:
+        start_byte = 0
+
+      f.seek(FAT_TABLE_START + head_cluster * 2)
+      next_cluster = read_le_short(f)
+      if next_cluster > MAX_CLUSTER_ID:
+        head_cluster = self.extend_cluster(head_cluster, len(data))
+      else:
+        head_cluster = next_cluster
+      assert head_cluster > 0, "Cannot write free cluster"
+
+def add_item(directory, item):
+  """
+  Copy a file into the given FAT directory. If the path given is a directory,
+  copy recursively.
+  directory: fat_dir to copy the file in to
+  item: Path of local file to copy
+  """
+  if os.path.isdir(item):
+    base = os.path.basename(item)
+    if len(base) == 0:
+      base = os.path.basename(item[:-1])
+    sub = directory.new_subdirectory(base)
+    for next_item in os.listdir(item):
+      add_item(sub, os.path.join(item, next_item))
+  else:
+    with open(item, 'rb') as f:
+      directory.new_file(os.path.basename(item), f)
+
+if __name__ == "__main__":
+  if len(sys.argv) < 3:
+    print("Usage: fat16copy.py <image> <file> [<file> ...]")
+    print("Files are copied into the root of the image.")
+    print("Directories are copied recursively")
+    sys.exit(1)
+
+  root = fat(sys.argv[1]).root
+
+  for p in sys.argv[2:]:
+    add_item(root, p)
diff --git a/tools/findleaves.py b/tools/findleaves.py
index 3a9e508..72cc024 100755
--- a/tools/findleaves.py
+++ b/tools/findleaves.py
@@ -23,7 +23,7 @@
 import os
 import sys
 
-def perform_find(mindepth, prune, dirlist, filename):
+def perform_find(mindepth, prune, dirlist, filenames):
   result = []
   pruneleaves = set(map(lambda x: os.path.split(x)[1], prune))
   for rootdir in dirlist:
@@ -48,19 +48,24 @@
         if depth < mindepth:
           continue
       # match
-      if filename in files:
-        result.append(os.path.join(root, filename))
-        del dirs[:]
+      for filename in filenames:
+        if filename in files:
+          result.append(os.path.join(root, filename))
+          del dirs[:]
   return result
 
 def usage():
-  sys.stderr.write("""Usage: %(progName)s [<options>] <dirlist> <filename>
+  sys.stderr.write("""Usage: %(progName)s [<options>] [--dir=<dir>] <filenames>
 Options:
    --mindepth=<mindepth>
        Both behave in the same way as their find(1) equivalents.
    --prune=<dirname>
        Avoids returning results from inside any directory called <dirname>
        (e.g., "*/out/*"). May be used multiple times.
+   --dir=<dir>
+       Add a directory to search.  May be repeated multiple times.  For backwards
+       compatibility, if no --dir argument is provided then all but the last entry
+       in <filenames> are treated as directories.
 """ % {
       "progName": os.path.split(sys.argv[0])[1],
     })
@@ -69,6 +74,7 @@
 def main(argv):
   mindepth = -1
   prune = []
+  dirlist = []
   i=1
   while i<len(argv) and len(argv[i])>2 and argv[i][0:2] == "--":
     arg = argv[i]
@@ -82,14 +88,24 @@
       if len(p) == 0:
         usage()
       prune.append(p)
+    elif arg.startswith("--dir="):
+      d = arg[len("--dir="):]
+      if len(p) == 0:
+        usage()
+      dirlist.append(d)
     else:
       usage()
     i += 1
-  if len(argv)-i < 2: # need both <dirlist> and <filename>
-    usage()
-  dirlist = argv[i:-1]
-  filename = argv[-1]
-  results = list(set(perform_find(mindepth, prune, dirlist, filename)))
+  if len(dirlist) == 0: # backwards compatibility
+    if len(argv)-i < 2: # need both <dirlist> and <filename>
+      usage()
+    dirlist = argv[i:-1]
+    filenames = [argv[-1]]
+  else:
+    if len(argv)-i < 1: # need <filename>
+      usage()
+    filenames = argv[i:]
+  results = list(set(perform_find(mindepth, prune, dirlist, filenames)))
   results.sort()
   for r in results:
     print r
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
index 34a3522..fb4a0c4 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -23,20 +23,38 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
-# To Build the custom target binary for the host to generate the fs_config
-# override files. The executable is hard coded to include the
-# $(TARGET_ANDROID_FILESYSTEM_CONFIG_H) file if it exists.
-# Expectations:
-#    device/<vendor>/<device>/android_filesystem_config.h
-#        fills in struct fs_path_config android_device_dirs[] and
-#                 struct fs_path_config android_device_files[]
-#    device/<vendor>/<device>/device.mk
-#        PRODUCT_PACKAGES += fs_config_dirs fs_config_files
-
-# If not specified, check if default one to be found
+# One can override the default android_filesystem_config.h file in one of two ways:
+#
+# 1. The old way:
+#   To Build the custom target binary for the host to generate the fs_config
+#   override files. The executable is hard coded to include the
+#   $(TARGET_ANDROID_FILESYSTEM_CONFIG_H) file if it exists.
+#   Expectations:
+#      device/<vendor>/<device>/android_filesystem_config.h
+#          fills in struct fs_path_config android_device_dirs[] and
+#                   struct fs_path_config android_device_files[]
+#      device/<vendor>/<device>/device.mk
+#          PRODUCT_PACKAGES += fs_config_dirs fs_config_files
+#   If not specified, check if default one to be found
+#
+# 2. The new way:
+#   set TARGET_FS_CONFIG_GEN to contain a list of intermediate format files
+#   for generating the android_filesystem_config.h file.
+#
+# More information can be found in the README
 ANDROID_FS_CONFIG_H := android_filesystem_config.h
 
 ifneq ($(TARGET_ANDROID_FILESYSTEM_CONFIG_H),)
+ifneq ($(TARGET_FS_CONFIG_GEN),)
+$(error Cannot set TARGET_ANDROID_FILESYSTEM_CONFIG_H and TARGET_FS_CONFIG_GEN simultaneously)
+endif
+
+# One and only one file can be specified.
+ifneq ($(words $(TARGET_ANDROID_FILESYSTEM_CONFIG_H)),1)
+$(error Multiple fs_config files specified, \
+ see "$(TARGET_ANDROID_FILESYSTEM_CONFIG_H)".)
+endif
+
 ifeq ($(filter %/$(ANDROID_FS_CONFIG_H),$(TARGET_ANDROID_FILESYSTEM_CONFIG_H)),)
 $(error TARGET_ANDROID_FILESYSTEM_CONFIG_H file name must be $(ANDROID_FS_CONFIG_H), \
  see "$(notdir $(TARGET_ANDROID_FILESYSTEM_CONFIG_H))".)
@@ -44,20 +62,43 @@
 
 my_fs_config_h := $(TARGET_ANDROID_FILESYSTEM_CONFIG_H)
 else ifneq ($(wildcard $(TARGET_DEVICE_DIR)/$(ANDROID_FS_CONFIG_H)),)
+
+ifneq ($(TARGET_FS_CONFIG_GEN),)
+$(error Cannot provide $(TARGET_DEVICE_DIR)/$(ANDROID_FS_CONFIG_H) and set TARGET_FS_CONFIG_GEN simultaneously)
+endif
 my_fs_config_h := $(TARGET_DEVICE_DIR)/$(ANDROID_FS_CONFIG_H)
+
 else
 my_fs_config_h := $(LOCAL_PATH)/default/$(ANDROID_FS_CONFIG_H)
 endif
 
+##################################
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := fs_config_generate.c
 LOCAL_MODULE := fs_config_generate_$(TARGET_DEVICE)
+LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_SHARED_LIBRARIES := libcutils
 LOCAL_CFLAGS := -Werror -Wno-error=\#warnings
+
+ifneq ($(TARGET_FS_CONFIG_GEN),)
+gen := $(local-generated-sources-dir)/$(ANDROID_FS_CONFIG_H)
+$(gen): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
+$(gen): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
+$(gen): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/fs_config_generator.py $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
+$(gen): $(TARGET_FS_CONFIG_GEN) $(LOCAL_PATH)/fs_config_generator.py
+	$(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES := $(gen)
+my_fs_config_h := $(gen)
+gen :=
+endif
+
 LOCAL_C_INCLUDES := $(dir $(my_fs_config_h))
+
 include $(BUILD_HOST_EXECUTABLE)
 fs_config_generate_bin := $(LOCAL_INSTALLED_MODULE)
 
+##################################
 # Generate the system/etc/fs_config_dirs binary file for the target
 # Add fs_config_dirs to PRODUCT_PACKAGES in the device make file to enable
 include $(CLEAR_VARS)
@@ -69,6 +110,7 @@
 	@mkdir -p $(dir $@)
 	$< -D -o $@
 
+##################################
 # Generate the system/etc/fs_config_files binary file for the target
 # Add fs_config_files to PRODUCT_PACKAGES in the device make file to enable
 include $(CLEAR_VARS)
diff --git a/tools/fs_config/README b/tools/fs_config/README
new file mode 100644
index 0000000..7eca4a3
--- /dev/null
+++ b/tools/fs_config/README
@@ -0,0 +1,119 @@
+ _____  _____  _____  _____  __  __  _____
+/  _  \/   __\/  _  \|  _  \/  \/  \/   __\
+|  _  <|   __||  _  ||  |  ||  \/  ||   __|
+\__|\_/\_____/\__|__/|_____/\__ \__/\_____/
+
+
+Generating the android_filesystem_config.h
+
+To generate the android_filesystem_config.h file, one can choose from
+one of two methods. The first method, is to declare
+TARGET_ANDROID_FILESYSTEM_CONFIG_H in the device BoardConfig.mk file. This
+variable can only have one item in it, and it is used directly as the
+android_filesystem_config.h header when building
+fs_config_generate_$(TARGET_DEVICE) which is used to generate fs_config_files
+and fs_config_dirs target executable.
+
+The limitation with this, is that it can only be set once, thus if the device
+has a make hierarchy, then each device needs its own file, and cannot share
+from a common source or that common source needs to include everything from
+both devices.
+
+The other way is to set TARGET_FS_CONFIG_GEN, which can be a list of
+intermediate fs configuration files. It is a build error on any one
+these conditions:
+ * Specify TARGET_FS_CONFIG_GEN and TARGET_ANDROID_FILESYSTEM_CONFIG_H
+ * Specify TARGET_FS_CONFIG_GEN and provide
+   $(TARGET_DEVICE_DIR)/android_filesystem_config.h
+
+The parsing of the config file follows the Python ConfigParser specification,
+with the sections and fields as defined below. There are two types of sections,
+both sections require all options to be specified. The first section type is
+the "caps" section.
+
+The "caps" section follows the following syntax:
+
+[path]
+mode: Octal file mode
+user: AID_<user>
+group: AID_<group>
+caps: cap*
+
+Where:
+
+[path]
+  The filesystem path to configure. A path ending in / is considered a dir,
+  else its a file.
+
+mode:
+  A valid octal file mode of at least 3 digits. If 3 is specified, it is
+  prefixed with a 0, else mode is used as is.
+
+user:
+  The exact, C define for a valid AID. Note custom AIDs can be defined in the
+  AID section documented below.
+
+group:
+  The exact, C define for a valid AID. Note custom AIDs can be defined in the
+  AID section documented below.
+
+caps:
+  The name as declared in
+  system/core/include/private/android_filesystem_capability.h without the
+  leading CAP_. Mixed case is allowed. Caps can also be the raw:
+   * binary (0b0101)
+   * octal (0455)
+   * int (42)
+   * hex (0xFF)
+  For multiple caps, just separate by whitespace.
+
+It is an error to specify multiple sections with the same [path]. Per the ini
+specifications enforced by Pythons ConfigParser.
+
+
+The next section type is the "AID" section, for specifying OEM specific AIDS.
+
+The AID section follows the following syntax:
+
+[AID_<name>]
+value: <number>
+
+Where:
+
+[AID_<name>]
+  The <name> can be any valid character for a #define identifier in C.
+
+value:
+  A valid C style number string. Hex, octal, binary and decimal are supported. See "caps"
+  above for more details on number formatting.
+
+It is an error to specify multiple sections with the same [AID_<name>]. Per the ini
+specifications enforced by Pythons ConfigParser. It is also an error to specify
+multiple sections with the same value option. It is also an error to specify a value
+that is outside of the inclusive OEM ranges:
+ * AID_OEM_RESERVED_START(2900) - AID_OEM_RESERVED_END(2999)
+ * AID_OEM_RESERVED_2_START(5000) - AID_OEM_RESERVED_2_END(5999)
+
+as defined by system/core/include/private/android_filesystem_config.h.
+
+Ordering within the TARGET_FS_CONFIG_GEN files is not relevant. The paths for files are sorted
+like so within their respective array definition:
+ * specified path before prefix match
+ ** ie foo before f*
+ * lexicographical less than before other
+ ** ie boo before foo
+
+Given these paths:
+
+paths=['ac', 'a', 'acd', 'an', 'a*', 'aa', 'ac*']
+
+The sort order would be:
+paths=['a', 'aa', 'ac', 'acd', 'an', 'ac*', 'a*']
+
+Thus the fs_config tools will match on specified paths before attempting prefix, and match on the
+longest matching prefix.
+
+The declared AIDS are sorted in ascending numerical order based on the option "value". The string
+representation of value is preserved. Both choices were made for maximum readability of the generated
+file and to line up files. Sync lines are placed with the source file as comments in the generated
+header file.
diff --git a/tools/fs_config/fs_config.c b/tools/fs_config/fs_config.c
index e797957..48f300b 100644
--- a/tools/fs_config/fs_config.c
+++ b/tools/fs_config/fs_config.c
@@ -105,6 +105,9 @@
       switch (buffer[i]) {
         case '\n':
           buffer[i-is_dir] = '\0';
+          if (i == 0) {
+            is_dir = 1; // empty line is considered as root directory
+          }
           i = 1025;
           break;
         case '/':
diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py
new file mode 100755
index 0000000..482c2bc
--- /dev/null
+++ b/tools/fs_config/fs_config_generator.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python
+
+import ConfigParser
+import re
+import sys
+
+
+GENERATED = '''
+/*
+ * THIS IS AN AUTOGENERATED FILE! DO NOT MODIFY
+ */
+'''
+
+INCLUDE = '#include <private/android_filesystem_config.h>'
+
+DEFINE_NO_DIRS = '#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS\n'
+DEFINE_NO_FILES = '#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES\n'
+
+DEFAULT_WARNING = '#warning No device-supplied android_filesystem_config.h, using empty default.'
+
+NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS_ENTRY = '{ 00000, AID_ROOT,      AID_ROOT,      0, "system/etc/fs_config_dirs" },'
+NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES_ENTRY = '{ 00000, AID_ROOT,      AID_ROOT,      0, "system/etc/fs_config_files" },'
+
+IFDEF_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS = '#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS'
+ENDIF = '#endif'
+
+OPEN_FILE_STRUCT = 'static const struct fs_path_config android_device_files[] = {'
+OPEN_DIR_STRUCT = 'static const struct fs_path_config android_device_dirs[] = {'
+CLOSE_FILE_STRUCT = '};'
+
+GENERIC_DEFINE = "#define %s\t%s"
+
+FILE_COMMENT = '// Defined in file: \"%s\"'
+
+# from system/core/include/private/android_filesystem_config.h
+AID_OEM_RESERVED_RANGES = [
+    (2900, 2999),
+    (5000, 5999),
+]
+
+
+AID_MATCH = re.compile('AID_[a-zA-Z]+')
+
+def handle_aid(file_name, section_name, config, aids, seen_aids):
+    value = config.get(section_name, 'value')
+
+    errmsg = '%s for: \"' + section_name + '" file: \"' + file_name + '\"'
+
+    if not value:
+        raise Exception(errmsg % 'Found specified but unset "value"')
+
+    v = convert_int(value)
+    if not v:
+        raise Exception(errmsg % ('Invalid "value", not a number, got: \"%s\"' % value))
+
+    # Values must be within OEM range
+    if not any(lower <= v <= upper for (lower, upper) in AID_OEM_RESERVED_RANGES):
+        s = '"value" not in valid range %s, got: %s'
+        s = s % (str(AID_OEM_RESERVED_RANGES), value)
+        raise Exception(errmsg % s)
+
+    # use the normalized int value in the dict and detect
+    # duplicate definitions of the same vallue
+    v = str(v)
+    if v in seen_aids[1]:
+        # map of value to aid name
+        a = seen_aids[1][v]
+
+        # aid name to file
+        f = seen_aids[0][a]
+
+        s = 'Duplicate AID value "%s" found on AID: "%s".' % (value, seen_aids[1][v])
+        s += ' Previous found in file: "%s."' % f
+        raise Exception(errmsg % s)
+
+    seen_aids[1][v] = section_name
+
+    # Append a tuple of (AID_*, base10(value), str(value))
+    # We keep the str version of value so we can print that out in the
+    # generated header so investigating parties can identify parts.
+    # We store the base10 value for sorting, so everything is ascending
+    # later.
+    aids.append((file_name, section_name, v, value))
+
+def convert_int(num):
+
+        try:
+            if num.startswith('0x'):
+                return int(num, 16)
+            elif num.startswith('0b'):
+                return int(num, 2)
+            elif num.startswith('0'):
+                return int(num, 8)
+            else:
+                return int(num, 10)
+        except ValueError:
+            pass
+        return None
+
+def handle_path(file_name, section_name, config, files, dirs):
+
+            mode = config.get(section_name, 'mode')
+            user = config.get(section_name, 'user')
+            group = config.get(section_name, 'group')
+            caps = config.get(section_name, 'caps')
+
+            errmsg = 'Found specified but unset option: \"%s" in file: \"' + file_name + '\"'
+
+            if not mode:
+                raise Exception(errmsg % 'mode')
+
+            if not user:
+                raise Exception(errmsg % 'user')
+
+            if not group:
+                raise Exception(errmsg % 'group')
+
+            if not caps:
+                raise Exception(errmsg % 'caps')
+
+            caps = caps.split()
+
+            tmp = []
+            for x in caps:
+                if convert_int(x):
+                    tmp.append('(' + x + ')')
+                else:
+                    tmp.append('(1ULL << CAP_' + x.upper() + ')')
+
+            caps = tmp
+
+            path = '"' + section_name + '"'
+
+            if len(mode) == 3:
+                mode = '0' + mode
+
+            try:
+                int(mode, 8)
+            except:
+                raise Exception('Mode must be octal characters, got: "' + mode + '"')
+
+            if len(mode) != 4:
+                raise Exception('Mode must be 3 or 4 characters, got: "' + mode + '"')
+
+
+            caps = '|'.join(caps)
+
+            x = [ mode, user, group, caps, section_name ]
+            if section_name[-1] == '/':
+                dirs.append((file_name, x))
+            else:
+                files.append((file_name, x))
+
+def handle_dup(name, file_name, section_name, seen):
+        if section_name in seen:
+            dups = '"' + seen[section_name] + '" and '
+            dups += file_name
+            raise Exception('Duplicate ' + name + ' "' + section_name + '" found in files: ' + dups)
+
+def parse(file_name, files, dirs, aids, seen_paths, seen_aids):
+
+        config = ConfigParser.ConfigParser()
+        config.read(file_name)
+
+        for s in config.sections():
+
+            if AID_MATCH.match(s) and config.has_option(s, 'value'):
+                handle_dup('AID', file_name, s, seen_aids[0])
+                seen_aids[0][s] = file_name
+                handle_aid(file_name, s, config, aids, seen_aids)
+            else:
+                handle_dup('path', file_name, s, seen_paths)
+                seen_paths[s] = file_name
+                handle_path(file_name, s, config, files, dirs)
+
+def generate(files, dirs, aids):
+    print GENERATED
+    print INCLUDE
+    print
+
+    are_dirs = len(dirs) > 0
+    are_files = len(files) > 0
+    are_aids = len(aids) > 0
+
+    if are_aids:
+        # sort on value of (file_name, name, value, strvalue)
+        aids.sort(key=lambda x: x[2])
+        for a in aids:
+            # use the preserved str value
+            print FILE_COMMENT % a[0]
+            print GENERIC_DEFINE % (a[1], a[2])
+
+        print
+
+    if not are_dirs:
+        print DEFINE_NO_DIRS
+
+    if not are_files:
+        print DEFINE_NO_FILES
+
+    if not are_files and not are_dirs and not are_aids:
+        print DEFAULT_WARNING
+        return
+
+    if are_files:
+        print OPEN_FILE_STRUCT
+        for tup in files:
+            f = tup[0]
+            c = tup[1]
+            c[4] = '"' + c[4] + '"'
+            c = '{ ' + '    ,'.join(c) + ' },'
+            print FILE_COMMENT % f
+            print '    ' + c
+
+        if not are_dirs:
+            print IFDEF_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+            print '    ' + NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS_ENTRY
+            print ENDIF
+        print CLOSE_FILE_STRUCT
+
+    if are_dirs:
+        print OPEN_DIR_STRUCT
+        for d in dirs:
+            f[4] = '"' + f[4] + '"'
+            d = '{ ' + '    ,'.join(d) + ' },'
+            print '    ' + d
+
+        print CLOSE_FILE_STRUCT
+
+def file_key(x):
+
+    # Wrapper class for custom prefix matching strings
+    class S(object):
+        def __init__(self, str):
+
+            self.orig = str
+            self.is_prefix = str[-1] == '*'
+            if self.is_prefix:
+                self.str = str[:-1]
+            else:
+                self.str = str
+
+        def __lt__(self, other):
+
+            # if were both suffixed the smallest string
+            # is 'bigger'
+            if self.is_prefix and other.is_prefix:
+                b = len(self.str) > len(other.str)
+            # If I am an the suffix match, im bigger
+            elif self.is_prefix:
+                b = False
+            # If other is the suffix match, he's bigger
+            elif other.is_prefix:
+                b = True
+            # Alphabetical
+            else:
+                b = self.str < other.str
+            return b
+
+    return S(x[4])
+
+def main():
+
+    files = []
+    dirs = []
+    aids = []
+    seen_paths = {}
+
+    # (name to file, value to aid)
+    seen_aids = ({}, {})
+
+    for x in sys.argv[1:]:
+        parse(x, files, dirs, aids, seen_paths, seen_aids)
+
+    files.sort(key= lambda x: file_key(x[1]))
+    generate(files, dirs, aids)
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/ijar/Android.bp b/tools/ijar/Android.bp
new file mode 100644
index 0000000..a244a2d
--- /dev/null
+++ b/tools/ijar/Android.bp
@@ -0,0 +1,18 @@
+// Copyright 2015 The Android Open Source Project
+//
+// The rest of files in this directory comes from
+// https://github.com/bazelbuild/bazel/tree/master/third_party/ijar
+
+cc_binary_host {
+    srcs: [
+        "classfile.cc",
+        "ijar.cc",
+        "zip.cc",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    host_ldlibs: ["-lz"],
+    name: "ijar",
+}
diff --git a/tools/ijar/Android.mk b/tools/ijar/Android.mk
deleted file mode 100644
index 8b2a02c..0000000
--- a/tools/ijar/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2015 The Android Open Source Project
-#
-# The rest of files in this directory comes from
-# https://github.com/bazelbuild/bazel/tree/master/third_party/ijar
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_SRC_FILES := classfile.cc ijar.cc zip.cc
-LOCAL_CFLAGS += -Wall -Werror
-LOCAL_SHARED_LIBRARIES := libz-host
-LOCAL_MODULE := ijar
-# libc++ is not supported for TARGET_BUILD_APPS builds
-LOCAL_CXX_STL := libstdc++
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/ijar/classfile.cc b/tools/ijar/classfile.cc
index e0cf42e..d33e0db 100644
--- a/tools/ijar/classfile.cc
+++ b/tools/ijar/classfile.cc
@@ -123,7 +123,7 @@
 // See sec.4.4 of JVM spec.
 struct Constant {
 
-  Constant(u1 tag) :
+  explicit Constant(u1 tag) :
       slot_(0),
       tag_(tag) {}
 
@@ -180,7 +180,7 @@
 // See sec.4.4.1 of JVM spec.
 struct Constant_Class : Constant
 {
-  Constant_Class(u2 name_index) :
+  explicit Constant_Class(u2 name_index) :
       Constant(CONSTANT_Class),
       name_index_(name_index) {}
 
@@ -231,7 +231,7 @@
 // See sec.4.4.3 of JVM spec.
 struct Constant_String : Constant
 {
-  Constant_String(u2 string_index) :
+  explicit Constant_String(u2 string_index) :
       Constant(CONSTANT_String),
       string_index_(string_index) {}
 
@@ -360,7 +360,7 @@
 // See sec.4.4.9 of JVM spec.
 struct Constant_MethodType : Constant
 {
-  Constant_MethodType(u2 descriptor_index) :
+  explicit Constant_MethodType(u2 descriptor_index) :
       Constant(CONSTANT_MethodType),
       descriptor_index_(descriptor_index) {}
 
diff --git a/tools/ijar/zip.cc b/tools/ijar/zip.cc
index ca5f396..3aa06db 100644
--- a/tools/ijar/zip.cc
+++ b/tools/ijar/zip.cc
@@ -846,6 +846,7 @@
   memcpy(entry->file_name, filename, file_name_length_);
   entry->extra_field_length = 0;
   entry->extra_field = (const u1 *)"";
+  entry->crc32 = 0;
 
   // Output the ZIP local_file_header:
   put_u4le(q, LOCAL_FILE_HEADER_SIGNATURE);
diff --git a/tools/libhost/Android.bp b/tools/libhost/Android.bp
new file mode 100644
index 0000000..e5a5ecf
--- /dev/null
+++ b/tools/libhost/Android.bp
@@ -0,0 +1,20 @@
+cc_library_host_static {
+
+    srcs: ["CopyFile.c"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    name: "libhost",
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    stl: "none",
+
+}
diff --git a/libs/host/CopyFile.c b/tools/libhost/CopyFile.c
similarity index 100%
rename from libs/host/CopyFile.c
rename to tools/libhost/CopyFile.c
diff --git a/libs/host/include/host/CopyFile.h b/tools/libhost/include/host/CopyFile.h
similarity index 100%
rename from libs/host/include/host/CopyFile.h
rename to tools/libhost/include/host/CopyFile.h
diff --git a/tools/makeparallel/makeparallel.cpp b/tools/makeparallel/makeparallel.cpp
index 3c39846..c70fa9a 100644
--- a/tools/makeparallel/makeparallel.cpp
+++ b/tools/makeparallel/makeparallel.cpp
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/resource.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -343,6 +344,15 @@
     // child
     unsetenv("MAKEFLAGS");
     unsetenv("MAKELEVEL");
+
+    // make 3.81 sets the stack ulimit to unlimited, which may cause problems
+    // for child processes
+    struct rlimit rlim{};
+    if (getrlimit(RLIMIT_STACK, &rlim) == 0 && rlim.rlim_cur == RLIM_INFINITY) {
+      rlim.rlim_cur = 8*1024*1024;
+      setrlimit(RLIMIT_STACK, &rlim);
+    }
+
     int ret = execvp(path, args.data());
     if (ret < 0) {
       error(errno, errno, "exec %s failed", path);
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 7cb9072..8c5dbcf 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -19,7 +19,31 @@
 not have an IMAGES/ top-level subdirectory), produce the images and
 add them to the zipfile.
 
-Usage:  add_img_to_target_files target_files
+Usage:  add_img_to_target_files [flag] target_files
+
+  -a  (--add_missing)
+      Build and add missing images to "IMAGES/". If this option is
+      not specified, this script will simply exit when "IMAGES/"
+      directory exists in the target file.
+
+  -r  (--rebuild_recovery)
+      Rebuild the recovery patch and write it to the system image. Only
+      meaningful when system image needs to be rebuilt.
+
+  --replace_verity_private_key
+      Replace the private key used for verity signing. (same as the option
+      in sign_target_files_apks)
+
+  --replace_verity_public_key
+       Replace the certificate (public key) used for verity verification. (same
+       as the option in sign_target_files_apks)
+
+  --is_signing
+      Skip building & adding the images for "userdata" and "cache" if we
+      are signing the target files.
+
+  --verity_signer_path
+      Specify the signer path to build verity metadata.
 """
 
 import sys
@@ -31,7 +55,9 @@
 import datetime
 import errno
 import os
+import shlex
 import shutil
+import subprocess
 import tempfile
 import zipfile
 
@@ -44,16 +70,17 @@
 OPTIONS.rebuild_recovery = False
 OPTIONS.replace_verity_public_key = False
 OPTIONS.replace_verity_private_key = False
+OPTIONS.is_signing = False
 OPTIONS.verity_signer_path = None
 
 def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
   """Turn the contents of SYSTEM into a system image and store it in
-  output_zip."""
+  output_zip. Returns the name of the system image file."""
 
   prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "system.img")
   if os.path.exists(prebuilt_path):
     print "system.img already exists in %s, no need to rebuild..." % (prefix,)
-    return
+    return prebuilt_path
 
   def output_sink(fn, data):
     ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
@@ -68,8 +95,27 @@
   block_list = common.MakeTempFile(prefix="system-blocklist-", suffix=".map")
   imgname = BuildSystem(OPTIONS.input_tmp, OPTIONS.info_dict,
                         block_list=block_list)
+
+  # AVB: if enabled, calculate and add dm-verity integrity hashes and
+  # metadata to system.img.
+  if OPTIONS.info_dict.get("board_avb_enable", None) == "true":
+    avbtool = os.getenv('AVBTOOL') or "avbtool"
+    part_size = OPTIONS.info_dict.get("system_size", None)
+    cmd = [avbtool, "add_hashtree_footer", "--image", imgname,
+           "--partition_size", str(part_size), "--partition_name", "system"]
+    common.AppendAVBSigningArgs(cmd)
+    args = OPTIONS.info_dict.get("board_avb_system_add_hashtree_footer_args",
+                                 None)
+    if args and args.strip():
+      cmd.extend(shlex.split(args))
+    p = common.Run(cmd, stdout=subprocess.PIPE)
+    p.communicate()
+    assert p.returncode == 0, "avbtool add_hashtree_footer of %s failed" % (
+      os.path.basename(OPTIONS.input_tmp))
+
   common.ZipWrite(output_zip, imgname, prefix + "system.img")
   common.ZipWrite(output_zip, block_list, prefix + "system.map")
+  return imgname
 
 
 def BuildSystem(input_dir, info_dict, block_list=None):
@@ -167,11 +213,9 @@
     print "userdata.img already exists in %s, no need to rebuild..." % (prefix,)
     return
 
+  # Skip userdata.img if no size.
   image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "data")
-  # We only allow yaffs to have a 0/missing partition_size.
-  # Extfs, f2fs must have a size. Skip userdata.img if no size.
-  if (not image_props.get("fs_type", "").startswith("yaffs") and
-      not image_props.get("partition_size")):
+  if not image_props.get("partition_size"):
     return
 
   print "creating userdata.img..."
@@ -211,6 +255,54 @@
   shutil.rmtree(temp_dir)
 
 
+def AddVBMeta(output_zip, boot_img_path, system_img_path, prefix="IMAGES/"):
+  """Create a VBMeta image and store it in output_zip."""
+  _, img_file_name = tempfile.mkstemp()
+  avbtool = os.getenv('AVBTOOL') or "avbtool"
+  cmd = [avbtool, "make_vbmeta_image",
+         "--output", img_file_name,
+         "--include_descriptors_from_image", boot_img_path,
+         "--include_descriptors_from_image", system_img_path,
+         "--generate_dm_verity_cmdline_from_hashtree", system_img_path]
+  common.AppendAVBSigningArgs(cmd)
+  args = OPTIONS.info_dict.get("board_avb_make_vbmeta_image_args", None)
+  if args and args.strip():
+    cmd.extend(shlex.split(args))
+  p = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  p.communicate()
+  assert p.returncode == 0, "avbtool make_vbmeta_image failed"
+  common.ZipWrite(output_zip, img_file_name, prefix + "vbmeta.img")
+
+
+def AddPartitionTable(output_zip, prefix="IMAGES/"):
+  """Create a partition table image and store it in output_zip."""
+
+  _, img_file_name = tempfile.mkstemp()
+  _, bpt_file_name = tempfile.mkstemp()
+
+  # use BPTTOOL from environ, or "bpttool" if empty or not set.
+  bpttool = os.getenv("BPTTOOL") or "bpttool"
+  cmd = [bpttool, "make_table", "--output_json", bpt_file_name,
+         "--output_gpt", img_file_name]
+  input_files_str = OPTIONS.info_dict["board_bpt_input_files"]
+  input_files = input_files_str.split(" ")
+  for i in input_files:
+    cmd.extend(["--input", i])
+  disk_size = OPTIONS.info_dict.get("board_bpt_disk_size")
+  if disk_size:
+    cmd.extend(["--disk_size", disk_size])
+  args = OPTIONS.info_dict.get("board_bpt_make_table_args")
+  if args:
+    cmd.extend(shlex.split(args))
+
+  p = common.Run(cmd, stdout=subprocess.PIPE)
+  p.communicate()
+  assert p.returncode == 0, "bpttool make_table failed"
+
+  common.ZipWrite(output_zip, img_file_name, prefix + "partition-table.img")
+  common.ZipWrite(output_zip, bpt_file_name, prefix + "partition-table.bpt")
+
+
 def AddCache(output_zip, prefix="IMAGES/"):
   """Create an empty cache image and store it in output_zip."""
 
@@ -272,22 +364,25 @@
 
   common.ZipClose(input_zip)
   output_zip = zipfile.ZipFile(filename, "a",
-                               compression=zipfile.ZIP_DEFLATED)
+                               compression=zipfile.ZIP_DEFLATED,
+                               allowZip64=True)
 
   has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")
+  system_root_image = (OPTIONS.info_dict.get("system_root_image", None) == "true")
 
   def banner(s):
     print "\n\n++++ " + s + " ++++\n\n"
 
-  banner("boot")
   prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", "boot.img")
   boot_image = None
   if os.path.exists(prebuilt_path):
+    banner("boot")
     print "boot.img already exists in IMAGES/, no need to rebuild..."
     if OPTIONS.rebuild_recovery:
       boot_image = common.GetBootableImage(
           "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
   else:
+    banner("boot")
     boot_image = common.GetBootableImage(
         "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
     if boot_image:
@@ -310,27 +405,51 @@
         recovery_image.AddToZip(output_zip)
 
   banner("system")
-  AddSystem(output_zip, recovery_img=recovery_image, boot_img=boot_image)
+  system_img_path = AddSystem(
+    output_zip, recovery_img=recovery_image, boot_img=boot_image)
   if has_vendor:
     banner("vendor")
     AddVendor(output_zip)
-  banner("userdata")
-  AddUserdata(output_zip)
-  banner("cache")
-  AddCache(output_zip)
+  if not OPTIONS.is_signing:
+    banner("userdata")
+    AddUserdata(output_zip)
+    banner("cache")
+    AddCache(output_zip)
+  if OPTIONS.info_dict.get("board_bpt_enable", None) == "true":
+    banner("partition-table")
+    AddPartitionTable(output_zip)
+  if OPTIONS.info_dict.get("board_avb_enable", None) == "true":
+    banner("vbmeta")
+    boot_contents = boot_image.WriteToTemp()
+    AddVBMeta(output_zip, boot_contents.name, system_img_path)
 
-  # For devices using A/B update, copy over images from RADIO/ to IMAGES/ and
-  # make sure we have all the needed images ready under IMAGES/.
+  # For devices using A/B update, copy over images from RADIO/ and/or
+  # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
+  # images ready under IMAGES/. All images should have '.img' as extension.
+  banner("radio")
   ab_partitions = os.path.join(OPTIONS.input_tmp, "META", "ab_partitions.txt")
   if os.path.exists(ab_partitions):
     with open(ab_partitions, 'r') as f:
       lines = f.readlines()
     for line in lines:
       img_name = line.strip() + ".img"
+      prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
+      if os.path.exists(prebuilt_path):
+        print "%s already exists, no need to overwrite..." % (img_name,)
+        continue
+
       img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
+      img_vendor_dir = os.path.join(
+        OPTIONS.input_tmp, "VENDOR_IMAGES")
       if os.path.exists(img_radio_path):
         common.ZipWrite(output_zip, img_radio_path,
                         os.path.join("IMAGES", img_name))
+      else:
+        for root, _, files in os.walk(img_vendor_dir):
+          if img_name in files:
+            common.ZipWrite(output_zip, os.path.join(root, img_name),
+              os.path.join("IMAGES", img_name))
+            break
 
       # Zip spec says: All slashes MUST be forward slashes.
       img_path = 'IMAGES/' + img_name
@@ -348,6 +467,8 @@
       OPTIONS.replace_verity_private_key = (True, a)
     elif o == "--replace_verity_public_key":
       OPTIONS.replace_verity_public_key = (True, a)
+    elif o == "--is_signing":
+      OPTIONS.is_signing = True
     elif o == "--verity_signer_path":
       OPTIONS.verity_signer_path = a
     else:
@@ -359,6 +480,7 @@
       extra_long_opts=["add_missing", "rebuild_recovery",
                        "replace_verity_public_key=",
                        "replace_verity_private_key=",
+                       "is_signing",
                        "verity_signer_path="],
       extra_option_handler=option_handler)
 
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 66d5907..70bb4eb 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -695,10 +695,19 @@
     with open(prefix + ".new.dat", "wb") as new_f:
       for xf in self.transfers:
         if xf.style == "zero":
-          pass
+          tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
+          print("%10d %10d (%6.2f%%) %7s %s %s" % (
+              tgt_size, tgt_size, 100.0, xf.style, xf.tgt_name,
+              str(xf.tgt_ranges)))
+
         elif xf.style == "new":
           for piece in self.tgt.ReadRangeSet(xf.tgt_ranges):
             new_f.write(piece)
+          tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
+          print("%10d %10d (%6.2f%%) %7s %s %s" % (
+              tgt_size, tgt_size, 100.0, xf.style,
+              xf.tgt_name, str(xf.tgt_ranges)))
+
         elif xf.style == "diff":
           src = self.src.ReadRangeSet(xf.src_ranges)
           tgt = self.tgt.ReadRangeSet(xf.tgt_ranges)
@@ -725,6 +734,12 @@
             # These are identical; we don't need to generate a patch,
             # just issue copy commands on the device.
             xf.style = "move"
+            if xf.src_ranges != xf.tgt_ranges:
+              print("%10d %10d (%6.2f%%) %7s %s %s (from %s)" % (
+                  tgt_size, tgt_size, 100.0, xf.style,
+                  xf.tgt_name if xf.tgt_name == xf.src_name else (
+                      xf.tgt_name + " (from " + xf.src_name + ")"),
+                  str(xf.tgt_ranges), str(xf.src_ranges)))
           else:
             # For files in zip format (eg, APKs, JARs, etc.) we would
             # like to use imgdiff -z if possible (because it usually
@@ -772,10 +787,11 @@
           size = len(patch)
           with lock:
             patches[patchnum] = (patch, xf)
-            print("%10d %10d (%6.2f%%) %7s %s" % (
+            print("%10d %10d (%6.2f%%) %7s %s %s %s" % (
                 size, tgt_size, size * 100.0 / tgt_size, xf.style,
                 xf.tgt_name if xf.tgt_name == xf.src_name else (
-                    xf.tgt_name + " (from " + xf.src_name + ")")))
+                    xf.tgt_name + " (from " + xf.src_name + ")"),
+                str(xf.tgt_ranges), str(xf.src_ranges)))
 
       threads = [threading.Thread(target=diff_worker)
                  for _ in range(self.threads)]
@@ -1101,27 +1117,23 @@
   def FindTransfers(self):
     """Parse the file_map to generate all the transfers."""
 
-    def AddTransfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id,
-                    split=False):
-      """Wrapper function for adding a Transfer().
+    def AddSplitTransfers(tgt_name, src_name, tgt_ranges, src_ranges,
+                          style, by_id):
+      """Add one or multiple Transfer()s by splitting large files.
 
       For BBOTA v3, we need to stash source blocks for resumable feature.
       However, with the growth of file size and the shrink of the cache
       partition source blocks are too large to be stashed. If a file occupies
-      too many blocks (greater than MAX_BLOCKS_PER_DIFF_TRANSFER), we split it
-      into smaller pieces by getting multiple Transfer()s.
+      too many blocks, we split it into smaller pieces by getting multiple
+      Transfer()s.
 
       The downside is that after splitting, we may increase the package size
       since the split pieces don't align well. According to our experiments,
       1/8 of the cache size as the per-piece limit appears to be optimal.
       Compared to the fixed 1024-block limit, it reduces the overall package
-      size by 30% volantis, and 20% for angler and bullhead."""
+      size by 30% for volantis, and 20% for angler and bullhead."""
 
-      # We care about diff transfers only.
-      if style != "diff" or not split:
-        Transfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id)
-        return
-
+      # Possibly split large files into smaller chunks.
       pieces = 0
       cache_size = common.OPTIONS.cache_size
       split_threshold = 0.125
@@ -1157,6 +1169,74 @@
         Transfer(tgt_split_name, src_split_name, tgt_ranges, src_ranges, style,
                  by_id)
 
+    def AddTransfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id,
+                    split=False):
+      """Wrapper function for adding a Transfer()."""
+
+      # We specialize diff transfers only (which covers bsdiff/imgdiff/move);
+      # otherwise add the Transfer() as is.
+      if style != "diff" or not split:
+        Transfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id)
+        return
+
+      # Handle .odex files specially to analyze the block-wise difference. If
+      # most of the blocks are identical with only few changes (e.g. header),
+      # we will patch the changed blocks only. This avoids stashing unchanged
+      # blocks while patching. We limit the analysis to files without size
+      # changes only. This is to avoid sacrificing the OTA generation cost too
+      # much.
+      if (tgt_name.split(".")[-1].lower() == 'odex' and
+          tgt_ranges.size() == src_ranges.size()):
+
+        # 0.5 threshold can be further tuned. The tradeoff is: if only very
+        # few blocks remain identical, we lose the opportunity to use imgdiff
+        # that may have better compression ratio than bsdiff.
+        crop_threshold = 0.5
+
+        tgt_skipped = RangeSet()
+        src_skipped = RangeSet()
+        tgt_size = tgt_ranges.size()
+        tgt_changed = 0
+        for src_block, tgt_block in zip(src_ranges.next_item(),
+                                        tgt_ranges.next_item()):
+          src_rs = RangeSet(str(src_block))
+          tgt_rs = RangeSet(str(tgt_block))
+          if self.src.ReadRangeSet(src_rs) == self.tgt.ReadRangeSet(tgt_rs):
+            tgt_skipped = tgt_skipped.union(tgt_rs)
+            src_skipped = src_skipped.union(src_rs)
+          else:
+            tgt_changed += tgt_rs.size()
+
+          # Terminate early if no clear sign of benefits.
+          if tgt_changed > tgt_size * crop_threshold:
+            break
+
+        if tgt_changed < tgt_size * crop_threshold:
+          assert tgt_changed + tgt_skipped.size() == tgt_size
+          print('%10d %10d (%6.2f%%) %s' % (tgt_skipped.size(), tgt_size,
+                tgt_skipped.size() * 100.0 / tgt_size, tgt_name))
+          AddSplitTransfers(
+              "%s-skipped" % (tgt_name,),
+              "%s-skipped" % (src_name,),
+              tgt_skipped, src_skipped, style, by_id)
+
+          # Intentionally change the file extension to avoid being imgdiff'd as
+          # the files are no longer in their original format.
+          tgt_name = "%s-cropped" % (tgt_name,)
+          src_name = "%s-cropped" % (src_name,)
+          tgt_ranges = tgt_ranges.subtract(tgt_skipped)
+          src_ranges = src_ranges.subtract(src_skipped)
+
+          # Possibly having no changed blocks.
+          if not tgt_ranges:
+            return
+
+      # Add the transfer(s).
+      AddSplitTransfers(
+          tgt_name, src_name, tgt_ranges, src_ranges, style, by_id)
+
+    print("Finding transfers...")
+
     empty = RangeSet()
     for tgt_fn, tgt_ranges in self.tgt.file_map.items():
       if tgt_fn == "__ZERO":
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index d78896a..a7b3fdd 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -15,9 +15,9 @@
 # limitations under the License.
 
 """
-Build image output_image_file from input_directory and properties_file.
+Build image output_image_file from input_directory, properties_file, and target_out_dir
 
-Usage:  build_image input_directory properties_file output_image_file
+Usage:  build_image input_directory properties_file output_image_file target_out_dir
 
 """
 import os
@@ -109,7 +109,8 @@
   Args:
     partition_size: the size of the partition to be verified.
   Returns:
-    The size of the partition adjusted for verity metadata.
+    A tuple of the size of the partition adjusted for verity metadata, and
+    the size of verity metadata.
   """
   key = "%d %d" % (partition_size, fec_supported)
   if key in AdjustPartitionSizeForVerity.results:
@@ -121,27 +122,31 @@
 
   # verity tree and fec sizes depend on the partition size, which
   # means this estimate is always going to be unnecessarily small
-  lo = partition_size - GetVeritySize(hi, fec_supported)
+  verity_size = GetVeritySize(hi, fec_supported)
+  lo = partition_size - verity_size
   result = lo
 
   # do a binary search for the optimal size
   while lo < hi:
     i = ((lo + hi) // (2 * BLOCK_SIZE)) * BLOCK_SIZE
-    size = i + GetVeritySize(i, fec_supported)
-    if size <= partition_size:
+    v = GetVeritySize(i, fec_supported)
+    if i + v <= partition_size:
       if result < i:
         result = i
+        verity_size = v
       lo = i + BLOCK_SIZE
     else:
       hi = i
 
-  AdjustPartitionSizeForVerity.results[key] = result
-  return result
+  AdjustPartitionSizeForVerity.results[key] = (result, verity_size)
+  return (result, verity_size)
 
 AdjustPartitionSizeForVerity.results = {}
 
-def BuildVerityFEC(sparse_image_path, verity_path, verity_fec_path):
-  cmd = "fec -e %s %s %s" % (sparse_image_path, verity_path, verity_fec_path)
+def BuildVerityFEC(sparse_image_path, verity_path, verity_fec_path,
+                   padding_size):
+  cmd = "fec -e -p %d %s %s %s" % (padding_size, sparse_image_path,
+                                   verity_path, verity_fec_path)
   print cmd
   status, output = commands.getstatusoutput(cmd)
   if status:
@@ -204,7 +209,7 @@
 
 def BuildVerifiedImage(data_image_path, verity_image_path,
                        verity_metadata_path, verity_fec_path,
-                       fec_supported):
+                       padding_size, fec_supported):
   if not Append(verity_image_path, verity_metadata_path,
                 "Could not append verity metadata!"):
     return False
@@ -212,7 +217,7 @@
   if fec_supported:
     # build FEC for the entire partition, including metadata
     if not BuildVerityFEC(data_image_path, verity_image_path,
-                          verity_fec_path):
+                          verity_fec_path, padding_size):
       return False
 
     if not Append(verity_image_path, verity_fec_path, "Could not append FEC!"):
@@ -250,7 +255,7 @@
     True on success, False otherwise.
   """
   # get properties
-  image_size = prop_dict["partition_size"]
+  image_size = int(prop_dict["partition_size"])
   block_dev = prop_dict["verity_block_device"]
   signer_key = prop_dict["verity_key"] + ".pk8"
   if OPTIONS.verity_signer_path is not None:
@@ -281,10 +286,17 @@
     return False
 
   # build the full verified image
+  target_size = int(prop_dict["original_partition_size"])
+  verity_size = int(prop_dict["verity_size"])
+
+  padding_size = target_size - image_size - verity_size
+  assert padding_size >= 0
+
   if not BuildVerifiedImage(out_file,
                             verity_image_path,
                             verity_metadata_path,
                             verity_fec_path,
+                            padding_size,
                             fec_supported):
     shutil.rmtree(tempdir_name, ignore_errors=True)
     return False
@@ -355,12 +367,13 @@
   # verified.
   if verity_supported and is_verity_partition:
     partition_size = int(prop_dict.get("partition_size"))
-    adjusted_size = AdjustPartitionSizeForVerity(partition_size,
-                                                 verity_fec_supported)
+    (adjusted_size, verity_size) = AdjustPartitionSizeForVerity(partition_size,
+                                                                verity_fec_supported)
     if not adjusted_size:
       return False
     prop_dict["partition_size"] = str(adjusted_size)
     prop_dict["original_partition_size"] = str(partition_size)
+    prop_dict["verity_size"] = str(verity_size)
 
   if fs_type.startswith("ext"):
     build_command = ["mkuserimg.sh"]
@@ -412,14 +425,8 @@
     build_command = ["mkf2fsuserimg.sh"]
     build_command.extend([out_file, prop_dict["partition_size"]])
   else:
-    build_command = ["mkyaffs2image", "-f"]
-    if prop_dict.get("mkyaffs2_extra_flags", None):
-      build_command.extend(prop_dict["mkyaffs2_extra_flags"].split())
-    build_command.append(in_dir)
-    build_command.append(out_file)
-    if "selinux_fc" in prop_dict:
-      build_command.append(prop_dict["selinux_fc"])
-      build_command.append(prop_dict["mount_point"])
+    print("Error: unknown filesystem type '%s'" % (fs_type))
+    return False
 
   if in_dir != origin_in:
     # Construct a staging directory of the root file system.
@@ -525,7 +532,6 @@
   common_props = (
       "extfs_sparse_flag",
       "squashfs_sparse_flag",
-      "mkyaffs2_extra_flags",
       "selinux_fc",
       "skip_fsck",
       "verity",
diff --git a/tools/releasetools/check_ota_package_signature.py b/tools/releasetools/check_ota_package_signature.py
new file mode 100755
index 0000000..0da61b1
--- /dev/null
+++ b/tools/releasetools/check_ota_package_signature.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 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.
+
+"""
+Verify a given OTA package with the specifed certificate.
+"""
+
+from __future__ import print_function
+
+import argparse
+import common
+import re
+import subprocess
+import sys
+
+from hashlib import sha1
+from hashlib import sha256
+
+
+def cert_uses_sha256(cert):
+  """Check if the cert uses SHA-256 hashing algorithm."""
+
+  cmd = ['openssl', 'x509', '-text', '-noout', '-in', cert]
+  p1 = common.Run(cmd, stdout=subprocess.PIPE)
+  cert_dump, _ = p1.communicate()
+
+  algorithm = re.search(r'Signature Algorithm: ([a-zA-Z0-9]+)', cert_dump)
+  assert algorithm, "Failed to identify the signature algorithm."
+
+  assert not algorithm.group(1).startswith('ecdsa'), (
+      'This script doesn\'t support verifying ECDSA signed package yet.')
+
+  return algorithm.group(1).startswith('sha256')
+
+
+def verify_package(cert, package):
+  """Verify the given package with the certificate.
+
+  (Comments from bootable/recovery/verifier.cpp:)
+
+  An archive with a whole-file signature will end in six bytes:
+
+    (2-byte signature start) $ff $ff (2-byte comment size)
+
+  (As far as the ZIP format is concerned, these are part of the
+  archive comment.) We start by reading this footer, this tells
+  us how far back from the end we have to start reading to find
+  the whole comment.
+  """
+
+  print('Package: %s' % (package,))
+  print('Certificate: %s' % (cert,))
+
+  # Read in the package.
+  with open(package) as package_file:
+    package_bytes = package_file.read()
+
+  length = len(package_bytes)
+  assert length >= 6, "Not big enough to contain footer."
+
+  footer = [ord(x) for x in package_bytes[-6:]]
+  assert footer[2] == 0xff and footer[3] == 0xff, "Footer is wrong."
+
+  signature_start_from_end = (footer[1] << 8) + footer[0]
+  assert signature_start_from_end > 6, "Signature start is in the footer."
+
+  signature_start = length - signature_start_from_end
+
+  # Determine how much of the file is covered by the signature. This is
+  # everything except the signature data and length, which includes all of the
+  # EOCD except for the comment length field (2 bytes) and the comment data.
+  comment_len = (footer[5] << 8) + footer[4]
+  signed_len = length - comment_len - 2
+
+  print('Package length: %d' % (length,))
+  print('Comment length: %d' % (comment_len,))
+  print('Signed data length: %d' % (signed_len,))
+  print('Signature start: %d' % (signature_start,))
+
+  use_sha256 = cert_uses_sha256(cert)
+  print('Use SHA-256: %s' % (use_sha256,))
+
+  if use_sha256:
+    h = sha256()
+  else:
+    h = sha1()
+  h.update(package_bytes[:signed_len])
+  package_digest = h.hexdigest().lower()
+
+  print('Digest: %s\n' % (package_digest,))
+
+  # Get the signature from the input package.
+  signature = package_bytes[signature_start:-6]
+  sig_file = common.MakeTempFile(prefix='sig-', suffix='')
+  with open(sig_file, 'wb') as f:
+    f.write(signature)
+
+  # Parse the signature and get the hash.
+  cmd = ['openssl', 'asn1parse', '-inform', 'DER', '-in', sig_file]
+  p1 = common.Run(cmd, stdout=subprocess.PIPE)
+  sig, _ = p1.communicate()
+  assert p1.returncode == 0, "Failed to parse the signature."
+
+  digest_line = sig.strip().split('\n')[-1]
+  digest_string = digest_line.split(':')[3]
+  digest_file = common.MakeTempFile(prefix='digest-', suffix='')
+  with open(digest_file, 'wb') as f:
+    f.write(digest_string.decode('hex'))
+
+  # Verify the digest by outputing the decrypted result in ASN.1 structure.
+  decrypted_file = common.MakeTempFile(prefix='decrypted-', suffix='')
+  cmd = ['openssl', 'rsautl', '-verify', '-certin', '-inkey', cert,
+         '-in', digest_file, '-out', decrypted_file]
+  p1 = common.Run(cmd, stdout=subprocess.PIPE)
+  p1.communicate()
+  assert p1.returncode == 0, "Failed to run openssl rsautl -verify."
+
+  # Parse the output ASN.1 structure.
+  cmd = ['openssl', 'asn1parse', '-inform', 'DER', '-in', decrypted_file]
+  p1 = common.Run(cmd, stdout=subprocess.PIPE)
+  decrypted_output, _ = p1.communicate()
+  assert p1.returncode == 0, "Failed to parse the output."
+
+  digest_line = decrypted_output.strip().split('\n')[-1]
+  digest_string = digest_line.split(':')[3].lower()
+
+  # Verify that the two digest strings match.
+  assert package_digest == digest_string, "Verification failed."
+
+  # Verified successfully upon reaching here.
+  print('VERIFIED\n')
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('certificate', help='The certificate to be used.')
+  parser.add_argument('package', help='The OTA package to be verified.')
+  args = parser.parse_args()
+
+  verify_package(args.certificate, args.package)
+
+
+if __name__ == '__main__':
+  try:
+    main()
+  except AssertionError as err:
+    print('\n    ERROR: %s\n' % (err,))
+    sys.exit(1)
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index 5c541ab..3048488 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -245,7 +245,7 @@
             fullname = os.path.join(dirpath, fn)
             displayname = fullname[len(d)+1:]
             apk = APK(fullname, displayname)
-            self.apks[apk.package] = apk
+            self.apks[apk.filename] = apk
             self.apks_by_basename[os.path.basename(apk.filename)] = apk
 
             self.max_pkg_len = max(self.max_pkg_len, len(apk.package))
@@ -316,8 +316,7 @@
                                         self.max_pkg_len, apk.package,
                                         apk.shared_uid)
         else:
-          print "  %-*s  %-*s" % (self.max_fn_len, apk.filename,
-                                  self.max_pkg_len, apk.package)
+          print "  %-*s  %s" % (self.max_fn_len, apk.filename, apk.package)
       print
 
   def CompareWith(self, other):
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 422ba43..fad6a5e 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -155,14 +155,6 @@
   # files.  Look for them, in case we're processing an old
   # target_files zip.
 
-  if "mkyaffs2_extra_flags" not in d:
-    try:
-      d["mkyaffs2_extra_flags"] = read_helper(
-          "META/mkyaffs2-extra-flags.txt").strip()
-    except KeyError:
-      # ok if flags don't exist
-      pass
-
   if "recovery_api_version" not in d:
     try:
       d["recovery_api_version"] = read_helper(
@@ -392,6 +384,16 @@
     print "%-25s = (%s) %s" % (k, type(v).__name__, v)
 
 
+def AppendAVBSigningArgs(cmd):
+  """Append signing arguments for avbtool."""
+  keypath = OPTIONS.info_dict.get("board_avb_key_path", None)
+  algorithm = OPTIONS.info_dict.get("board_avb_algorithm", None)
+  if not keypath or not algorithm:
+    algorithm = "SHA256_RSA4096"
+    keypath = "external/avb/test/data/testkey_rsa4096.pem"
+  cmd.extend(["--key", keypath, "--algorithm", algorithm])
+
+
 def _BuildBootableImage(sourcedir, fs_config_file, info_dict=None,
                         has_ramdisk=False):
   """Build a bootable image from the specified sourcedir.
@@ -511,6 +513,21 @@
     img_unsigned.close()
     img_keyblock.close()
 
+  # AVB: if enabled, calculate and add hash to boot.img.
+  if info_dict.get("board_avb_enable", None) == "true":
+    avbtool = os.getenv('AVBTOOL') or "avbtool"
+    part_size = info_dict.get("boot_size", None)
+    cmd = [avbtool, "add_hash_footer", "--image", img.name,
+           "--partition_size", str(part_size), "--partition_name", "boot"]
+    AppendAVBSigningArgs(cmd)
+    args = info_dict.get("board_avb_boot_add_hash_footer_args", None)
+    if args and args.strip():
+      cmd.extend(shlex.split(args))
+    p = Run(cmd, stdout=subprocess.PIPE)
+    p.communicate()
+    assert p.returncode == 0, "avbtool add_hash_footer of %s failed" % (
+        os.path.basename(OPTIONS.input_tmp))
+
   img.seek(os.SEEK_SET, 0)
   data = img.read()
 
@@ -522,7 +539,7 @@
 
 
 def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
-                     info_dict=None):
+                     info_dict=None, system_img_path=None):
   """Return a File object with the desired bootable image.
 
   Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name 'prebuilt_name',
@@ -753,10 +770,6 @@
   if not fs_type or not limit:
     return
 
-  if fs_type == "yaffs2":
-    # image size should be increased by 1/64th to account for the
-    # spare area (64 bytes per 2k page)
-    limit = limit / 2048 * (2048+64)
   size = len(data)
   pct = float(size) * 100.0 / limit
   msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit)
@@ -1578,8 +1591,6 @@
 
 # map recovery.fstab's fs_types to mount/format "partition types"
 PARTITION_TYPES = {
-    "yaffs2": "MTD",
-    "mtd": "MTD",
     "ext4": "EMMC",
     "emmc": "EMMC",
     "f2fs": "EMMC",
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 2ecc5cb..3028b2a 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -121,6 +121,17 @@
                common.ErrorCode.THUMBPRINT_MISMATCH, " or ".join(fp))
     self.script.append(cmd)
 
+  def AssertFingerprintOrThumbprint(self, fp, tp):
+    """Assert that the current recovery build fingerprint is fp, or thumbprint
+       is tp."""
+    cmd = ('getprop("ro.build.fingerprint") == "{fp}" ||\n'
+           '    getprop("ro.build.thumbprint") == "{tp}" ||\n'
+           '    abort("Package expects build fingerprint of {fp} or '
+           'thumbprint of {tp}; this device has a fingerprint of " '
+           '+ getprop("ro.build.fingerprint") and a thumbprint of " '
+           '+ getprop("ro.build.thumbprint") + ".");').format(fp=fp, tp=tp)
+    self.script.append(cmd)
+
   def AssertOlderBuild(self, timestamp, timestamp_text):
     """Assert that the build on the device is older (or the same as)
     the given timestamp."""
@@ -159,7 +170,7 @@
     self.script.append("set_progress(%f);" % (frac,))
 
   def PatchCheck(self, filename, *sha1):
-    """Check that the given file (or MTD reference) has one of the
+    """Check that the given file has one of the
     given *sha1 hashes, checking the version saved in cache if the
     file does not match."""
     self.script.append(
@@ -169,7 +180,7 @@
             common.ErrorCode.BAD_PATCH_FILE, filename))
 
   def Verify(self, filename):
-    """Check that the given file (or MTD reference) has one of the
+    """Check that the given file has one of the
     given hashes (encoded in the filename)."""
     self.script.append(
         'apply_patch_check("{filename}") && '
@@ -178,7 +189,7 @@
             filename=filename))
 
   def FileCheck(self, filename, *sha1):
-    """Check that the given file (or MTD reference) has one of the
+    """Check that the given file has one of the
     given *sha1 hashes."""
     self.script.append('assert(sha1_check(read_file("%s")' % (filename,) +
                        "".join([', "%s"' % (i,) for i in sha1]) +
@@ -318,11 +329,7 @@
       p = fstab[mount_point]
       partition_type = common.PARTITION_TYPES[p.fs_type]
       args = {'device': p.device, 'fn': fn}
-      if partition_type == "MTD":
-        self.script.append(
-            'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");'
-            % args)
-      elif partition_type == "EMMC":
+      if partition_type == "EMMC":
         if mapfn:
           args["map"] = mapfn
           self.script.append(
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index b69ddac..f32d9d8 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -64,11 +64,6 @@
       Generate an OTA package that will wipe the user data partition
       when installed.
 
-  -n  (--no_prereq)
-      Omit the timestamp prereq check normally included at the top of
-      the build scripts (used for developer OTA packages which
-      legitimately need to go back and forth).
-
   --downgrade
       Intentionally generate an incremental OTA that updates from a newer
       build to an older one (based on timestamp comparison). "post-timestamp"
@@ -113,6 +108,17 @@
       Generate a log file that shows the differences in the source and target
       builds for an incremental package. This option is only meaningful when
       -i is specified.
+
+  --payload_signer <signer>
+      Specify the signer when signing the payload and metadata for A/B OTAs.
+      By default (i.e. without this flag), it calls 'openssl pkeyutl' to sign
+      with the package private key. If the private key cannot be accessed
+      directly, a payload signer that knows how to do that should be specified.
+      The signer will be supplied with "-inkey <path_to_key>",
+      "-in <input_file>" and "-out <output_file>" parameters.
+
+  --payload_signer_args <args>
+      Specify the arguments needed for payload signer.
 """
 
 import sys
@@ -124,6 +130,7 @@
 import multiprocessing
 import os
 import subprocess
+import shlex
 import tempfile
 import zipfile
 
@@ -139,7 +146,6 @@
 OPTIONS.prohibit_verbatim = set(("system/build.prop",))
 OPTIONS.patch_threshold = 0.95
 OPTIONS.wipe_user_data = False
-OPTIONS.omit_prereq = False
 OPTIONS.downgrade = False
 OPTIONS.extra_script = None
 OPTIONS.aslr_mode = True
@@ -160,6 +166,8 @@
 OPTIONS.stash_threshold = 0.8
 OPTIONS.gen_verify = False
 OPTIONS.log_diff = None
+OPTIONS.payload_signer = None
+OPTIONS.payload_signer_args = []
 
 def MostPopularKey(d, default):
   """Given a dict, return the key corresponding to the largest
@@ -439,7 +447,7 @@
 
 def AppendAssertions(script, info_dict, oem_dict=None):
   oem_props = info_dict.get("oem_fingerprint_properties")
-  if oem_props is None or len(oem_props) == 0:
+  if not oem_props:
     device = GetBuildProp("ro.product.device", info_dict)
     script.AssertDevice(device)
   else:
@@ -528,10 +536,10 @@
   # in the target build.
   script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict)
 
-  oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
   recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
+  oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
   oem_dict = None
-  if oem_props is not None and len(oem_props) > 0:
+  if oem_props:
     if OPTIONS.oem_source is None:
       raise common.ExternalError("OEM source required for this build")
     if not OPTIONS.oem_no_mount:
@@ -539,9 +547,9 @@
     oem_dict = common.LoadDictionaryFromLines(
         open(OPTIONS.oem_source).readlines())
 
+  target_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.info_dict)
   metadata = {
-      "post-build": CalculateFingerprint(oem_props, oem_dict,
-                                         OPTIONS.info_dict),
+      "post-build": target_fp,
       "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
                                    OPTIONS.info_dict),
       "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict),
@@ -561,10 +569,9 @@
 
   metadata["ota-type"] = "BLOCK" if block_based else "FILE"
 
-  if not OPTIONS.omit_prereq:
-    ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict)
-    ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict)
-    script.AssertOlderBuild(ts, ts_text)
+  ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict)
+  ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict)
+  script.AssertOlderBuild(ts, ts_text)
 
   AppendAssertions(script, OPTIONS.info_dict, oem_dict)
   device_specific.FullOTA_Assertions()
@@ -610,8 +617,7 @@
 """ % bcb_dev)
 
   # Dump fingerprints
-  script.Print("Target: %s" % CalculateFingerprint(
-      oem_props, oem_dict, OPTIONS.info_dict))
+  script.Print("Target: %s" % target_fp)
 
   device_specific.FullOTA_InstallBegin()
 
@@ -773,17 +779,18 @@
   target_version = OPTIONS.target_info_dict["recovery_api_version"]
 
   if source_version == 0:
-    print ("WARNING: generating edify script for a source that "
-           "can't install it.")
+    print("WARNING: generating edify script for a source that "
+          "can't install it.")
   script = edify_generator.EdifyGenerator(
       source_version, OPTIONS.target_info_dict,
       fstab=OPTIONS.source_info_dict["fstab"])
 
-  oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
   recovery_mount_options = OPTIONS.source_info_dict.get(
       "recovery_mount_options")
+  source_oem_props = OPTIONS.source_info_dict.get("oem_fingerprint_properties")
+  target_oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties")
   oem_dict = None
-  if oem_props is not None and len(oem_props) > 0:
+  if source_oem_props or target_oem_props:
     if OPTIONS.oem_source is None:
       raise common.ExternalError("OEM source required for this build")
     if not OPTIONS.oem_no_mount:
@@ -792,8 +799,8 @@
         open(OPTIONS.oem_source).readlines())
 
   metadata = {
-      "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
-                                   OPTIONS.source_info_dict),
+      "pre-device": GetOemProperty("ro.product.device", source_oem_props,
+                                   oem_dict, OPTIONS.source_info_dict),
       "ota-type": "BLOCK",
   }
 
@@ -828,9 +835,9 @@
       metadata=metadata,
       info_dict=OPTIONS.source_info_dict)
 
-  source_fp = CalculateFingerprint(oem_props, oem_dict,
+  source_fp = CalculateFingerprint(source_oem_props, oem_dict,
                                    OPTIONS.source_info_dict)
-  target_fp = CalculateFingerprint(oem_props, oem_dict,
+  target_fp = CalculateFingerprint(target_oem_props, oem_dict,
                                    OPTIONS.target_info_dict)
   metadata["pre-build"] = source_fp
   metadata["post-build"] = target_fp
@@ -859,15 +866,17 @@
         int(i) for i in
         OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
 
-  # Check first block of system partition for remount R/W only if
-  # disk type is ext4
-  system_partition = OPTIONS.source_info_dict["fstab"]["/system"]
-  check_first_block = system_partition.fs_type == "ext4"
+  # Check the first block of the source system partition for remount R/W only
+  # if the filesystem is ext4.
+  system_src_partition = OPTIONS.source_info_dict["fstab"]["/system"]
+  check_first_block = system_src_partition.fs_type == "ext4"
   # Disable using imgdiff for squashfs. 'imgdiff -z' expects input files to be
   # in zip formats. However with squashfs, a) all files are compressed in LZ4;
   # b) the blocks listed in block map may not contain all the bytes for a given
   # file (because they're rounded to be 4K-aligned).
-  disable_imgdiff = system_partition.fs_type == "squashfs"
+  system_tgt_partition = OPTIONS.target_info_dict["fstab"]["/system"]
+  disable_imgdiff = (system_src_partition.fs_type == "squashfs" or
+                     system_tgt_partition.fs_type == "squashfs")
   system_diff = common.BlockDifference("system", system_tgt, system_src,
                                        check_first_block,
                                        version=blockimgdiff_version,
@@ -938,32 +947,39 @@
 """ % bcb_dev)
 
   # Dump fingerprints
-  script.Print("Source: %s" % CalculateFingerprint(
-      oem_props, oem_dict, OPTIONS.source_info_dict))
-  script.Print("Target: %s" % CalculateFingerprint(
-      oem_props, oem_dict, OPTIONS.target_info_dict))
+  script.Print(source_fp)
+  script.Print(target_fp)
 
   script.Print("Verifying current system...")
 
   device_specific.IncrementalOTA_VerifyBegin()
 
-  if oem_props is None:
-    # When blockimgdiff version is less than 3 (non-resumable block-based OTA),
-    # patching on a device that's already on the target build will damage the
-    # system. Because operations like move don't check the block state, they
-    # always apply the changes unconditionally.
-    if blockimgdiff_version <= 2:
+  # When blockimgdiff version is less than 3 (non-resumable block-based OTA),
+  # patching on a device that's already on the target build will damage the
+  # system. Because operations like move don't check the block state, they
+  # always apply the changes unconditionally.
+  if blockimgdiff_version <= 2:
+    if source_oem_props is None:
       script.AssertSomeFingerprint(source_fp)
     else:
-      script.AssertSomeFingerprint(source_fp, target_fp)
-  else:
-    if blockimgdiff_version <= 2:
       script.AssertSomeThumbprint(
           GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
-    else:
+
+  else: # blockimgdiff_version > 2
+    if source_oem_props is None and target_oem_props is None:
+      script.AssertSomeFingerprint(source_fp, target_fp)
+    elif source_oem_props is not None and target_oem_props is not None:
       script.AssertSomeThumbprint(
           GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),
           GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
+    elif source_oem_props is None and target_oem_props is not None:
+      script.AssertFingerprintOrThumbprint(
+          source_fp,
+          GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict))
+    else:
+      script.AssertFingerprintOrThumbprint(
+          target_fp,
+          GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
 
   # Check the required cache size (i.e. stashed blocks).
   size = []
@@ -1086,10 +1102,11 @@
   recovery_mount_options = OPTIONS.info_dict.get(
       "recovery_mount_options")
   oem_dict = None
-  if oem_props is not None and len(oem_props) > 0:
+  if oem_props:
     if OPTIONS.oem_source is None:
       raise common.ExternalError("OEM source required for this build")
-    script.Mount("/oem", recovery_mount_options)
+    if not OPTIONS.oem_no_mount:
+      script.Mount("/oem", recovery_mount_options)
     oem_dict = common.LoadDictionaryFromLines(
         open(OPTIONS.oem_source).readlines())
 
@@ -1157,23 +1174,28 @@
                                       source_file=None):
   """Generate an Android OTA package that has A/B update payload."""
 
+  # The place where the output from the subprocess should go.
+  log_file = sys.stdout if OPTIONS.verbose else subprocess.PIPE
+
   # Setup signing keys.
   if OPTIONS.package_key is None:
     OPTIONS.package_key = OPTIONS.info_dict.get(
         "default_system_dev_certificate",
         "build/target/product/security/testkey")
 
-  # A/B updater expects key in RSA format.
-  cmd = ["openssl", "pkcs8",
-         "-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
-         "-inform", "DER", "-nocrypt"]
-  rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
-  cmd.extend(["-out", rsa_key])
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.wait()
-  assert p1.returncode == 0, "openssl pkcs8 failed"
+  # A/B updater expects a signing key in RSA format. Gets the key ready for
+  # later use in step 3, unless a payload_signer has been specified.
+  if OPTIONS.payload_signer is None:
+    cmd = ["openssl", "pkcs8",
+           "-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
+           "-inform", "DER", "-nocrypt"]
+    rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
+    cmd.extend(["-out", rsa_key])
+    p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+    p1.communicate()
+    assert p1.returncode == 0, "openssl pkcs8 failed"
 
-  # Stage the output zip package for signing.
+  # Stage the output zip package for package signing.
   temp_zip_file = tempfile.NamedTemporaryFile()
   output_zip = zipfile.ZipFile(temp_zip_file, "w",
                                compression=zipfile.ZIP_DEFLATED)
@@ -1212,8 +1234,8 @@
          "--target_image", target_file]
   if source_file is not None:
     cmd.extend(["--source_image", source_file])
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.wait()
+  p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+  p1.communicate()
   assert p1.returncode == 0, "brillo_update_payload generate failed"
 
   # 2. Generate hashes of the payload and metadata files.
@@ -1224,8 +1246,8 @@
          "--signature_size", "256",
          "--metadata_hash_file", metadata_sig_file,
          "--payload_hash_file", payload_sig_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.wait()
+  p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+  p1.communicate()
   assert p1.returncode == 0, "brillo_update_payload hash failed"
 
   # 3. Sign the hashes and insert them back into the payload file.
@@ -1234,23 +1256,31 @@
   signed_metadata_sig_file = common.MakeTempFile(prefix="signed-sig-",
                                                  suffix=".bin")
   # 3a. Sign the payload hash.
-  cmd = ["openssl", "pkeyutl", "-sign",
-         "-inkey", rsa_key,
-         "-pkeyopt", "digest:sha256",
-         "-in", payload_sig_file,
-         "-out", signed_payload_sig_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.wait()
+  if OPTIONS.payload_signer is not None:
+    cmd = [OPTIONS.payload_signer]
+    cmd.extend(OPTIONS.payload_signer_args)
+  else:
+    cmd = ["openssl", "pkeyutl", "-sign",
+           "-inkey", rsa_key,
+           "-pkeyopt", "digest:sha256"]
+  cmd.extend(["-in", payload_sig_file,
+              "-out", signed_payload_sig_file])
+  p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+  p1.communicate()
   assert p1.returncode == 0, "openssl sign payload failed"
 
   # 3b. Sign the metadata hash.
-  cmd = ["openssl", "pkeyutl", "-sign",
-         "-inkey", rsa_key,
-         "-pkeyopt", "digest:sha256",
-         "-in", metadata_sig_file,
-         "-out", signed_metadata_sig_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.wait()
+  if OPTIONS.payload_signer is not None:
+    cmd = [OPTIONS.payload_signer]
+    cmd.extend(OPTIONS.payload_signer_args)
+  else:
+    cmd = ["openssl", "pkeyutl", "-sign",
+           "-inkey", rsa_key,
+           "-pkeyopt", "digest:sha256"]
+  cmd.extend(["-in", metadata_sig_file,
+              "-out", signed_metadata_sig_file])
+  p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+  p1.communicate()
   assert p1.returncode == 0, "openssl sign metadata failed"
 
   # 3c. Insert the signatures back into the payload file.
@@ -1262,8 +1292,8 @@
          "--signature_size", "256",
          "--metadata_signature_file", signed_metadata_sig_file,
          "--payload_signature_file", signed_payload_sig_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.wait()
+  p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+  p1.communicate()
   assert p1.returncode == 0, "brillo_update_payload sign failed"
 
   # 4. Dump the signed payload properties.
@@ -1272,10 +1302,15 @@
   cmd = ["brillo_update_payload", "properties",
          "--payload", signed_payload_file,
          "--properties_file", properties_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.wait()
+  p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+  p1.communicate()
   assert p1.returncode == 0, "brillo_update_payload properties failed"
 
+  if OPTIONS.wipe_user_data:
+    with open(properties_file, "a") as f:
+      f.write("POWERWASH=1\n")
+    metadata["ota-wipe"] = "yes"
+
   # Add the signed payload file and properties into the zip.
   common.ZipWrite(output_zip, properties_file, arcname="payload_properties.txt")
   common.ZipWrite(output_zip, signed_payload_file, arcname="payload.bin",
@@ -1432,17 +1467,18 @@
   target_version = OPTIONS.target_info_dict["recovery_api_version"]
 
   if source_version == 0:
-    print ("WARNING: generating edify script for a source that "
-           "can't install it.")
+    print("WARNING: generating edify script for a source that "
+          "can't install it.")
   script = edify_generator.EdifyGenerator(
       source_version, OPTIONS.target_info_dict,
       fstab=OPTIONS.source_info_dict["fstab"])
 
-  oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
   recovery_mount_options = OPTIONS.source_info_dict.get(
       "recovery_mount_options")
+  source_oem_props = OPTIONS.source_info_dict.get("oem_fingerprint_properties")
+  target_oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties")
   oem_dict = None
-  if oem_props is not None and len(oem_props) > 0:
+  if source_oem_props or target_oem_props:
     if OPTIONS.oem_source is None:
       raise common.ExternalError("OEM source required for this build")
     if not OPTIONS.oem_no_mount:
@@ -1451,8 +1487,8 @@
         open(OPTIONS.oem_source).readlines())
 
   metadata = {
-      "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
-                                   OPTIONS.source_info_dict),
+      "pre-device": GetOemProperty("ro.product.device", source_oem_props,
+                                   oem_dict, OPTIONS.source_info_dict),
       "ota-type": "FILE",
   }
 
@@ -1495,17 +1531,25 @@
   else:
     vendor_diff = None
 
-  target_fp = CalculateFingerprint(oem_props, oem_dict,
+  target_fp = CalculateFingerprint(target_oem_props, oem_dict,
                                    OPTIONS.target_info_dict)
-  source_fp = CalculateFingerprint(oem_props, oem_dict,
+  source_fp = CalculateFingerprint(source_oem_props, oem_dict,
                                    OPTIONS.source_info_dict)
 
-  if oem_props is None:
+  if source_oem_props is None and target_oem_props is None:
     script.AssertSomeFingerprint(source_fp, target_fp)
-  else:
+  elif source_oem_props is not None and target_oem_props is not None:
     script.AssertSomeThumbprint(
         GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),
         GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
+  elif source_oem_props is None and target_oem_props is not None:
+    script.AssertFingerprintOrThumbprint(
+        source_fp,
+        GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict))
+  else:
+    script.AssertFingerprintOrThumbprint(
+        target_fp,
+        GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
 
   metadata["pre-build"] = source_fp
   metadata["post-build"] = target_fp
@@ -1856,8 +1900,6 @@
       OPTIONS.full_bootloader = True
     elif o in ("-w", "--wipe_user_data"):
       OPTIONS.wipe_user_data = True
-    elif o in ("-n", "--no_prereq"):
-      OPTIONS.omit_prereq = True
     elif o == "--downgrade":
       OPTIONS.downgrade = True
       OPTIONS.wipe_user_data = True
@@ -1900,12 +1942,16 @@
       OPTIONS.gen_verify = True
     elif o == "--log_diff":
       OPTIONS.log_diff = a
+    elif o == "--payload_signer":
+      OPTIONS.payload_signer = a
+    elif o == "--payload_signer_args":
+      OPTIONS.payload_signer_args = shlex.split(a)
     else:
       return False
     return True
 
   args = common.ParseOptions(argv, __doc__,
-                             extra_opts="b:k:i:d:wne:t:a:2o:",
+                             extra_opts="b:k:i:d:we:t:a:2o:",
                              extra_long_opts=[
                                  "board_config=",
                                  "package_key=",
@@ -1913,7 +1959,6 @@
                                  "full_radio",
                                  "full_bootloader",
                                  "wipe_user_data",
-                                 "no_prereq",
                                  "downgrade",
                                  "extra_script=",
                                  "worker_threads=",
@@ -1929,6 +1974,8 @@
                                  "stash_threshold=",
                                  "gen_verify",
                                  "log_diff=",
+                                 "payload_signer=",
+                                 "payload_signer_args=",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
@@ -1944,8 +1991,7 @@
     # Otherwise the device may go back from arbitrary build with this full
     # OTA package.
     if OPTIONS.incremental_source is None:
-      raise ValueError("Cannot generate downgradable full OTAs - consider"
-                       "using --omit_prereq?")
+      raise ValueError("Cannot generate downgradable full OTAs")
 
   # Load the dict file from the zip directly to have a peek at the OTA type.
   # For packages using A/B update, unzipping is not needed.
diff --git a/tools/releasetools/rangelib.py b/tools/releasetools/rangelib.py
index aa572cc..fa6eec1 100644
--- a/tools/releasetools/rangelib.py
+++ b/tools/releasetools/rangelib.py
@@ -71,6 +71,19 @@
     """
     return cls(text)
 
+  @classmethod
+  def parse_raw(cls, text):
+    """Parse a string generated by RangeSet.to_string_raw().
+
+    >>> RangeSet.parse_raw(RangeSet("0-9").to_string_raw())
+    <RangeSet("0-9")>
+    """
+
+    raw = [int(i) for i in text.split(',')]
+    assert raw[0] == len(raw[1:]), "Invalid raw string."
+
+    return cls(data=raw[1:])
+
   def _parse_internal(self, text):
     data = []
     last = -1
@@ -300,6 +313,20 @@
         n -= e - s
     return RangeSet(data=out)
 
+  def next_item(self):
+    """Return the next integer represented by the RangeSet.
+
+    >>> list(RangeSet("0-9").next_item())
+    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    >>> list(RangeSet("10-19 3-5").next_item())
+    [3, 4, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+    >>> list(rangelib.RangeSet("10-19 3 5 7").next_item())
+    [3, 5, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+    """
+    for s, e in self:
+      for element in range(s, e):
+        yield element
+
 
 if __name__ == "__main__":
   import doctest
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index f758ae0..7f69a57 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -51,10 +51,12 @@
       in which they appear on the command line.
 
   -o  (--replace_ota_keys)
-      Replace the certificate (public key) used by OTA package
-      verification with the one specified in the input target_files
-      zip (in the META/otakeys.txt file).  Key remapping (-k and -d)
-      is performed on this key.
+      Replace the certificate (public key) used by OTA package verification
+      with the ones specified in the input target_files zip (in the
+      META/otakeys.txt file). Key remapping (-k and -d) is performed on the
+      keys. For A/B devices, the payload verification key will be replaced
+      as well. If there're multiple OTA keys, only the first one will be used
+      for payload verification.
 
   -t  (--tag_changes)  <+tag>,<-tag>,...
       Comma-separated list of changes to make to the set of tags (in
@@ -63,6 +65,19 @@
       removed.  Changes are processed in the order they appear.
       Default value is "-test-keys,-dev-keys,+release-keys".
 
+  --replace_verity_private_key <key>
+      Replace the private key used for verity signing. It expects a filename
+      WITHOUT the extension (e.g. verity_key).
+
+  --replace_verity_public_key <key>
+      Replace the certificate (public key) used for verity verification. The
+      key file replaces the one at BOOT/RAMDISK/verity_key (or ROOT/verity_key
+      for devices using system_root_image). It expects the key filename WITH
+      the extension (e.g. verity_key.pub).
+
+  --replace_verity_keyid <path_to_X509_PEM_cert_file>
+      Replace the veritykeyid in BOOT/cmdline of input_target_file_zip
+      with keyid of the cert pointed by <path_to_X509_PEM_cert_file>.
 """
 
 import sys
@@ -92,6 +107,7 @@
 OPTIONS.replace_ota_keys = False
 OPTIONS.replace_verity_public_key = False
 OPTIONS.replace_verity_private_key = False
+OPTIONS.replace_verity_keyid = False
 OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys")
 
 def GetApkCerts(tf_zip):
@@ -171,7 +187,9 @@
                  for i in input_tf_zip.infolist()
                  if i.filename.endswith('.apk')])
   rebuild_recovery = False
+  system_root_image = misc_info.get("system_root_image") == "true"
 
+  # tmpdir will only be used to regenerate the recovery-from-boot patch.
   tmpdir = tempfile.mkdtemp()
   def write_to_temp(fn, attr, data):
     fn = os.path.join(tmpdir, fn)
@@ -196,25 +214,6 @@
     data = input_tf_zip.read(info.filename)
     out_info = copy.copy(info)
 
-    # Replace keys if requested.
-    if (info.filename == "META/misc_info.txt" and
-        OPTIONS.replace_verity_private_key):
-      ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info,
-                              OPTIONS.replace_verity_private_key[1])
-    elif (info.filename in ("BOOT/RAMDISK/verity_key",
-                            "BOOT/verity_key") and
-          OPTIONS.replace_verity_public_key):
-      new_data = ReplaceVerityPublicKey(output_tf_zip, info.filename,
-                                        OPTIONS.replace_verity_public_key[1])
-      write_to_temp(info.filename, info.external_attr, new_data)
-    # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch.
-    elif (info.filename.startswith("BOOT/") or
-          info.filename.startswith("RECOVERY/") or
-          info.filename.startswith("META/") or
-          info.filename.startswith("ROOT/") or
-          info.filename == "SYSTEM/etc/recovery-resource.dat"):
-      write_to_temp(info.filename, info.external_attr, data)
-
     # Sign APKs.
     if info.filename.endswith(".apk"):
       name = os.path.basename(info.filename)
@@ -228,44 +227,113 @@
         # an APK we're not supposed to sign.
         print "NOT signing: %s" % (name,)
         common.ZipWriteStr(output_tf_zip, out_info, data)
+
+    # System properties.
     elif info.filename in ("SYSTEM/build.prop",
                            "VENDOR/build.prop",
                            "BOOT/RAMDISK/default.prop",
+                           "ROOT/default.prop",
                            "RECOVERY/RAMDISK/default.prop"):
       print "rewriting %s:" % (info.filename,)
       new_data = RewriteProps(data, misc_info)
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
       if info.filename in ("BOOT/RAMDISK/default.prop",
+                           "ROOT/default.prop",
                            "RECOVERY/RAMDISK/default.prop"):
         write_to_temp(info.filename, info.external_attr, new_data)
+
     elif info.filename.endswith("mac_permissions.xml"):
       print "rewriting %s with new keys." % (info.filename,)
       new_data = ReplaceCerts(data)
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
+
+    # Trigger a rebuild of the recovery patch if needed.
     elif info.filename in ("SYSTEM/recovery-from-boot.p",
                            "SYSTEM/etc/recovery.img",
                            "SYSTEM/bin/install-recovery.sh"):
       rebuild_recovery = True
+
+    # Don't copy OTA keys if we're replacing them.
     elif (OPTIONS.replace_ota_keys and
-          info.filename in ("RECOVERY/RAMDISK/res/keys",
-                            "SYSTEM/etc/security/otacerts.zip")):
-      # don't copy these files if we're regenerating them below
+          info.filename in (
+              "BOOT/RAMDISK/res/keys",
+              "BOOT/RAMDISK/etc/update_engine/update-payload-key.pub.pem",
+              "RECOVERY/RAMDISK/res/keys",
+              "SYSTEM/etc/security/otacerts.zip",
+              "SYSTEM/etc/update_engine/update-payload-key.pub.pem")):
       pass
+
+    # Skip META/misc_info.txt if we will replace the verity private key later.
     elif (OPTIONS.replace_verity_private_key and
           info.filename == "META/misc_info.txt"):
       pass
+
+    # Skip verity public key if we will replace it.
     elif (OPTIONS.replace_verity_public_key and
           info.filename in ("BOOT/RAMDISK/verity_key",
-                            "BOOT/verity_key")):
+                            "ROOT/verity_key")):
       pass
+
+    # Skip verity keyid (for system_root_image use) if we will replace it.
+    elif (OPTIONS.replace_verity_keyid and
+          info.filename == "BOOT/cmdline"):
+      pass
+
+    # Skip the care_map as we will regenerate the system/vendor images.
+    elif info.filename == "META/care_map.txt":
+      pass
+
+    # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch. This case
+    # must come AFTER other matching rules.
+    elif (info.filename.startswith("BOOT/") or
+          info.filename.startswith("RECOVERY/") or
+          info.filename.startswith("META/") or
+          info.filename.startswith("ROOT/") or
+          info.filename == "SYSTEM/etc/recovery-resource.dat"):
+      write_to_temp(info.filename, info.external_attr, data)
+      common.ZipWriteStr(output_tf_zip, out_info, data)
+
+    # A non-APK file; copy it verbatim.
     else:
-      # a non-APK file; copy it verbatim
       common.ZipWriteStr(output_tf_zip, out_info, data)
 
   if OPTIONS.replace_ota_keys:
     new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info)
     if new_recovery_keys:
-      write_to_temp("RECOVERY/RAMDISK/res/keys", 0o755 << 16, new_recovery_keys)
+      if system_root_image:
+        recovery_keys_location = "BOOT/RAMDISK/res/keys"
+      else:
+        recovery_keys_location = "RECOVERY/RAMDISK/res/keys"
+      # The "new_recovery_keys" has been already written into the output_tf_zip
+      # while calling ReplaceOtaKeys(). We're just putting the same copy to
+      # tmpdir in case we need to regenerate the recovery-from-boot patch.
+      write_to_temp(recovery_keys_location, 0o755 << 16, new_recovery_keys)
+
+  # Replace the keyid string in META/misc_info.txt.
+  if OPTIONS.replace_verity_private_key:
+    ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info,
+                            OPTIONS.replace_verity_private_key[1])
+
+  if OPTIONS.replace_verity_public_key:
+    if system_root_image:
+      dest = "ROOT/verity_key"
+    else:
+      dest = "BOOT/RAMDISK/verity_key"
+    # We are replacing the one in boot image only, since the one under
+    # recovery won't ever be needed.
+    new_data = ReplaceVerityPublicKey(
+        output_tf_zip, dest, OPTIONS.replace_verity_public_key[1])
+    write_to_temp(dest, 0o755 << 16, new_data)
+
+  # Replace the keyid string in BOOT/cmdline.
+  if OPTIONS.replace_verity_keyid:
+    new_cmdline = ReplaceVerityKeyId(input_tf_zip, output_tf_zip,
+      OPTIONS.replace_verity_keyid[1])
+    # Writing the new cmdline to tmpdir is redundant as the bootimage
+    # gets build in the add_image_to_target_files and rebuild_recovery
+    # is not exercised while building the boot image for the A/B
+    # path
+    write_to_temp("BOOT/cmdline", 0o755 << 16, new_cmdline)
 
   if rebuild_recovery:
     recovery_img = common.GetBootableImage(
@@ -398,7 +466,8 @@
                            "build/target/product/security/testkey")
     mapped_keys.append(
         OPTIONS.key_map.get(devkey, devkey) + ".x509.pem")
-    print "META/otakeys.txt has no keys; using", mapped_keys[0]
+    print("META/otakeys.txt has no keys; using %s for OTA package"
+          " verification." % (mapped_keys[0],))
 
   # recovery uses a version of the key that has been slightly
   # predigested (by DumpPublicKey.java) and put in res/keys.
@@ -411,8 +480,13 @@
   new_recovery_keys, _ = p.communicate()
   if p.returncode != 0:
     raise common.ExternalError("failed to run dumpkeys")
-  common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys",
-                     new_recovery_keys)
+
+  # system_root_image puts the recovery keys at BOOT/RAMDISK.
+  if misc_info.get("system_root_image") == "true":
+    recovery_keys_location = "BOOT/RAMDISK/res/keys"
+  else:
+    recovery_keys_location = "RECOVERY/RAMDISK/res/keys"
+  common.ZipWriteStr(output_tf_zip, recovery_keys_location, new_recovery_keys)
 
   # SystemUpdateActivity uses the x509.pem version of the keys, but
   # put into a zipfile system/etc/security/otacerts.zip.
@@ -426,8 +500,31 @@
   common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip",
                      temp_file.getvalue())
 
+  # 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],)
+    cmd = common.Run(
+        ["openssl", "x509", "-pubkey", "-noout", "-in", mapped_keys[0]],
+        stdout=subprocess.PIPE)
+    pubkey, _ = cmd.communicate()
+    common.ZipWriteStr(
+        output_tf_zip,
+        "SYSTEM/etc/update_engine/update-payload-key.pub.pem",
+        pubkey)
+    common.ZipWriteStr(
+        output_tf_zip,
+        "BOOT/RAMDISK/etc/update_engine/update-payload-key.pub.pem",
+        pubkey)
+
   return new_recovery_keys
 
+
 def ReplaceVerityPublicKey(targetfile_zip, filename, key_path):
   print "Replacing verity public key with %s" % key_path
   with open(key_path) as f:
@@ -435,6 +532,7 @@
   common.ZipWriteStr(targetfile_zip, filename, data)
   return data
 
+
 def ReplaceVerityPrivateKey(targetfile_input_zip, targetfile_output_zip,
                             misc_info, key_path):
   print "Replacing verity private key with %s" % key_path
@@ -444,6 +542,35 @@
   common.ZipWriteStr(targetfile_output_zip, "META/misc_info.txt", new_misc_info)
   misc_info["verity_key"] = key_path
 
+
+def ReplaceVerityKeyId(targetfile_input_zip, targetfile_output_zip, keypath):
+  in_cmdline = targetfile_input_zip.read("BOOT/cmdline")
+  # copy in_cmdline to output_zip if veritykeyid is not present in in_cmdline
+  if "veritykeyid" not in in_cmdline:
+    common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", in_cmdline)
+    return in_cmdline
+  out_cmdline = []
+  for param in in_cmdline.split():
+    if "veritykeyid" in param:
+      # extract keyid using openssl command
+      p = common.Run(
+          ["openssl", "x509", "-in", keypath, "-text"],
+          stdout=subprocess.PIPE)
+      keyid, stderr = p.communicate()
+      keyid = re.search(
+          r'keyid:([0-9a-fA-F:]*)', keyid).group(1).replace(':', '').lower()
+      print "Replacing verity keyid with %s error=%s" % (keyid, stderr)
+      out_cmdline.append("veritykeyid=id:%s" % (keyid,))
+    else:
+      out_cmdline.append(param)
+
+  out_cmdline = ' '.join(out_cmdline)
+  out_cmdline = out_cmdline.strip()
+  print "out_cmdline %s" % (out_cmdline)
+  common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", out_cmdline)
+  return out_cmdline
+
+
 def BuildKeyMap(misc_info, key_mapping_options):
   for s, d in key_mapping_options:
     if s is None:   # -d option
@@ -468,7 +595,6 @@
   codename = None
   for line in data.split("\n"):
     line = line.strip()
-    original_line = line
     if line and line[0] != '#' and "=" in line:
       key, value = line.split("=", 1)
       key = key.strip()
@@ -491,7 +617,6 @@
   codenames = None
   for line in data.split("\n"):
     line = line.strip()
-    original_line = line
     if line and line[0] != '#' and "=" in line:
       key, value = line.split("=", 1)
       key = key.strip()
@@ -541,6 +666,8 @@
       OPTIONS.replace_verity_public_key = (True, a)
     elif o == "--replace_verity_private_key":
       OPTIONS.replace_verity_private_key = (True, a)
+    elif o == "--replace_verity_keyid":
+      OPTIONS.replace_verity_keyid = (True, a)
     else:
       return False
     return True
@@ -553,7 +680,8 @@
                                               "replace_ota_keys",
                                               "tag_changes=",
                                               "replace_verity_public_key=",
-                                              "replace_verity_private_key="],
+                                              "replace_verity_private_key=",
+                                              "replace_verity_keyid="],
                              extra_option_handler=option_handler)
 
   if len(args) != 2:
@@ -571,12 +699,8 @@
   CheckAllApksSigned(input_zip, apk_key_map)
 
   key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
-  platform_api_level, platform_codename = GetApiLevelAndCodename(input_zip)
+  platform_api_level, _ = GetApiLevelAndCodename(input_zip)
   codename_to_api_level_map = GetCodenameToApiLevelMap(input_zip)
-  # Android N will be API Level 24, but isn't yet.
-  # TODO: Remove this workaround once Android N is officially API Level 24.
-  if platform_api_level == 23 and platform_codename == "N":
-    platform_api_level = 24
 
   ProcessTargetFiles(input_zip, output_zip, misc_info,
                      apk_key_map, key_passwords,
@@ -586,7 +710,9 @@
   common.ZipClose(input_zip)
   common.ZipClose(output_zip)
 
-  add_img_to_target_files.AddImagesToTargetFiles(args[1])
+  # Skip building userdata.img and cache.img when signing the target files.
+  new_args = ["--is_signing", args[1]]
+  add_img_to_target_files.main(new_args)
 
   print "done."
 
diff --git a/tools/releasetools/target_files_diff.py b/tools/releasetools/target_files_diff.py
index 0f717e0..7415f27 100755
--- a/tools/releasetools/target_files_diff.py
+++ b/tools/releasetools/target_files_diff.py
@@ -51,10 +51,6 @@
               'RECOVERY/RAMDISK/selinux_version']:
     return True
 
-  # b/26956807 .odex files are not deterministic
-  if name.endswith('.odex'):
-    return True
-
   return False
 
 
diff --git a/tools/releasetools/test_rangelib.py b/tools/releasetools/test_rangelib.py
index a61a64e..e181187 100644
--- a/tools/releasetools/test_rangelib.py
+++ b/tools/releasetools/test_rangelib.py
@@ -124,3 +124,28 @@
     self.assertTrue(RangeSet(data=[2, 9, 30, 31, 31, 32, 35, 36]).monotonic)
     self.assertTrue(RangeSet(data=[0, 5, 5, 10]).monotonic)
     self.assertFalse(RangeSet(data=[5, 10, 0, 5]).monotonic)
+
+  def test_parse_raw(self):
+    self.assertEqual(
+        RangeSet.parse_raw(RangeSet("0-9").to_string_raw()),
+        RangeSet("0-9"))
+    self.assertEqual(RangeSet.parse_raw(
+        RangeSet("2-10 12").to_string_raw()),
+        RangeSet("2-10 12"))
+    self.assertEqual(
+        RangeSet.parse_raw(RangeSet("11 2-10 12 1 0").to_string_raw()),
+        RangeSet("11 2-10 12 1 0"))
+
+    with self.assertRaises(AssertionError):
+      RangeSet.parse_raw("4,0,10")
+
+  def test_next_item(self):
+    self.assertEqual(
+        list(RangeSet("0-9").next_item()),
+        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+    self.assertEqual(
+        list(RangeSet("10-19 3-5").next_item()),
+        [3, 4, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
+    self.assertEqual(
+        list(RangeSet("10-19 3 5 7").next_item()),
+        [3, 5, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
diff --git a/tools/rgb2565/Android.mk b/tools/rgb2565/Android.mk
deleted file mode 100644
index 189584d..0000000
--- a/tools/rgb2565/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2008 The Android Open Source Project
-#
-# Android.mk for rgb2565
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-# rgb2565 host tool
-# =========================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := to565.c
-
-LOCAL_CFLAGS += -O2 -Wall -Wno-unused-parameter
-LOCAL_MODULE := rgb2565
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/rgb2565/to565.c b/tools/rgb2565/to565.c
deleted file mode 100644
index abf9cdb..0000000
--- a/tools/rgb2565/to565.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2008 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#define to565(r,g,b)                                            \
-    ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
-
-#define from565_r(x) ((((x) >> 11) & 0x1f) * 255 / 31)
-#define from565_g(x) ((((x) >> 5) & 0x3f) * 255 / 63)
-#define from565_b(x) (((x) & 0x1f) * 255 / 31)
-
-void to_565_raw(void)
-{
-    unsigned char in[3];
-    unsigned short out;
-
-    while(read(0, in, 3) == 3) {
-        out = to565(in[0],in[1],in[2]);
-        write(1, &out, 2);
-    }
-    return;
-}
-
-void to_565_raw_dither(int width)
-{
-    unsigned char in[3];
-    unsigned short out;
-    int i = 0;
-    int e;
-
-    int* error = malloc((width+2) * 3 * sizeof(int));
-    int* next_error = malloc((width+2) * 3 * sizeof(int));
-    memset(error, 0, (width+2) * 3 * sizeof(int));
-    memset(next_error, 0, (width+2) * 3 * sizeof(int));
-    error += 3;        // array goes from [-3..((width+1)*3+2)]
-    next_error += 3;
-
-    while(read(0, in, 3) == 3) {
-        int r = in[0] + error[i*3+0];
-        int rb = (r < 0) ? 0 : ((r > 255) ? 255 : r);
-
-        int g = in[1] + error[i*3+1];
-        int gb = (g < 0) ? 0 : ((g > 255) ? 255 : g);
-
-        int b = in[2] + error[i*3+2];
-        int bb = (b < 0) ? 0 : ((b > 255) ? 255 : b);
-
-        out = to565(rb, gb, bb);
-        write(1, &out, 2);
-
-#define apply_error(ch) {                                               \
-            next_error[(i-1)*3+ch] += e * 3 / 16;                       \
-            next_error[(i)*3+ch] += e * 5 / 16;                         \
-            next_error[(i+1)*3+ch] += e * 1 / 16;                       \
-            error[(i+1)*3+ch] += e - ((e*1/16) + (e*3/16) + (e*5/16));  \
-        }
-
-        e = r - from565_r(out);
-        apply_error(0);
-
-        e = g - from565_g(out);
-        apply_error(1);
-
-        e = b - from565_b(out);
-        apply_error(2);
-
-#undef apply_error
-
-        ++i;
-        if (i == width) {
-            // error <- next_error; next_error <- 0
-            int* temp = error; error = next_error; next_error = temp;
-            memset(next_error, 0, (width+1) * 3 * sizeof(int));
-            i = 0;
-        }
-    }
-
-    free(error-3);
-    free(next_error-3);
-
-    return;
-}
-
-void to_565_rle(void)
-{
-    unsigned char in[3];
-    unsigned short last, color, count;
-    unsigned total = 0;
-    count = 0;
-
-    while(read(0, in, 3) == 3) {
-        color = to565(in[0],in[1],in[2]);
-        if (count) {
-            if ((color == last) && (count != 65535)) {
-                count++;
-                continue;
-            } else {
-                write(1, &count, 2);
-                write(1, &last, 2);
-                total += count;
-            }
-        }
-        last = color;
-        count = 1;
-    }
-    if (count) {
-        write(1, &count, 2);
-        write(1, &last, 2);
-        total += count;
-    }
-    fprintf(stderr,"%d pixels\n",total);
-}
-
-int main(int argc, char **argv)
-{
-    if ((argc == 2) && (!strcmp(argv[1],"-rle"))) {
-        to_565_rle();
-    } else {
-        if (argc > 2 && (!strcmp(argv[1], "-w"))) {
-            to_565_raw_dither(atoi(argv[2]));
-        } else {
-            to_565_raw();
-        }
-    }
-    return 0;
-}
diff --git a/tools/signapk/Android.mk b/tools/signapk/Android.mk
index ac217c7..4506e2f 100644
--- a/tools/signapk/Android.mk
+++ b/tools/signapk/Android.mk
@@ -21,7 +21,11 @@
 LOCAL_MODULE := signapk
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_JAR_MANIFEST := SignApk.mf
-LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host bouncycastle-bcpkix-host conscrypt-host
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    apksig \
+    bouncycastle-host \
+    bouncycastle-bcpkix-host \
+    conscrypt-host
 LOCAL_REQUIRED_MODULES := libconscrypt_openjdk_jni
 include $(BUILD_HOST_JAVA_LIBRARY)
 
diff --git a/tools/signapk/src/com/android/signapk/ApkSignerV2.java b/tools/signapk/src/com/android/signapk/ApkSignerV2.java
deleted file mode 100644
index 46cd11e..0000000
--- a/tools/signapk/src/com/android/signapk/ApkSignerV2.java
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.signapk;
-
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.security.DigestException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.MGF1ParameterSpec;
-import java.security.spec.PSSParameterSpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * APK Signature Scheme v2 signer.
- *
- * <p>APK Signature Scheme v2 is a whole-file signature scheme which aims to protect every single
- * bit of the APK, as opposed to the JAR Signature Scheme which protects only the names and
- * uncompressed contents of ZIP entries.
- */
-public abstract class ApkSignerV2 {
-    /*
-     * The two main goals of APK Signature Scheme v2 are:
-     * 1. Detect any unauthorized modifications to the APK. This is achieved by making the signature
-     *    cover every byte of the APK being signed.
-     * 2. Enable much faster signature and integrity verification. This is achieved by requiring
-     *    only a minimal amount of APK parsing before the signature is verified, thus completely
-     *    bypassing ZIP entry decompression and by making integrity verification parallelizable by
-     *    employing a hash tree.
-     *
-     * The generated signature block is wrapped into an APK Signing Block and inserted into the
-     * original APK immediately before the start of ZIP Central Directory. This is to ensure that
-     * JAR and ZIP parsers continue to work on the signed APK. The APK Signing Block is designed for
-     * extensibility. For example, a future signature scheme could insert its signatures there as
-     * well. The contract of the APK Signing Block is that all contents outside of the block must be
-     * protected by signatures inside the block.
-     */
-
-    public static final int SIGNATURE_RSA_PSS_WITH_SHA256 = 0x0101;
-    public static final int SIGNATURE_RSA_PSS_WITH_SHA512 = 0x0102;
-    public static final int SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256 = 0x0103;
-    public static final int SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512 = 0x0104;
-    public static final int SIGNATURE_ECDSA_WITH_SHA256 = 0x0201;
-    public static final int SIGNATURE_ECDSA_WITH_SHA512 = 0x0202;
-    public static final int SIGNATURE_DSA_WITH_SHA256 = 0x0301;
-    public static final int SIGNATURE_DSA_WITH_SHA512 = 0x0302;
-
-    /**
-     * {@code .SF} file header section attribute indicating that the APK is signed not just with
-     * JAR signature scheme but also with APK Signature Scheme v2 or newer. This attribute
-     * facilitates v2 signature stripping detection.
-     *
-     * <p>The attribute contains a comma-separated set of signature scheme IDs.
-     */
-    public static final String SF_ATTRIBUTE_ANDROID_APK_SIGNED_NAME = "X-Android-APK-Signed";
-    public static final String SF_ATTRIBUTE_ANDROID_APK_SIGNED_VALUE = "2";
-
-    private static final int CONTENT_DIGEST_CHUNKED_SHA256 = 0;
-    private static final int CONTENT_DIGEST_CHUNKED_SHA512 = 1;
-
-    private static final int CONTENT_DIGESTED_CHUNK_MAX_SIZE_BYTES = 1024 * 1024;
-
-    private static final byte[] APK_SIGNING_BLOCK_MAGIC =
-          new byte[] {
-              0x41, 0x50, 0x4b, 0x20, 0x53, 0x69, 0x67, 0x20,
-              0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x34, 0x32,
-          };
-    private static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a;
-
-    private ApkSignerV2() {}
-
-    /**
-     * Signer configuration.
-     */
-    public static final class SignerConfig {
-        /** Private key. */
-        public PrivateKey privateKey;
-
-        /**
-         * Certificates, with the first certificate containing the public key corresponding to
-         * {@link #privateKey}.
-         */
-        public List<X509Certificate> certificates;
-
-        /**
-         * List of signature algorithms with which to sign (see {@code SIGNATURE_...} constants).
-         */
-        public List<Integer> signatureAlgorithms;
-    }
-
-    /**
-     * Signs the provided APK using APK Signature Scheme v2 and returns the signed APK as a list of
-     * consecutive chunks.
-     *
-     * <p>NOTE: To enable APK signature verifier to detect v2 signature stripping, header sections
-     * of META-INF/*.SF files of APK being signed must contain the
-     * {@code X-Android-APK-Signed: true} attribute.
-     *
-     * @param inputApk contents of the APK to be signed. The APK starts at the current position
-     *        of the buffer and ends at the limit of the buffer.
-     * @param signerConfigs signer configurations, one for each signer.
-     *
-     * @throws ApkParseException if the APK cannot be parsed.
-     * @throws InvalidKeyException if a signing key is not suitable for this signature scheme or
-     *         cannot be used in general.
-     * @throws SignatureException if an error occurs when computing digests of generating
-     *         signatures.
-     */
-    public static ByteBuffer[] sign(
-            ByteBuffer inputApk,
-            List<SignerConfig> signerConfigs)
-                    throws ApkParseException, InvalidKeyException, SignatureException {
-        // Slice/create a view in the inputApk to make sure that:
-        // 1. inputApk is what's between position and limit of the original inputApk, and
-        // 2. changes to position, limit, and byte order are not reflected in the original.
-        ByteBuffer originalInputApk = inputApk;
-        inputApk = originalInputApk.slice();
-        inputApk.order(ByteOrder.LITTLE_ENDIAN);
-
-        // Locate ZIP End of Central Directory (EoCD), Central Directory, and check that Central
-        // Directory is immediately followed by the ZIP End of Central Directory.
-        int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(inputApk);
-        if (eocdOffset == -1) {
-            throw new ApkParseException("Failed to locate ZIP End of Central Directory");
-        }
-        if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(inputApk, eocdOffset)) {
-            throw new ApkParseException("ZIP64 format not supported");
-        }
-        inputApk.position(eocdOffset);
-        long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(inputApk);
-        if (centralDirSizeLong > Integer.MAX_VALUE) {
-            throw new ApkParseException(
-                    "ZIP Central Directory size out of range: " + centralDirSizeLong);
-        }
-        int centralDirSize = (int) centralDirSizeLong;
-        long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(inputApk);
-        if (centralDirOffsetLong > Integer.MAX_VALUE) {
-            throw new ApkParseException(
-                    "ZIP Central Directory offset in file out of range: " + centralDirOffsetLong);
-        }
-        int centralDirOffset = (int) centralDirOffsetLong;
-        int expectedEocdOffset = centralDirOffset + centralDirSize;
-        if (expectedEocdOffset < centralDirOffset) {
-            throw new ApkParseException(
-                    "ZIP Central Directory extent too large. Offset: " + centralDirOffset
-                            + ", size: " + centralDirSize);
-        }
-        if (eocdOffset != expectedEocdOffset) {
-            throw new ApkParseException(
-                    "ZIP Central Directory not immeiately followed by ZIP End of"
-                            + " Central Directory. CD end: " + expectedEocdOffset
-                            + ", EoCD start: " + eocdOffset);
-        }
-
-        // Create ByteBuffers holding the contents of everything before ZIP Central Directory,
-        // ZIP Central Directory, and ZIP End of Central Directory.
-        inputApk.clear();
-        ByteBuffer beforeCentralDir = getByteBuffer(inputApk, centralDirOffset);
-        ByteBuffer centralDir = getByteBuffer(inputApk, eocdOffset - centralDirOffset);
-        // Create a copy of End of Central Directory because we'll need modify its contents later.
-        byte[] eocdBytes = new byte[inputApk.remaining()];
-        inputApk.get(eocdBytes);
-        ByteBuffer eocd = ByteBuffer.wrap(eocdBytes);
-        eocd.order(inputApk.order());
-
-        // Figure which which digests to use for APK contents.
-        Set<Integer> contentDigestAlgorithms = new HashSet<>();
-        for (SignerConfig signerConfig : signerConfigs) {
-            for (int signatureAlgorithm : signerConfig.signatureAlgorithms) {
-                contentDigestAlgorithms.add(
-                        getSignatureAlgorithmContentDigestAlgorithm(signatureAlgorithm));
-            }
-        }
-
-        // Compute digests of APK contents.
-        Map<Integer, byte[]> contentDigests; // digest algorithm ID -> digest
-        try {
-            contentDigests =
-                    computeContentDigests(
-                            contentDigestAlgorithms,
-                            new ByteBuffer[] {beforeCentralDir, centralDir, eocd});
-        } catch (DigestException e) {
-            throw new SignatureException("Failed to compute digests of APK", e);
-        }
-
-        // Sign the digests and wrap the signatures and signer info into an APK Signing Block.
-        ByteBuffer apkSigningBlock =
-                ByteBuffer.wrap(generateApkSigningBlock(signerConfigs, contentDigests));
-
-        // Update Central Directory Offset in End of Central Directory Record. Central Directory
-        // follows the APK Signing Block and thus is shifted by the size of the APK Signing Block.
-        centralDirOffset += apkSigningBlock.remaining();
-        eocd.clear();
-        ZipUtils.setZipEocdCentralDirectoryOffset(eocd, centralDirOffset);
-
-        // Follow the Java NIO pattern for ByteBuffer whose contents have been consumed.
-        originalInputApk.position(originalInputApk.limit());
-
-        // Reset positions (to 0) and limits (to capacity) in the ByteBuffers below to follow the
-        // Java NIO pattern for ByteBuffers which are ready for their contents to be read by caller.
-        // Contrary to the name, this does not clear the contents of these ByteBuffer.
-        beforeCentralDir.clear();
-        centralDir.clear();
-        eocd.clear();
-
-        // Insert APK Signing Block immediately before the ZIP Central Directory.
-        return new ByteBuffer[] {
-            beforeCentralDir,
-            apkSigningBlock,
-            centralDir,
-            eocd,
-        };
-    }
-
-    private static Map<Integer, byte[]> computeContentDigests(
-            Set<Integer> digestAlgorithms,
-            ByteBuffer[] contents) throws DigestException {
-        // For each digest algorithm the result is computed as follows:
-        // 1. Each segment of contents is split into consecutive chunks of 1 MB in size.
-        //    The final chunk will be shorter iff the length of segment is not a multiple of 1 MB.
-        //    No chunks are produced for empty (zero length) segments.
-        // 2. The digest of each chunk is computed over the concatenation of byte 0xa5, the chunk's
-        //    length in bytes (uint32 little-endian) and the chunk's contents.
-        // 3. The output digest is computed over the concatenation of the byte 0x5a, the number of
-        //    chunks (uint32 little-endian) and the concatenation of digests of chunks of all
-        //    segments in-order.
-
-        int chunkCount = 0;
-        for (ByteBuffer input : contents) {
-            chunkCount += getChunkCount(input.remaining(), CONTENT_DIGESTED_CHUNK_MAX_SIZE_BYTES);
-        }
-
-        final Map<Integer, byte[]> digestsOfChunks = new HashMap<>(digestAlgorithms.size());
-        for (int digestAlgorithm : digestAlgorithms) {
-            int digestOutputSizeBytes = getContentDigestAlgorithmOutputSizeBytes(digestAlgorithm);
-            byte[] concatenationOfChunkCountAndChunkDigests =
-                    new byte[5 + chunkCount * digestOutputSizeBytes];
-            concatenationOfChunkCountAndChunkDigests[0] = 0x5a;
-            setUnsignedInt32LittleEngian(
-                    chunkCount, concatenationOfChunkCountAndChunkDigests, 1);
-            digestsOfChunks.put(digestAlgorithm, concatenationOfChunkCountAndChunkDigests);
-        }
-
-        int chunkIndex = 0;
-        byte[] chunkContentPrefix = new byte[5];
-        chunkContentPrefix[0] = (byte) 0xa5;
-        // Optimization opportunity: digests of chunks can be computed in parallel.
-        for (ByteBuffer input : contents) {
-            while (input.hasRemaining()) {
-                int chunkSize =
-                        Math.min(input.remaining(), CONTENT_DIGESTED_CHUNK_MAX_SIZE_BYTES);
-                final ByteBuffer chunk = getByteBuffer(input, chunkSize);
-                for (int digestAlgorithm : digestAlgorithms) {
-                    String jcaAlgorithmName =
-                            getContentDigestAlgorithmJcaDigestAlgorithm(digestAlgorithm);
-                    MessageDigest md;
-                    try {
-                        md = MessageDigest.getInstance(jcaAlgorithmName);
-                    } catch (NoSuchAlgorithmException e) {
-                        throw new DigestException(
-                                jcaAlgorithmName + " MessageDigest not supported", e);
-                    }
-                    // Reset position to 0 and limit to capacity. Position would've been modified
-                    // by the preceding iteration of this loop. NOTE: Contrary to the method name,
-                    // this does not modify the contents of the chunk.
-                    chunk.clear();
-                    setUnsignedInt32LittleEngian(chunk.remaining(), chunkContentPrefix, 1);
-                    md.update(chunkContentPrefix);
-                    md.update(chunk);
-                    byte[] concatenationOfChunkCountAndChunkDigests =
-                            digestsOfChunks.get(digestAlgorithm);
-                    int expectedDigestSizeBytes =
-                            getContentDigestAlgorithmOutputSizeBytes(digestAlgorithm);
-                    int actualDigestSizeBytes =
-                            md.digest(
-                                    concatenationOfChunkCountAndChunkDigests,
-                                    5 + chunkIndex * expectedDigestSizeBytes,
-                                    expectedDigestSizeBytes);
-                    if (actualDigestSizeBytes != expectedDigestSizeBytes) {
-                        throw new DigestException(
-                                "Unexpected output size of " + md.getAlgorithm()
-                                        + " digest: " + actualDigestSizeBytes);
-                    }
-                }
-                chunkIndex++;
-            }
-        }
-
-        Map<Integer, byte[]> result = new HashMap<>(digestAlgorithms.size());
-        for (Map.Entry<Integer, byte[]> entry : digestsOfChunks.entrySet()) {
-            int digestAlgorithm = entry.getKey();
-            byte[] concatenationOfChunkCountAndChunkDigests = entry.getValue();
-            String jcaAlgorithmName = getContentDigestAlgorithmJcaDigestAlgorithm(digestAlgorithm);
-            MessageDigest md;
-            try {
-                md = MessageDigest.getInstance(jcaAlgorithmName);
-            } catch (NoSuchAlgorithmException e) {
-                throw new DigestException(jcaAlgorithmName + " MessageDigest not supported", e);
-            }
-            result.put(digestAlgorithm, md.digest(concatenationOfChunkCountAndChunkDigests));
-        }
-        return result;
-    }
-
-    private static final int getChunkCount(int inputSize, int chunkSize) {
-        return (inputSize + chunkSize - 1) / chunkSize;
-    }
-
-    private static void setUnsignedInt32LittleEngian(int value, byte[] result, int offset) {
-        result[offset] = (byte) (value & 0xff);
-        result[offset + 1] = (byte) ((value >> 8) & 0xff);
-        result[offset + 2] = (byte) ((value >> 16) & 0xff);
-        result[offset + 3] = (byte) ((value >> 24) & 0xff);
-    }
-
-    private static byte[] generateApkSigningBlock(
-            List<SignerConfig> signerConfigs,
-            Map<Integer, byte[]> contentDigests) throws InvalidKeyException, SignatureException {
-        byte[] apkSignatureSchemeV2Block =
-                generateApkSignatureSchemeV2Block(signerConfigs, contentDigests);
-        return generateApkSigningBlock(apkSignatureSchemeV2Block);
-    }
-
-    private static byte[] generateApkSigningBlock(byte[] apkSignatureSchemeV2Block) {
-        // FORMAT:
-        // uint64:  size (excluding this field)
-        // repeated ID-value pairs:
-        //     uint64:           size (excluding this field)
-        //     uint32:           ID
-        //     (size - 4) bytes: value
-        // uint64:  size (same as the one above)
-        // uint128: magic
-
-        int resultSize =
-                8 // size
-                + 8 + 4 + apkSignatureSchemeV2Block.length // v2Block as ID-value pair
-                + 8 // size
-                + 16 // magic
-                ;
-        ByteBuffer result = ByteBuffer.allocate(resultSize);
-        result.order(ByteOrder.LITTLE_ENDIAN);
-        long blockSizeFieldValue = resultSize - 8;
-        result.putLong(blockSizeFieldValue);
-
-        long pairSizeFieldValue = 4 + apkSignatureSchemeV2Block.length;
-        result.putLong(pairSizeFieldValue);
-        result.putInt(APK_SIGNATURE_SCHEME_V2_BLOCK_ID);
-        result.put(apkSignatureSchemeV2Block);
-
-        result.putLong(blockSizeFieldValue);
-        result.put(APK_SIGNING_BLOCK_MAGIC);
-
-        return result.array();
-    }
-
-    private static byte[] generateApkSignatureSchemeV2Block(
-            List<SignerConfig> signerConfigs,
-            Map<Integer, byte[]> contentDigests) throws InvalidKeyException, SignatureException {
-        // FORMAT:
-        // * length-prefixed sequence of length-prefixed signer blocks.
-
-        List<byte[]> signerBlocks = new ArrayList<>(signerConfigs.size());
-        int signerNumber = 0;
-        for (SignerConfig signerConfig : signerConfigs) {
-            signerNumber++;
-            byte[] signerBlock;
-            try {
-                signerBlock = generateSignerBlock(signerConfig, contentDigests);
-            } catch (InvalidKeyException e) {
-                throw new InvalidKeyException("Signer #" + signerNumber + " failed", e);
-            } catch (SignatureException e) {
-                throw new SignatureException("Signer #" + signerNumber + " failed", e);
-            }
-            signerBlocks.add(signerBlock);
-        }
-
-        return encodeAsSequenceOfLengthPrefixedElements(
-                new byte[][] {
-                    encodeAsSequenceOfLengthPrefixedElements(signerBlocks),
-                });
-    }
-
-    private static byte[] generateSignerBlock(
-            SignerConfig signerConfig,
-            Map<Integer, byte[]> contentDigests) throws InvalidKeyException, SignatureException {
-        if (signerConfig.certificates.isEmpty()) {
-            throw new SignatureException("No certificates configured for signer");
-        }
-        PublicKey publicKey = signerConfig.certificates.get(0).getPublicKey();
-
-        byte[] encodedPublicKey = encodePublicKey(publicKey);
-
-        V2SignatureSchemeBlock.SignedData signedData = new V2SignatureSchemeBlock.SignedData();
-        try {
-            signedData.certificates = encodeCertificates(signerConfig.certificates);
-        } catch (CertificateEncodingException e) {
-            throw new SignatureException("Failed to encode certificates", e);
-        }
-
-        List<Pair<Integer, byte[]>> digests =
-                new ArrayList<>(signerConfig.signatureAlgorithms.size());
-        for (int signatureAlgorithm : signerConfig.signatureAlgorithms) {
-            int contentDigestAlgorithm =
-                    getSignatureAlgorithmContentDigestAlgorithm(signatureAlgorithm);
-            byte[] contentDigest = contentDigests.get(contentDigestAlgorithm);
-            if (contentDigest == null) {
-                throw new RuntimeException(
-                        getContentDigestAlgorithmJcaDigestAlgorithm(contentDigestAlgorithm)
-                        + " content digest for "
-                        + getSignatureAlgorithmJcaSignatureAlgorithm(signatureAlgorithm)
-                        + " not computed");
-            }
-            digests.add(Pair.create(signatureAlgorithm, contentDigest));
-        }
-        signedData.digests = digests;
-
-        V2SignatureSchemeBlock.Signer signer = new V2SignatureSchemeBlock.Signer();
-        // FORMAT:
-        // * length-prefixed sequence of length-prefixed digests:
-        //   * uint32: signature algorithm ID
-        //   * length-prefixed bytes: digest of contents
-        // * length-prefixed sequence of certificates:
-        //   * length-prefixed bytes: X.509 certificate (ASN.1 DER encoded).
-        // * length-prefixed sequence of length-prefixed additional attributes:
-        //   * uint32: ID
-        //   * (length - 4) bytes: value
-        signer.signedData = encodeAsSequenceOfLengthPrefixedElements(new byte[][] {
-            encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes(signedData.digests),
-            encodeAsSequenceOfLengthPrefixedElements(signedData.certificates),
-            // additional attributes
-            new byte[0],
-        });
-        signer.publicKey = encodedPublicKey;
-        signer.signatures = new ArrayList<>();
-        for (int signatureAlgorithm : signerConfig.signatureAlgorithms) {
-            Pair<String, ? extends AlgorithmParameterSpec> signatureParams =
-                    getSignatureAlgorithmJcaSignatureAlgorithm(signatureAlgorithm);
-            String jcaSignatureAlgorithm = signatureParams.getFirst();
-            AlgorithmParameterSpec jcaSignatureAlgorithmParams = signatureParams.getSecond();
-            byte[] signatureBytes;
-            try {
-                Signature signature = Signature.getInstance(jcaSignatureAlgorithm);
-                signature.initSign(signerConfig.privateKey);
-                if (jcaSignatureAlgorithmParams != null) {
-                    signature.setParameter(jcaSignatureAlgorithmParams);
-                }
-                signature.update(signer.signedData);
-                signatureBytes = signature.sign();
-            } catch (InvalidKeyException e) {
-                throw new InvalidKeyException("Failed sign using " + jcaSignatureAlgorithm, e);
-            } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
-                    | SignatureException e) {
-                throw new SignatureException("Failed sign using " + jcaSignatureAlgorithm, e);
-            }
-
-            try {
-                Signature signature = Signature.getInstance(jcaSignatureAlgorithm);
-                signature.initVerify(publicKey);
-                if (jcaSignatureAlgorithmParams != null) {
-                    signature.setParameter(jcaSignatureAlgorithmParams);
-                }
-                signature.update(signer.signedData);
-                if (!signature.verify(signatureBytes)) {
-                    throw new SignatureException("Signature did not verify");
-                }
-            } catch (InvalidKeyException e) {
-                throw new InvalidKeyException("Failed to verify generated " + jcaSignatureAlgorithm
-                        + " signature using public key from certificate", e);
-            } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
-                    | SignatureException e) {
-                throw new SignatureException("Failed to verify generated " + jcaSignatureAlgorithm
-                        + " signature using public key from certificate", e);
-            }
-
-            signer.signatures.add(Pair.create(signatureAlgorithm, signatureBytes));
-        }
-
-        // FORMAT:
-        // * length-prefixed signed data
-        // * length-prefixed sequence of length-prefixed signatures:
-        //   * uint32: signature algorithm ID
-        //   * length-prefixed bytes: signature of signed data
-        // * length-prefixed bytes: public key (X.509 SubjectPublicKeyInfo, ASN.1 DER encoded)
-        return encodeAsSequenceOfLengthPrefixedElements(
-                new byte[][] {
-                    signer.signedData,
-                    encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes(
-                            signer.signatures),
-                    signer.publicKey,
-                });
-    }
-
-    private static final class V2SignatureSchemeBlock {
-        private static final class Signer {
-            public byte[] signedData;
-            public List<Pair<Integer, byte[]>> signatures;
-            public byte[] publicKey;
-        }
-
-        private static final class SignedData {
-            public List<Pair<Integer, byte[]>> digests;
-            public List<byte[]> certificates;
-        }
-    }
-
-    private static byte[] encodePublicKey(PublicKey publicKey) throws InvalidKeyException {
-        byte[] encodedPublicKey = null;
-        if ("X.509".equals(publicKey.getFormat())) {
-            encodedPublicKey = publicKey.getEncoded();
-        }
-        if (encodedPublicKey == null) {
-            try {
-                encodedPublicKey =
-                        KeyFactory.getInstance(publicKey.getAlgorithm())
-                                .getKeySpec(publicKey, X509EncodedKeySpec.class)
-                                .getEncoded();
-            } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
-                throw new InvalidKeyException(
-                        "Failed to obtain X.509 encoded form of public key " + publicKey
-                                + " of class " + publicKey.getClass().getName(),
-                        e);
-            }
-        }
-        if ((encodedPublicKey == null) || (encodedPublicKey.length == 0)) {
-            throw new InvalidKeyException(
-                    "Failed to obtain X.509 encoded form of public key " + publicKey
-                            + " of class " + publicKey.getClass().getName());
-        }
-        return encodedPublicKey;
-    }
-
-    public static List<byte[]> encodeCertificates(List<X509Certificate> certificates)
-            throws CertificateEncodingException {
-        List<byte[]> result = new ArrayList<>();
-        for (X509Certificate certificate : certificates) {
-            result.add(certificate.getEncoded());
-        }
-        return result;
-    }
-
-    private static byte[] encodeAsSequenceOfLengthPrefixedElements(List<byte[]> sequence) {
-        return encodeAsSequenceOfLengthPrefixedElements(
-                sequence.toArray(new byte[sequence.size()][]));
-    }
-
-    private static byte[] encodeAsSequenceOfLengthPrefixedElements(byte[][] sequence) {
-        int payloadSize = 0;
-        for (byte[] element : sequence) {
-            payloadSize += 4 + element.length;
-        }
-        ByteBuffer result = ByteBuffer.allocate(payloadSize);
-        result.order(ByteOrder.LITTLE_ENDIAN);
-        for (byte[] element : sequence) {
-            result.putInt(element.length);
-            result.put(element);
-        }
-        return result.array();
-      }
-
-    private static byte[] encodeAsSequenceOfLengthPrefixedPairsOfIntAndLengthPrefixedBytes(
-            List<Pair<Integer, byte[]>> sequence) {
-        int resultSize = 0;
-        for (Pair<Integer, byte[]> element : sequence) {
-            resultSize += 12 + element.getSecond().length;
-        }
-        ByteBuffer result = ByteBuffer.allocate(resultSize);
-        result.order(ByteOrder.LITTLE_ENDIAN);
-        for (Pair<Integer, byte[]> element : sequence) {
-            byte[] second = element.getSecond();
-            result.putInt(8 + second.length);
-            result.putInt(element.getFirst());
-            result.putInt(second.length);
-            result.put(second);
-        }
-        return result.array();
-    }
-
-    /**
-     * Relative <em>get</em> method for reading {@code size} number of bytes from the current
-     * position of this buffer.
-     *
-     * <p>This method reads the next {@code size} bytes at this buffer's current position,
-     * returning them as a {@code ByteBuffer} with start set to 0, limit and capacity set to
-     * {@code size}, byte order set to this buffer's byte order; and then increments the position by
-     * {@code size}.
-     */
-    private static ByteBuffer getByteBuffer(ByteBuffer source, int size) {
-        if (size < 0) {
-            throw new IllegalArgumentException("size: " + size);
-        }
-        int originalLimit = source.limit();
-        int position = source.position();
-        int limit = position + size;
-        if ((limit < position) || (limit > originalLimit)) {
-            throw new BufferUnderflowException();
-        }
-        source.limit(limit);
-        try {
-            ByteBuffer result = source.slice();
-            result.order(source.order());
-            source.position(limit);
-            return result;
-        } finally {
-            source.limit(originalLimit);
-        }
-    }
-
-    private static Pair<String, ? extends AlgorithmParameterSpec>
-            getSignatureAlgorithmJcaSignatureAlgorithm(int sigAlgorithm) {
-        switch (sigAlgorithm) {
-            case SIGNATURE_RSA_PSS_WITH_SHA256:
-                return Pair.create(
-                        "SHA256withRSA/PSS",
-                        new PSSParameterSpec(
-                                "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 256 / 8, 1));
-            case SIGNATURE_RSA_PSS_WITH_SHA512:
-                return Pair.create(
-                        "SHA512withRSA/PSS",
-                        new PSSParameterSpec(
-                                "SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 512 / 8, 1));
-            case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256:
-                return Pair.create("SHA256withRSA", null);
-            case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512:
-                return Pair.create("SHA512withRSA", null);
-            case SIGNATURE_ECDSA_WITH_SHA256:
-                return Pair.create("SHA256withECDSA", null);
-            case SIGNATURE_ECDSA_WITH_SHA512:
-                return Pair.create("SHA512withECDSA", null);
-            case SIGNATURE_DSA_WITH_SHA256:
-                return Pair.create("SHA256withDSA", null);
-            case SIGNATURE_DSA_WITH_SHA512:
-                return Pair.create("SHA512withDSA", null);
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown signature algorithm: 0x"
-                                + Long.toHexString(sigAlgorithm & 0xffffffff));
-        }
-    }
-
-    private static int getSignatureAlgorithmContentDigestAlgorithm(int sigAlgorithm) {
-        switch (sigAlgorithm) {
-            case SIGNATURE_RSA_PSS_WITH_SHA256:
-            case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256:
-            case SIGNATURE_ECDSA_WITH_SHA256:
-            case SIGNATURE_DSA_WITH_SHA256:
-                return CONTENT_DIGEST_CHUNKED_SHA256;
-            case SIGNATURE_RSA_PSS_WITH_SHA512:
-            case SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512:
-            case SIGNATURE_ECDSA_WITH_SHA512:
-            case SIGNATURE_DSA_WITH_SHA512:
-                return CONTENT_DIGEST_CHUNKED_SHA512;
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown signature algorithm: 0x"
-                                + Long.toHexString(sigAlgorithm & 0xffffffff));
-        }
-    }
-
-    private static String getContentDigestAlgorithmJcaDigestAlgorithm(int digestAlgorithm) {
-        switch (digestAlgorithm) {
-            case CONTENT_DIGEST_CHUNKED_SHA256:
-                return "SHA-256";
-            case CONTENT_DIGEST_CHUNKED_SHA512:
-                return "SHA-512";
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown content digest algorthm: " + digestAlgorithm);
-        }
-    }
-
-    private static int getContentDigestAlgorithmOutputSizeBytes(int digestAlgorithm) {
-        switch (digestAlgorithm) {
-            case CONTENT_DIGEST_CHUNKED_SHA256:
-                return 256 / 8;
-            case CONTENT_DIGEST_CHUNKED_SHA512:
-                return 512 / 8;
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown content digest algorthm: " + digestAlgorithm);
-        }
-    }
-
-    /**
-     * Indicates that APK file could not be parsed.
-     */
-    public static class ApkParseException extends Exception {
-        private static final long serialVersionUID = 1L;
-
-        public ApkParseException(String message) {
-            super(message);
-        }
-
-        public ApkParseException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-}
diff --git a/tools/signapk/src/com/android/signapk/Pair.java b/tools/signapk/src/com/android/signapk/Pair.java
deleted file mode 100644
index e4a6c92..0000000
--- a/tools/signapk/src/com/android/signapk/Pair.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.signapk;
-
-/**
- * Pair of two elements.
- */
-public final class Pair<A, B> {
-    private final A mFirst;
-    private final B mSecond;
-
-    private Pair(A first, B second) {
-        mFirst = first;
-        mSecond = second;
-    }
-
-    public static <A, B> Pair<A, B> create(A first, B second) {
-        return new Pair<A, B>(first, second);
-    }
-
-    public A getFirst() {
-        return mFirst;
-    }
-
-    public B getSecond() {
-        return mSecond;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((mFirst == null) ? 0 : mFirst.hashCode());
-        result = prime * result + ((mSecond == null) ? 0 : mSecond.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        @SuppressWarnings("rawtypes")
-        Pair other = (Pair) obj;
-        if (mFirst == null) {
-            if (other.mFirst != null) {
-                return false;
-            }
-        } else if (!mFirst.equals(other.mFirst)) {
-            return false;
-        }
-        if (mSecond == null) {
-            if (other.mSecond != null) {
-                return false;
-            }
-        } else if (!mSecond.equals(other.mSecond)) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java
index ba84b42..10e220c 100644
--- a/tools/signapk/src/com/android/signapk/SignApk.java
+++ b/tools/signapk/src/com/android/signapk/SignApk.java
@@ -23,7 +23,6 @@
 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 import org.bouncycastle.cert.jcajce.JcaCertStore;
 import org.bouncycastle.cms.CMSException;
-import org.bouncycastle.cms.CMSProcessableByteArray;
 import org.bouncycastle.cms.CMSSignedData;
 import org.bouncycastle.cms.CMSSignedDataGenerator;
 import org.bouncycastle.cms.CMSTypedData;
@@ -33,9 +32,15 @@
 import org.bouncycastle.operator.OperatorCreationException;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
-import org.bouncycastle.util.encoders.Base64;
 import org.conscrypt.OpenSSLProvider;
 
+import com.android.apksig.ApkSignerEngine;
+import com.android.apksig.DefaultApkSignerEngine;
+import com.android.apksig.apk.ApkUtils;
+import com.android.apksig.util.DataSink;
+import com.android.apksig.util.DataSources;
+import com.android.apksig.zip.ZipFormatException;
+
 import java.io.Console;
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -49,18 +54,15 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.io.PrintStream;
 import java.lang.reflect.Constructor;
 import java.nio.ByteBuffer;
-import java.security.DigestOutputStream;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
 import java.security.Key;
 import java.security.KeyFactory;
-import java.security.MessageDigest;
 import java.security.PrivateKey;
 import java.security.Provider;
-import java.security.PublicKey;
 import java.security.Security;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateFactory;
@@ -70,18 +72,14 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.TimeZone;
-import java.util.TreeMap;
-import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
 import java.util.regex.Pattern;
+
 import javax.crypto.Cipher;
 import javax.crypto.EncryptedPrivateKeyInfo;
 import javax.crypto.SecretKeyFactory;
@@ -111,39 +109,35 @@
  * APK Signature Scheme v2.
  */
 class SignApk {
-    private static final String CERT_SF_NAME = "META-INF/CERT.SF";
-    private static final String CERT_SIG_NAME = "META-INF/CERT.%s";
-    private static final String CERT_SF_MULTI_NAME = "META-INF/CERT%d.SF";
-    private static final String CERT_SIG_MULTI_NAME = "META-INF/CERT%d.%s";
-
     private static final String OTACERT_NAME = "META-INF/com/android/otacert";
 
+    /**
+     * Extensible data block/field header ID used for storing information about alignment of
+     * uncompressed entries as well as for aligning the entries's data. See ZIP appnote.txt section
+     * 4.5 Extensible data fields.
+     */
+    private static final short ALIGNMENT_ZIP_EXTRA_DATA_FIELD_HEADER_ID = (short) 0xd935;
+
+    /**
+     * Minimum size (in bytes) of the extensible data block/field used for alignment of uncompressed
+     * entries.
+     */
+    private static final short ALIGNMENT_ZIP_EXTRA_DATA_FIELD_MIN_SIZE_BYTES = 6;
+
     // bitmasks for which hash algorithms we need the manifest to include.
     private static final int USE_SHA1 = 1;
     private static final int USE_SHA256 = 2;
 
-    /** Digest algorithm used when signing the APK using APK Signature Scheme v2. */
-    private static final String APK_SIG_SCHEME_V2_DIGEST_ALGORITHM = "SHA-256";
-
     /**
-     * Minimum Android SDK API Level which accepts JAR signatures which use SHA-256. Older platform
-     * versions accept only SHA-1 signatures.
+     * Returns the digest algorithm ID (one of {@code USE_SHA1} or {@code USE_SHA256}) to be used
+     * for signing an OTA update package using the private key corresponding to the provided
+     * certificate.
      */
-    private static final int MIN_API_LEVEL_FOR_SHA256_JAR_SIGNATURES = 18;
-
-    /**
-     * Return one of USE_SHA1 or USE_SHA256 according to the signature
-     * algorithm specified in the cert.
-     */
-    private static int getDigestAlgorithm(X509Certificate cert, int minSdkVersion) {
+    private static int getDigestAlgorithmForOta(X509Certificate cert) {
         String sigAlg = cert.getSigAlgName().toUpperCase(Locale.US);
         if ("SHA1WITHRSA".equals(sigAlg) || "MD5WITHRSA".equals(sigAlg)) {
             // see "HISTORICAL NOTE" above.
-            if (minSdkVersion < MIN_API_LEVEL_FOR_SHA256_JAR_SIGNATURES) {
-                return USE_SHA1;
-            } else {
-                return USE_SHA256;
-            }
+            return USE_SHA1;
         } else if (sigAlg.startsWith("SHA256WITH")) {
             return USE_SHA256;
         } else {
@@ -152,28 +146,35 @@
         }
     }
 
-    /** Returns the expected signature algorithm for this key type. */
-    private static String getSignatureAlgorithm(X509Certificate cert, int minSdkVersion) {
-        String keyType = cert.getPublicKey().getAlgorithm().toUpperCase(Locale.US);
-        if ("RSA".equalsIgnoreCase(keyType)) {
-            if ((minSdkVersion >= MIN_API_LEVEL_FOR_SHA256_JAR_SIGNATURES)
-                    || (getDigestAlgorithm(cert, minSdkVersion) == USE_SHA256)) {
-                return "SHA256withRSA";
-            } else {
-                return "SHA1withRSA";
-            }
-        } else if ("EC".equalsIgnoreCase(keyType)) {
-            return "SHA256withECDSA";
+    /**
+     * Returns the JCA {@link java.security.Signature} algorithm to be used for signing and OTA
+     * update package using the private key corresponding to the provided certificate and the
+     * provided digest algorithm (see {@code USE_SHA1} and {@code USE_SHA256} constants).
+     */
+    private static String getJcaSignatureAlgorithmForOta(
+            X509Certificate cert, int hash) {
+        String sigAlgDigestPrefix;
+        switch (hash) {
+            case USE_SHA1:
+                sigAlgDigestPrefix = "SHA1";
+                break;
+            case USE_SHA256:
+                sigAlgDigestPrefix = "SHA256";
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown hash ID: " + hash);
+        }
+
+        String keyAlgorithm = cert.getPublicKey().getAlgorithm();
+        if ("RSA".equalsIgnoreCase(keyAlgorithm)) {
+            return sigAlgDigestPrefix + "withRSA";
+        } else if ("EC".equalsIgnoreCase(keyAlgorithm)) {
+            return sigAlgDigestPrefix + "withECDSA";
         } else {
-            throw new IllegalArgumentException("unsupported key type: " + keyType);
+            throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
         }
     }
 
-    // Files matching this pattern are not copied to the output.
-    private static Pattern stripPattern =
-        Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA|EC)|com/android/otacert))|(" +
-                        Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
-
     private static X509Certificate readPublicKey(File file)
         throws IOException, GeneralSecurityException {
         FileInputStream input = new FileInputStream(file);
@@ -279,100 +280,16 @@
     }
 
     /**
-     * Add the hash(es) of every file to the manifest, creating it if
-     * necessary.
-     */
-    private static Manifest addDigestsToManifest(JarFile jar, int hashes)
-        throws IOException, GeneralSecurityException {
-        Manifest input = jar.getManifest();
-        Manifest output = new Manifest();
-        Attributes main = output.getMainAttributes();
-        if (input != null) {
-            main.putAll(input.getMainAttributes());
-        } else {
-            main.putValue("Manifest-Version", "1.0");
-            main.putValue("Created-By", "1.0 (Android SignApk)");
-        }
-
-        MessageDigest md_sha1 = null;
-        MessageDigest md_sha256 = null;
-        if ((hashes & USE_SHA1) != 0) {
-            md_sha1 = MessageDigest.getInstance("SHA1");
-        }
-        if ((hashes & USE_SHA256) != 0) {
-            md_sha256 = MessageDigest.getInstance("SHA256");
-        }
-
-        byte[] buffer = new byte[4096];
-        int num;
-
-        // We sort the input entries by name, and add them to the
-        // output manifest in sorted order.  We expect that the output
-        // map will be deterministic.
-
-        TreeMap<String, JarEntry> byName = new TreeMap<String, JarEntry>();
-
-        for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
-            JarEntry entry = e.nextElement();
-            byName.put(entry.getName(), entry);
-        }
-
-        for (JarEntry entry: byName.values()) {
-            String name = entry.getName();
-            if (!entry.isDirectory() &&
-                (stripPattern == null || !stripPattern.matcher(name).matches())) {
-                InputStream data = jar.getInputStream(entry);
-                while ((num = data.read(buffer)) > 0) {
-                    if (md_sha1 != null) md_sha1.update(buffer, 0, num);
-                    if (md_sha256 != null) md_sha256.update(buffer, 0, num);
-                }
-
-                Attributes attr = null;
-                if (input != null) attr = input.getAttributes(name);
-                attr = attr != null ? new Attributes(attr) : new Attributes();
-                // Remove any previously computed digests from this entry's attributes.
-                for (Iterator<Object> i = attr.keySet().iterator(); i.hasNext();) {
-                    Object key = i.next();
-                    if (!(key instanceof Attributes.Name)) {
-                        continue;
-                    }
-                    String attributeNameLowerCase =
-                            ((Attributes.Name) key).toString().toLowerCase(Locale.US);
-                    if (attributeNameLowerCase.endsWith("-digest")) {
-                        i.remove();
-                    }
-                }
-                // Add SHA-1 digest if requested
-                if (md_sha1 != null) {
-                    attr.putValue("SHA1-Digest",
-                                  new String(Base64.encode(md_sha1.digest()), "ASCII"));
-                }
-                // Add SHA-256 digest if requested
-                if (md_sha256 != null) {
-                    attr.putValue("SHA-256-Digest",
-                                  new String(Base64.encode(md_sha256.digest()), "ASCII"));
-                }
-                output.getEntries().put(name, attr);
-            }
-        }
-
-        return output;
-    }
-
-    /**
      * Add a copy of the public key to the archive; this should
      * exactly match one of the files in
      * /system/etc/security/otacerts.zip on the device.  (The same
-     * cert can be extracted from the CERT.RSA file but this is much
-     * easier to get at.)
+     * cert can be extracted from the OTA update package's signature
+     * block but this is much easier to get at.)
      */
     private static void addOtacert(JarOutputStream outputJar,
                                    File publicKeyFile,
-                                   long timestamp,
-                                   Manifest manifest,
-                                   int hash)
-        throws IOException, GeneralSecurityException {
-        MessageDigest md = MessageDigest.getInstance(hash == USE_SHA1 ? "SHA1" : "SHA256");
+                                   long timestamp)
+        throws IOException {
 
         JarEntry je = new JarEntry(OTACERT_NAME);
         je.setTime(timestamp);
@@ -382,108 +299,14 @@
         int read;
         while ((read = input.read(b)) != -1) {
             outputJar.write(b, 0, read);
-            md.update(b, 0, read);
         }
         input.close();
-
-        Attributes attr = new Attributes();
-        attr.putValue(hash == USE_SHA1 ? "SHA1-Digest" : "SHA-256-Digest",
-                      new String(Base64.encode(md.digest()), "ASCII"));
-        manifest.getEntries().put(OTACERT_NAME, attr);
     }
 
 
-    /** Write to another stream and track how many bytes have been
-     *  written.
-     */
-    private static class CountOutputStream extends FilterOutputStream {
-        private int mCount;
-
-        public CountOutputStream(OutputStream out) {
-            super(out);
-            mCount = 0;
-        }
-
-        @Override
-        public void write(int b) throws IOException {
-            super.write(b);
-            mCount++;
-        }
-
-        @Override
-        public void write(byte[] b, int off, int len) throws IOException {
-            super.write(b, off, len);
-            mCount += len;
-        }
-
-        public int size() {
-            return mCount;
-        }
-    }
-
-    /** Write a .SF file with a digest of the specified manifest. */
-    private static void writeSignatureFile(Manifest manifest, OutputStream out,
-            int hash, boolean additionallySignedUsingAnApkSignatureScheme)
-        throws IOException, GeneralSecurityException {
-        Manifest sf = new Manifest();
-        Attributes main = sf.getMainAttributes();
-        main.putValue("Signature-Version", "1.0");
-        main.putValue("Created-By", "1.0 (Android SignApk)");
-        if (additionallySignedUsingAnApkSignatureScheme) {
-            // Add APK Signature Scheme v2 signature stripping protection.
-            // This attribute indicates that this APK is supposed to have been signed using one or
-            // more APK-specific signature schemes in addition to the standard JAR signature scheme
-            // used by this code. APK signature verifier should reject the APK if it does not
-            // contain a signature for the signature scheme the verifier prefers out of this set.
-            main.putValue(
-                    ApkSignerV2.SF_ATTRIBUTE_ANDROID_APK_SIGNED_NAME,
-                    ApkSignerV2.SF_ATTRIBUTE_ANDROID_APK_SIGNED_VALUE);
-        }
-
-        MessageDigest md = MessageDigest.getInstance(
-            hash == USE_SHA256 ? "SHA256" : "SHA1");
-        PrintStream print = new PrintStream(
-            new DigestOutputStream(new ByteArrayOutputStream(), md),
-            true, "UTF-8");
-
-        // Digest of the entire manifest
-        manifest.write(print);
-        print.flush();
-        main.putValue(hash == USE_SHA256 ? "SHA-256-Digest-Manifest" : "SHA1-Digest-Manifest",
-                      new String(Base64.encode(md.digest()), "ASCII"));
-
-        Map<String, Attributes> entries = manifest.getEntries();
-        for (Map.Entry<String, Attributes> entry : entries.entrySet()) {
-            // Digest of the manifest stanza for this entry.
-            print.print("Name: " + entry.getKey() + "\r\n");
-            for (Map.Entry<Object, Object> att : entry.getValue().entrySet()) {
-                print.print(att.getKey() + ": " + att.getValue() + "\r\n");
-            }
-            print.print("\r\n");
-            print.flush();
-
-            Attributes sfAttr = new Attributes();
-            sfAttr.putValue(hash == USE_SHA256 ? "SHA-256-Digest" : "SHA1-Digest",
-                            new String(Base64.encode(md.digest()), "ASCII"));
-            sf.getEntries().put(entry.getKey(), sfAttr);
-        }
-
-        CountOutputStream cout = new CountOutputStream(out);
-        sf.write(cout);
-
-        // A bug in the java.util.jar implementation of Android platforms
-        // up to version 1.6 will cause a spurious IOException to be thrown
-        // if the length of the signature file is a multiple of 1024 bytes.
-        // As a workaround, add an extra CRLF in this case.
-        if ((cout.size() % 1024) == 0) {
-            cout.write('\r');
-            cout.write('\n');
-        }
-    }
-
     /** Sign data and write the digital signature to 'out'. */
     private static void writeSignatureBlock(
-        CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey, int minSdkVersion,
+        CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey, int hash,
         OutputStream out)
         throws IOException,
                CertificateEncodingException,
@@ -495,7 +318,8 @@
 
         CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
         ContentSigner signer =
-                new JcaContentSignerBuilder(getSignatureAlgorithm(publicKey, minSdkVersion))
+                new JcaContentSignerBuilder(
+                        getJcaSignatureAlgorithmForOta(publicKey, hash))
                         .build(privateKey);
         gen.addSignerInfoGenerator(
             new JcaSignerInfoGeneratorBuilder(
@@ -513,18 +337,58 @@
     }
 
     /**
-     * Copy all the files in a manifest from input to output.  We set
-     * the modification times in the output to a fixed time, so as to
-     * reduce variation in the output file and make incremental OTAs
-     * more efficient.
+     * Adds ZIP entries which represent the v1 signature (JAR signature scheme).
      */
-    private static void copyFiles(Manifest manifest, JarFile in, JarOutputStream out,
-                                  long timestamp, int defaultAlignment) throws IOException {
+    private static void addV1Signature(
+            ApkSignerEngine apkSigner,
+            ApkSignerEngine.OutputJarSignatureRequest v1Signature,
+            JarOutputStream out,
+            long timestamp) throws IOException {
+        for (ApkSignerEngine.OutputJarSignatureRequest.JarEntry entry
+                : v1Signature.getAdditionalJarEntries()) {
+            String entryName = entry.getName();
+            JarEntry outEntry = new JarEntry(entryName);
+            outEntry.setTime(timestamp);
+            out.putNextEntry(outEntry);
+            byte[] entryData = entry.getData();
+            out.write(entryData);
+            ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest =
+                    apkSigner.outputJarEntry(entryName);
+            if (inspectEntryRequest != null) {
+                inspectEntryRequest.getDataSink().consume(entryData, 0, entryData.length);
+                inspectEntryRequest.done();
+            }
+        }
+    }
+
+    /**
+     * Copy all JAR entries from input to output. We set the modification times in the output to a
+     * fixed time, so as to reduce variation in the output file and make incremental OTAs more
+     * efficient.
+     */
+    private static void copyFiles(
+            JarFile in,
+            Pattern ignoredFilenamePattern,
+            ApkSignerEngine apkSigner,
+            JarOutputStream out,
+            long timestamp,
+            int defaultAlignment) throws IOException {
         byte[] buffer = new byte[4096];
         int num;
 
-        Map<String, Attributes> entries = manifest.getEntries();
-        ArrayList<String> names = new ArrayList<String>(entries.keySet());
+        ArrayList<String> names = new ArrayList<String>();
+        for (Enumeration<JarEntry> e = in.entries(); e.hasMoreElements();) {
+            JarEntry entry = e.nextElement();
+            if (entry.isDirectory()) {
+                continue;
+            }
+            String entryName = entry.getName();
+            if ((ignoredFilenamePattern != null)
+                    && (ignoredFilenamePattern.matcher(entryName).matches())) {
+                continue;
+            }
+            names.add(entryName);
+        }
         Collections.sort(names);
 
         boolean firstEntry = true;
@@ -537,12 +401,21 @@
         // the start of the file and makes it easier to do alignment
         // on them (since only stored entries are aligned).
 
+        List<String> remainingNames = new ArrayList<>(names.size());
         for (String name : names) {
             JarEntry inEntry = in.getJarEntry(name);
-            JarEntry outEntry = null;
-            if (inEntry.getMethod() != JarEntry.STORED) continue;
+            if (inEntry.getMethod() != JarEntry.STORED) {
+                // Defer outputting this entry until we're ready to output compressed entries.
+                remainingNames.add(name);
+                continue;
+            }
+
+            if (!shouldOutputApkEntry(apkSigner, in, inEntry, buffer)) {
+                continue;
+            }
+
             // Preserve the STORED method of the input entry.
-            outEntry = new JarEntry(inEntry);
+            JarEntry outEntry = new JarEntry(inEntry);
             outEntry.setTime(timestamp);
             // Discard comment and extra fields of this entry to
             // simplify alignment logic below and for consistency with
@@ -550,57 +423,134 @@
             outEntry.setComment(null);
             outEntry.setExtra(null);
 
-            // 'offset' is the offset into the file at which we expect
-            // the file data to begin.  This is the value we need to
-            // make a multiple of 'alignement'.
+            int alignment = getStoredEntryDataAlignment(name, defaultAlignment);
+            // Alignment of the entry's data is achieved by adding a data block to the entry's Local
+            // File Header extra field. The data block contains information about the alignment
+            // value and the necessary padding bytes (0x00) to achieve the alignment.  This works
+            // because the entry's data will be located immediately after the extra field.
+            // See ZIP APPNOTE.txt section "4.5 Extensible data fields" for details about the format
+            // of the extra field.
+
+            // 'offset' is the offset into the file at which we expect the entry's data to begin.
+            // This is the value we need to make a multiple of 'alignment'.
             offset += JarFile.LOCHDR + outEntry.getName().length();
             if (firstEntry) {
-                // The first entry in a jar file has an extra field of
-                // four bytes that you can't get rid of; any extra
-                // data you specify in the JarEntry is appended to
-                // these forced four bytes.  This is JAR_MAGIC in
-                // JarOutputStream; the bytes are 0xfeca0000.
+                // The first entry in a jar file has an extra field of four bytes that you can't get
+                // rid of; any extra data you specify in the JarEntry is appended to these forced
+                // four bytes.  This is JAR_MAGIC in JarOutputStream; the bytes are 0xfeca0000.
+                // See http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6808540
+                // and http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4138619.
                 offset += 4;
                 firstEntry = false;
             }
-            int alignment = getStoredEntryDataAlignment(name, defaultAlignment);
-            if (alignment > 0 && (offset % alignment != 0)) {
-                // Set the "extra data" of the entry to between 1 and
-                // alignment-1 bytes, to make the file data begin at
-                // an aligned offset.
-                int needed = alignment - (int)(offset % alignment);
-                outEntry.setExtra(new byte[needed]);
-                offset += needed;
+            int extraPaddingSizeBytes = 0;
+            if (alignment > 0) {
+                long paddingStartOffset = offset + ALIGNMENT_ZIP_EXTRA_DATA_FIELD_MIN_SIZE_BYTES;
+                extraPaddingSizeBytes =
+                        (alignment - (int) (paddingStartOffset % alignment)) % alignment;
             }
+            byte[] extra =
+                    new byte[ALIGNMENT_ZIP_EXTRA_DATA_FIELD_MIN_SIZE_BYTES + extraPaddingSizeBytes];
+            ByteBuffer extraBuf = ByteBuffer.wrap(extra);
+            extraBuf.order(ByteOrder.LITTLE_ENDIAN);
+            extraBuf.putShort(ALIGNMENT_ZIP_EXTRA_DATA_FIELD_HEADER_ID); // Header ID
+            extraBuf.putShort((short) (2 + extraPaddingSizeBytes)); // Data Size
+            extraBuf.putShort((short) alignment);
+            outEntry.setExtra(extra);
+            offset += extra.length;
 
             out.putNextEntry(outEntry);
+            ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest =
+                    (apkSigner != null) ? apkSigner.outputJarEntry(name) : null;
+            DataSink entryDataSink =
+                    (inspectEntryRequest != null) ? inspectEntryRequest.getDataSink() : null;
 
-            InputStream data = in.getInputStream(inEntry);
-            while ((num = data.read(buffer)) > 0) {
-                out.write(buffer, 0, num);
-                offset += num;
+            try (InputStream data = in.getInputStream(inEntry)) {
+                while ((num = data.read(buffer)) > 0) {
+                    out.write(buffer, 0, num);
+                    if (entryDataSink != null) {
+                        entryDataSink.consume(buffer, 0, num);
+                    }
+                    offset += num;
+                }
             }
             out.flush();
+            if (inspectEntryRequest != null) {
+                inspectEntryRequest.done();
+            }
         }
 
         // Copy all the non-STORED entries.  We don't attempt to
         // maintain the 'offset' variable past this point; we don't do
         // alignment on these entries.
 
-        for (String name : names) {
+        for (String name : remainingNames) {
             JarEntry inEntry = in.getJarEntry(name);
-            JarEntry outEntry = null;
-            if (inEntry.getMethod() == JarEntry.STORED) continue;
+            if (!shouldOutputApkEntry(apkSigner, in, inEntry, buffer)) {
+                continue;
+            }
+
             // Create a new entry so that the compressed len is recomputed.
-            outEntry = new JarEntry(name);
+            JarEntry outEntry = new JarEntry(name);
             outEntry.setTime(timestamp);
             out.putNextEntry(outEntry);
+            ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest =
+                    (apkSigner != null) ? apkSigner.outputJarEntry(name) : null;
+            DataSink entryDataSink =
+                    (inspectEntryRequest != null) ? inspectEntryRequest.getDataSink() : null;
 
             InputStream data = in.getInputStream(inEntry);
             while ((num = data.read(buffer)) > 0) {
                 out.write(buffer, 0, num);
+                if (entryDataSink != null) {
+                    entryDataSink.consume(buffer, 0, num);
+                }
             }
             out.flush();
+            if (inspectEntryRequest != null) {
+                inspectEntryRequest.done();
+            }
+        }
+    }
+
+    private static boolean shouldOutputApkEntry(
+            ApkSignerEngine apkSigner, JarFile inFile, JarEntry inEntry, byte[] tmpbuf)
+                    throws IOException {
+        if (apkSigner == null) {
+            return true;
+        }
+
+        ApkSignerEngine.InputJarEntryInstructions instructions =
+                apkSigner.inputJarEntry(inEntry.getName());
+        ApkSignerEngine.InspectJarEntryRequest inspectEntryRequest =
+                instructions.getInspectJarEntryRequest();
+        if (inspectEntryRequest != null) {
+            provideJarEntry(inFile, inEntry, inspectEntryRequest, tmpbuf);
+        }
+        switch (instructions.getOutputPolicy()) {
+            case OUTPUT:
+                return true;
+            case SKIP:
+            case OUTPUT_BY_ENGINE:
+                return false;
+            default:
+                throw new RuntimeException(
+                        "Unsupported output policy: " + instructions.getOutputPolicy());
+        }
+    }
+
+    private static void provideJarEntry(
+            JarFile jarFile,
+            JarEntry jarEntry,
+            ApkSignerEngine.InspectJarEntryRequest request,
+            byte[] tmpbuf) throws IOException {
+        DataSink dataSink = request.getDataSink();
+        try (InputStream in = jarFile.getInputStream(jarEntry)) {
+            int chunkSize;
+            while ((chunkSize = in.read(tmpbuf)) > 0) {
+                dataSink.consume(tmpbuf, 0, chunkSize);
+            }
+            request.done();
         }
     }
 
@@ -686,21 +636,26 @@
         private final File publicKeyFile;
         private final X509Certificate publicKey;
         private final PrivateKey privateKey;
+        private final int hash;
         private final long timestamp;
-        private final int minSdkVersion;
         private final OutputStream outputStream;
         private final ASN1ObjectIdentifier type;
         private WholeFileSignerOutputStream signer;
 
+        // Files matching this pattern are not copied to the output.
+        private static final Pattern STRIP_PATTERN =
+                Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA|EC)|com/android/otacert))|("
+                        + Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
+
         public CMSSigner(JarFile inputJar, File publicKeyFile,
-                         X509Certificate publicKey, PrivateKey privateKey, long timestamp,
-                         int minSdkVersion, OutputStream outputStream) {
+                         X509Certificate publicKey, PrivateKey privateKey, int hash,
+                         long timestamp, OutputStream outputStream) {
             this.inputJar = inputJar;
             this.publicKeyFile = publicKeyFile;
             this.publicKey = publicKey;
             this.privateKey = privateKey;
+            this.hash = hash;
             this.timestamp = timestamp;
-            this.minSdkVersion = minSdkVersion;
             this.outputStream = outputStream;
             this.type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
         }
@@ -725,19 +680,8 @@
                 signer = new WholeFileSignerOutputStream(out, outputStream);
                 JarOutputStream outputJar = new JarOutputStream(signer);
 
-                int hash = getDigestAlgorithm(publicKey, minSdkVersion);
-
-                Manifest manifest = addDigestsToManifest(inputJar, hash);
-                copyFiles(manifest, inputJar, outputJar, timestamp, 0);
-                addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash);
-
-                signFile(manifest,
-                         new X509Certificate[]{ publicKey },
-                         new PrivateKey[]{ privateKey },
-                         timestamp,
-                         minSdkVersion,
-                         false, // Don't sign using APK Signature Scheme v2
-                         outputJar);
+                copyFiles(inputJar, STRIP_PATTERN, null, outputJar, timestamp, 0);
+                addOtacert(outputJar, publicKeyFile, timestamp);
 
                 signer.notifyClosing();
                 outputJar.close();
@@ -753,7 +697,7 @@
                    CertificateEncodingException,
                    OperatorCreationException,
                    CMSException {
-            SignApk.writeSignatureBlock(this, publicKey, privateKey, minSdkVersion, temp);
+            SignApk.writeSignatureBlock(this, publicKey, privateKey, hash, temp);
         }
 
         public WholeFileSignerOutputStream getSigner() {
@@ -763,10 +707,10 @@
 
     private static void signWholeFile(JarFile inputJar, File publicKeyFile,
                                       X509Certificate publicKey, PrivateKey privateKey,
-                                      long timestamp, int minSdkVersion,
+                                      int hash, long timestamp,
                                       OutputStream outputStream) throws Exception {
         CMSSigner cmsOut = new CMSSigner(inputJar, publicKeyFile,
-                publicKey, privateKey, timestamp, minSdkVersion, outputStream);
+                publicKey, privateKey, hash, timestamp, outputStream);
 
         ByteArrayOutputStream temp = new ByteArrayOutputStream();
 
@@ -774,7 +718,7 @@
         // archive comment, so that tools that display the comment
         // (hopefully) show something sensible.
         // TODO: anything more useful we can put in this message?
-        byte[] message = "signed by SignApk".getBytes("UTF-8");
+        byte[] message = "signed by SignApk".getBytes(StandardCharsets.UTF_8);
         temp.write(message);
         temp.write(0);
 
@@ -830,48 +774,6 @@
         temp.writeTo(outputStream);
     }
 
-    private static void signFile(Manifest manifest,
-                                 X509Certificate[] publicKey, PrivateKey[] privateKey,
-                                 long timestamp,
-                                 int minSdkVersion,
-                                 boolean additionallySignedUsingAnApkSignatureScheme,
-                                 JarOutputStream outputJar)
-        throws Exception {
-
-        // MANIFEST.MF
-        JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
-        je.setTime(timestamp);
-        outputJar.putNextEntry(je);
-        manifest.write(outputJar);
-
-        int numKeys = publicKey.length;
-        for (int k = 0; k < numKeys; ++k) {
-            // CERT.SF / CERT#.SF
-            je = new JarEntry(numKeys == 1 ? CERT_SF_NAME :
-                              (String.format(CERT_SF_MULTI_NAME, k)));
-            je.setTime(timestamp);
-            outputJar.putNextEntry(je);
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            writeSignatureFile(
-                    manifest,
-                    baos,
-                    getDigestAlgorithm(publicKey[k], minSdkVersion),
-                    additionallySignedUsingAnApkSignatureScheme);
-            byte[] signedData = baos.toByteArray();
-            outputJar.write(signedData);
-
-            // CERT.{EC,RSA} / CERT#.{EC,RSA}
-            final String keyType = publicKey[k].getPublicKey().getAlgorithm();
-            je = new JarEntry(numKeys == 1 ?
-                              (String.format(CERT_SIG_NAME, keyType)) :
-                              (String.format(CERT_SIG_MULTI_NAME, k, keyType)));
-            je.setTime(timestamp);
-            outputJar.putNextEntry(je);
-            writeSignatureBlock(new CMSProcessableByteArray(signedData),
-                                publicKey[k], privateKey[k], minSdkVersion, outputJar);
-        }
-    }
-
     /**
      * Tries to load a JSE Provider by class name. This is for custom PrivateKey
      * types that might be stored in PKCS#11-like storage.
@@ -924,81 +826,68 @@
         Security.insertProviderAt((Provider) o, 1);
     }
 
-    /**
-     * Converts the provided lists of private keys, their X.509 certificates, and digest algorithms
-     * into a list of APK Signature Scheme v2 {@code SignerConfig} instances.
-     */
-    public static List<ApkSignerV2.SignerConfig> createV2SignerConfigs(
-            PrivateKey[] privateKeys, X509Certificate[] certificates, String[] digestAlgorithms)
-                    throws InvalidKeyException {
+    private static List<DefaultApkSignerEngine.SignerConfig> createSignerConfigs(
+            PrivateKey[] privateKeys, X509Certificate[] certificates) {
         if (privateKeys.length != certificates.length) {
             throw new IllegalArgumentException(
                     "The number of private keys must match the number of certificates: "
                             + privateKeys.length + " vs" + certificates.length);
         }
-        List<ApkSignerV2.SignerConfig> result = new ArrayList<>(privateKeys.length);
+        List<DefaultApkSignerEngine.SignerConfig> signerConfigs = new ArrayList<>();
+        String signerNameFormat = (privateKeys.length == 1) ? "CERT" : "CERT%s";
         for (int i = 0; i < privateKeys.length; i++) {
-            PrivateKey privateKey = privateKeys[i];
-            X509Certificate certificate = certificates[i];
-            PublicKey publicKey = certificate.getPublicKey();
-            String keyAlgorithm = privateKey.getAlgorithm();
-            if (!keyAlgorithm.equalsIgnoreCase(publicKey.getAlgorithm())) {
-                throw new InvalidKeyException(
-                        "Key algorithm of private key #" + (i + 1) + " does not match key"
-                        + " algorithm of public key #" + (i + 1) + ": " + keyAlgorithm
-                        + " vs " + publicKey.getAlgorithm());
-            }
-            ApkSignerV2.SignerConfig signerConfig = new ApkSignerV2.SignerConfig();
-            signerConfig.privateKey = privateKey;
-            signerConfig.certificates = Collections.singletonList(certificate);
-            List<Integer> signatureAlgorithms = new ArrayList<>(digestAlgorithms.length);
-            for (String digestAlgorithm : digestAlgorithms) {
-                try {
-                    signatureAlgorithms.add(
-                            getV2SignatureAlgorithm(keyAlgorithm, digestAlgorithm));
-                } catch (IllegalArgumentException e) {
-                    throw new InvalidKeyException(
-                            "Unsupported key and digest algorithm combination for signer #"
-                                    + (i + 1),
-                            e);
-                }
-            }
-            signerConfig.signatureAlgorithms = signatureAlgorithms;
-            result.add(signerConfig);
+            String signerName = String.format(Locale.US, signerNameFormat, (i + 1));
+            DefaultApkSignerEngine.SignerConfig signerConfig =
+                    new DefaultApkSignerEngine.SignerConfig.Builder(
+                            signerName,
+                            privateKeys[i],
+                            Collections.singletonList(certificates[i]))
+                            .build();
+            signerConfigs.add(signerConfig);
         }
-        return result;
+        return signerConfigs;
     }
 
-    private static int getV2SignatureAlgorithm(String keyAlgorithm, String digestAlgorithm) {
-        if ("SHA-256".equalsIgnoreCase(digestAlgorithm)) {
-            if ("RSA".equalsIgnoreCase(keyAlgorithm)) {
-                // Use RSASSA-PKCS1-v1_5 signature scheme instead of RSASSA-PSS to guarantee
-                // deterministic signatures which make life easier for OTA updates (fewer files
-                // changed when deterministic signature schemes are used).
-                return ApkSignerV2.SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA256;
-            } else if ("EC".equalsIgnoreCase(keyAlgorithm)) {
-                return ApkSignerV2.SIGNATURE_ECDSA_WITH_SHA256;
-            } else if ("DSA".equalsIgnoreCase(keyAlgorithm)) {
-                return ApkSignerV2.SIGNATURE_DSA_WITH_SHA256;
-            } else {
-                throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
-            }
-        } else if ("SHA-512".equalsIgnoreCase(digestAlgorithm)) {
-            if ("RSA".equalsIgnoreCase(keyAlgorithm)) {
-                // Use RSASSA-PKCS1-v1_5 signature scheme instead of RSASSA-PSS to guarantee
-                // deterministic signatures which make life easier for OTA updates (fewer files
-                // changed when deterministic signature schemes are used).
-                return ApkSignerV2.SIGNATURE_RSA_PKCS1_V1_5_WITH_SHA512;
-            } else if ("EC".equalsIgnoreCase(keyAlgorithm)) {
-                return ApkSignerV2.SIGNATURE_ECDSA_WITH_SHA512;
-            } else if ("DSA".equalsIgnoreCase(keyAlgorithm)) {
-                return ApkSignerV2.SIGNATURE_DSA_WITH_SHA512;
-            } else {
-                throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
-            }
-        } else {
-            throw new IllegalArgumentException("Unsupported digest algorithm: " + digestAlgorithm);
+    private static class ZipSections {
+        ByteBuffer beforeCentralDir;
+        ByteBuffer centralDir;
+        ByteBuffer eocd;
+    }
+
+    private static ZipSections findMainZipSections(ByteBuffer apk)
+            throws IOException, ZipFormatException {
+        apk.slice();
+        ApkUtils.ZipSections sections = ApkUtils.findZipSections(DataSources.asDataSource(apk));
+        long centralDirStartOffset = sections.getZipCentralDirectoryOffset();
+        long centralDirSizeBytes = sections.getZipCentralDirectorySizeBytes();
+        long centralDirEndOffset = centralDirStartOffset + centralDirSizeBytes;
+        long eocdStartOffset = sections.getZipEndOfCentralDirectoryOffset();
+        if (centralDirEndOffset != eocdStartOffset) {
+            throw new ZipFormatException(
+                    "ZIP Central Directory is not immediately followed by End of Central Directory"
+                            + ". CD end: " + centralDirEndOffset
+                            + ", EoCD start: " + eocdStartOffset);
         }
+        apk.position(0);
+        apk.limit((int) centralDirStartOffset);
+        ByteBuffer beforeCentralDir = apk.slice();
+
+        apk.position((int) centralDirStartOffset);
+        apk.limit((int) centralDirEndOffset);
+        ByteBuffer centralDir = apk.slice();
+
+        apk.position((int) eocdStartOffset);
+        apk.limit(apk.capacity());
+        ByteBuffer eocd = apk.slice();
+
+        apk.position(0);
+        apk.limit(apk.capacity());
+
+        ZipSections result = new ZipSections();
+        result.beforeCentralDir = beforeCentralDir;
+        result.centralDir = centralDir;
+        result.eocd = eocd;
+        return result;
     }
 
     private static void usage() {
@@ -1075,7 +964,6 @@
 
         JarFile inputJar = null;
         FileOutputStream outputFile = null;
-        int hashes = 0;
 
         try {
             File firstPublicKeyFile = new File(args[argstart+0]);
@@ -1085,7 +973,6 @@
                 for (int i = 0; i < numKeys; ++i) {
                     int argNum = argstart + i*2;
                     publicKey[i] = readPublicKey(new File(args[argNum]));
-                    hashes |= getDigestAlgorithm(publicKey[i], minSdkVersion);
                 }
             } catch (IllegalArgumentException e) {
                 System.err.println(e);
@@ -1111,55 +998,87 @@
             // NOTE: Signing currently recompresses any compressed entries using Deflate (default
             // compression level for OTA update files and maximum compession level for APKs).
             if (signWholeFile) {
-                SignApk.signWholeFile(inputJar, firstPublicKeyFile,
-                                      publicKey[0], privateKey[0],
-                                      timestamp, minSdkVersion,
-                                      outputFile);
+                int digestAlgorithm = getDigestAlgorithmForOta(publicKey[0]);
+                signWholeFile(inputJar, firstPublicKeyFile,
+                        publicKey[0], privateKey[0], digestAlgorithm,
+                        timestamp,
+                        outputFile);
             } else {
-                // Generate, in memory, an APK signed using standard JAR Signature Scheme.
-                ByteArrayOutputStream v1SignedApkBuf = new ByteArrayOutputStream();
-                JarOutputStream outputJar = new JarOutputStream(v1SignedApkBuf);
-                // Use maximum compression for compressed entries because the APK lives forever on
-                // the system partition.
-                outputJar.setLevel(9);
-                Manifest manifest = addDigestsToManifest(inputJar, hashes);
-                copyFiles(manifest, inputJar, outputJar, timestamp, alignment);
-                signFile(
-                        manifest,
-                        publicKey, privateKey,
-                        timestamp, minSdkVersion, signUsingApkSignatureSchemeV2,
-                        outputJar);
-                outputJar.close();
-                ByteBuffer v1SignedApk = ByteBuffer.wrap(v1SignedApkBuf.toByteArray());
-                v1SignedApkBuf.reset();
+                try (ApkSignerEngine apkSigner =
+                        new DefaultApkSignerEngine.Builder(
+                                createSignerConfigs(privateKey, publicKey), minSdkVersion)
+                                .setV1SigningEnabled(true)
+                                .setV2SigningEnabled(signUsingApkSignatureSchemeV2)
+                                .setOtherSignersSignaturesPreserved(false)
+                                .setCreatedBy("1.0 (Android SignApk)")
+                                .build()) {
+                    // We don't preserve the input APK's APK Signing Block (which contains v2
+                    // signatures)
+                    apkSigner.inputApkSigningBlock(null);
 
-                ByteBuffer[] outputChunks;
-                if (signUsingApkSignatureSchemeV2) {
-                    // Additionally sign the APK using the APK Signature Scheme v2.
-                    ByteBuffer apkContents = v1SignedApk;
-                    List<ApkSignerV2.SignerConfig> signerConfigs =
-                            createV2SignerConfigs(
-                                    privateKey,
-                                    publicKey,
-                                    new String[] {APK_SIG_SCHEME_V2_DIGEST_ALGORITHM});
-                    outputChunks = ApkSignerV2.sign(apkContents, signerConfigs);
-                } else {
-                    // Output the JAR-signed APK as is.
-                    outputChunks = new ByteBuffer[] {v1SignedApk};
+                    // Build the output APK in memory, by copying input APK's ZIP entries across
+                    // and then signing the output APK.
+                    ByteArrayOutputStream v1SignedApkBuf = new ByteArrayOutputStream();
+                    JarOutputStream outputJar = new JarOutputStream(v1SignedApkBuf);
+                    // Use maximum compression for compressed entries because the APK lives forever
+                    // on the system partition.
+                    outputJar.setLevel(9);
+                    copyFiles(inputJar, null, apkSigner, outputJar, timestamp, alignment);
+                    ApkSignerEngine.OutputJarSignatureRequest addV1SignatureRequest =
+                            apkSigner.outputJarEntries();
+                    if (addV1SignatureRequest != null) {
+                        addV1Signature(apkSigner, addV1SignatureRequest, outputJar, timestamp);
+                        addV1SignatureRequest.done();
+                    }
+                    outputJar.close();
+                    ByteBuffer v1SignedApk = ByteBuffer.wrap(v1SignedApkBuf.toByteArray());
+                    v1SignedApkBuf.reset();
+                    ByteBuffer[] outputChunks = new ByteBuffer[] {v1SignedApk};
+
+                    ZipSections zipSections = findMainZipSections(v1SignedApk);
+                    ApkSignerEngine.OutputApkSigningBlockRequest addV2SignatureRequest =
+                            apkSigner.outputZipSections(
+                                    DataSources.asDataSource(zipSections.beforeCentralDir),
+                                    DataSources.asDataSource(zipSections.centralDir),
+                                    DataSources.asDataSource(zipSections.eocd));
+                    if (addV2SignatureRequest != null) {
+                        // Need to insert the returned APK Signing Block before ZIP Central
+                        // Directory.
+                        byte[] apkSigningBlock = addV2SignatureRequest.getApkSigningBlock();
+                        // Because the APK Signing Block is inserted before the Central Directory,
+                        // we need to adjust accordingly the offset of Central Directory inside the
+                        // ZIP End of Central Directory (EoCD) record.
+                        ByteBuffer modifiedEocd = ByteBuffer.allocate(zipSections.eocd.remaining());
+                        modifiedEocd.put(zipSections.eocd);
+                        modifiedEocd.flip();
+                        modifiedEocd.order(ByteOrder.LITTLE_ENDIAN);
+                        ApkUtils.setZipEocdCentralDirectoryOffset(
+                                modifiedEocd,
+                                zipSections.beforeCentralDir.remaining() + apkSigningBlock.length);
+                        outputChunks =
+                                new ByteBuffer[] {
+                                        zipSections.beforeCentralDir,
+                                        ByteBuffer.wrap(apkSigningBlock),
+                                        zipSections.centralDir,
+                                        modifiedEocd};
+                        addV2SignatureRequest.done();
+                    }
+
+                    // This assumes outputChunks are array-backed. To avoid this assumption, the
+                    // code could be rewritten to use FileChannel.
+                    for (ByteBuffer outputChunk : outputChunks) {
+                        outputFile.write(
+                                outputChunk.array(),
+                                outputChunk.arrayOffset() + outputChunk.position(),
+                                outputChunk.remaining());
+                        outputChunk.position(outputChunk.limit());
+                    }
+
+                    outputFile.close();
+                    outputFile = null;
+                    apkSigner.outputDone();
                 }
 
-                // This assumes outputChunks are array-backed. To avoid this assumption, the
-                // code could be rewritten to use FileChannel.
-                for (ByteBuffer outputChunk : outputChunks) {
-                    outputFile.write(
-                            outputChunk.array(),
-                            outputChunk.arrayOffset() + outputChunk.position(),
-                            outputChunk.remaining());
-                    outputChunk.position(outputChunk.limit());
-                }
-
-                outputFile.close();
-                outputFile = null;
                 return;
             }
         } catch (Exception e) {
diff --git a/tools/signapk/src/com/android/signapk/ZipUtils.java b/tools/signapk/src/com/android/signapk/ZipUtils.java
deleted file mode 100644
index 7575a77..0000000
--- a/tools/signapk/src/com/android/signapk/ZipUtils.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.signapk;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * Assorted ZIP format helpers.
- *
- * <p>NOTE: Most helper methods operating on {@code ByteBuffer} instances expect that the byte
- * order of these buffers is little-endian.
- */
-public abstract class ZipUtils {
-    private ZipUtils() {}
-
-    private static final int ZIP_EOCD_REC_MIN_SIZE = 22;
-    private static final int ZIP_EOCD_REC_SIG = 0x06054b50;
-    private static final int ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET = 12;
-    private static final int ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET = 16;
-    private static final int ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET = 20;
-
-    private static final int ZIP64_EOCD_LOCATOR_SIZE = 20;
-    private static final int ZIP64_EOCD_LOCATOR_SIG = 0x07064b50;
-
-    private static final int UINT16_MAX_VALUE = 0xffff;
-
-    /**
-     * Returns the position at which ZIP End of Central Directory record starts in the provided
-     * buffer or {@code -1} if the record is not present.
-     *
-     * <p>NOTE: Byte order of {@code zipContents} must be little-endian.
-     */
-    public static int findZipEndOfCentralDirectoryRecord(ByteBuffer zipContents) {
-        assertByteOrderLittleEndian(zipContents);
-
-        // ZIP End of Central Directory (EOCD) record is located at the very end of the ZIP archive.
-        // The record can be identified by its 4-byte signature/magic which is located at the very
-        // beginning of the record. A complication is that the record is variable-length because of
-        // the comment field.
-        // The algorithm for locating the ZIP EOCD record is as follows. We search backwards from
-        // end of the buffer for the EOCD record signature. Whenever we find a signature, we check
-        // the candidate record's comment length is such that the remainder of the record takes up
-        // exactly the remaining bytes in the buffer. The search is bounded because the maximum
-        // size of the comment field is 65535 bytes because the field is an unsigned 16-bit number.
-
-        int archiveSize = zipContents.capacity();
-        if (archiveSize < ZIP_EOCD_REC_MIN_SIZE) {
-            return -1;
-        }
-        int maxCommentLength = Math.min(archiveSize - ZIP_EOCD_REC_MIN_SIZE, UINT16_MAX_VALUE);
-        int eocdWithEmptyCommentStartPosition = archiveSize - ZIP_EOCD_REC_MIN_SIZE;
-        for (int expectedCommentLength = 0; expectedCommentLength < maxCommentLength;
-                expectedCommentLength++) {
-            int eocdStartPos = eocdWithEmptyCommentStartPosition - expectedCommentLength;
-            if (zipContents.getInt(eocdStartPos) == ZIP_EOCD_REC_SIG) {
-                int actualCommentLength =
-                        getUnsignedInt16(
-                                zipContents, eocdStartPos + ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET);
-                if (actualCommentLength == expectedCommentLength) {
-                    return eocdStartPos;
-                }
-            }
-        }
-
-        return -1;
-    }
-
-    /**
-     * Returns {@code true} if the provided buffer contains a ZIP64 End of Central Directory
-     * Locator.
-     *
-     * <p>NOTE: Byte order of {@code zipContents} must be little-endian.
-     */
-    public static final boolean isZip64EndOfCentralDirectoryLocatorPresent(
-            ByteBuffer zipContents, int zipEndOfCentralDirectoryPosition) {
-        assertByteOrderLittleEndian(zipContents);
-
-        // ZIP64 End of Central Directory Locator immediately precedes the ZIP End of Central
-        // Directory Record.
-
-        int locatorPosition = zipEndOfCentralDirectoryPosition - ZIP64_EOCD_LOCATOR_SIZE;
-        if (locatorPosition < 0) {
-            return false;
-        }
-
-        return zipContents.getInt(locatorPosition) == ZIP64_EOCD_LOCATOR_SIG;
-    }
-
-    /**
-     * Returns the offset of the start of the ZIP Central Directory in the archive.
-     *
-     * <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
-     */
-    public static long getZipEocdCentralDirectoryOffset(ByteBuffer zipEndOfCentralDirectory) {
-        assertByteOrderLittleEndian(zipEndOfCentralDirectory);
-        return getUnsignedInt32(
-                zipEndOfCentralDirectory,
-                zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET);
-    }
-
-    /**
-     * Sets the offset of the start of the ZIP Central Directory in the archive.
-     *
-     * <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
-     */
-    public static void setZipEocdCentralDirectoryOffset(
-            ByteBuffer zipEndOfCentralDirectory, long offset) {
-        assertByteOrderLittleEndian(zipEndOfCentralDirectory);
-        setUnsignedInt32(
-                zipEndOfCentralDirectory,
-                zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET,
-                offset);
-    }
-
-    /**
-     * Returns the size (in bytes) of the ZIP Central Directory.
-     *
-     * <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
-     */
-    public static long getZipEocdCentralDirectorySizeBytes(ByteBuffer zipEndOfCentralDirectory) {
-        assertByteOrderLittleEndian(zipEndOfCentralDirectory);
-        return getUnsignedInt32(
-                zipEndOfCentralDirectory,
-                zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET);
-    }
-
-    private static void assertByteOrderLittleEndian(ByteBuffer buffer) {
-        if (buffer.order() != ByteOrder.LITTLE_ENDIAN) {
-            throw new IllegalArgumentException("ByteBuffer byte order must be little endian");
-        }
-    }
-
-    private static int getUnsignedInt16(ByteBuffer buffer, int offset) {
-        return buffer.getShort(offset) & 0xffff;
-    }
-
-    private static long getUnsignedInt32(ByteBuffer buffer, int offset) {
-        return buffer.getInt(offset) & 0xffffffffL;
-    }
-
-    private static void setUnsignedInt32(ByteBuffer buffer, int offset, long value) {
-        if ((value < 0) || (value > 0xffffffffL)) {
-            throw new IllegalArgumentException("uint32 value of out range: " + value);
-        }
-        buffer.putInt(buffer.position() + offset, (int) value);
-    }
-}
diff --git a/tools/soong_to_convert.py b/tools/soong_to_convert.py
new file mode 100755
index 0000000..379a1ad
--- /dev/null
+++ b/tools/soong_to_convert.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 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.
+
+"""Tool to prioritize which modules to convert to Soong.
+
+Generally, you'd use this through the make integration, which automatically
+generates the CSV input file that this tool expects:
+
+  $ m $OUT/soong_to_convert.txt
+  $ less $OUT/soong_to_convert.txt
+
+The output is a list of modules that are probably ready to convert to Soong:
+
+  # Blocked on Module (potential problems)
+           283 libEGL (srcs_dotarm)
+           246 libicuuc (dotdot_incs dotdot_srcs)
+           221 libspeexresampler
+           215 libcamera_metadata
+               ...
+             0 zram-perf (dotdot_incs)
+
+The number at the beginning of the line shows how many native modules depend
+on that module.
+
+All of their dependencies have been satisfied, and any potential problems
+that Make can detect are listed in parenthesis after the module:
+
+  dotdot_srcs: LOCAL_SRC_FILES contains paths outside $(LOCAL_PATH)
+  dotdot_incs: LOCAL_C_INCLUDES contains paths include '..'
+  srcs_dotarm: LOCAL_SRC_FILES contains source files like <...>.c.arm
+  aidl: LOCAL_SRC_FILES contains .aidl sources
+  dbus: LOCAL_SRC_FILES contains .dbus-xml sources
+  objc: LOCAL_SRC_FILES contains Objective-C sources
+  proto: LOCAL_SRC_FILES contains .proto sources
+  rs: LOCAL_SRC_FILES contains renderscript sources
+  vts: LOCAL_SRC_FILES contains .vts sources
+
+Not all problems can be discovered, but this is a starting point.
+
+"""
+
+from __future__ import print_function
+
+import csv
+import sys
+
+def count_deps(depsdb, module, seen):
+    """Based on the depsdb, count the number of transitive dependencies.
+
+    You can pass in an reversed dependency graph to conut the number of
+    modules that depend on the module."""
+    count = 0
+    seen.append(module)
+    if module in depsdb:
+        for dep in depsdb[module]:
+            if dep in seen:
+                continue
+            count += 1 + count_deps(depsdb, dep, seen)
+    return count
+
+def process(reader):
+    """Read the input file and produce a list of modules ready to move to Soong
+    """
+    problems = dict()
+    deps = dict()
+    reverse_deps = dict()
+
+    for (module, problem, dependencies) in reader:
+        problems[module] = problem
+        deps[module] = [d for d in dependencies.strip().split(' ') if d != ""]
+        for dep in deps[module]:
+            if not dep in reverse_deps:
+                reverse_deps[dep] = []
+            reverse_deps[dep].append(module)
+
+    results = []
+    for module in problems:
+        # Only display actionable conversions, ones without missing dependencies
+        if len(deps[module]) != 0:
+            continue
+
+        extra = ""
+        if len(problems[module]) > 0:
+            extra = " ({})".format(problems[module])
+        results.append((count_deps(reverse_deps, module, []), module + extra))
+
+    return sorted(results, key=lambda result: (-result[0], result[1]))
+
+def display(results):
+    """Displays the results"""
+    count_header = "# Blocked on"
+    count_width = len(count_header)
+    print("{} Module (potential problems)".format(count_header))
+    for (count, module) in results:
+        print("{:>{}} {}".format(count, count_width, module))
+
+def main(filename):
+    """Read the CSV file, print the results"""
+    with open(filename, 'rb') as csvfile:
+        results = process(csv.reader(csvfile))
+
+    display(results)
+
+if __name__ == "__main__":
+    if len(sys.argv) != 2:
+        print("usage: soong_conversion.py <file>", file=sys.stderr)
+        sys.exit(1)
+
+    main(sys.argv[1])
diff --git a/tools/warn.py b/tools/warn.py
index 8097123..4ed4952 100755
--- a/tools/warn.py
+++ b/tools/warn.py
@@ -1,563 +1,2355 @@
-#!/usr/bin/env python
+#!/usr/bin/python
 # This file uses the following encoding: utf-8
 
-import sys
+"""Grep warnings messages and output HTML tables or warning counts in CSV.
+
+Default is to output warnings in HTML tables grouped by warning severity.
+Use option --byproject to output tables grouped by source file projects.
+Use option --gencsv to output warning counts in CSV format.
+"""
+
+# List of important data structures and functions in this script.
+#
+# To parse and keep warning message in the input file:
+#   severity:                classification of message severity
+#   severity.range           [0, 1, ... last_severity_level]
+#   severity.colors          for header background
+#   severity.column_headers  for the warning count table
+#   severity.headers         for warning message tables
+#   warn_patterns:
+#   warn_patterns[w]['category']     tool that issued the warning, not used now
+#   warn_patterns[w]['description']  table heading
+#   warn_patterns[w]['members']      matched warnings from input
+#   warn_patterns[w]['option']       compiler flag to control the warning
+#   warn_patterns[w]['patterns']     regular expressions to match warnings
+#   warn_patterns[w]['projects'][p]  number of warnings of pattern w in p
+#   warn_patterns[w]['severity']     severity level
+#   project_list[p][0]               project name
+#   project_list[p][1]               regular expression to match a project path
+#   project_patterns[p]              re.compile(project_list[p][1])
+#   project_names[p]                 project_list[p][0]
+#   warning_messages     array of each warning message, without source url
+#   warning_records      array of [idx to warn_patterns,
+#                                  idx to project_names,
+#                                  idx to warning_messages]
+#   platform_version
+#   target_product
+#   target_variant
+#   compile_patterns, parse_input_file
+#
+# To emit html page of warning messages:
+#   flags: --byproject, --url, --separator
+# Old stuff for static html components:
+#   html_script_style:  static html scripts and styles
+#   htmlbig:
+#   dump_stats, dump_html_prologue, dump_html_epilogue:
+#   emit_buttons:
+#   dump_fixed
+#   sort_warnings:
+#   emit_stats_by_project:
+#   all_patterns,
+#   findproject, classify_warning
+#   dump_html
+#
+# New dynamic HTML page's static JavaScript data:
+#   Some data are copied from Python to JavaScript, to generate HTML elements.
+#   FlagURL                args.url
+#   FlagSeparator          args.separator
+#   SeverityColors:        severity.colors
+#   SeverityHeaders:       severity.headers
+#   SeverityColumnHeaders: severity.column_headers
+#   ProjectNames:          project_names, or project_list[*][0]
+#   WarnPatternsSeverity:     warn_patterns[*]['severity']
+#   WarnPatternsDescription:  warn_patterns[*]['description']
+#   WarnPatternsOption:       warn_patterns[*]['option']
+#   WarningMessages:          warning_messages
+#   Warnings:                 warning_records
+#   StatsHeader:           warning count table header row
+#   StatsRows:             array of warning count table rows
+#
+# New dynamic HTML page's dynamic JavaScript data:
+#
+# New dynamic HTML related function to emit data:
+#   escape_string, strip_escape_string, emit_warning_arrays
+#   emit_js_data():
+#
+# To emit csv files of warning message counts:
+#   flag --gencsv
+#   description_for_csv, string_for_csv:
+#   count_severity(sev, kind):
+#   dump_csv():
+
+import argparse
 import re
 
-if len(sys.argv) == 1:
-    print 'usage: ' + sys.argv[0] + ' <build.log>'
-    sys.exit()
+parser = argparse.ArgumentParser(description='Convert a build log into HTML')
+parser.add_argument('--gencsv',
+                    help='Generate a CSV file with number of various warnings',
+                    action='store_true',
+                    default=False)
+parser.add_argument('--byproject',
+                    help='Separate warnings in HTML output by project names',
+                    action='store_true',
+                    default=False)
+parser.add_argument('--url',
+                    help='Root URL of an Android source code tree prefixed '
+                    'before files in warnings')
+parser.add_argument('--separator',
+                    help='Separator between the end of a URL and the line '
+                    'number argument. e.g. #')
+parser.add_argument(dest='buildlog', metavar='build.log',
+                    help='Path to build.log file')
+args = parser.parse_args()
 
-# if you add another level, don't forget to give it a color below
-class severity:
-    UNKNOWN=0
-    SKIP=100
-    FIXMENOW=1
-    HIGH=2
-    MEDIUM=3
-    LOW=4
-    HARMLESS=5
 
-def colorforseverity(sev):
-    if sev == severity.FIXMENOW:
-        return 'fuchsia'
-    if sev == severity.HIGH:
-        return 'red'
-    if sev == severity.MEDIUM:
-        return 'orange'
-    if sev == severity.LOW:
-        return 'yellow'
-    if sev == severity.HARMLESS:
-        return 'limegreen'
-    if sev == severity.UNKNOWN:
-        return 'blue'
-    return 'grey'
+class Severity(object):
+  """Severity levels and attributes."""
+  # numbered by dump order
+  FIXMENOW = 0
+  HIGH = 1
+  MEDIUM = 2
+  LOW = 3
+  TIDY = 4
+  HARMLESS = 5
+  UNKNOWN = 6
+  SKIP = 7
+  range = range(8)
+  attributes = [
+      # pylint:disable=bad-whitespace
+      ['fuchsia',   'FixNow',    'Critical warnings, fix me now'],
+      ['red',       'High',      'High severity warnings'],
+      ['orange',    'Medium',    'Medium severity warnings'],
+      ['yellow',    'Low',       'Low severity warnings'],
+      ['peachpuff', 'Tidy',      'Clang-Tidy warnings'],
+      ['limegreen', 'Harmless',  'Harmless warnings'],
+      ['lightblue', 'Unknown',   'Unknown warnings'],
+      ['grey',      'Unhandled', 'Unhandled warnings']
+  ]
+  colors = [a[0] for a in attributes]
+  column_headers = [a[1] for a in attributes]
+  headers = [a[2] for a in attributes]
 
-warnpatterns = [
-    { 'category':'make',    'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'make: overriding commands/ignoring old commands',
-        'patterns':[r".*: warning: overriding commands for target .+",
-                    r".*: warning: ignoring old commands for target .+"] },
-    { 'category':'C/C++',   'severity':severity.HIGH,     'members':[], 'option':'-Wimplicit-function-declaration',
-        'description':'Implicit function declaration',
-        'patterns':[r".*: warning: implicit declaration of function .+"] },
-    { 'category':'C/C++',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: conflicting types for '.+'"] },
-    { 'category':'C/C++',   'severity':severity.HIGH,     'members':[], 'option':'-Wtype-limits',
-        'description':'Expression always evaluates to true or false',
-        'patterns':[r".*: warning: comparison is always false due to limited range of data type",
-                    r".*: warning: comparison of unsigned expression >= 0 is always true",
-                    r".*: warning: comparison of unsigned expression < 0 is always false"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Incompatible pointer types',
-        'patterns':[r".*: warning: assignment from incompatible pointer type",
-                    r".*: warning: return from incompatible pointer type",
-                    r".*: warning: passing argument [0-9]+ of '.*' from incompatible pointer type",
-                    r".*: warning: initialization from incompatible pointer type"] },
-    { 'category':'C/C++',   'severity':severity.HIGH,     'members':[], 'option':'-fno-builtin',
-        'description':'Incompatible declaration of built in function',
-        'patterns':[r".*: warning: incompatible implicit declaration of built-in function .+"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wunused-parameter',
-        'description':'Unused parameter',
-        'patterns':[r".*: warning: unused parameter '.*'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wunused',
-        'description':'Unused function, variable or label',
-        'patterns':[r".*: warning: '.+' defined but not used",
-                    r".*: warning: unused variable '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wunused-value',
-        'description':'Statement with no effect',
-        'patterns':[r".*: warning: statement with no effect"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wmissing-field-initializers',
-        'description':'Missing initializer',
-        'patterns':[r".*: warning: missing initializer"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: \(near initialization for '.+'\)"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wformat',
-        'description':'Format string does not match arguments',
-        'patterns':[r".*: warning: format '.+' expects type '.+', but argument [0-9]+ has type '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wformat-extra-args',
-        'description':'Too many arguments for format string',
-        'patterns':[r".*: warning: too many arguments for format"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wsign-compare',
-        'description':'Comparison between signed and unsigned',
-        'patterns':[r".*: warning: comparison between signed and unsigned",
-                    r".*: warning: comparison of promoted \~unsigned with unsigned",
-                    r".*: warning: signed and unsigned type in conditional expression"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Comparison between enum and non-enum',
-        'patterns':[r".*: warning: enumeral and non-enumeral type in conditional expression"] },
-    { 'category':'libpng',  'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'libpng: zero area',
-        'patterns':[r".*libpng warning: Ignoring attempt to set cHRM RGB triangle with zero area"] },
-    { 'category':'aapt',    'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'aapt: no comment for public symbol',
-        'patterns':[r".*: warning: No comment for public symbol .+"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wmissing-braces',
-        'description':'Missing braces around initializer',
-        'patterns':[r".*: warning: missing braces around initializer.*"] },
-    { 'category':'C/C++',   'severity':severity.HARMLESS, 'members':[], 'option':'',
-        'description':'No newline at end of file',
-        'patterns':[r".*: warning: no newline at end of file"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wcast-qual',
-        'description':'Qualifier discarded',
-        'patterns':[r".*: warning: passing argument [0-9]+ of '.+' discards qualifiers from pointer target type",
-                    r".*: warning: assignment discards qualifiers from pointer target type",
-                    r".*: warning: return discards qualifiers from pointer target type"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wattributes',
-        'description':'Attribute ignored',
-        'patterns':[r".*: warning: '_*packed_*' attribute ignored"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wattributes',
-        'description':'Visibility mismatch',
-        'patterns':[r".*: warning: '.+' declared with greater visibility than the type of its field '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Shift count greater than width of type',
-        'patterns':[r".*: warning: (left|right) shift count >= width of type"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'extern &lt;foo&gt; is initialized',
-        'patterns':[r".*: warning: '.+' initialized and declared 'extern'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wold-style-declaration',
-        'description':'Old style declaration',
-        'patterns':[r".*: warning: 'static' is not at beginning of declaration"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wuninitialized',
-        'description':'Variable may be used uninitialized',
-        'patterns':[r".*: warning: '.+' may be used uninitialized in this function"] },
-    { 'category':'C/C++',   'severity':severity.HIGH,     'members':[], 'option':'-Wuninitialized',
-        'description':'Variable is used uninitialized',
-        'patterns':[r".*: warning: '.+' is used uninitialized in this function"] },
-    { 'category':'ld',      'severity':severity.MEDIUM,   'members':[], 'option':'-fshort-enums',
-        'description':'ld: possible enum size mismatch',
-        'patterns':[r".*: warning: .* uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wpointer-sign',
-        'description':'Pointer targets differ in signedness',
-        'patterns':[r".*: warning: pointer targets in initialization differ in signedness",
-                    r".*: warning: pointer targets in assignment differ in signedness",
-                    r".*: warning: pointer targets in return differ in signedness",
-                    r".*: warning: pointer targets in passing argument [0-9]+ of '.+' differ in signedness"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wstrict-overflow',
-        'description':'Assuming overflow does not occur',
-        'patterns':[r".*: warning: assuming signed overflow does not occur when assuming that .* is always (true|false)"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wempty-body',
-        'description':'Suggest adding braces around empty body',
-        'patterns':[r".*: warning: suggest braces around empty body in an 'if' statement",
-                    r".*: warning: empty body in an if-statement",
-                    r".*: warning: suggest braces around empty body in an 'else' statement",
-                    r".*: warning: empty body in an else-statement"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wparentheses',
-        'description':'Suggest adding parentheses',
-        'patterns':[r".*: warning: suggest explicit braces to avoid ambiguous 'else'",
-                    r".*: warning: suggest parentheses around arithmetic in operand of '.+'",
-                    r".*: warning: suggest parentheses around comparison in operand of '.+'",
-                    r".*: warning: suggest parentheses around '.+?' .+ '.+?'",
-                    r".*: warning: suggest parentheses around assignment used as truth value"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Static variable used in non-static inline function',
-        'patterns':[r".*: warning: '.+' is static but used in inline function '.+' which is not static"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], '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':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: type defaults to 'int' in declaration of '.+'"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: parameter names \(without types\) in function declaration"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wstrict-aliasing',
-        'description':'Dereferencing &lt;foo&gt; breaks strict aliasing rules',
-        'patterns':[r".*: warning: dereferencing .* break strict-aliasing rules"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wpointer-to-int-cast',
-        'description':'Cast from pointer to integer of different size',
-        'patterns':[r".*: warning: cast from pointer to integer of different size"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wint-to-pointer-cast',
-        '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,   'members':[], 'option':'',
-        'description':'Symbol redefined',
-        'patterns':[r".*: warning: "".+"" redefined"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: this is the location of the previous definition"] },
-    { 'category':'ld',      'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'ld: type and size of dynamic symbol are not defined',
-        'patterns':[r".*: warning: type and size of dynamic symbol `.+' are not defined"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Pointer from integer without cast',
-        'patterns':[r".*: warning: assignment makes pointer from integer without a cast"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Pointer from integer without cast',
-        'patterns':[r".*: warning: passing argument [0-9]+ of '.+' makes pointer from integer without a cast"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Integer from pointer without cast',
-        'patterns':[r".*: warning: assignment makes integer from pointer without a cast"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Integer from pointer without cast',
-        'patterns':[r".*: warning: passing argument [0-9]+ of '.+' makes integer from pointer without a cast"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Integer from pointer without cast',
-        'patterns':[r".*: warning: return makes integer from pointer without a cast"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wunknown-pragmas',
-        'description':'Ignoring pragma',
-        'patterns':[r".*: warning: ignoring #pragma .+"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wclobbered',
-        'description':'Variable might be clobbered by longjmp or vfork',
-        'patterns':[r".*: warning: variable '.+' might be clobbered by 'longjmp' or 'vfork'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wclobbered',
-        'description':'Argument might be clobbered by longjmp or vfork',
-        'patterns':[r".*: warning: argument '.+' might be clobbered by 'longjmp' or 'vfork'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wredundant-decls',
-        'description':'Redundant declaration',
-        'patterns':[r".*: warning: redundant redeclaration of '.+'"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: previous declaration of '.+' was here"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wswitch-enum',
-        'description':'Enum value not handled in switch',
-        'patterns':[r".*: warning: enumeration value '.+' not handled in switch"] },
-    { 'category':'java',    'severity':severity.MEDIUM,   'members':[], '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,   'members':[], 'option':'',
-        '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':'aapt',    'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'aapt: No default translation',
-        'patterns':[r".*: warning: string '.+' has no default translation in .*"] },
-    { 'category':'aapt',    'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'aapt: Missing default or required localization',
-        'patterns':[r".*: warning: \*\*\*\* string '.+' has no default or required localization for '.+' in .+"] },
-    { 'category':'aapt',    'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'aapt: String marked untranslatable, but translation exists',
-        'patterns':[r".*: warning: string '.+' in .* marked untranslatable but exists in locale '??_??'"] },
-    { 'category':'aapt',    'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'aapt: empty span in string',
-        'patterns':[r".*: warning: empty '.+' span found in text '.+"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Taking address of temporary',
-        'patterns':[r".*: warning: taking address of temporary"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Possible broken line continuation',
-        'patterns':[r".*: warning: backslash and newline separated by space"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Warray-bounds',
-        'description':'Array subscript out of bounds',
-        'patterns':[r".*: warning: array subscript is above array bounds",
-                    r".*: warning: array subscript is below array bounds"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Decimal constant is unsigned only in ISO C90',
-        'patterns':[r".*: warning: this decimal constant is unsigned only in ISO C90"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wmain',
-        'description':'main is usually a function',
-        'patterns':[r".*: warning: 'main' is usually a function"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Typedef ignored',
-        'patterns':[r".*: warning: 'typedef' was ignored in this declaration"] },
-    { 'category':'C/C++',   'severity':severity.HIGH,     'members':[], 'option':'-Waddress',
-        'description':'Address always evaluates to true',
-        'patterns':[r".*: warning: the address of '.+' will always evaluate as 'true'"] },
-    { 'category':'C/C++',   'severity':severity.FIXMENOW, 'members':[], 'option':'',
-        'description':'Freeing a non-heap object',
-        'patterns':[r".*: warning: attempt to free a non-heap object '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wchar-subscripts',
-        'description':'Array subscript has type char',
-        'patterns':[r".*: warning: array subscript has type 'char'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Constant too large for type',
-        'patterns':[r".*: warning: integer constant is too large for '.+' type"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Woverflow',
-        'description':'Constant too large for type, truncated',
-        'patterns':[r".*: warning: large integer implicitly truncated to unsigned type"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Woverflow',
-        'description':'Overflow in implicit constant conversion',
-        'patterns':[r".*: warning: overflow in implicit constant conversion"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Declaration does not declare anything',
-        'patterns':[r".*: warning: declaration 'class .+' does not declare anything"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wreorder',
-        'description':'Initialization order will be different',
-        'patterns':[r".*: warning: '.+' will be initialized after"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning:   '.+'"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning:   base '.+'"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning:   when initialized here"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wmissing-parameter-type',
-        'description':'Parameter type not specified',
-        'patterns':[r".*: warning: type of '.+' defaults to 'int'"] },
-    { 'category':'gcc',     'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Invalid option for C file',
-        'patterns':[r".*: warning: command line option "".+"" is valid for C\+\+\/ObjC\+\+ but not for C"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'User warning',
-        'patterns':[r".*: warning: #warning "".+"""] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wextra',
-        'description':'Dereferencing void*',
-        'patterns':[r".*: warning: dereferencing 'void \*' pointer"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wextra',
-        'description':'Comparison of pointer to zero',
-        'patterns':[r".*: warning: ordered comparison of pointer with integer zero"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wwrite-strings',
-        'description':'Conversion of string constant to non-const char*',
-        'patterns':[r".*: warning: deprecated conversion from string constant to '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wstrict-prototypes',
-        'description':'Function declaration isn''t a prototype',
-        'patterns':[r".*: warning: function declaration isn't a prototype"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wignored-qualifiers',
-        'description':'Type qualifiers ignored on function return value',
-        'patterns':[r".*: warning: type qualifiers ignored on function return type"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'&lt;foo&gt; declared inside parameter list, scope limited to this definition',
-        'patterns':[r".*: warning: '.+' declared inside parameter list"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: its scope is only this definition or declaration, which is probably not what you want"] },
-    { 'category':'C/C++',   'severity':severity.LOW,      'members':[], 'option':'-Wcomment',
-        'description':'Line continuation inside comment',
-        'patterns':[r".*: warning: multi-line comment"] },
-    { 'category':'C/C++',   'severity':severity.LOW,      'members':[], 'option':'-Wcomment',
-        'description':'Comment inside comment',
-        'patterns':[r".*: warning: "".+"" within comment"] },
-    { 'category':'C/C++',   'severity':severity.HARMLESS, 'members':[], 'option':'',
-        'description':'Extra tokens after #endif',
-        'patterns':[r".*: warning: extra tokens at end of #endif directive"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wenum-compare',
-        'description':'Comparison between different enums',
-        'patterns':[r".*: warning: comparison between 'enum .+' and 'enum .+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wconversion',
-        'description':'Implicit conversion of negative number to unsigned type',
-        'patterns':[r".*: warning: converting negative value '.+' to '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'',
-        'description':'Passing NULL as non-pointer argument',
-        'patterns':[r".*: warning: passing NULL to non-pointer argument [0-9]+ of '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wctor-dtor-privacy',
-        'description':'Class seems unusable because of private ctor/dtor' ,
-        'patterns':[r".*: warning: all member functions in class '.+' are private"] },
+warn_patterns = [
+    # pylint:disable=line-too-long,g-inconsistent-quotes
+    {'category': 'make', 'severity': Severity.MEDIUM,
+     'description': 'make: overriding commands/ignoring old commands',
+     'patterns': [r".*: warning: overriding commands for target .+",
+                  r".*: warning: ignoring old commands for target .+"]},
+    {'category': 'make', 'severity': Severity.HIGH,
+     'description': 'make: LOCAL_CLANG is false',
+     'patterns': [r".*: warning: LOCAL_CLANG is set to false"]},
+    {'category': 'make', 'severity': Severity.HIGH,
+     'description': 'SDK App using platform shared library',
+     'patterns': [r".*: warning: .+ \(.*app:sdk.*\) should not link to .+ \(native:platform\)"]},
+    {'category': 'make', 'severity': Severity.HIGH,
+     'description': 'System module linking to a vendor module',
+     'patterns': [r".*: warning: .+ \(.+\) should not link to .+ \(partition:.+\)"]},
+    {'category': 'make', 'severity': Severity.MEDIUM,
+     'description': 'Invalid SDK/NDK linking',
+     'patterns': [r".*: warning: .+ \(.+\) should not link to .+ \(.+\)"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Wimplicit-function-declaration',
+     'description': 'Implicit function declaration',
+     'patterns': [r".*: warning: implicit declaration of function .+",
+                  r".*: warning: implicitly declaring library function"]},
+    {'category': 'C/C++', 'severity': Severity.SKIP,
+     'description': 'skip, conflicting types for ...',
+     'patterns': [r".*: warning: conflicting types for '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Wtype-limits',
+     'description': 'Expression always evaluates to true or false',
+     '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': 'Use transient memory for control value',
+     'patterns': [r".*: warning: .+Using such transient memory for the control value is .*dangerous."]},
+    {'category': 'C/C++', 'severity': Severity.HIGH,
+     '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, 'option': 'infinite-recursion',
+     'description': 'Infinite recursion',
+     'patterns': [r".*: warning: all paths through this function will call itself"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH,
+     'description': 'Potential buffer overflow',
+     'patterns': [r".*: warning: Size argument is greater than .+ the destination buffer",
+                  r".*: warning: Potential buffer overflow.",
+                  r".*: warning: String copy function overflows destination buffer"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Incompatible pointer types',
+     'patterns': [r".*: warning: assignment from incompatible pointer type",
+                  r".*: warning: return from incompatible pointer type",
+                  r".*: warning: passing argument [0-9]+ of '.*' from incompatible pointer type",
+                  r".*: warning: initialization from incompatible pointer type"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-fno-builtin',
+     'description': 'Incompatible declaration of built in function',
+     'patterns': [r".*: warning: incompatible implicit declaration of built-in function .+"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Wincompatible-library-redeclaration',
+     'description': 'Incompatible redeclaration of library function',
+     'patterns': [r".*: warning: incompatible redeclaration of library function .+"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH,
+     'description': 'Null passed as non-null argument',
+     'patterns': [r".*: warning: Null passed to a callee that requires a non-null"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wunused-parameter',
+     'description': 'Unused parameter',
+     'patterns': [r".*: warning: unused parameter '.*'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wunused',
+     'description': 'Unused function, variable or label',
+     'patterns': [r".*: warning: '.+' defined but not used",
+                  r".*: warning: unused function '.+'",
+                  r".*: warning: private field '.+' is not used",
+                  r".*: warning: unused variable '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wunused-value',
+     'description': 'Statement with no effect or result unused',
+     'patterns': [r".*: warning: statement with no effect",
+                  r".*: warning: expression result unused"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wunused-result',
+     'description': 'Ignoreing return value of function',
+     'patterns': [r".*: warning: ignoring return value of function .+Wunused-result"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wmissing-field-initializers',
+     'description': 'Missing initializer',
+     'patterns': [r".*: warning: missing initializer"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wdelete-non-virtual-dtor',
+     'description': 'Need virtual destructor',
+     'patterns': [r".*: warning: delete called .* has virtual functions but non-virtual destructor"]},
+    {'category': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip, near initialization for ...',
+     'patterns': [r".*: warning: \(near initialization for '.+'\)"]},
+    {'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': '-Wformat',
+     'description': 'Format string does not match arguments',
+     'patterns': [r".*: warning: format '.+' expects type '.+', but argument [0-9]+ has type '.+'",
+                  r".*: warning: more '%' conversions than data arguments",
+                  r".*: warning: data argument not used by format string",
+                  r".*: warning: incomplete format specifier",
+                  r".*: warning: unknown conversion type .* in format",
+                  r".*: warning: format .+ expects .+ but argument .+Wformat=",
+                  r".*: warning: field precision should have .+ but argument has .+Wformat",
+                  r".*: warning: format specifies type .+ but the argument has .*type .+Wformat"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wformat-extra-args',
+     'description': 'Too many arguments for format string',
+     'patterns': [r".*: warning: too many arguments for format"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wformat-invalid-specifier',
+     'description': 'Invalid format specifier',
+     'patterns': [r".*: warning: invalid .+ specifier '.+'.+format-invalid-specifier"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wsign-compare',
+     'description': 'Comparison between signed and unsigned',
+     'patterns': [r".*: warning: comparison between signed and unsigned",
+                  r".*: warning: comparison of promoted \~unsigned with unsigned",
+                  r".*: warning: signed and unsigned type in conditional expression"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Comparison between enum and non-enum',
+     'patterns': [r".*: warning: enumeral and non-enumeral type in conditional expression"]},
+    {'category': 'libpng', 'severity': Severity.MEDIUM,
+     'description': 'libpng: zero area',
+     'patterns': [r".*libpng warning: Ignoring attempt to set cHRM RGB triangle with zero area"]},
+    {'category': 'aapt', 'severity': Severity.MEDIUM,
+     'description': 'aapt: no comment for public symbol',
+     'patterns': [r".*: warning: No comment for public symbol .+"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wmissing-braces',
+     'description': 'Missing braces around initializer',
+     'patterns': [r".*: warning: missing braces around initializer.*"]},
+    {'category': 'C/C++', 'severity': Severity.HARMLESS,
+     'description': 'No newline at end of file',
+     'patterns': [r".*: warning: no newline at end of file"]},
+    {'category': 'C/C++', 'severity': Severity.HARMLESS,
+     'description': 'Missing space after macro name',
+     'patterns': [r".*: warning: missing whitespace after the macro name"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wcast-align',
+     'description': 'Cast increases required alignment',
+     'patterns': [r".*: warning: cast from .* to .* increases required alignment .*"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wcast-qual',
+     'description': 'Qualifier discarded',
+     'patterns': [r".*: warning: passing argument [0-9]+ of '.+' discards qualifiers from pointer target type",
+                  r".*: warning: assignment discards qualifiers from pointer target type",
+                  r".*: warning: passing .+ to parameter of type .+ discards qualifiers",
+                  r".*: warning: assigning to .+ from .+ discards qualifiers",
+                  r".*: warning: initializing .+ discards qualifiers .+types-discards-qualifiers",
+                  r".*: warning: return discards qualifiers from pointer target type"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wunknown-attributes',
+     'description': 'Unknown attribute',
+     'patterns': [r".*: warning: unknown attribute '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wignored-attributes',
+     'description': 'Attribute ignored',
+     'patterns': [r".*: warning: '_*packed_*' attribute ignored",
+                  r".*: warning: attribute declaration must precede definition .+ignored-attributes"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wvisibility',
+     'description': 'Visibility problem',
+     'patterns': [r".*: warning: declaration of '.+' will not be visible outside of this function"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wattributes',
+     'description': 'Visibility mismatch',
+     'patterns': [r".*: warning: '.+' declared with greater visibility than the type of its field '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Shift count greater than width of type',
+     'patterns': [r".*: warning: (left|right) shift count >= width of type"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wextern-initializer',
+     'description': 'extern &lt;foo&gt; is initialized',
+     'patterns': [r".*: warning: '.+' initialized and declared 'extern'",
+                  r".*: warning: 'extern' variable has an initializer"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wold-style-declaration',
+     'description': 'Old style declaration',
+     'patterns': [r".*: warning: 'static' is not at beginning of declaration"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wreturn-type',
+     'description': 'Missing return value',
+     'patterns': [r".*: warning: control reaches end of non-void function"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wimplicit-int',
+     'description': 'Implicit int type',
+     'patterns': [r".*: warning: type specifier missing, defaults to 'int'",
+                  r".*: warning: type defaults to 'int' in declaration of '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wmain-return-type',
+     'description': 'Main function should return int',
+     'patterns': [r".*: warning: return type of 'main' is not 'int'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wuninitialized',
+     'description': 'Variable may be used uninitialized',
+     'patterns': [r".*: warning: '.+' may be used uninitialized in this function"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Wuninitialized',
+     'description': 'Variable is used uninitialized',
+     'patterns': [r".*: warning: '.+' is used uninitialized in this function",
+                  r".*: warning: variable '.+' is uninitialized when used here"]},
+    {'category': 'ld', 'severity': Severity.MEDIUM, 'option': '-fshort-enums',
+     'description': 'ld: possible enum size mismatch',
+     'patterns': [r".*: warning: .* uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wpointer-sign',
+     'description': 'Pointer targets differ in signedness',
+     'patterns': [r".*: warning: pointer targets in initialization differ in signedness",
+                  r".*: warning: pointer targets in assignment differ in signedness",
+                  r".*: warning: pointer targets in return differ in signedness",
+                  r".*: warning: pointer targets in passing argument [0-9]+ of '.+' differ in signedness"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wstrict-overflow',
+     'description': 'Assuming overflow does not occur',
+     'patterns': [r".*: warning: assuming signed overflow does not occur when assuming that .* is always (true|false)"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wempty-body',
+     'description': 'Suggest adding braces around empty body',
+     'patterns': [r".*: warning: suggest braces around empty body in an 'if' statement",
+                  r".*: warning: empty body in an if-statement",
+                  r".*: warning: suggest braces around empty body in an 'else' statement",
+                  r".*: warning: empty body in an else-statement"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wparentheses',
+     'description': 'Suggest adding parentheses',
+     'patterns': [r".*: warning: suggest explicit braces to avoid ambiguous 'else'",
+                  r".*: warning: suggest parentheses around arithmetic in operand of '.+'",
+                  r".*: warning: suggest parentheses around comparison in operand of '.+'",
+                  r".*: warning: logical not is only applied to the left hand side of this comparison",
+                  r".*: warning: using the result of an assignment as a condition without parentheses",
+                  r".*: warning: .+ has lower precedence than .+ be evaluated first .+Wparentheses",
+                  r".*: warning: suggest parentheses around '.+?' .+ '.+?'",
+                  r".*: warning: suggest parentheses around assignment used as truth value"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Static variable used in non-static inline function',
+     'patterns': [r".*: warning: '.+' is static but used in inline function '.+' which is not static"]},
+    {'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': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip, parameter name (without types) in function declaration',
+     'patterns': [r".*: warning: parameter names \(without types\) in function declaration"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wstrict-aliasing',
+     'description': 'Dereferencing &lt;foo&gt; breaks strict aliasing rules',
+     'patterns': [r".*: warning: dereferencing .* break strict-aliasing rules"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wpointer-to-int-cast',
+     'description': 'Cast from pointer to integer of different size',
+     'patterns': [r".*: warning: cast from pointer to integer of different size",
+                  r".*: warning: initialization makes pointer from integer without a cast"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wint-to-pointer-cast',
+     '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"]},
+    {'category': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip, ... location of the previous definition',
+     'patterns': [r".*: warning: this is the location of the previous definition"]},
+    {'category': 'ld', 'severity': Severity.MEDIUM,
+     'description': 'ld: type and size of dynamic symbol are not defined',
+     'patterns': [r".*: warning: type and size of dynamic symbol `.+' are not defined"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Pointer from integer without cast',
+     'patterns': [r".*: warning: assignment makes pointer from integer without a cast"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Pointer from integer without cast',
+     'patterns': [r".*: warning: passing argument [0-9]+ of '.+' makes pointer from integer without a cast"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Integer from pointer without cast',
+     'patterns': [r".*: warning: assignment makes integer from pointer without a cast"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Integer from pointer without cast',
+     'patterns': [r".*: warning: passing argument [0-9]+ of '.+' makes integer from pointer without a cast"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Integer from pointer without cast',
+     'patterns': [r".*: warning: return makes integer from pointer without a cast"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wunknown-pragmas',
+     'description': 'Ignoring pragma',
+     'patterns': [r".*: warning: ignoring #pragma .+"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-W#pragma-messages',
+     'description': 'Pragma warning messages',
+     'patterns': [r".*: warning: .+W#pragma-messages"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wclobbered',
+     'description': 'Variable might be clobbered by longjmp or vfork',
+     'patterns': [r".*: warning: variable '.+' might be clobbered by 'longjmp' or 'vfork'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wclobbered',
+     'description': 'Argument might be clobbered by longjmp or vfork',
+     'patterns': [r".*: warning: argument '.+' might be clobbered by 'longjmp' or 'vfork'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wredundant-decls',
+     'description': 'Redundant declaration',
+     'patterns': [r".*: warning: redundant redeclaration of '.+'"]},
+    {'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',
+     'description': 'Enum value not handled in switch',
+     'patterns': [r".*: warning: .*enumeration value.* not handled in switch.+Wswitch"]},
+    {'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"]},
+
+    # Warnings from Error Prone.
+    {'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\] .+']},
+
+    # Warnings from Error Prone (auto generated list).
+    {'category': 'java',
+     'severity': Severity.LOW,
+     'description':
+         'Java: Deprecated item is not annotated with @Deprecated',
+     'patterns': [r".*: warning: \[DepAnn\] .+"]},
+    {'category': 'java',
+     'severity': Severity.LOW,
+     'description':
+         'Java: Fallthrough warning suppression has no effect if warning is suppressed',
+     'patterns': [r".*: warning: \[FallthroughSuppression\] .+"]},
+    {'category': 'java',
+     'severity': Severity.LOW,
+     'description':
+         'Java: Prefer \'L\' to \'l\' for the suffix to long literals',
+     'patterns': [r".*: warning: \[LongLiteralLowerCaseSuffix\] .+"]},
+    {'category': 'java',
+     'severity': Severity.LOW,
+     'description':
+         'Java: @Binds is a more efficient and declaritive mechanism for delegating a binding.',
+     'patterns': [r".*: warning: \[UseBinds\] .+"]},
+    {'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: 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: BigDecimal(double) and BigDecimal.valueOf(double) may lose precision, prefer BigDecimal(String) or BigDecimal(long)',
+     'patterns': [r".*: warning: \[BigDecimalLiteralDouble\] .+"]},
+    {'category': 'java',
+     'severity': Severity.MEDIUM,
+     'description':
+         'Java: Mockito cannot mock final classes',
+     'patterns': [r".*: warning: \[CannotMockFinalClass\] .+"]},
+    {'category': 'java',
+     'severity': Severity.MEDIUM,
+     'description':
+         'Java: This code, which counts elements using a loop, can be replaced by a simpler library method',
+     'patterns': [r".*: warning: \[ElementsCountedInLoop\] .+"]},
+    {'category': 'java',
+     'severity': Severity.MEDIUM,
+     'description':
+         'Java: Empty top-level type declaration',
+     'patterns': [r".*: warning: \[EmptyTopLevelDeclaration\] .+"]},
+    {'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: 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: This annotation has incompatible modifiers as specified by its @IncompatibleModifiers annotation',
+     'patterns': [r".*: warning: \[IncompatibleModifiers\] .+"]},
+    {'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: 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: Enum switch statement is missing cases',
+     'patterns': [r".*: warning: \[MissingCasesInEnumSwitch\] .+"]},
+    {'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: Source files should not contain multiple top-level class declarations',
+     'patterns': [r".*: warning: \[MultipleTopLevelClasses\] .+"]},
+    {'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: @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: Package names should match the directory they are declared in',
+     'patterns': [r".*: warning: \[PackageLocation\] .+"]},
+    {'category': 'java',
+     'severity': Severity.MEDIUM,
+     'description':
+         'Java: Second argument to Preconditions.* is a call to String.format(), which can be unwrapped',
+     'patterns': [r".*: warning: \[PreconditionsErrorMessageEagerEvaluation\] .+"]},
+    {'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: Protobuf fields cannot be null, so this check is redundant',
+     'patterns': [r".*: warning: \[ProtoFieldPreconditionsCheckNotNull\] .+"]},
+    {'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: A static variable or method should not be accessed from an object instance',
+     'patterns': [r".*: warning: \[StaticAccessedFromInstance\] .+"]},
+    {'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: 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: Using static imports for types is unnecessary',
+     'patterns': [r".*: warning: \[UnnecessaryStaticImport\] .+"]},
+    {'category': 'java',
+     'severity': Severity.MEDIUM,
+     'description':
+         'Java: Unsynchronized method overrides a synchronized method.',
+     'patterns': [r".*: warning: \[UnsynchronizedOverridesSynchronized\] .+"]},
+    {'category': 'java',
+     'severity': Severity.MEDIUM,
+     'description':
+         'Java: Non-constant variable missing @Var annotation',
+     'patterns': [r".*: warning: \[Var\] .+"]},
+    {'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: 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: Hardcoded reference to /sdcard',
+     'patterns': [r".*: warning: \[HardCodedSdCardPath\] .+"]},
+    {'category': 'java',
+     'severity': Severity.MEDIUM,
+     'description':
+         'Java: Incompatible type as argument to Object-accepting Java collections method',
+     'patterns': [r".*: warning: \[CollectionIncompatibleType\] .+"]},
+    {'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: Although Guice allows injecting final fields, doing so is not recommended because the injected value may not be visible to other threads.',
+     'patterns': [r".*: warning: \[GuiceInjectOnFinalField\] .+"]},
+    {'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: Double-checked locking on non-volatile fields is unsafe',
+     'patterns': [r".*: warning: \[DoubleCheckedLocking\] .+"]},
+    {'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: 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.HIGH,
+     'description':
+         'Java: Reference equality used to compare arrays',
+     'patterns': [r".*: warning: \[ArrayEquals\] .+"]},
+    {'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: 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: Possible sign flip from narrowing conversion',
+     'patterns': [r".*: warning: \[BadComparable\] .+"]},
+    {'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: valueOf provides better time and space performance',
+     'patterns': [r".*: warning: \[BoxedPrimitiveConstructor\] .+"]},
+    {'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: Inner class is non-static but does not reference enclosing class',
+     'patterns': [r".*: warning: \[ClassCanBeStatic\] .+"]},
+    {'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: 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: Non-compile-time constant expression passed to parameter with @CompileTimeConstant type annotation.',
+     'patterns': [r".*: warning: \[CompileTimeConstant\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Exception created but not thrown',
+     'patterns': [r".*: warning: \[DeadException\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Division by integer literal zero',
+     'patterns': [r".*: warning: \[DivZero\] .+"]},
+    {'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: Method annotated @ForOverride must be protected or package-private and only invoked from declaring class',
+     'patterns': [r".*: warning: \[ForOverride\] .+"]},
+    {'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: 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: An object is tested for equality to itself using Guava Libraries',
+     'patterns': [r".*: warning: \[GuavaSelfEquals\] .+"]},
+    {'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: Cipher.getInstance() is invoked using either the default settings or ECB mode',
+     'patterns': [r".*: warning: \[InsecureCipherMode\] .+"]},
+    {'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: The argument to Class#isInstance(Object) should not be a Class',
+     'patterns': [r".*: warning: \[IsInstanceOfClass\] .+"]},
+    {'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 prefix name with "test"',
+     'patterns': [r".*: warning: \[JUnit3TestNotRun\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: setUp() method will not be run; Please add a @Before annotation',
+     'patterns': [r".*: warning: \[JUnit4SetUpNotRun\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: tearDown() method will not be run; Please add an @After annotation',
+     'patterns': [r".*: warning: \[JUnit4TearDownNotRun\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Test method will not be run; please add @Test annotation',
+     'patterns': [r".*: warning: \[JUnit4TestNotRun\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Printf-like format string does not match its arguments',
+     'patterns': [r".*: warning: \[MalformedFormatString\] .+"]},
+    {'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: Modifying a collection with itself',
+     'patterns': [r".*: warning: \[ModifyingCollectionWithItself\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Compound assignments to bytes, shorts, chars, and floats hide dangerous casts',
+     'patterns': [r".*: warning: \[NarrowingCompoundAssignment\] .+"]},
+    {'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',
+     '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: 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: Varargs doesn\'t agree for overridden method',
+     'patterns': [r".*: warning: \[Overrides\] .+"]},
+    {'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: 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:  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: \[SelfComparision\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Variable compared to itself',
+     'patterns': [r".*: warning: \[SelfEquality\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: An object is tested for equality to itself',
+     'patterns': [r".*: warning: \[SelfEquals\] .+"]},
+    {'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: 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: 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: 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: 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: Use of wildcard imports is forbidden',
+     'patterns': [r".*: warning: \[WildcardImport\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Method parameter has wrong package',
+     'patterns': [r".*: warning: \[ParameterPackage\] .+"]},
+    {'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: Return value of android.graphics.Rect.intersect() must be checked',
+     'patterns': [r".*: warning: \[RectIntersectReturnValueIgnored\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Invalid printf-style format string',
+     'patterns': [r".*: warning: \[FormatString\] .+"]},
+    {'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: Injected constructors cannot be optional nor have binding annotations',
+     'patterns': [r".*: warning: \[InjectedConstructorAnnotations\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: The target of a scoping annotation must be set to METHOD and/or TYPE.',
+     'patterns': [r".*: warning: \[InjectInvalidTargetingOnScopingAnnotation\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Abstract 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: A class may not have more than one injectable constructor.',
+     'patterns': [r".*: warning: \[MoreThanOneInjectableConstructor\] .+"]},
+    {'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: Annotations cannot be both Qualifiers/BindingAnnotations and Scopes',
+     'patterns': [r".*: warning: \[OverlappingQualifierAndScopeAnnotation\] .+"]},
+    {'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: Dagger @Provides methods may not return null unless annotated with @Nullable',
+     'patterns': [r".*: warning: \[DaggerProvidesNull\] .+"]},
+    {'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: This method is not annotated with @Inject, but it overrides a  method that is  annotated with @javax.inject.Inject.',
+     'patterns': [r".*: warning: \[OverridesJavaxInjectableMethod\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Checks for unguarded accesses to fields and methods with @GuardedBy annotations',
+     'patterns': [r".*: warning: \[GuardedByChecker\] .+"]},
+    {'category': 'java',
+     'severity': Severity.HIGH,
+     'description':
+         'Java: Invalid @GuardedBy expression',
+     'patterns': [r".*: warning: \[GuardedByValidator\] .+"]},
+    {'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: This method does not acquire the locks specified by its @LockMethod annotation',
+     'patterns': [r".*: warning: \[LockMethodChecker\] .+"]},
+    {'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.UNKNOWN,
+     'description': 'Java: Unclassified/unrecognized warnings',
+     'patterns': [r".*: warning: \[.+\] .+"]},
+
+    {'category': 'aapt', 'severity': Severity.MEDIUM,
+     'description': 'aapt: No default translation',
+     'patterns': [r".*: warning: string '.+' has no default translation in .*"]},
+    {'category': 'aapt', 'severity': Severity.MEDIUM,
+     'description': 'aapt: Missing default or required localization',
+     'patterns': [r".*: warning: \*\*\*\* string '.+' has no default or required localization for '.+' in .+"]},
+    {'category': 'aapt', 'severity': Severity.MEDIUM,
+     'description': 'aapt: String marked untranslatable, but translation exists',
+     'patterns': [r".*: warning: string '.+' in .* marked untranslatable but exists in locale '??_??'"]},
+    {'category': 'aapt', 'severity': Severity.MEDIUM,
+     'description': 'aapt: empty span in string',
+     'patterns': [r".*: warning: empty '.+' span found in text '.+"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Taking address of temporary',
+     'patterns': [r".*: warning: taking address of temporary"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Possible broken line continuation',
+     'patterns': [r".*: warning: backslash and newline separated by space"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wundefined-var-template',
+     'description': 'Undefined variable template',
+     'patterns': [r".*: warning: instantiation of variable .* no definition is available"]},
+    {'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,
+     'description': 'Excess elements in initializer',
+     'patterns': [r".*: warning: excess elements in .+ initializer"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Decimal constant is unsigned only in ISO C90',
+     'patterns': [r".*: warning: this decimal constant is unsigned only in ISO C90"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wmain',
+     'description': 'main is usually a function',
+     'patterns': [r".*: warning: 'main' is usually a function"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Typedef ignored',
+     'patterns': [r".*: warning: 'typedef' was ignored in this declaration"]},
+    {'category': 'C/C++', 'severity': Severity.HIGH, 'option': '-Waddress',
+     'description': 'Address always evaluates to true',
+     'patterns': [r".*: warning: the address of '.+' will always evaluate as 'true'"]},
+    {'category': 'C/C++', 'severity': Severity.FIXMENOW,
+     'description': 'Freeing a non-heap object',
+     'patterns': [r".*: warning: attempt to free a non-heap object '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wchar-subscripts',
+     'description': 'Array subscript has type char',
+     'patterns': [r".*: warning: array subscript .+ type 'char'.+Wchar-subscripts"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Constant too large for type',
+     'patterns': [r".*: warning: integer constant is too large for '.+' type"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Woverflow',
+     'description': 'Constant too large for type, truncated',
+     'patterns': [r".*: warning: large integer implicitly truncated to unsigned type"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Winteger-overflow',
+     'description': 'Overflow in expression',
+     'patterns': [r".*: warning: overflow in expression; .*Winteger-overflow"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Woverflow',
+     'description': 'Overflow in implicit constant conversion',
+     'patterns': [r".*: warning: overflow in implicit constant conversion"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Declaration does not declare anything',
+     'patterns': [r".*: warning: declaration 'class .+' does not declare anything"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wreorder',
+     'description': 'Initialization order will be different',
+     'patterns': [r".*: warning: '.+' will be initialized after",
+                  r".*: warning: field .+ will be initialized after .+Wreorder"]},
+    {'category': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip,   ....',
+     'patterns': [r".*: warning:   '.+'"]},
+    {'category': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip,   base ...',
+     'patterns': [r".*: warning:   base '.+'"]},
+    {'category': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip,   when initialized here',
+     'patterns': [r".*: warning:   when initialized here"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wmissing-parameter-type',
+     'description': 'Parameter type not specified',
+     'patterns': [r".*: warning: type of '.+' defaults to 'int'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wmissing-declarations',
+     'description': 'Missing declarations',
+     'patterns': [r".*: warning: declaration does not declare anything"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wmissing-noreturn',
+     'description': 'Missing noreturn',
+     'patterns': [r".*: warning: function '.*' could be declared with attribute 'noreturn'"]},
+    # pylint:disable=anomalous-backslash-in-string
+    # TODO(chh): fix the backslash pylint warning.
+    {'category': 'gcc', 'severity': Severity.MEDIUM,
+     'description': 'Invalid option for C file',
+     'patterns': [r".*: warning: command line option "".+"" is valid for C\+\+\/ObjC\+\+ but not for C"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'User warning',
+     'patterns': [r".*: warning: #warning "".+"""]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wvexing-parse',
+     'description': 'Vexing parsing problem',
+     'patterns': [r".*: warning: empty parentheses interpreted as a function declaration"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wextra',
+     'description': 'Dereferencing void*',
+     'patterns': [r".*: warning: dereferencing 'void \*' pointer"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Comparison of pointer and integer',
+     'patterns': [r".*: warning: ordered comparison of pointer with integer zero",
+                  r".*: warning: .*comparison between pointer and integer"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Use of error-prone unary operator',
+     'patterns': [r".*: warning: use of unary operator that may be intended as compound assignment"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wwrite-strings',
+     'description': 'Conversion of string constant to non-const char*',
+     'patterns': [r".*: warning: deprecated conversion from string constant to '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wstrict-prototypes',
+     'description': 'Function declaration isn''t a prototype',
+     'patterns': [r".*: warning: function declaration isn't a prototype"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wignored-qualifiers',
+     'description': 'Type qualifiers ignored on function return value',
+     'patterns': [r".*: warning: type qualifiers ignored on function return type",
+                  r".*: warning: .+ type qualifier .+ has no effect .+Wignored-qualifiers"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': '&lt;foo&gt; declared inside parameter list, scope limited to this definition',
+     'patterns': [r".*: warning: '.+' declared inside parameter list"]},
+    {'category': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip, its scope is only this ...',
+     'patterns': [r".*: warning: its scope is only this definition or declaration, which is probably not what you want"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wcomment',
+     'description': 'Line continuation inside comment',
+     '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.TIDY,
+     'description': 'clang-tidy 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"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wdeprecated-declarations',
+     'description': 'Deprecated declarations',
+     'patterns': [r".*: warning: .+ is deprecated.+deprecated-declarations"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wdeprecated-register',
+     'description': 'Deprecated register',
+     'patterns': [r".*: warning: 'register' storage class specifier is deprecated"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wpointer-sign',
+     'description': 'Converts between pointers to integer types with different sign',
+     'patterns': [r".*: warning: .+ converts between pointers to integer types with different sign"]},
+    {'category': 'C/C++', 'severity': Severity.HARMLESS,
+     'description': 'Extra tokens after #endif',
+     '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"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wconversion',
+     'description': 'Conversion may change value',
+     'patterns': [r".*: warning: converting negative value '.+' to '.+'",
+                  r".*: warning: conversion to '.+' .+ may (alter|change)"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wconversion-null',
+     'description': 'Converting to non-pointer type from NULL',
+     'patterns': [r".*: warning: converting to non-pointer type '.+' from NULL"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wnull-conversion',
+     'description': 'Converting NULL to non-pointer type',
+     'patterns': [r".*: warning: implicit conversion of NULL constant to '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wnon-literal-null-conversion',
+     '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"]},
+    {'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 '.+'"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wctor-dtor-privacy',
+     'description': 'Class seems unusable because of private ctor/dtor',
+     'patterns': [r".*: warning: all member functions in class '.+' are private"]},
     # skip this next one, because it only points out some RefBase-based classes where having a private destructor is perfectly fine
-    { 'category':'C/C++',   'severity':severity.SKIP,     'members':[], 'option':'-Wctor-dtor-privacy',
-        'description':'Class seems unusable because of private ctor/dtor' ,
-        'patterns':[r".*: warning: 'class .+' only defines a private destructor and has no friends"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wctor-dtor-privacy',
-        'description':'Class seems unusable because of private ctor/dtor' ,
-        'patterns':[r".*: warning: 'class .+' only defines private constructors and has no friends"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wpointer-arith',
-        'description':'void* used in arithmetic' ,
-        'patterns':[r".*: warning: pointer of type 'void \*' used in (arithmetic|subtraction)",
-                    r".*: warning: wrong type argument to increment"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,   'members':[], 'option':'-Wsign-promo',
-        'description':'Overload resolution chose to promote from unsigned or enum to signed type' ,
-        'patterns':[r".*: warning: passing '.+' chooses 'int' over '.* int'"] },
-    { 'category':'cont.',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning:   in call to '.+'"] },
-    { 'category':'C/C++',   'severity':severity.HIGH,     'members':[], '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,     'members':[], 'option':'',
-        'description':'Converting from <type> to <other type>',
-        'patterns':[r".*: warning: converting to '.+' from '.+'"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,     'members':[], 'option':'',
-        'description':'Return value from void function',
-        'patterns':[r".*: warning: 'return' with a value, in function returning void"] },
-    { 'category':'C/C++',   'severity':severity.LOW,     'members':[], 'option':'',
-        'description':'Useless specifier',
-        'patterns':[r".*: warning: useless storage class specifier in empty declaration"] },
-    { 'category':'logtags',   'severity':severity.LOW,     'members':[], 'option':'',
-        'description':'Duplicate logtag',
-        'patterns':[r".*: warning: tag "".+"" \(None\) duplicated in .+"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,     'members':[], 'option':'',
-        'description':'Operator new returns NULL',
-        'patterns':[r".*: warning: 'operator new' must not return NULL unless it is declared 'throw\(\)' .+"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,     'members':[], 'option':'',
-        'description':'NULL used in arithmetic',
-        'patterns':[r".*: warning: NULL used in arithmetic"] },
-    { 'category':'C/C++',   'severity':severity.MEDIUM,     'members':[], 'option':'',
-        'description':'Use of deprecated method',
-        'patterns':[r".*: warning: '.+' is deprecated .+"] },
+    {'category': 'C/C++', 'severity': Severity.SKIP, 'option': '-Wctor-dtor-privacy',
+     'description': 'Class seems unusable because of private ctor/dtor',
+     'patterns': [r".*: warning: 'class .+' only defines a private destructor and has no friends"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wctor-dtor-privacy',
+     'description': 'Class seems unusable because of private ctor/dtor',
+     'patterns': [r".*: warning: 'class .+' only defines private constructors and has no friends"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wgnu-static-float-init',
+     'description': 'In-class initializer for static const float/double',
+     'patterns': [r".*: warning: in-class initializer for static data member of .+const (float|double)"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wpointer-arith',
+     'description': 'void* used in arithmetic',
+     'patterns': [r".*: warning: pointer of type 'void \*' used in (arithmetic|subtraction)",
+                  r".*: warning: arithmetic on .+ to void is a GNU extension.*Wpointer-arith",
+                  r".*: warning: wrong type argument to increment"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wsign-promo',
+     'description': 'Overload resolution chose to promote from unsigned or enum to signed type',
+     'patterns': [r".*: warning: passing '.+' chooses '.+' over '.+'.*Wsign-promo"]},
+    {'category': 'cont.', 'severity': Severity.SKIP,
+     'description': 'skip,   in call to ...',
+     'patterns': [r".*: warning:   in call to '.+'"]},
+    {'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': 'Return value from void function',
+     'patterns': [r".*: warning: 'return' with a value, in function returning void"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': 'multichar',
+     'description': 'Multi-character character constant',
+     'patterns': [r".*: warning: multi-character character constant"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': 'writable-strings',
+     'description': 'Conversion from string literal to char*',
+     'patterns': [r".*: warning: .+ does not allow conversion from string literal to 'char \*'"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wextra-semi',
+     'description': 'Extra \';\'',
+     'patterns': [r".*: warning: extra ';' .+extra-semi"]},
+    {'category': 'C/C++', 'severity': Severity.LOW,
+     'description': 'Useless specifier',
+     'patterns': [r".*: warning: useless storage class specifier in empty declaration"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wduplicate-decl-specifier',
+     'description': 'Duplicate declaration specifier',
+     'patterns': [r".*: warning: duplicate '.+' declaration specifier"]},
+    {'category': 'logtags', 'severity': Severity.LOW,
+     'description': 'Duplicate logtag',
+     'patterns': [r".*: warning: tag \".+\" \(.+\) duplicated in .+"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'typedef-redefinition',
+     'description': 'Typedef redefinition',
+     'patterns': [r".*: warning: redefinition of typedef '.+' is a C11 feature"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'gnu-designator',
+     'description': 'GNU old-style field designator',
+     'patterns': [r".*: warning: use of GNU old-style field designator extension"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'missing-field-initializers',
+     'description': 'Missing field initializers',
+     'patterns': [r".*: warning: missing field '.+' initializer"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'missing-braces',
+     'description': 'Missing braces',
+     'patterns': [r".*: warning: suggest braces around initialization of",
+                  r".*: warning: too many braces around scalar initializer .+Wmany-braces-around-scalar-init",
+                  r".*: warning: braces around scalar initializer"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'sign-compare',
+     'description': 'Comparison of integers of different signs',
+     'patterns': [r".*: warning: comparison of integers of different signs.+sign-compare"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'dangling-else',
+     'description': 'Add braces to avoid dangling else',
+     'patterns': [r".*: warning: add explicit braces to avoid dangling else"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'initializer-overrides',
+     'description': 'Initializer overrides prior initialization',
+     'patterns': [r".*: warning: initializer overrides prior initialization of this subobject"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'self-assign',
+     'description': 'Assigning value to self',
+     'patterns': [r".*: warning: explicitly assigning value of .+ to itself"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'gnu-variable-sized-type-not-at-end',
+     'description': 'GNU extension, variable sized type not at end',
+     'patterns': [r".*: warning: field '.+' with variable sized type '.+' not at the end of a struct or class"]},
+    {'category': 'logtags', 'severity': Severity.LOW, 'option': 'tautological-constant-out-of-range-compare',
+     'description': 'Comparison of constant is always false/true',
+     'patterns': [r".*: comparison of .+ is always .+Wtautological-constant-out-of-range-compare"]},
+    {'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',
+     'description': 'Incompatible 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"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': 'tautological-compare',
+     'description': 'Comparison of self is always false',
+     'patterns': [r".*: self-comparison always evaluates to false"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': 'constant-logical-operand',
+     'description': 'Logical op with constant operand',
+     'patterns': [r".*: use of logical '.+' with constant operand"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': 'literal-suffix',
+     'description': 'Needs a space between literal and string macro',
+     'patterns': [r".*: warning: invalid suffix on literal.+ requires a space .+Wliteral-suffix"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '#warnings',
+     'description': 'Warnings from #warning',
+     'patterns': [r".*: warning: .+-W#warnings"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': 'absolute-value',
+     'description': 'Using float/int absolute value function with int/float argument',
+     'patterns': [r".*: warning: using .+ absolute value function .+ when argument is .+ type .+Wabsolute-value",
+                  r".*: warning: absolute value function '.+' given .+ which may cause truncation .+Wabsolute-value"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Wc++11-extensions',
+     'description': 'Using C++11 extensions',
+     'patterns': [r".*: warning: 'auto' type specifier is a C\+\+11 extension"]},
+    {'category': 'C/C++', 'severity': Severity.LOW,
+     'description': 'Refers to implicitly defined namespace',
+     'patterns': [r".*: warning: using directive refers to implicitly-defined namespace .+"]},
+    {'category': 'C/C++', 'severity': Severity.LOW, 'option': '-Winvalid-pp-token',
+     'description': 'Invalid pp token',
+     'patterns': [r".*: warning: missing .+Winvalid-pp-token"]},
+
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Operator new returns NULL',
+     'patterns': [r".*: warning: 'operator new' must not return NULL unless it is declared 'throw\(\)' .+"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wnull-arithmetic',
+     'description': 'NULL used in arithmetic',
+     'patterns': [r".*: warning: NULL used in arithmetic",
+                  r".*: warning: comparison between NULL and non-pointer"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': 'header-guard',
+     'description': 'Misspelled header guard',
+     'patterns': [r".*: warning: '.+' is used as a header guard .+ followed by .+ different macro"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': 'empty-body',
+     'description': 'Empty loop body',
+     'patterns': [r".*: warning: .+ loop has empty body"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': 'enum-conversion',
+     'description': 'Implicit conversion from enumeration type',
+     'patterns': [r".*: warning: implicit conversion from enumeration type '.+'"]},
+    {'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': '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"]},
+    {'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"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wsizeof-pointer-memacces',
+     'description': 'Bad argument size of memory access functions',
+     'patterns': [r".*: warning: .+\[-Wsizeof-pointer-memaccess\]"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Return value not checked',
+     'patterns': [r".*: warning: The return value from .+ is not checked"]},
+    {'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, '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"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM,
+     'description': 'Closing a previously closed file',
+     'patterns': [r".*: warning: Closing a previously closed file"]},
+    {'category': 'C/C++', 'severity': Severity.MEDIUM, 'option': '-Wunnamed-type-template-args',
+     'description': 'Unnamed template type argument',
+     'patterns': [r".*: warning: template argument.+Wunnamed-type-template-args"]},
+
+    {'category': 'C/C++', 'severity': Severity.HARMLESS,
+     'description': 'Discarded qualifier from pointer target type',
+     'patterns': [r".*: warning: .+ discards '.+' qualifier from pointer target type"]},
+    {'category': 'C/C++', 'severity': Severity.HARMLESS,
+     'description': 'Use snprintf instead of sprintf',
+     'patterns': [r".*: warning: .*sprintf is often misused; please use snprintf"]},
+    {'category': 'C/C++', 'severity': Severity.HARMLESS,
+     'description': 'Unsupported optimizaton flag',
+     'patterns': [r".*: warning: optimization flag '.+' is not supported"]},
+    {'category': 'C/C++', 'severity': Severity.HARMLESS,
+     'description': 'Extra or missing parentheses',
+     'patterns': [r".*: warning: equality comparison with extraneous parentheses",
+                  r".*: warning: .+ within .+Wlogical-op-parentheses"]},
+    {'category': 'C/C++', 'severity': Severity.HARMLESS, 'option': 'mismatched-tags',
+     'description': 'Mismatched class vs struct tags',
+     'patterns': [r".*: warning: '.+' defined as a .+ here but previously declared as a .+mismatched-tags",
+                  r".*: warning: .+ was previously declared as a .+mismatched-tags"]},
 
     # 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,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: ,$"] },
-    { 'category':'C/C++',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: $"] },
-    { 'category':'C/C++',   'severity':severity.SKIP,     'members':[], 'option':'',
-        'description':'',
-        'patterns':[r".*: warning: In file included from .+,"] },
+    {'category': 'C/C++', 'severity': Severity.SKIP,
+     'description': 'skip, ,',
+     'patterns': [r".*: warning: ,$"]},
+    {'category': 'C/C++', 'severity': Severity.SKIP,
+     'description': 'skip,',
+     'patterns': [r".*: warning: $"]},
+    {'category': 'C/C++', 'severity': Severity.SKIP,
+     'description': 'skip, In file included from ...',
+     'patterns': [r".*: warning: In file included from .+,"]},
+
+    # warnings from clang-tidy
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy readability',
+     'patterns': [r".*: .+\[readability-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy c++ core guidelines',
+     'patterns': [r".*: .+\[cppcoreguidelines-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-default-arguments',
+     'patterns': [r".*: .+\[google-default-arguments\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-runtime-int',
+     'patterns': [r".*: .+\[google-runtime-int\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-runtime-operator',
+     'patterns': [r".*: .+\[google-runtime-operator\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-runtime-references',
+     'patterns': [r".*: .+\[google-runtime-references\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-build',
+     'patterns': [r".*: .+\[google-build-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-explicit',
+     'patterns': [r".*: .+\[google-explicit-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-readability',
+     'patterns': [r".*: .+\[google-readability-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google-global',
+     'patterns': [r".*: .+\[google-global-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy google- other',
+     'patterns': [r".*: .+\[google-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy modernize',
+     'patterns': [r".*: .+\[modernize-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy misc',
+     'patterns': [r".*: .+\[misc-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy performance-faster-string-find',
+     'patterns': [r".*: .+\[performance-faster-string-find\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy performance-for-range-copy',
+     'patterns': [r".*: .+\[performance-for-range-copy\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy performance-implicit-cast-in-loop',
+     'patterns': [r".*: .+\[performance-implicit-cast-in-loop\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy performance-unnecessary-copy-initialization',
+     'patterns': [r".*: .+\[performance-unnecessary-copy-initialization\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy performance-unnecessary-value-param',
+     'patterns': [r".*: .+\[performance-unnecessary-value-param\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Unreachable code',
+     'patterns': [r".*: warning: This statement is never executed.*UnreachableCode"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Size of malloc may overflow',
+     'patterns': [r".*: warning: .* size of .* may overflow .*MallocOverflow"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Stream pointer might be NULL',
+     'patterns': [r".*: warning: Stream pointer might be NULL .*unix.Stream"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Opened file never closed',
+     'patterns': [r".*: warning: Opened File never closed.*unix.Stream"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer sozeof() on a pointer type',
+     'patterns': [r".*: warning: .*calls sizeof.* on a pointer type.*SizeofPtr"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Pointer arithmetic on non-array variables',
+     'patterns': [r".*: warning: Pointer arithmetic on non-array variables .*PointerArithm"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Subtraction of pointers of different memory chunks',
+     'patterns': [r".*: warning: Subtraction of two pointers .*PointerSub"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Access out-of-bound array element',
+     'patterns': [r".*: warning: Access out-of-bound array element .*ArrayBound"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Out of bound memory access',
+     'patterns': [r".*: warning: Out of bound memory access .*ArrayBoundV2"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer Possible lock order reversal',
+     'patterns': [r".*: warning: .* Possible lock order reversal.*PthreadLock"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     '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.TIDY,
+     'description': 'clang-analyzer cast to struct',
+     'patterns': [r".*: warning: Casting a non-structure type to a structure type .*CastToStruct"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer call path problems',
+     'patterns': [r".*: warning: Call Path : .+"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-analyzer other',
+     'patterns': [r".*: .+\[clang-analyzer-.+\]$",
+                  r".*: Call Path : .+$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy CERT',
+     'patterns': [r".*: .+\[cert-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-tidy llvm',
+     'patterns': [r".*: .+\[llvm-.+\]$"]},
+    {'category': 'C/C++', 'severity': Severity.TIDY,
+     'description': 'clang-diagnostic',
+     'patterns': [r".*: .+\[clang-diagnostic-.+\]$"]},
 
     # catch-all for warnings this script doesn't know about yet
-    { 'category':'C/C++',   'severity':severity.UNKNOWN,  'members':[], 'option':'',
-        'description':'Unclassified/unrecognized warnings',
-        'patterns':[r".*: warning: .+"] },
+    {'category': 'C/C++', 'severity': Severity.UNKNOWN,
+     'description': 'Unclassified/unrecognized warnings',
+     'patterns': [r".*: warning: .+"]},
 ]
 
-anchor = 0
-cur_row_color = 0
-row_colors = [ 'e0e0e0', 'd0d0d0' ]
 
-def output(text):
-    print text,
-
-def htmlbig(param):
-    return '<font size="+2">' + param + '</font>'
-
-def dumphtmlprologue(title):
-    output('<html>\n<head>\n<title>' + title + '</title>\n<body>\n')
-    output(htmlbig(title))
-    output('<p>\n')
-
-def tablerow(text):
-    global cur_row_color
-    output('<tr bgcolor="' + row_colors[cur_row_color] + '"><td colspan="2">',)
-    cur_row_color = 1 - cur_row_color
-    output(text,)
-    output('</td></tr>')
-
-def begintable(text, backgroundcolor):
-    global anchor
-    output('<table border="1" rules="cols" frame="box" width="100%" bgcolor="black"><tr bgcolor="' +
-        backgroundcolor + '"><a name="anchor' + str(anchor) + '"><td>')
-    output(htmlbig(text[0]) + '<br>')
-    for i in text[1:]:
-        output(i + '<br>')
-    output('</td>')
-    output('<td width="100" bgcolor="grey"><a align="right" href="#anchor' + str(anchor-1) +
-        '">previous</a><br><a align="right" href="#anchor' + str(anchor+1) + '">next</a>')
-    output('</td></a></tr>')
-    anchor += 1
-
-def endtable():
-    output('</table><p>')
+def project_name_and_pattern(name, pattern):
+  return [name, '(^|.*/)' + pattern + '/.*: warning:']
 
 
-# dump some stats about total number of warnings and such
-def dumpstats():
-    known = 0
-    unknown = 0
-    for i in warnpatterns:
-        if i['severity'] == severity.UNKNOWN:
-            unknown += len(i['members'])
-        elif i['severity'] != severity.SKIP:
-            known += len(i['members'])
-    output('Number of classified warnings: <b>' + str(known) + '</b><br>' )
-    output('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>')
-    total = unknown + known
-    output('Total number of warnings: <b>' + str(total) + '</b>')
-    if total < 1000:
-        output('(low count may indicate incremental build)')
-    output('<p>')
-
-def allpatterns(cat):
-    pats = ''
-    for i in cat['patterns']:
-        pats += i
-        pats += ' / '
-    return pats
-
-def descriptionfor(cat):
-    if cat['description'] != '':
-        return cat['description']
-    return allpatterns(cat)
+def simple_project_pattern(pattern):
+  return project_name_and_pattern(pattern, pattern)
 
 
-# show which warnings no longer occur
-def dumpfixed():
-    tablestarted = False
-    for i in warnpatterns:
-        if len(i['members']) == 0 and i['severity'] != severity.SKIP:
-            if tablestarted == False:
-                tablestarted = True
-                begintable(['Fixed warnings', 'No more occurences. Please consider turning these in to errors if possible, before they are reintroduced in to the build'], 'blue')
-            tablerow(i['description'] + ' (' + allpatterns(i) + ') ' + i['option'])
-    if tablestarted:
-        endtable()
+# A list of [project_name, file_path_pattern].
+# project_name should not contain comma, to be used in CSV output.
+project_list = [
+    simple_project_pattern('art'),
+    simple_project_pattern('bionic'),
+    simple_project_pattern('bootable'),
+    simple_project_pattern('build'),
+    simple_project_pattern('cts'),
+    simple_project_pattern('dalvik'),
+    simple_project_pattern('developers'),
+    simple_project_pattern('development'),
+    simple_project_pattern('device'),
+    simple_project_pattern('doc'),
+    # match external/google* before external/
+    project_name_and_pattern('external/google', 'external/google.*'),
+    project_name_and_pattern('external/non-google', 'external'),
+    simple_project_pattern('frameworks/av/camera'),
+    simple_project_pattern('frameworks/av/cmds'),
+    simple_project_pattern('frameworks/av/drm'),
+    simple_project_pattern('frameworks/av/include'),
+    simple_project_pattern('frameworks/av/media'),
+    simple_project_pattern('frameworks/av/radio'),
+    simple_project_pattern('frameworks/av/services'),
+    project_name_and_pattern('frameworks/av/Other', 'frameworks/av'),
+    simple_project_pattern('frameworks/base'),
+    simple_project_pattern('frameworks/compile'),
+    simple_project_pattern('frameworks/minikin'),
+    simple_project_pattern('frameworks/native'),
+    simple_project_pattern('frameworks/opt'),
+    simple_project_pattern('frameworks/rs'),
+    simple_project_pattern('frameworks/webview'),
+    simple_project_pattern('frameworks/wilhelm'),
+    project_name_and_pattern('frameworks/Other', 'frameworks'),
+    simple_project_pattern('hardware/akm'),
+    simple_project_pattern('hardware/broadcom'),
+    simple_project_pattern('hardware/google'),
+    simple_project_pattern('hardware/intel'),
+    simple_project_pattern('hardware/interfaces'),
+    simple_project_pattern('hardware/libhardware'),
+    simple_project_pattern('hardware/libhardware_legacy'),
+    simple_project_pattern('hardware/qcom'),
+    simple_project_pattern('hardware/ril'),
+    project_name_and_pattern('hardware/Other', 'hardware'),
+    simple_project_pattern('kernel'),
+    simple_project_pattern('libcore'),
+    simple_project_pattern('libnativehelper'),
+    simple_project_pattern('ndk'),
+    # match vendor/unbungled_google/packages before other packages
+    simple_project_pattern('unbundled_google'),
+    simple_project_pattern('packages'),
+    simple_project_pattern('pdk'),
+    simple_project_pattern('prebuilts'),
+    simple_project_pattern('system/bt'),
+    simple_project_pattern('system/connectivity'),
+    simple_project_pattern('system/core'),
+    simple_project_pattern('system/extras'),
+    simple_project_pattern('system/gatekeeper'),
+    simple_project_pattern('system/keymaster'),
+    simple_project_pattern('system/libhwbinder'),
+    simple_project_pattern('system/media'),
+    simple_project_pattern('system/netd'),
+    simple_project_pattern('system/security'),
+    simple_project_pattern('system/sepolicy'),
+    simple_project_pattern('system/tools'),
+    simple_project_pattern('system/vold'),
+    project_name_and_pattern('system/Other', 'system'),
+    simple_project_pattern('toolchain'),
+    simple_project_pattern('test'),
+    simple_project_pattern('tools'),
+    # match vendor/google* before vendor/
+    project_name_and_pattern('vendor/google', 'vendor/google.*'),
+    project_name_and_pattern('vendor/non-google', 'vendor'),
+    # keep out/obj and other patterns at the end.
+    ['out/obj',
+     '.*/(gen|obj[^/]*)/(include|EXECUTABLES|SHARED_LIBRARIES|'
+     'STATIC_LIBRARIES|NATIVE_TESTS)/.*: warning:'],
+    ['other', '.*']  # all other unrecognized patterns
+]
+
+project_patterns = []
+project_names = []
+warning_messages = []
+warning_records = []
 
 
-# dump a category, provided it is not marked as 'SKIP' and has more than 0 occurrences
-def dumpcategory(cat):
-    if cat['severity'] != severity.SKIP and len(cat['members']) != 0:
-        header = [descriptionfor(cat),str(len(cat['members'])) + ' occurences:']
-        if cat['option'] != '':
-            header[1:1] = [' (related option: ' + cat['option'] +')']
-        begintable(header, colorforseverity(cat['severity']))
-        for i in cat['members']:
-            tablerow(i)
-        endtable()
+def initialize_arrays():
+  """Complete global arrays before they are used."""
+  global project_names, project_patterns
+  project_names = [p[0] for p in project_list]
+  project_patterns = [re.compile(p[1]) for p in project_list]
+  for w in warn_patterns:
+    w['members'] = []
+    if 'option' not in w:
+      w['option'] = ''
+    # Each warning pattern has a 'projects' dictionary, that
+    # maps a project name to number of warnings in that project.
+    w['projects'] = {}
 
 
-# dump everything for a given severity
-def dumpseverity(sev):
-    for i in warnpatterns:
-        if i['severity'] == sev:
-            dumpcategory(i)
+initialize_arrays()
 
 
-def classifywarning(line):
-    for i in warnpatterns:
-        for cpat in i['compiledpatterns']:
-            if cpat.match(line):
-                i['members'].append(line)
-                return
+platform_version = 'unknown'
+target_product = 'unknown'
+target_variant = 'unknown'
+
+
+##### Data and functions to dump html file. ##################################
+
+html_head_scripts = """\
+  <script type="text/javascript">
+  function expand(id) {
+    var e = document.getElementById(id);
+    var f = document.getElementById(id + "_mark");
+    if (e.style.display == 'block') {
+       e.style.display = 'none';
+       f.innerHTML = '&#x2295';
+    }
+    else {
+       e.style.display = 'block';
+       f.innerHTML = '&#x2296';
+    }
+  };
+  function expandCollapse(show) {
+    for (var id = 1; ; id++) {
+      var e = document.getElementById(id + "");
+      var f = document.getElementById(id + "_mark");
+      if (!e || !f) break;
+      e.style.display = (show ? 'block' : 'none');
+      f.innerHTML = (show ? '&#x2296' : '&#x2295');
+    }
+  };
+  </script>
+  <style type="text/css">
+  th,td{border-collapse:collapse; border:1px solid black;}
+  .button{color:blue;font-size:110%;font-weight:bolder;}
+  .bt{color:black;background-color:transparent;border:none;outline:none;
+      font-size:140%;font-weight:bolder;}
+  .c0{background-color:#e0e0e0;}
+  .c1{background-color:#d0d0d0;}
+  .t1{border-collapse:collapse; width:100%; border:1px solid black;}
+  </style>
+  <script src="https://www.gstatic.com/charts/loader.js"></script>
+"""
+
+
+def html_big(param):
+  return '<font size="+2">' + param + '</font>'
+
+
+def dump_html_prologue(title):
+  print '<html>\n<head>'
+  print '<title>' + title + '</title>'
+  print html_head_scripts
+  emit_stats_by_project()
+  print '</head>\n<body>'
+  print html_big(title)
+  print '<p>'
+
+
+def dump_html_epilogue():
+  print '</body>\n</head>\n</html>'
+
+
+def sort_warnings():
+  for i in warn_patterns:
+    i['members'] = sorted(set(i['members']))
+
+
+def emit_stats_by_project():
+  """Dump a google chart table of warnings per project and severity."""
+  # warnings[p][s] is number of warnings in project p of severity s.
+  warnings = {p: {s: 0 for s in Severity.range} for p in project_names}
+  for i in warn_patterns:
+    s = i['severity']
+    for p in i['projects']:
+      warnings[p][s] += i['projects'][p]
+
+  # total_by_project[p] is number of warnings in project p.
+  total_by_project = {p: sum(warnings[p][s] for s in Severity.range)
+                      for p in project_names}
+
+  # total_by_severity[s] is number of warnings of severity s.
+  total_by_severity = {s: sum(warnings[p][s] for p in project_names)
+                       for s in Severity.range}
+
+  # emit table header
+  stats_header = ['Project']
+  for s in Severity.range:
+    if total_by_severity[s]:
+      stats_header.append("<span style='background-color:{}'>{}</span>".
+                          format(Severity.colors[s],
+                                 Severity.column_headers[s]))
+  stats_header.append('TOTAL')
+
+  # emit a row of warning counts per project, skip no-warning projects
+  total_all_projects = 0
+  stats_rows = []
+  for p in project_names:
+    if total_by_project[p]:
+      one_row = [p]
+      for s in Severity.range:
+        if total_by_severity[s]:
+          one_row.append(warnings[p][s])
+      one_row.append(total_by_project[p])
+      stats_rows.append(one_row)
+      total_all_projects += total_by_project[p]
+
+  # emit a row of warning counts per severity
+  total_all_severities = 0
+  one_row = ['<b>TOTAL</b>']
+  for s in Severity.range:
+    if total_by_severity[s]:
+      one_row.append(total_by_severity[s])
+      total_all_severities += total_by_severity[s]
+  one_row.append(total_all_projects)
+  stats_rows.append(one_row)
+  print '<script>'
+  emit_const_string_array('StatsHeader', stats_header)
+  emit_const_object_array('StatsRows', stats_rows)
+  print draw_table_javascript
+  print '</script>'
+
+
+def dump_stats():
+  """Dump some stats about total number of warnings and such."""
+  known = 0
+  skipped = 0
+  unknown = 0
+  sort_warnings()
+  for i in warn_patterns:
+    if i['severity'] == Severity.UNKNOWN:
+      unknown += len(i['members'])
+    elif i['severity'] == Severity.SKIP:
+      skipped += len(i['members'])
     else:
+      known += len(i['members'])
+  print 'Number of classified warnings: <b>' + str(known) + '</b><br>'
+  print 'Number of skipped warnings: <b>' + str(skipped) + '</b><br>'
+  print 'Number of unclassified warnings: <b>' + str(unknown) + '</b><br>'
+  total = unknown + known + skipped
+  extra_msg = ''
+  if total < 1000:
+    extra_msg = ' (low count may indicate incremental build)'
+  print 'Total number of warnings: <b>' + str(total) + '</b>' + extra_msg
+
+
+# New base table of warnings, [severity, warn_id, project, warning_message]
+# Need buttons to show warnings in different grouping options.
+# (1) Current, group by severity, id for each warning pattern
+#     sort by severity, warn_id, warning_message
+# (2) Current --byproject, group by severity,
+#     id for each warning pattern + project name
+#     sort by severity, warn_id, project, warning_message
+# (3) New, group by project + severity,
+#     id for each warning pattern
+#     sort by project, severity, warn_id, warning_message
+def emit_buttons():
+  print ('<button class="button" onclick="expandCollapse(1);">'
+         'Expand all warnings</button>\n'
+         '<button class="button" onclick="expandCollapse(0);">'
+         'Collapse all warnings</button>\n'
+         '<button class="button" onclick="groupBySeverity();">'
+         'Group warnings by severity</button>\n'
+         '<button class="button" onclick="groupByProject();">'
+         'Group warnings by project</button><br>')
+
+
+def all_patterns(category):
+  patterns = ''
+  for i in category['patterns']:
+    patterns += i
+    patterns += ' / '
+  return patterns
+
+
+def dump_fixed():
+  """Show which warnings no longer occur."""
+  anchor = 'fixed_warnings'
+  mark = anchor + '_mark'
+  print ('\n<br><p style="background-color:lightblue"><b>'
+         '<button id="' + mark + '" '
+         'class="bt" onclick="expand(\'' + anchor + '\');">'
+         '&#x2295</button> Fixed warnings. '
+         'No more occurrences. Please consider turning these into '
+         'errors if possible, before they are reintroduced in to the build'
+         ':</b></p>')
+  print '<blockquote>'
+  fixed_patterns = []
+  for i in warn_patterns:
+    if not i['members']:
+      fixed_patterns.append(i['description'] + ' (' +
+                            all_patterns(i) + ')')
+    if i['option']:
+      fixed_patterns.append(' ' + i['option'])
+  fixed_patterns.sort()
+  print '<div id="' + anchor + '" style="display:none;"><table>'
+  cur_row_class = 0
+  for text in fixed_patterns:
+    cur_row_class = 1 - cur_row_class
+    # remove last '\n'
+    t = text[:-1] if text[-1] == '\n' else text
+    print '<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>'
+  print '</table></div>'
+  print '</blockquote>'
+
+
+def find_project_index(line):
+  for p in range(len(project_patterns)):
+    if project_patterns[p].match(line):
+      return p
+  return -1
+
+
+def classify_warning(line):
+  for i in range(len(warn_patterns)):
+    w = warn_patterns[i]
+    for cpat in w['compiled_patterns']:
+      if cpat.match(line):
+        w['members'].append(line)
+        p = find_project_index(line)
+        index = len(warning_messages)
+        warning_messages.append(line)
+        warning_records.append([i, p, index])
+        pname = '???' if p < 0 else project_names[p]
+        # Count warnings by project.
+        if pname in w['projects']:
+          w['projects'][pname] += 1
+        else:
+          w['projects'][pname] = 1
+        return
+      else:
         # If we end up here, there was a problem parsing the log
         # probably caused by 'make -j' mixing the output from
         # 2 or more concurrent compiles
         pass
 
-# precompiling every pattern speeds up parsing by about 30x
-def compilepatterns():
-    for i in warnpatterns:
-        i['compiledpatterns'] = []
-        for pat in i['patterns']:
-            i['compiledpatterns'].append(re.compile(pat))
 
-infile = open(sys.argv[1], 'r')
-warnings = []
+def compile_patterns():
+  """Precompiling every pattern speeds up parsing by about 30x."""
+  for i in warn_patterns:
+    i['compiled_patterns'] = []
+    for pat in i['patterns']:
+      i['compiled_patterns'].append(re.compile(pat))
 
-platformversion = 'unknown'
-targetproduct = 'unknown'
-targetvariant = 'unknown'
-linecounter = 0
 
-warningpattern = re.compile('.* warning:.*')
-compilepatterns()
+def parse_input_file():
+  """Parse input file, match warning lines."""
+  global platform_version
+  global target_product
+  global target_variant
+  infile = open(args.buildlog, 'r')
+  line_counter = 0
 
-# read the log file and classify all the warnings
-lastmatchedline = ''
-for line in infile:
+  warning_pattern = re.compile('.* warning:.*')
+  compile_patterns()
+
+  # read the log file and classify all the warnings
+  warning_lines = set()
+  for line in infile:
     # replace fancy quotes with plain ol' quotes
-    line = line.replace("‘", "'");
-    line = line.replace("’", "'");
-    if warningpattern.match(line):
-        if line != lastmatchedline:
-            classifywarning(line)
-            lastmatchedline = line
+    line = line.replace('‘', "'")
+    line = line.replace('’', "'")
+    if warning_pattern.match(line):
+      if line not in warning_lines:
+        classify_warning(line)
+        warning_lines.add(line)
+    elif line_counter < 50:
+      # save a little bit of time by only doing this for the first few lines
+      line_counter += 1
+      m = re.search('(?<=^PLATFORM_VERSION=).*', line)
+      if m is not None:
+        platform_version = m.group(0)
+      m = re.search('(?<=^TARGET_PRODUCT=).*', line)
+      if m is not None:
+        target_product = m.group(0)
+      m = re.search('(?<=^TARGET_BUILD_VARIANT=).*', line)
+      if m is not None:
+        target_variant = m.group(0)
+
+
+# Return s with escaped quotation characters.
+def escape_string(s):
+  return s.replace('"', '\\"')
+
+
+# Return s without trailing '\n' and escape the quotation characters.
+def strip_escape_string(s):
+  if not s:
+    return s
+  s = s[:-1] if s[-1] == '\n' else s
+  return escape_string(s)
+
+
+def emit_warning_array(name):
+  print 'var warning_{} = ['.format(name)
+  for i in range(len(warn_patterns)):
+    print '{},'.format(warn_patterns[i][name])
+  print '];'
+
+
+def emit_warning_arrays():
+  emit_warning_array('severity')
+  print 'var warning_description = ['
+  for i in range(len(warn_patterns)):
+    if warn_patterns[i]['members']:
+      print '"{}",'.format(escape_string(warn_patterns[i]['description']))
     else:
-        # save a little bit of time by only doing this for the first few lines
-        if linecounter < 50:
-            linecounter +=1
-            m = re.search('(?<=^PLATFORM_VERSION=).*', line)
-            if m != None:
-                platformversion = m.group(0)
-            m = re.search('(?<=^TARGET_PRODUCT=).*', line)
-            if m != None:
-                targetproduct = m.group(0)
-            m = re.search('(?<=^TARGET_BUILD_VARIANT=).*', line)
-            if m != None:
-                targetvariant = m.group(0)
+      print '"",'  # no such warning
+  print '];'
+
+scripts_for_warning_groups = """
+  function compareMessages(x1, x2) { // of the same warning type
+    return (WarningMessages[x1[2]] <= WarningMessages[x2[2]]) ? -1 : 1;
+  }
+  function byMessageCount(x1, x2) {
+    return x2[2] - x1[2];  // reversed order
+  }
+  function bySeverityMessageCount(x1, x2) {
+    // orer by severity first
+    if (x1[1] != x2[1])
+      return  x1[1] - x2[1];
+    return byMessageCount(x1, x2);
+  }
+  const ParseLinePattern = /^([^ :]+):(\\d+):(.+)/;
+  function addURL(line) {
+    if (FlagURL == "") return line;
+    if (FlagSeparator == "") {
+      return line.replace(ParseLinePattern,
+        "<a href='" + FlagURL + "/$1'>$1</a>:$2:$3");
+    }
+    return line.replace(ParseLinePattern,
+      "<a href='" + FlagURL + "/$1" + FlagSeparator + "$2'>$1:$2</a>:$3");
+  }
+  function createArrayOfDictionaries(n) {
+    var result = [];
+    for (var i=0; i<n; i++) result.push({});
+    return result;
+  }
+  function groupWarningsBySeverity() {
+    // groups is an array of dictionaries,
+    // each dictionary maps from warning type to array of warning messages.
+    var groups = createArrayOfDictionaries(SeverityColors.length);
+    for (var i=0; i<Warnings.length; i++) {
+      var w = Warnings[i][0];
+      var s = WarnPatternsSeverity[w];
+      var k = w.toString();
+      if (!(k in groups[s]))
+        groups[s][k] = [];
+      groups[s][k].push(Warnings[i]);
+    }
+    return groups;
+  }
+  function groupWarningsByProject() {
+    var groups = createArrayOfDictionaries(ProjectNames.length);
+    for (var i=0; i<Warnings.length; i++) {
+      var w = Warnings[i][0];
+      var p = Warnings[i][1];
+      var k = w.toString();
+      if (!(k in groups[p]))
+        groups[p][k] = [];
+      groups[p][k].push(Warnings[i]);
+    }
+    return groups;
+  }
+  var GlobalAnchor = 0;
+  function createWarningSection(header, color, group) {
+    var result = "";
+    var groupKeys = [];
+    var totalMessages = 0;
+    for (var k in group) {
+       totalMessages += group[k].length;
+       groupKeys.push([k, WarnPatternsSeverity[parseInt(k)], group[k].length]);
+    }
+    groupKeys.sort(bySeverityMessageCount);
+    for (var idx=0; idx<groupKeys.length; idx++) {
+      var k = groupKeys[idx][0];
+      var messages = group[k];
+      var w = parseInt(k);
+      var wcolor = SeverityColors[WarnPatternsSeverity[w]];
+      var description = WarnPatternsDescription[w];
+      if (description.length == 0)
+          description = "???";
+      GlobalAnchor += 1;
+      result += "<table class='t1'><tr bgcolor='" + wcolor + "'><td>" +
+                "<button class='bt' id='" + GlobalAnchor + "_mark" +
+                "' onclick='expand(\\"" + GlobalAnchor + "\\");'>" +
+                "&#x2295</button> " +
+                description + " (" + messages.length + ")</td></tr></table>";
+      result += "<div id='" + GlobalAnchor +
+                "' style='display:none;'><table class='t1'>";
+      var c = 0;
+      messages.sort(compareMessages);
+      for (var i=0; i<messages.length; i++) {
+        result += "<tr><td class='c" + c + "'>" +
+                  addURL(WarningMessages[messages[i][2]]) + "</td></tr>";
+        c = 1 - c;
+      }
+      result += "</table></div>";
+    }
+    if (result.length > 0) {
+      return "<br><span style='background-color:" + color + "'><b>" +
+             header + ": " + totalMessages +
+             "</b></span><blockquote><table class='t1'>" +
+             result + "</table></blockquote>";
+
+    }
+    return "";  // empty section
+  }
+  function generateSectionsBySeverity() {
+    var result = "";
+    var groups = groupWarningsBySeverity();
+    for (s=0; s<SeverityColors.length; s++) {
+      result += createWarningSection(SeverityHeaders[s], SeverityColors[s], groups[s]);
+    }
+    return result;
+  }
+  function generateSectionsByProject() {
+    var result = "";
+    var groups = groupWarningsByProject();
+    for (i=0; i<groups.length; i++) {
+      result += createWarningSection(ProjectNames[i], 'lightgrey', groups[i]);
+    }
+    return result;
+  }
+  function groupWarnings(generator) {
+    GlobalAnchor = 0;
+    var e = document.getElementById("warning_groups");
+    e.innerHTML = generator();
+  }
+  function groupBySeverity() {
+    groupWarnings(generateSectionsBySeverity);
+  }
+  function groupByProject() {
+    groupWarnings(generateSectionsByProject);
+  }
+"""
 
 
-# dump the html output to stdout
-dumphtmlprologue('Warnings for ' + platformversion + ' - ' + targetproduct + ' - ' + targetvariant)
-dumpstats()
-dumpseverity(severity.FIXMENOW)
-dumpseverity(severity.HIGH)
-dumpseverity(severity.MEDIUM)
-dumpseverity(severity.LOW)
-dumpseverity(severity.HARMLESS)
-dumpseverity(severity.UNKNOWN)
-dumpfixed()
+# Emit a JavaScript const string
+def emit_const_string(name, value):
+  print 'const ' + name + ' = "' + escape_string(value) + '";'
 
+
+# Emit a JavaScript const integer array.
+def emit_const_int_array(name, array):
+  print 'const ' + name + ' = ['
+  for n in array:
+    print str(n) + ','
+  print '];'
+
+
+# Emit a JavaScript const string array.
+def emit_const_string_array(name, array):
+  print 'const ' + name + ' = ['
+  for s in array:
+    print '"' + strip_escape_string(s) + '",'
+  print '];'
+
+
+# Emit a JavaScript const object array.
+def emit_const_object_array(name, array):
+  print 'const ' + name + ' = ['
+  for x in array:
+    print str(x) + ','
+  print '];'
+
+
+def emit_js_data():
+  """Dump dynamic HTML page's static JavaScript data."""
+  emit_const_string('FlagURL', args.url if args.url else '')
+  emit_const_string('FlagSeparator', args.separator if args.separator else '')
+  emit_const_string_array('SeverityColors', Severity.colors)
+  emit_const_string_array('SeverityHeaders', Severity.headers)
+  emit_const_string_array('SeverityColumnHeaders', Severity.column_headers)
+  emit_const_string_array('ProjectNames', project_names)
+  emit_const_int_array('WarnPatternsSeverity',
+                       [w['severity'] for w in warn_patterns])
+  emit_const_string_array('WarnPatternsDescription',
+                          [w['description'] for w in warn_patterns])
+  emit_const_string_array('WarnPatternsOption',
+                          [w['option'] for w in warn_patterns])
+  emit_const_string_array('WarningMessages', warning_messages)
+  emit_const_object_array('Warnings', warning_records)
+
+draw_table_javascript = """
+google.charts.load('current', {'packages':['table']});
+google.charts.setOnLoadCallback(drawTable);
+function drawTable() {
+  var data = new google.visualization.DataTable();
+  data.addColumn('string', StatsHeader[0]);
+  for (var i=1; i<StatsHeader.length; i++) {
+    data.addColumn('number', StatsHeader[i]);
+  }
+  data.addRows(StatsRows);
+  for (var i=0; i<StatsRows.length; i++) {
+    for (var j=0; j<StatsHeader.length; j++) {
+      data.setProperty(i, j, 'style', 'border:1px solid black;');
+    }
+  }
+  var table = new google.visualization.Table(document.getElementById('stats_table'));
+  table.draw(data, {allowHtml: true, alternatingRowStyle: true});
+}
+"""
+
+
+def dump_html():
+  """Dump the html output to stdout."""
+  dump_html_prologue('Warnings for ' + platform_version + ' - ' +
+                     target_product + ' - ' + target_variant)
+  dump_stats()
+  print '<br><div id="stats_table"></div><br>'
+  print '\n<script>'
+  emit_js_data()
+  print scripts_for_warning_groups
+  print '</script>'
+  emit_buttons()
+  # Warning messages are grouped by severities or project names.
+  print '<br><div id="warning_groups"></div>'
+  if args.byproject:
+    print '<script>groupByProject();</script>'
+  else:
+    print '<script>groupBySeverity();</script>'
+  dump_fixed()
+  dump_html_epilogue()
+
+
+##### Functions to count warnings and dump csv file. #########################
+
+
+def description_for_csv(category):
+  if not category['description']:
+    return '?'
+  return category['description']
+
+
+def string_for_csv(s):
+  # Only some Java warning desciptions have used quotation marks.
+  # TODO(chh): if s has double quote character, s should be quoted.
+  if ',' in s:
+    # TODO(chh): replace a double quote with two double quotes in s.
+    return '"{}"'.format(s)
+  return s
+
+
+def count_severity(sev, kind):
+  """Count warnings of given severity."""
+  total = 0
+  for i in warn_patterns:
+    if i['severity'] == sev and i['members']:
+      n = len(i['members'])
+      total += n
+      warning = string_for_csv(kind + ': ' + description_for_csv(i))
+      print '{},,{}'.format(n, warning)
+      # print number of warnings for each project, ordered by project name.
+      projects = i['projects'].keys()
+      projects.sort()
+      for p in projects:
+        print '{},{},{}'.format(i['projects'][p], p, warning)
+  print '{},,{}'.format(total, kind + ' warnings')
+  return total
+
+
+# dump number of warnings in csv format to stdout
+def dump_csv():
+  """Dump number of warnings in csv format to stdout."""
+  sort_warnings()
+  total = 0
+  for s in Severity.range:
+    total += count_severity(s, Severity.column_headers[s])
+  print '{},,{}'.format(total, 'All warnings')
+
+
+def main():
+  parse_input_file()
+  if args.gencsv:
+    dump_csv()
+  else:
+    dump_html()
+
+
+# Run main function if warn.py is the main program.
+if __name__ == '__main__':
+  main()
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index a2dfd02..aef91a5 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -33,12 +33,12 @@
     fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
     fprintf(stderr,
         "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
-        "       zipalign -c [-v] <align> infile.zip\n\n" );
+        "       zipalign -c [-p] [-v] <align> infile.zip\n\n" );
     fprintf(stderr,
         "  <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
     fprintf(stderr, "  -c: check alignment only (does not modify file)\n");
     fprintf(stderr, "  -f: overwrite existing outfile.zip\n");
-    fprintf(stderr, "  -p: page align stored shared object files\n");
+    fprintf(stderr, "  -p: memory page alignment for stored shared object files\n");
     fprintf(stderr, "  -v: verbose output\n");
     fprintf(stderr, "  -z: recompress using Zopfli\n");
 }
diff --git a/tools/zipalign/ZipEntry.h b/tools/zipalign/ZipEntry.h
index e06567d..431b6db 100644
--- a/tools/zipalign/ZipEntry.h
+++ b/tools/zipalign/ZipEntry.h
@@ -290,7 +290,7 @@
             mExtraField(NULL),
             mFileComment(NULL)
         {}
-        virtual ~CentralDirEntry(void) {
+        ~CentralDirEntry(void) {
             delete[] mFileName;
             delete[] mExtraField;
             delete[] mFileComment;
diff --git a/tools/ziptime/Android.bp b/tools/ziptime/Android.bp
new file mode 100644
index 0000000..874d346
--- /dev/null
+++ b/tools/ziptime/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//
+// Zip timestamp removal tool
+//
+
+cc_binary_host {
+
+    srcs: [
+        "ZipTime.cpp",
+        "ZipEntry.cpp",
+        "ZipFile.cpp",
+    ],
+
+    name: "ziptime",
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+
+}
diff --git a/tools/ziptime/Android.mk b/tools/ziptime/Android.mk
deleted file mode 100644
index 3575229..0000000
--- a/tools/ziptime/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-#
-# Zip timestamp removal tool
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	ZipTime.cpp \
-	ZipEntry.cpp \
-	ZipFile.cpp
-
-LOCAL_MODULE := ziptime
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-include $(BUILD_HOST_EXECUTABLE)