Fix samples metadata concat. am: 8d565ed204 am: bafc0b1baf am: 20e91f4e7a
am: 3dc35a0148

Change-Id: I1dcbc4eadda8cf03bbad1c4278efdd6dad0c6eaf
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 a97c71a..6f72d4a 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -378,6 +378,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/*)
 
+$(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 5badde5..aaba379 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,12 +522,10 @@
 
 INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
 
-BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
 ifdef BOARD_KERNEL_BASE
   INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
 endif
 
-BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
 ifdef BOARD_KERNEL_PAGESIZE
   INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
 endif
@@ -516,9 +537,9 @@
 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)"
+INTERNAL_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
+ifdef INTERNAL_KERNEL_CMDLINE
+INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
 endif
 
 INTERNAL_MKBOOTIMG_VERSION_ARGS := \
@@ -538,7 +559,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: $@")
@@ -585,6 +630,7 @@
 endif # BOARD_USES_RECOVERY_AS_BOOT
 
 else	# TARGET_NO_KERNEL
+INTERNAL_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
 # HACK: The top-level targets depend on the bootimage.  Not all targets
 # can produce a bootimage, though, and emulator targets need the ramdisk
 # instead.  Fake it out by calling the ramdisk the bootimage.
@@ -671,7 +717,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
@@ -828,6 +874,10 @@
 $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
 $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(FUTILITY)" >> $(1))
 $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_signing_args=$(INTERNAL_AVB_SIGNING_ARGS)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_avbtool=$(AVBTOOL)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "system_avb_enable=$(BOARD_AVB_ENABLE)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "system_avb_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
 $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),\
     $(hide) echo "recovery_as_boot=true" >> $(1))
 $(if $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)),\
@@ -928,13 +978,12 @@
 	--ramdisk $(recovery_ramdisk)
 
 # Assumes this has already been stripped
-ifdef BOARD_KERNEL_CMDLINE
-  INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
+ifdef INTERNAL_KERNEL_CMDLINE
+  INTERNAL_RECOVERYIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
 endif
 ifdef BOARD_KERNEL_BASE
   INTERNAL_RECOVERYIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
 endif
-BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
 ifdef BOARD_KERNEL_PAGESIZE
   INTERNAL_RECOVERYIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
 endif
@@ -1001,6 +1050,12 @@
   )
   $(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)), \
     $(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
+  $(if $(and $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),$(filter true,$(BOARD_AVB_ENABLE))), \
+      $(hide) $(AVBTOOL) add_hash_footer \
+        --image $(1) \
+        --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
+        --partition_name boot $(INTERNAL_AVB_SIGNING_ARGS) \
+        $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS))
   $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
     $(hide) $(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE)), \
     $(hide) $(call assert-max-image-size,$(1),$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)))
@@ -1073,7 +1128,6 @@
         $(ALL_PDK_FUSION_FILES))
 
 INTERNAL_SYSTEMIMAGE_FILES := $(filter $(TARGET_OUT)/%, \
-    $(ALL_PREBUILT) \
     $(ALL_GENERATED_SOURCES) \
     $(ALL_DEFAULT_INSTALLED_MODULES) \
     $(PDK_FUSION_SYSIMG_FILES) \
@@ -1143,7 +1197,7 @@
            exit 1 )
 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
@@ -1171,7 +1225,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))
@@ -1303,7 +1357,7 @@
     $(hide) echo "Target boot fs tarball: $(INSTALLED_BOOTTARBALL_TARGET)"
     $(hide) mkdir -p $(PRODUCT_OUT)/boot
     $(hide) cp -f $(INTERNAL_BOOTIMAGE_FILES) $(PRODUCT_OUT)/boot/.
-    $(hide) echo $(BOARD_KERNEL_CMDLINE) > $(PRODUCT_OUT)/boot/cmdline
+    $(hide) echo $(INTERNAL_KERNEL_CMDLINE) > $(PRODUCT_OUT)/boot/cmdline
     $(hide) $(MKTARBALL) $(FS_GET_STATS) \
                  $(PRODUCT_OUT) boot $(PRIVATE_BOOT_TAR) \
                  $(INSTALLED_BOOTTARBALL_TARGET) $(TARGET_OUT)
@@ -1357,7 +1411,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
@@ -1391,6 +1446,40 @@
 
 
 # -----------------------------------------------------------------
+# 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 := \
@@ -1413,7 +1502,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
@@ -1425,6 +1514,60 @@
 IGNORE_CACHE_LINK := --exclude=cache
 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
 
 # -----------------------------------------------------------------
 # system_other partition image
@@ -1514,7 +1657,7 @@
 
 # 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
@@ -1599,8 +1742,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) \
@@ -1611,7 +1752,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) \
@@ -1691,10 +1831,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)
@@ -1717,10 +1861,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
@@ -1734,8 +1880,8 @@
 	$(hide) $(ACP) \
 		$(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
 endif
-ifdef BOARD_KERNEL_CMDLINE
-	$(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
+ifdef INTERNAL_KERNEL_CMDLINE
+	$(hide) echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
 endif
 ifdef BOARD_KERNEL_BASE
 	$(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/base
@@ -1763,8 +1909,8 @@
 	$(hide) $(ACP) \
 		$(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/BOOT/second
 endif
-ifdef BOARD_KERNEL_CMDLINE
-	$(hide) echo "$(BOARD_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
+ifdef INTERNAL_KERNEL_CMDLINE
+	$(hide) echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/BOOT/cmdline
 endif
 ifdef BOARD_KERNEL_BASE
 	$(hide) echo "$(BOARD_KERNEL_BASE)" > $(zip_root)/BOOT/base
@@ -1864,6 +2010,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) \
@@ -1872,6 +2035,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
@@ -1881,6 +2045,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
@@ -1896,9 +2071,9 @@
 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
@@ -1938,7 +2113,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 \
@@ -1964,12 +2140,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)
@@ -1987,13 +2161,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
@@ -2118,7 +2320,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) \
@@ -2153,6 +2354,7 @@
 	$(tools_notice_file_txt) \
 	$(OUT_DOCS)/offline-sdk-timestamp \
 	$(SYMBOLS_ZIP) \
+	$(COVERAGE_ZIP) \
 	$(INSTALLED_SYSTEMIMAGE) \
 	$(INSTALLED_USERDATAIMAGE_TARGET) \
 	$(INSTALLED_RAMDISK_TARGET) \
@@ -2250,6 +2452,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 6fc2935..bd34d22 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
@@ -230,9 +272,6 @@
 # dependent binaries of a .toc file will be rebuilt only when the content of
 # the .toc file is changed.
 ###########################################################
-ifndef LOCAL_IS_HOST_MODULE
-# Disable .toc optimization for host modules: we may run the host binaries during the build process
-# and the libraries' implementation matters.
 ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
 LOCAL_INTERMEDIATE_TARGETS += $(LOCAL_BUILT_MODULE).toc
 $(LOCAL_BUILT_MODULE).toc: $(LOCAL_BUILT_MODULE)
@@ -242,15 +281,14 @@
 # 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
-endif
+$(my_all_targets): $(LOCAL_BUILT_MODULE).toc
 endif
 
 ###########################################################
 ## 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))
@@ -276,6 +314,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)
 
@@ -288,8 +327,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.
@@ -298,51 +346,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
 
 ###########################################################
@@ -411,7 +454,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
 
 ###########################################################
@@ -435,11 +478,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
@@ -499,7 +542,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)))
@@ -517,6 +560,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 7b22903..4dcb152 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,52 @@
 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 := $(call math_max,$(LOCAL_SDK_VERSION),$(my_min_sdk_version))
+
+  # 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 +128,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 +158,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 +180,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 +249,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 +331,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 +410,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 +465,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 +499,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 +541,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 +573,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 +588,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 +604,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 +620,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 +644,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 +682,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 +703,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
@@ -630,7 +783,9 @@
 ###########################################################
 proto_sources := $(filter %.proto,$(my_src_files))
 ifneq ($(proto_sources),)
+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)))
@@ -638,6 +793,7 @@
 my_proto_c_includes := external/nanopb-c
 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 := $(LOCAL_CPP_EXTENSION)
 ifneq ($(my_proto_source_suffix),.cc)
@@ -648,10 +804,10 @@
 my_proto_c_includes := external/protobuf/src
 my_cflags += -DGOOGLE_PROTOBUF_NO_RTTI
 my_protoc_flags := --cpp_out=$(proto_gen_dir)
+my_protoc_deps :=
 endif
 my_proto_c_includes += $(proto_gen_dir)
 
-proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
 proto_generated_cpps := $(addprefix $(proto_gen_dir)/, \
     $(patsubst %.proto,%.pb$(my_proto_source_suffix),$(proto_sources_fullpath)))
 
@@ -671,7 +827,7 @@
 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)/% | $(ACP)
+$(proto_intermediate_cpps) : $(proto_intermediate_dir)/% : $(proto_gen_dir)/%
 	@echo "Copy: $@"
 	$(copy-file-to-target)
 	$(hide) cp $(basename $<).h $(basename $@).h
@@ -693,6 +849,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
@@ -708,6 +866,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))
@@ -763,6 +922,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
@@ -795,6 +955,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
@@ -829,7 +990,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))
@@ -842,7 +1003,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))
@@ -1057,6 +1218,7 @@
 $(call track-src-file-obj,$(objc_sources),$(objc_objects))
 
 ifneq ($(strip $(objc_objects)),)
+my_soong_problems += objc
 $(objc_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.m \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)m-to-o)
@@ -1072,6 +1234,7 @@
 $(call track-src-file-obj,$(objcpp_sources),$(objcpp_objects))
 
 ifneq ($(strip $(objcpp_objects)),)
+my_soong_problems += objc
 $(objcpp_objects): $(intermediates)/%.o: $(TOPDIR)$(LOCAL_PATH)/%.mm \
     $(my_additional_dependencies)
 	$(transform-$(PRIVATE_HOST)mm-to-o)
@@ -1168,11 +1331,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
@@ -1183,13 +1346,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
@@ -1233,16 +1429,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)
 
 
@@ -1292,26 +1489,32 @@
     $(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)/, \
       $(addsuffix $(so_suffix), \
         $(installed_shared_library_module_names)))
-ifdef LOCAL_IS_HOST_MODULE
-# Disable .toc optimization for host modules: we may run the host binaries during the build process
-# and the libraries' implementation matters.
-built_shared_library_deps := $(built_shared_libraries)
-else
 built_shared_library_deps := $(addsuffix .toc, $(built_shared_libraries))
-endif
 my_system_shared_libraries_fullpath :=
 endif
 
 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)
@@ -1320,7 +1523,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.
@@ -1353,10 +1556,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)
@@ -1374,6 +1581,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)
@@ -1387,13 +1675,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.
@@ -1415,30 +1705,62 @@
 ###########################################################
 export_includes := $(intermediates)/export_includes
 $(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(my_export_c_include_dirs)
+# 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_generated_sources) $(export_include_deps)
+$(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 690c0f6..0000000
--- a/core/clang/HOST_x86_common.mk
+++ /dev/null
@@ -1,55 +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 \
-  -B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/bin
-
-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..a081056
--- /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 e46d934..76f4613 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 \
@@ -245,17 +226,7 @@
 	$(PRODUCT_OUT)/system_other \
 	$(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.
@@ -264,12 +235,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)))
@@ -289,12 +254,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))
@@ -303,14 +262,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 fdaa624..71e73a4 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,8 +212,12 @@
 # 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_EXTRACT_APK:=
 LOCAL_EXTRACT_DPI_APK:=
+LOCAL_RECORDED_MODULE_TYPE:=
 
 # arch specific variables
 LOCAL_SRC_FILES_$(TARGET_ARCH):=
@@ -228,6 +240,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):=
@@ -362,10 +375,22 @@
 LOCAL_CLANG_64:=
 LOCAL_INIT_RC_32:=
 LOCAL_INIT_RC_64:=
+LOCAL_MODULE_SYMLINKS_32:=
+LOCAL_MODULE_SYMLINKS_64:=
 LOCAL_JAVA_LANGUAGE_VERSION:=
 LOCAL_IS_RUNTIME_RESOURCE_OVERLAY:=
 LOCAL_RRO_SKU:=
 
+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.
 # Leave the current makefile to make sure we don't break anything
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 6152060..e791d05 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
@@ -166,7 +149,7 @@
 
 # Pruned directory options used when using findleaves.py
 # See envsetup.mk for a description of SCAN_EXCLUDE_DIRS
-FIND_LEAVES_EXCLUDES := $(addprefix --prune=, $(OUT_DIR) $(SCAN_EXCLUDE_DIRS) .repo .git)
+FIND_LEAVES_EXCLUDES := $(addprefix --prune=, $(SCAN_EXCLUDE_DIRS) .repo .git)
 
 # The build system exposes several variables for where to find the kernel
 # headers:
@@ -198,8 +181,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
@@ -234,6 +217,9 @@
 endif
 TARGET_CPU_ABI2 := $(strip $(TARGET_CPU_ABI2))
 
+BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
+BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
+
 # Commands to generate .toc file common to ELF .so files.
 define _gen_toc_command_for_elf
 $(hide) ($($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)READELF) -d $(1) | grep SONAME || echo "No SONAME for $1") > $(2)
@@ -243,7 +229,7 @@
 # Commands to generate .toc file from Darwin dynamic library.
 define _gen_toc_command_for_macho
 $(hide) otool -l $(1) | grep LC_ID_DYLIB -A 5 > $(2)
-$(hide) nm -gP $(1) | cut -f1-2 -d" " | grep -v U$$ >> $(2)
+$(hide) nm -gP $(1) | cut -f1-2 -d" " | (grep -v U$$ >> $(2) || true)
 endef
 
 combo_target := HOST_
@@ -284,9 +270,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
@@ -340,26 +331,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)),)
@@ -369,14 +369,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
 
@@ -455,8 +447,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
@@ -469,14 +462,26 @@
 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
+ifeq ($(filter address,$(SANITIZE_HOST)),)
+prebuilt_build_tools_bin := $(prebuilt_build_tools)/$(HOST_PREBUILT_TAG)/bin
+else
+prebuilt_build_tools_bin := $(prebuilt_build_tools)/$(HOST_PREBUILT_TAG)/asan/bin
+endif
+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
@@ -494,6 +499,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 :=
 
 
 # ---------------------------------------------------------------
@@ -508,6 +515,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
 
@@ -520,6 +528,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)
@@ -529,6 +541,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)
@@ -543,26 +565,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
@@ -571,13 +590,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
@@ -632,152 +644,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
 
@@ -868,4 +781,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 dbcf276..2e14fef 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -19,9 +19,8 @@
   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.
@@ -52,6 +51,7 @@
 # Don't apply sanitizers to NDK code.
 ifdef LOCAL_SDK_VERSION
   my_sanitize :=
+  my_global_sanitize :=
 endif
 
 # Never always wins.
@@ -59,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)),)
@@ -71,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
 
@@ -117,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
@@ -136,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
 
@@ -159,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 84ea801..61e0461 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,21 +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.
-###########################################################
-define rot13
-$(shell echo $(1) | tr 'a-zA-Z' 'n-za-mN-ZA-M')
-endef
-
-
 ###########################################################
 ## Returns true if $(1) and $(2) are equal.  Returns
 ## the empty string if they are not equal.
@@ -761,6 +740,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 +836,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 +918,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 +1085,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 +1143,7 @@
 define transform-logtags-to-java
 @mkdir -p $(dir $@)
 @echo "logtags: $@ <= $<"
-$(hide) $(JAVATAGS) -o $@ $^
+$(hide) $(JAVATAGS) -o $@ $< $(PRIVATE_MERGED_TAG)
 endef
 
 
@@ -1199,22 +1206,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) \
@@ -1226,54 +1238,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
@@ -1298,7 +1344,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
 
@@ -1311,17 +1357,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) \
@@ -1331,52 +1368,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)
@@ -1388,7 +1464,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
@@ -1527,7 +1603,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)
@@ -1536,6 +1612,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
 ###########################################################
@@ -1572,6 +1731,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
@@ -1579,9 +1755,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
 
 
@@ -1598,21 +1776,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
@@ -1644,24 +1821,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
@@ -1676,14 +1853,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` \
@@ -1695,7 +1889,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
@@ -1715,24 +1909,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
@@ -1760,22 +1954,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
@@ -1799,18 +1993,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) \
 	) \
@@ -2071,7 +2264,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 && \
@@ -2082,7 +2274,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
 
@@ -2129,8 +2321,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 \
@@ -2170,11 +2365,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 \
@@ -2191,6 +2385,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) \
@@ -2203,9 +2400,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 ; \
@@ -2213,12 +2408,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).
@@ -2246,7 +2435,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
 
@@ -2304,8 +2493,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 \
@@ -2349,17 +2541,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.
@@ -2495,11 +2676,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.
 #
@@ -2513,19 +2692,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.
@@ -2554,7 +2720,7 @@
 # $(1): source file
 # $(2): destination file
 define copy-one-file
-$(2): $(1) | $(ACP)
+$(2): $(1)
 	@echo "Copy: $$@"
 	$$(copy-file-to-target)
 endef
@@ -2575,7 +2741,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)
@@ -2590,24 +2756,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
 
@@ -2615,6 +2786,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
 
@@ -2622,31 +2794,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
 
@@ -2661,6 +2835,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
@@ -2676,7 +2867,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
@@ -2758,7 +2949,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
 
@@ -2773,7 +2964,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
 
@@ -2889,6 +3080,135 @@
   $(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
+
+###########################################################
+# Basic math functions for positive integers <= 100
+#
+# (SDK versions for example)
+###########################################################
+__MATH_NUMBERS :=  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \
+                  21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
+                  41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
+                  61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
+                  81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
+
+# Returns true if $(1) is a positive integer <= 100, otherwise returns nothing.
+define math_is_number
+$(strip \
+  $(if $(1),,$(error Argument missing)) \
+  $(if $(word 2,$(1)),$(error Multiple words in a single argument: $(1))) \
+  $(if $(filter $(1),$(__MATH_NUMBERS)),true))
+endef
+
+#$(warning true == $(call math_is_number,2))
+#$(warning == $(call math_is_number,foo))
+#$(call math_is_number,1 2)
+#$(call math_is_number,no 2)
+
+define _math_check_valid
+$(if $(call math_is_number,$(1)),,$(error Only positive integers <= 100 are supported (not $(1))))
+endef
+
+#$(call _math_check_valid,0)
+#$(call _math_check_valid,1)
+#$(call _math_check_valid,100)
+#$(call _math_check_valid,101)
+#$(call _math_check_valid,)
+#$(call _math_check_valid,1 2)
+
+# Returns the greater of $1 or $2.
+# If $1 or $2 is not a positive integer <= 100, then an error is generated.
+define math_max
+$(strip $(call _math_check_valid,$(1)) $(call _math_check_valid,$(2)) \
+  $(lastword $(filter $(1) $(2),$(__MATH_NUMBERS))))
+endef
+
+#$(call math_max)
+#$(call math_max,1)
+#$(call math_max,1 2,3)
+#$(warning 1 == $(call math_max,1,1))
+#$(warning 42 == $(call math_max,5,42))
+#$(warning 42 == $(call math_max,42,5))
+
 ###########################################################
 ## Other includes
 ###########################################################
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 5df9dc3..ff0dfd5 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -61,7 +61,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 acd4a02..8154b4f 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -25,10 +25,6 @@
 COMPILED_CLASSES := $(call word-colon,1,$(firstword \
     $(filter %system/etc/compiled-classes,$(PRODUCT_COPY_FILES))))
 
-# start of image reserved address space
-LIBART_IMG_HOST_BASE_ADDRESS   := 0x60000000
-LIBART_IMG_TARGET_BASE_ADDRESS := 0x70000000
-
 define get-product-default-property
 $(strip $(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))))
 endef
@@ -45,7 +41,6 @@
 # building the image. We therefore limit the Xmx value. This isn't done
 # via a property as we want the larger Xmx value if we're running on a
 # MIPS device.
-LIBART_IMG_TARGET_BASE_ADDRESS := 0x30000000
 DEX2OAT_XMX := 128m
 endif
 
@@ -90,17 +85,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 b05d4da..52a67fe 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -49,8 +49,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
@@ -76,10 +79,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
@@ -97,7 +102,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
@@ -108,11 +115,14 @@
 endif
 
 $(built_odex): PRIVATE_DEX_PREOPT_FLAGS := $(LOCAL_DEX_PREOPT_FLAGS)
+$(built_vdex): $(built_odex)
 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 +137,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 6cfb6a1..12c0bb0 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
@@ -217,6 +218,8 @@
 endif
 endif
 
+SOONG_OUT_DIR := $(OUT_DIR)/soong
+
 DEBUG_OUT_DIR := $(OUT_DIR)/debug
 
 # Move the host or target under the debug/ directory
@@ -233,6 +236,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)
 
@@ -250,15 +254,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
@@ -267,6 +276,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
@@ -285,14 +297,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_
@@ -301,6 +310,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
@@ -340,10 +350,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)
@@ -369,8 +388,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
 
@@ -390,10 +414,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)
+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)
@@ -409,7 +438,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)
@@ -423,7 +456,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
@@ -435,6 +472,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
@@ -455,7 +493,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
@@ -468,3 +506,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 a612f83..1067e95 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,11 +77,13 @@
     stnod systemtarball-nodeps \
     userdataimage-nodeps userdatatarball-nodeps \
     cacheimage-nodeps \
+    bptimage-nodeps \
     vendorimage-nodeps \
     systemotherimage-nodeps \
     ramdisk-nodeps \
     bootimage-nodeps \
     recoveryimage-nodeps \
+    vbmetaimage-nodeps \
     product-graph dump-products
 
 ifneq ($(filter $(dont_bother_goals), $(MAKECMDGOALS)),)
@@ -100,22 +99,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
@@ -146,8 +140,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...)
 
@@ -178,7 +173,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)
 
@@ -280,6 +275,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
@@ -457,6 +454,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
@@ -502,21 +502,17 @@
 #
 # Typical build; include any Android.mk files we can find.
 #
-subdirs := $(TOP)
 
 FULL_BUILD := true
 
-# Before we go and include all of the module makefiles, stash away
-# the PRODUCT_* values so that later we can verify they are not modified.
-stash_product_vars:=true
-ifeq ($(stash_product_vars),true)
-  $(call stash-product-vars, __STASHED)
-endif
+# Before we go and include all of the module makefiles, mark the PRODUCT_*
+# values readonly so that they won't be modified.
+$(call readonly-product-vars)
 
 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
@@ -530,11 +526,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
 
@@ -543,16 +556,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.
@@ -566,26 +572,6 @@
 # Now with all Android.mks loaded we can do post cleaning steps.
 include $(BUILD_SYSTEM)/post_clean.mk
 
-ifeq ($(stash_product_vars),true)
-  $(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.
 # -------------------------------------------------------------------
@@ -613,19 +599,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.
@@ -640,7 +640,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)))\
        )\
@@ -654,16 +654,24 @@
 $(1): | $(2)
 endef
 
+# Use a normal dependency instead of an order-only dependency when installing
+# host dynamic binaries so that the timestamp of the final binary always
+# changes, even if the toc optimization has skipped relinking the binary
+# and its dependant shared libraries.
+define add-required-host-so-deps
+$(1): $(2)
+endef
+
 $(foreach m,$(ALL_MODULES), \
   $(eval r := $(ALL_MODULES.$(m).REQUIRED)) \
   $(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))) \
@@ -691,11 +699,14 @@
   $(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)))\
+  $(if $(filter $(1),HOST_),\
+    $(eval $(call add-required-host-so-deps,$(word 2,$(p)),$(r))),\
+    $(eval $(call add-required-deps,$(word 2,$(p)),$(r))))\
   $(eval ALL_MODULES.$(mod).REQUIRED += $(deps)))
 endef
 
@@ -876,9 +887,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.
@@ -889,17 +897,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
@@ -926,6 +932,9 @@
 .PHONY: cacheimage
 cacheimage: $(INSTALLED_CACHEIMAGE_TARGET)
 
+.PHONY: bptimage
+bptimage: $(INSTALLED_BPTIMAGE_TARGET)
+
 .PHONY: vendorimage
 vendorimage: $(INSTALLED_VENDORIMAGE_TARGET)
 
@@ -935,20 +944,11 @@
 .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
@@ -956,8 +956,10 @@
 	systemimage \
 	$(INSTALLED_BOOTIMAGE_TARGET) \
 	$(INSTALLED_RECOVERYIMAGE_TARGET) \
+	$(INSTALLED_VBMETAIMAGE_TARGET) \
 	$(INSTALLED_USERDATAIMAGE_TARGET) \
 	$(INSTALLED_CACHEIMAGE_TARGET) \
+	$(INSTALLED_BPTIMAGE_TARGET) \
 	$(INSTALLED_VENDORIMAGE_TARGET) \
 	$(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
 	$(INSTALLED_FILES_FILE) \
@@ -1001,6 +1003,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)
 
@@ -1021,6 +1026,7 @@
     $(INTERNAL_OTA_PACKAGE_TARGET) \
     $(BUILT_OTATOOLS_PACKAGE) \
     $(SYMBOLS_ZIP) \
+    $(COVERAGE_ZIP) \
     $(INSTALLED_FILES_FILE) \
     $(INSTALLED_FILES_FILE_VENDOR) \
     $(INSTALLED_FILES_FILE_SYSTEMOTHER) \
@@ -1064,6 +1070,7 @@
 $(call dist-for-goals,sdk win_sdk, \
     $(ALL_SDK_TARGETS) \
     $(SYMBOLS_ZIP) \
+    $(COVERAGE_ZIP) \
     $(INSTALLED_BUILD_PROP_TARGET) \
 )
 
@@ -1082,6 +1089,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)
@@ -1100,7 +1110,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.
@@ -1134,4 +1144,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..30146d2 100644
--- a/core/ninja.mk
+++ b/core/ninja.mk
@@ -1,16 +1,11 @@
-NINJA ?= prebuilts/ninja/$(HOST_PREBUILT_TAG)/ninja
-
-ifeq ($(USE_SOONG),true)
-USE_SOONG_FOR_KATI := true
-endif
-
-ifeq ($(USE_SOONG_FOR_KATI),true)
-include $(BUILD_SYSTEM)/soong.mk
+ifeq ($(filter address,$(SANITIZE_HOST)),)
+NINJA ?= prebuilts/build-tools/$(HOST_PREBUILT_TAG)/bin/ninja
 else
-KATI ?= $(HOST_OUT_EXECUTABLES)/ckati
-MAKEPARALLEL ?= $(HOST_OUT_EXECUTABLES)/makeparallel
+NINJA ?= prebuilts/build-tools/$(HOST_PREBUILT_TAG)/asan/bin/ninja
 endif
 
+include $(BUILD_SYSTEM)/soong.mk
+
 KATI_OUTPUT_PATTERNS := $(OUT_DIR)/build%.ninja $(OUT_DIR)/ninja%.sh
 
 # Modifier goals we don't need to pass to Ninja.
@@ -26,7 +21,9 @@
 	DUMP_% \
 	ECLIPSE-% \
 	PRODUCT-% \
+	AUX-% \
 	boottarball-nodeps \
+	brillo_tests \
 	btnod \
 	build-art% \
 	build_kernel-nodeps \
@@ -43,7 +40,6 @@
 	eng \
 	fusion \
 	oem_image \
-	old-cts \
 	online-system-api-sdk-docs \
 	pdk \
 	platform \
@@ -70,7 +66,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 +84,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 +104,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
@@ -146,7 +151,7 @@
 .PHONY: ninja_wrapper
 ninja_wrapper: $(COMBINED_BUILD_NINJA) $(MAKEPARALLEL)
 	@echo Starting build with ninja
-	+$(hide) export NINJA_STATUS="$(NINJA_STATUS)" && source $(KATI_ENV_SH) && $(NINJA_MAKEPARALLEL) $(NINJA) $(NINJA_GOALS) -C $(TOP) -f $(COMBINED_BUILD_NINJA) $(NINJA_ARGS)
+	+$(hide) export NINJA_STATUS="$(NINJA_STATUS)" && source $(KATI_ENV_SH) && exec $(NINJA_MAKEPARALLEL) $(NINJA) -d keepdepfile $(NINJA_GOALS) -C $(TOP) -f $(COMBINED_BUILD_NINJA) $(NINJA_ARGS)
 
 # Dummy Android.mk and CleanSpec.mk files so that kati won't recurse into the
 # out directory
@@ -159,34 +164,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 effc878..ce1754e 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 b6727fa..789d37a 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))
@@ -90,11 +105,11 @@
 endif
 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),)
@@ -113,7 +128,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
@@ -124,7 +139,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
@@ -151,6 +174,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))
 
@@ -200,6 +233,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
@@ -226,6 +260,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
@@ -243,7 +278,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
@@ -261,7 +296,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
@@ -305,14 +340,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)
 
@@ -322,7 +358,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
 
@@ -337,7 +373,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.
@@ -348,36 +384,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
@@ -392,9 +418,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
@@ -412,10 +453,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))
@@ -457,15 +498,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
@@ -476,6 +517,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 332b015..d4790d5 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -124,6 +124,9 @@
     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 \
 
 
 
@@ -293,33 +296,15 @@
 	GLOBAL_CLANG_CFLAGS_NO_OVERRIDE \
 
 #
-# Stash values of the variables in _product_stash_var_list.
-# $(1): Renamed prefix
+# Mark the variables in _product_stash_var_list as readonly
 #
-define stash-product-vars
+define readonly-product-vars
 $(foreach v,$(_product_stash_var_list), \
-        $(eval $(strip $(1))_$(call rot13,$(v)):=$$($$(v))) \
+	$(eval $(v) ?=) \
+	$(eval .KATI_READONLY := $(v)) \
  )
 endef
 
-#
-# Assert that the the variable stashed by stash-product-vars remains untouched.
-# $(1): The prefix as supplied to stash-product-vars
-#
-define assert-product-vars
-$(strip \
-  $(eval changed_variables:=)
-  $(foreach v,$(_product_stash_var_list), \
-    $(if $(call streq,$($(v)),$($(strip $(1))_$(call rot13,$(v)))),, \
-        $(eval $(warning $(v) has been modified: $($(v)))) \
-        $(eval $(warning previous value: $($(strip $(1))_$(call rot13,$(v))))) \
-        $(eval changed_variables := $(changed_variables) $(v))) \
-   ) \
-  $(if $(changed_variables),\
-    $(eval $(error The following variables have been changed: $(changed_variables))),)
-)
-endef
-
 define add-to-product-copy-files-if-exists
 $(if $(wildcard $(word 1,$(subst :, ,$(1)))),$(1))
 endef
diff --git a/core/product_config.mk b/core/product_config.mk
index 6438d51..ea20bcb 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -189,6 +189,8 @@
 all_product_configs := $(get-all-product-makefiles)
 endif
 
+all_named_products :=
+
 # Find the product config makefile for the current product.
 # all_product_configs consists items like:
 # <product_name>:<path_to_the_product_makefile>
@@ -202,9 +204,11 @@
     $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
     $(if $(_cpm_word2),\
         $(eval all_product_makefiles += $(_cpm_word2))\
+        $(eval all_named_products += $(_cpm_word2))\
         $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
             $(eval current_product_makefile += $(_cpm_word2)),),\
         $(eval all_product_makefiles += $(f))\
+        $(eval all_named_products += $(basename $(notdir $(f))))\
         $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
             $(eval current_product_makefile += $(f)),)))
 _cpm_words :=
diff --git a/core/setup_one_odex.mk b/core/setup_one_odex.mk
index 36b6817..37aeb60 100644
--- a/core/setup_one_odex.mk
+++ b/core/setup_one_odex.mk
@@ -34,8 +34,17 @@
 
 my_installed_odex := $(call get-odex-installed-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(LOCAL_INSTALLED_MODULE))
 
+my_built_vdex := $(patsubst %.odex,%.vdex,$(my_built_odex))
+my_installed_vdex := $(patsubst %.odex,%.vdex,$(my_installed_odex))
+
 $(eval $(call copy-one-file,$(my_built_odex),$(my_installed_odex)))
+$(eval $(call copy-one-file,$(my_built_vdex),$(my_installed_vdex)))
 
 built_odex += $(my_built_odex)
+built_vdex += $(my_built_vdex)
+
 installed_odex += $(my_installed_odex)
+installed_vdex += $(my_installed_vdex)
+
 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..1a8975a 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,43 @@
         $(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))
+
+ifdef LOCAL_IS_HOST_MODULE
+my_coverage_path := $($(my_prefix)OUT_COVERAGE)/$(patsubst $($(my_prefix)OUT)/%,%,$(my_module_path))
+else
+my_coverage_path := $(TARGET_OUT_COVERAGE)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path))
+endif
+
+GCNO_ARCHIVE := $(basename $(my_installed_module_stem))$(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_coverage_path)/$(GCNO_ARCHIVE) : $(intermediates)/$(GCNO_ARCHIVE)
+	$(copy-file-to-target)
+
+$(LOCAL_BUILT_MODULE): $(my_coverage_path)/$(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/old-cts.mk b/core/tasks/old-cts.mk
deleted file mode 100644
index 7024638..0000000
--- a/core/tasks/old-cts.mk
+++ /dev/null
@@ -1,399 +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.
-
-cts_dir := $(HOST_OUT)/old-cts
-cts_tools_src_dir := cts/tools
-
-cts_name := old-android-cts
-
-JUNIT_HOST_JAR := $(HOST_OUT_JAVA_LIBRARIES)/junit.jar
-HOSTTESTLIB_JAR := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar
-TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar
-CTS_TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/old-cts-tradefed.jar
-CTS_TF_EXEC_PATH ?= $(HOST_OUT_EXECUTABLES)/old-cts-tradefed
-CTS_TF_README_PATH := $(cts_tools_src_dir)/tradefed-host/README
-
-VMTESTSTF_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,vm-tests-tf,HOST)
-VMTESTSTF_JAR := $(VMTESTSTF_INTERMEDIATES)/android.core.vm-tests-tf.jar
-
-# The list of test packages that core-tests (libcore/Android.mk)
-# is split into.
-CTS_CORE_CASE_LIST := \
-	android.core.tests.libcore.package.dalvik \
-	android.core.tests.libcore.package.com \
-	android.core.tests.libcore.package.conscrypt \
-	android.core.tests.libcore.package.sun \
-	android.core.tests.libcore.package.tests \
-	android.core.tests.libcore.package.org \
-	android.core.tests.libcore.package.libcore \
-	android.core.tests.libcore.package.jsr166 \
-	android.core.tests.libcore.package.harmony_annotation \
-	android.core.tests.libcore.package.harmony_java_io \
-	android.core.tests.libcore.package.harmony_java_lang \
-	android.core.tests.libcore.package.harmony_java_math \
-	android.core.tests.libcore.package.harmony_java_net \
-	android.core.tests.libcore.package.harmony_java_nio \
-	android.core.tests.libcore.package.harmony_java_text \
-	android.core.tests.libcore.package.harmony_java_util \
-	android.core.tests.libcore.package.harmony_javax_security \
-	android.core.tests.libcore.package.okhttp \
-	android.core.tests.runner
-
-# Additional CTS packages for code under libcore
-CTS_CORE_CASE_LIST += \
-	android.core.tests.libcore.package.tzdata
-
-# The list of test packages that apache-harmony-tests (external/apache-harmony/Android.mk)
-# is split into.
-CTS_CORE_CASE_LIST += \
-	android.core.tests.libcore.package.harmony_beans \
-	android.core.tests.libcore.package.harmony_logging \
-	android.core.tests.libcore.package.harmony_prefs \
-	android.core.tests.libcore.package.harmony_sql
-
-
-CTS_TEST_JAR_LIST := \
-	cts-junit \
-	CtsJdwp \
-	cts-testng \
-	CtsLibcoreOj
-
-# Depend on the full package paths rather than the phony targets to avoid
-# rebuilding the packages every time.
-CTS_CORE_CASES := $(foreach pkg,$(CTS_CORE_CASE_LIST),$(call intermediates-dir-for,APPS,$(pkg))/package.apk)
-CTS_TEST_JAR_FILES := $(foreach c,$(CTS_TEST_JAR_LIST),$(call intermediates-dir-for,JAVA_LIBRARIES,$(c))/javalib.jar)
-
--include cts/OldCtsTestCaseList.mk
-
-# A module may have mutliple installed files (e.g. split apks)
-CTS_CASE_LIST_APKS :=
-$(foreach m, $(CTS_TEST_CASE_LIST),\
-  $(foreach fp, $(ALL_MODULES.$(m).BUILT_INSTALLED),\
-    $(eval pair := $(subst :,$(space),$(fp)))\
-    $(eval CTS_CASE_LIST_APKS += $(CTS_TESTCASES_OUT)/$(notdir $(word 2,$(pair))))))\
-$(foreach m, $(CTS_CORE_CASE_LIST),\
-  $(foreach fp, $(ALL_MODULES.$(m).BUILT_INSTALLED),\
-    $(eval pair := $(subst :,$(space),$(fp)))\
-    $(eval built := $(word 1,$(pair)))\
-    $(eval installed := $(CTS_TESTCASES_OUT)/$(notdir $(word 2,$(pair))))\
-    $(eval $(call copy-one-file, $(built), $(installed)))\
-    $(eval CTS_CASE_LIST_APKS += $(installed))))
-
-CTS_CASE_LIST_JARS :=
-$(foreach m, $(CTS_TEST_JAR_LIST),\
-  $(eval CTS_CASE_LIST_JARS += $(CTS_TESTCASES_OUT)/$(m).jar))
-
-CTS_SHARED_LIBS :=
-
-DEFAULT_TEST_PLAN := $(cts_dir)/$(cts_name)/resource/plans
-$(cts_dir)/all_cts_files_stamp: $(CTS_CORE_CASES) $(CTS_TEST_JAR_FILES) $(CTS_TEST_CASES) $(CTS_CASE_LIST_APKS) $(CTS_CASE_LIST_JARS) $(JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(VMTESTSTF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(CTS_TF_README_PATH) $(ADDITIONAL_TF_JARS) $(ACP) $(CTS_SHARED_LIBS)
-
-# Make necessary directory for CTS
-	$(hide) mkdir -p $(TMP_DIR)
-	$(hide) mkdir -p $(PRIVATE_DIR)/docs
-	$(hide) mkdir -p $(PRIVATE_DIR)/tools
-	$(hide) mkdir -p $(PRIVATE_DIR)/repository/testcases
-	$(hide) mkdir -p $(PRIVATE_DIR)/repository/plans
-# Copy executable and JARs to CTS directory
-	$(hide) $(ACP) -fp $(VMTESTSTF_JAR) $(CTS_TESTCASES_OUT)
-	$(hide) $(ACP) -fp $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(ADDITIONAL_TF_JARS) $(CTS_TF_README_PATH) $(PRIVATE_DIR)/tools
-	$(hide) $(call copy-files-with-structure, $(CTS_SHARED_LIBS),$(HOST_OUT)/,$(PRIVATE_DIR))
-	$(hide) touch $@
-
-# Generate the test descriptions for the core-tests
-# Parameters:
-# $1 : The output file where the description should be written (without the '.xml' extension)
-# $2 : The AndroidManifest.xml corresponding to the test package
-# $3 : The jar file name on PRIVATE_CLASSPATH containing junit tests to search for
-# $4 : The package prefix of classes to include, possible empty
-# $5 : The architecture of the current build
-# $6 : The directory containing vogar expectations files
-# $7 : The Android.mk corresponding to the test package (required for host-side tests only)
-define generate-core-test-description
-@echo "Generate core-test description ("$(notdir $(1))")"
-$(hide) java -Xmx256M \
-	-Xbootclasspath/a:$(PRIVATE_CLASSPATH):$(JUNIT_HOST_JAR) \
-	-classpath $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_JDK_TOOLS_JAR) \
-	$(PRIVATE_PARAMS) CollectAllTests $(1) $(2) $(3) "$(4)" $(5) $(6) $(7)
-endef
-
-OJ_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-oj,,COMMON)
-CORE_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-libart,,COMMON)
-CONSCRYPT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,conscrypt,,COMMON)
-BOUNCYCASTLE_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,bouncycastle,,COMMON)
-APACHEXML_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,apache-xml,,COMMON)
-OKHTTP_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,okhttp-nojarjar,,COMMON)
-OKHTTPTESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,okhttp-tests-nojarjar,,COMMON)
-OKHTTP_REPACKAGED_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,okhttp,,COMMON)
-APACHEHARMONYTESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,apache-harmony-tests,,COMMON)
-SQLITEJDBC_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,sqlite-jdbc,,COMMON)
-JUNIT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-junit,,COMMON)
-CORETESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)
-JSR166TESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,jsr166-tests,,COMMON)
-CONSCRYPTTESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,conscrypt-tests,,COMMON)
-TZDATAUPDATETESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,tzdata_update-tests,,COMMON)
-
-GEN_CLASSPATH := \
-    $(OJ_INTERMEDIATES)/classes.jar:$(CORE_INTERMEDIATES)/classes.jar:$(CONSCRYPT_INTERMEDIATES)/classes.jar:$(BOUNCYCASTLE_INTERMEDIATES)/classes.jar:$(APACHEXML_INTERMEDIATES)/classes.jar:$(APACHEHARMONYTESTS_INTERMEDIATES)/classes.jar:$(OKHTTP_INTERMEDIATES)/classes.jar:$(OKHTTPTESTS_INTERMEDIATES)/classes.jar:$(OKHTTP_REPACKAGED_INTERMEDIATES)/classes.jar:$(JUNIT_INTERMEDIATES)/classes.jar:$(SQLITEJDBC_INTERMEDIATES)/javalib.jar:$(CORETESTS_INTERMEDIATES)/javalib.jar:$(JSR166TESTS_INTERMEDIATES)/javalib.jar:$(CONSCRYPTTESTS_INTERMEDIATES)/javalib.jar:$(TZDATAUPDATETESTS_INTERMEDIATES)/javalib.jar
-
-CTS_CORE_XMLS := \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.dalvik.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.com.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.conscrypt.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.sun.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.tests.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.org.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.libcore.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.jsr166.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_annotation.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_io.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_lang.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_math.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_net.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_nio.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_text.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_util.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_javax_security.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_beans.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_logging.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_prefs.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_sql.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.okhttp.xml \
-	$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.tzdata.xml \
-
-$(CTS_CORE_XMLS): PRIVATE_CLASSPATH:=$(GEN_CLASSPATH)
-# Why does this depend on javalib.jar instead of classes.jar?  Because
-# even though the tool will operate on the classes.jar files, the
-# build system requires that dependencies use javalib.jar.  If
-# javalib.jar is up-to-date, then classes.jar is as well.  Depending
-# on classes.jar will build the files incorrectly.
-CTS_CORE_XMLS_DEPS := $(CTS_CORE_CASES) $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(JUNIT_HOST_JAR) $(CORE_INTERMEDIATES)/javalib.jar $(BOUNCYCASTLE_INTERMEDIATES)/javalib.jar $(APACHEXML_INTERMEDIATES)/javalib.jar $(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar $(OKHTTP_INTERMEDIATES)/javalib.jar $(OKHTTPTESTS_INTERMEDIATES)/javalib.jar $(OKHTTP_REPACKAGED_INTERMEDIATES)/javalib.jar $(SQLITEJDBC_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(CORETESTS_INTERMEDIATES)/javalib.jar $(JSR166TESTS_INTERMEDIATES)/javalib.jar $(CONSCRYPTTESTS_INTERMEDIATES)/javalib.jar $(TZDATAUPDATETESTS_INTERMEDIATES)/javalib.jar build/core/tasks/cts.mk | $(ACP)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.dalvik.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.dalvik,\
-		cts/tests/core/libcore/dalvik/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,dalvik,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.com.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.com,\
-		cts/tests/core/libcore/com/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,com,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.conscrypt.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.conscrypt,\
-		cts/tests/core/libcore/conscrypt/AndroidManifest.xml,\
-		$(CONSCRYPTTESTS_INTERMEDIATES)/javalib.jar,,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.sun.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.sun,\
-		cts/tests/core/libcore/sun/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,sun,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.tests.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.tests,\
-		cts/tests/core/libcore/tests/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,tests,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.org.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.org,\
-		cts/tests/core/libcore/org/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,\
-		org.w3c.domts:\
-		org.apache.harmony.security.tests:\
-		org.apache.harmony.nio.tests:\
-		org.apache.harmony.crypto.tests:\
-		org.apache.harmony.regex.tests:\
-		org.apache.harmony.luni.tests:\
-		org.apache.harmony.tests.internal.net.www.protocol:\
-		org.apache.harmony.tests.javax.net:\
-		org.apache.harmony.tests.javax.xml:\
-		org.json,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.libcore.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.libcore,\
-		cts/tests/core/libcore/libcore/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,libcore,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.jsr166.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.jsr166,\
-		cts/tests/core/libcore/jsr166/AndroidManifest.xml,\
-		$(JSR166TESTS_INTERMEDIATES)/javalib.jar,jsr166,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_annotation.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_annotation,\
-		cts/tests/core/libcore/harmony_annotation/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.annotation.tests,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_io.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_io,\
-		cts/tests/core/libcore/harmony_java_io/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.java.io,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_lang.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_lang,\
-		cts/tests/core/libcore/harmony_java_lang/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.java.lang,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_math.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_math,\
-		cts/tests/core/libcore/harmony_java_math/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.java.math,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_net.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_net,\
-		cts/tests/core/libcore/harmony_java_net/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.java.net,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_nio.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_nio,\
-		cts/tests/core/libcore/harmony_java_nio/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.java.nio,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_text.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_text,\
-		cts/tests/core/libcore/harmony_java_text/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.java.text,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_util.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_java_util,\
-		cts/tests/core/libcore/harmony_java_util/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.java.util,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_javax_security.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_javax_security,\
-		cts/tests/core/libcore/harmony_javax_security/AndroidManifest.xml,\
-		$(CORETESTS_INTERMEDIATES)/javalib.jar,org.apache.harmony.tests.javax.security,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_beans.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_beans,\
-		cts/tests/core/libcore/harmony_beans/AndroidManifest.xml,\
-		$(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.beans,\
-		$(TARGET_ARCH),libcore/expectations external/apache-harmony/Android.mk)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_logging.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_logging,\
-		cts/tests/core/libcore/harmony_logging/AndroidManifest.xml,\
-		$(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.logging,\
-		$(TARGET_ARCH),libcore/expectations external/apache-harmony/Android.mk)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_prefs.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_prefs,\
-		cts/tests/core/libcore/harmony_prefs/AndroidManifest.xml,\
-		$(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.prefs,\
-		$(TARGET_ARCH),libcore/expectations external/apache-harmony/Android.mk)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_sql.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.harmony_sql,\
-		cts/tests/core/libcore/harmony_sql/AndroidManifest.xml,\
-		$(APACHEHARMONYTESTS_INTERMEDIATES)/javalib.jar,com.android.org.apache.harmony.sql,\
-		$(TARGET_ARCH),libcore/expectations external/apache-harmony/Android.mk)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.okhttp.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.okhttp,\
-		cts/tests/core/libcore/okhttp/AndroidManifest.xml,\
-		$(OKHTTPTESTS_INTERMEDIATES)/javalib.jar,,\
-		$(TARGET_ARCH),libcore/expectations)
-
-$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.tzdata.xml: $(CTS_CORE_XMLS_DEPS)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.tzdata,\
-		cts/tests/core/libcore/tzdata/AndroidManifest.xml,\
-		$(TZDATAUPDATETESTS_INTERMEDIATES)/javalib.jar,,\
-		$(TARGET_ARCH),libcore/expectations)
-
-# ----- Generate the test descriptions for the vm-tests-tf -----
-#
-CORE_VM_TEST_TF_DESC := $(CTS_TESTCASES_OUT)/android.core.vm-tests-tf.xml
-
-# core tests only needed to get hold of junit-framework-classes
-OJ_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-oj,,COMMON)
-CORE_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-libart,,COMMON)
-JUNIT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-junit,,COMMON)
-
-GEN_CLASSPATH := $(OJ_INTERMEDIATES)/classes.jar:$(CORE_INTERMEDIATES)/classes.jar:$(JUNIT_INTERMEDIATES)/classes.jar:$(VMTESTSTF_JAR):$(TF_JAR)
-
-$(CORE_VM_TEST_TF_DESC): PRIVATE_CLASSPATH:=$(GEN_CLASSPATH)
-# Please see big comment above on why this line depends on javalib.jar instead of classes.jar
-$(CORE_VM_TEST_TF_DESC): $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(JUNIT_HOST_JAR) $(CORE_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(VMTESTSTF_JAR) | $(ACP)
-	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(call generate-core-test-description,$(CTS_TESTCASES_OUT)/android.core.vm-tests-tf,\
-		cts/tests/vm-tests-tf/AndroidManifest.xml,\
-		$(VMTESTSTF_JAR),"",\
-		$(TARGET_ARCH),\
-		libcore/expectations,\
-		cts/tools/vm-tests-tf/Android.mk)
-
-# Generate the default test plan for User.
-# Usage: buildCts.py <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>
-
-$(DEFAULT_TEST_PLAN): $(cts_dir)/all_cts_files_stamp $(cts_tools_src_dir)/utils/buildCts.py $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(CTS_CORE_XMLS) $(CTS_TEST_XMLS) $(CORE_VM_TEST_TF_DESC)
-	$(hide) $(cts_tools_src_dir)/utils/buildCts.py cts/tests/tests/ $(PRIVATE_DIR) $(TMP_DIR) \
-		$(TOP) $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar
-	$(hide) mkdir -p $(dir $@) && touch $@
-
-# Package CTS and clean up.
-#
-# TODO:
-#   Pack cts.bat into the same zip file as well. See http://buganizer/issue?id=1656821 for more details
-INTERNAL_CTS_TARGET := $(cts_dir)/$(cts_name).zip
-$(INTERNAL_CTS_TARGET): PRIVATE_NAME := $(cts_name)
-$(INTERNAL_CTS_TARGET): PRIVATE_CTS_DIR := $(cts_dir)
-$(INTERNAL_CTS_TARGET): PRIVATE_DIR := $(cts_dir)/$(cts_name)
-$(INTERNAL_CTS_TARGET): TMP_DIR := $(cts_dir)/temp
-$(INTERNAL_CTS_TARGET): $(cts_dir)/all_cts_files_stamp $(DEFAULT_TEST_PLAN)
-	$(hide) echo "Package CTS: $@"
-	$(hide) cd $(dir $@) && zip -rqX $(notdir $@) $(PRIVATE_NAME)
-
-.PHONY: old-cts
-old-cts: $(INTERNAL_CTS_TARGET) adb
-$(call dist-for-goals,old-cts,$(INTERNAL_CTS_TARGET))
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index e3761ae..ae967c6 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -47,19 +47,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))),,\
@@ -69,28 +93,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
 
@@ -113,4 +133,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 283e9cc..f53ff62 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/kati_all_products.sh b/tools/kati_all_products.sh
new file mode 100755
index 0000000..4567dbd
--- /dev/null
+++ b/tools/kati_all_products.sh
@@ -0,0 +1,7 @@
+#!/bin/bash -e
+
+cd $ANDROID_BUILD_TOP
+mkdir -p out.kati
+source build/envsetup.sh
+
+get_build_var all_named_products | sed "s/ /\n/g" | parallel "$@" --progress "(source build/envsetup.sh; lunch {}-eng && m -j OUT_DIR=out.kati/{} out.kati/{}/build-{}.ninja) >out.kati/log.{} 2>&1"
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..4ae8f61 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>
@@ -336,13 +337,44 @@
 
   args.push_back(nullptr);
 
-  pid_t pid = fork();
+  static pid_t pid;
+
+  // Set up signal handlers to forward SIGHUP, SIGINT, SIGQUIT, SIGTERM, and
+  // SIGALRM to child
+  struct sigaction action = {};
+  action.sa_flags = SA_SIGINFO | SA_RESTART,
+  action.sa_sigaction = [](int signal, siginfo_t*, void*) {
+    if (pid > 0) {
+      kill(pid, signal);
+    }
+  };
+
+  int ret = 0;
+  if (!ret) ret = sigaction(SIGHUP, &action, NULL);
+  if (!ret) ret = sigaction(SIGINT, &action, NULL);
+  if (!ret) ret = sigaction(SIGQUIT, &action, NULL);
+  if (!ret) ret = sigaction(SIGTERM, &action, NULL);
+  if (!ret) ret = sigaction(SIGALRM, &action, NULL);
+  if (ret < 0) {
+    error(errno, errno, "sigaction failed");
+  }
+
+  pid = fork();
   if (pid < 0) {
     error(errno, errno, "fork failed");
   } else if (pid == 0) {
     // 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);
@@ -351,9 +383,10 @@
   }
 
   // parent
+
   siginfo_t status = {};
   int exit_status = 0;
-  int ret = waitid(P_PID, pid, &status, WEXITED);
+  ret = waitid(P_PID, pid, &status, WEXITED);
   if (ret < 0) {
     error(errno, errno, "waitpid failed");
   } else if (status.si_code == CLD_EXITED) {
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 446b94f..54223b6 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -55,7 +55,9 @@
 import datetime
 import errno
 import os
+import shlex
 import shutil
+import subprocess
 import tempfile
 import zipfile
 
@@ -87,7 +89,7 @@
 
 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):
@@ -107,6 +109,7 @@
   block_list = common.MakeTempFile(prefix="system-blocklist-", suffix=".map")
   imgname = BuildSystem(OPTIONS.input_tmp, OPTIONS.info_dict,
                         block_list=block_list)
+
   common.ZipWrite(output_zip, imgname, prefix + "system.img")
   common.ZipWrite(output_zip, block_list, prefix + "system.map")
   return imgname
@@ -227,11 +230,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..."
@@ -271,6 +272,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."""
 
@@ -334,22 +383,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:
@@ -372,12 +424,12 @@
         recovery_image.AddToZip(output_zip)
 
   banner("system")
-  system_imgname = AddSystem(output_zip, recovery_img=recovery_image,
-                             boot_img=boot_image)
-  vendor_imgname = None
+  system_img_path = AddSystem(
+    output_zip, recovery_img=recovery_image, boot_img=boot_image)
+  vendor_img_path = None
   if has_vendor:
     banner("vendor")
-    vendor_imgname = AddVendor(output_zip)
+    vendor_img_path = AddVendor(output_zip)
   if has_system_other:
     banner("system_other")
     AddSystemOther(output_zip)
@@ -386,9 +438,18 @@
     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:
@@ -399,18 +460,31 @@
     for line in lines:
       if line.strip() == "system" and OPTIONS.info_dict.get(
           "system_verity_block_device", None) is not None:
-        assert os.path.exists(system_imgname)
-        care_map_list += GetCareMap("system", system_imgname)
+        assert os.path.exists(system_img_path)
+        care_map_list += GetCareMap("system", system_img_path)
       if line.strip() == "vendor" and OPTIONS.info_dict.get(
           "vendor_verity_block_device", None) is not None:
-        assert os.path.exists(vendor_imgname)
-        care_map_list += GetCareMap("vendor", vendor_imgname)
+        assert os.path.exists(vendor_img_path)
+        care_map_list += GetCareMap("vendor", vendor_img_path)
 
       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
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index a9217ee..28d70d3 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
@@ -27,6 +27,7 @@
 import sys
 import commands
 import common
+import shlex
 import shutil
 import sparse_img
 import tempfile
@@ -102,6 +103,51 @@
   simg = sparse_img.SparseImage(image_file, mode="r+b", build_map=False)
   simg.AppendFillChunk(0, blocks)
 
+def AVBCalcMaxImageSize(avbtool, partition_size, additional_args):
+  """Calculates max image size for a given partition size.
+
+  Args:
+    avbtool: String with path to avbtool.
+    partition_size: The size of the partition in question.
+    additional_args: Additional arguments to pass to 'avbtool
+      add_hashtree_image'.
+  Returns:
+    The maximum image size or 0 if an error occurred.
+  """
+  cmdline = "%s add_hashtree_footer " % avbtool
+  cmdline += "--partition_size %d " % partition_size
+  cmdline += "--calc_max_image_size "
+  cmdline += additional_args
+  (output, exit_code) = RunCommand(shlex.split(cmdline))
+  if exit_code != 0:
+    return 0
+  else:
+    return int(output)
+
+def AVBAddHashtree(image_path, avbtool, partition_size, partition_name,
+                   signing_args, additional_args):
+  """Adds dm-verity hashtree and AVB metadata to an image.
+
+  Args:
+    image_path: Path to image to modify.
+    avbtool: String with path to avbtool.
+    partition_size: The size of the partition in question.
+    partition_name: The name of the partition - will be embedded in metadata.
+    signing_args: Arguments for signing the image.
+    additional_args: Additional arguments to pass to 'avbtool
+      add_hashtree_image'.
+  Returns:
+    True if the operation succeeded.
+  """
+  cmdline = "%s add_hashtree_footer " % avbtool
+  cmdline += "--partition_size %d " % partition_size
+  cmdline += "--partition_name %s " % partition_name
+  cmdline += "--image %s " % image_path
+  cmdline += signing_args + " "
+  cmdline += additional_args
+  (_, exit_code) = RunCommand(shlex.split(cmdline))
+  return exit_code == 0
+
 def AdjustPartitionSizeForVerity(partition_size, fec_supported):
   """Modifies the provided partition size to account for the verity metadata.
 
@@ -109,7 +155,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 +168,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 +255,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 +263,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 +301,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 +332,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 +413,25 @@
   # 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)
+
+  # Adjust partition size for AVB.
+  if prop_dict.get("avb_enable") == "true":
+    avbtool = prop_dict.get("avb_avbtool")
+    partition_size = int(prop_dict.get("partition_size"))
+    additional_args = prop_dict["avb_add_hashtree_footer_args"]
+    max_image_size = AVBCalcMaxImageSize(avbtool, partition_size,
+                                         additional_args)
+    if max_image_size == 0:
+      return False
+    prop_dict["partition_size"] = str(max_image_size)
+    prop_dict["original_partition_size"] = str(partition_size)
 
   if fs_type.startswith("ext"):
     build_command = ["mkuserimg.sh"]
@@ -414,14 +485,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.
@@ -492,6 +557,17 @@
     if not MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict):
       return False
 
+  # Add AVB hashtree and metadata.
+  if "avb_enable" in prop_dict:
+    avbtool = prop_dict.get("avb_avbtool")
+    original_partition_size = int(prop_dict.get("original_partition_size"))
+    partition_name = prop_dict["partition_name"]
+    signing_args = prop_dict["avb_signing_args"]
+    additional_args = prop_dict["avb_add_hashtree_footer_args"]
+    if not AVBAddHashtree(out_file, avbtool, original_partition_size,
+                          partition_name, signing_args, additional_args):
+      return False
+
   if run_fsck and prop_dict.get("skip_fsck") != "true":
     success, unsparse_image = UnsparseImage(out_file, replace=False)
     if not success:
@@ -527,13 +603,14 @@
   common_props = (
       "extfs_sparse_flag",
       "squashfs_sparse_flag",
-      "mkyaffs2_extra_flags",
       "selinux_fc",
       "skip_fsck",
       "verity",
       "verity_key",
       "verity_signer_cmd",
-      "verity_fec"
+      "verity_fec",
+      "avb_signing_args",
+      "avb_avbtool"
       )
   for p in common_props:
     copy_prop(p, p)
@@ -556,6 +633,9 @@
     copy_prop("system_squashfs_block_size", "squashfs_block_size")
     copy_prop("system_squashfs_disable_4k_align", "squashfs_disable_4k_align")
     copy_prop("system_base_fs_file", "base_fs_file")
+    copy_prop("system_avb_enable", "avb_enable")
+    copy_prop("system_avb_add_hashtree_footer_args",
+              "avb_add_hashtree_footer_args")
   elif mount_point == "system_other":
     # We inherit the selinux policies of /system since we contain some of its files.
     d["mount_point"] = "system"
@@ -569,6 +649,9 @@
     copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
     copy_prop("system_squashfs_block_size", "squashfs_block_size")
     copy_prop("system_base_fs_file", "base_fs_file")
+    copy_prop("system_avb_enable", "avb_enable")
+    copy_prop("system_avb_add_hashtree_footer_args",
+              "avb_add_hashtree_footer_args")
   elif mount_point == "data":
     # Copy the generic fs type first, override with specific one if available.
     copy_prop("fs_type", "fs_type")
@@ -588,12 +671,15 @@
     copy_prop("vendor_squashfs_block_size", "squashfs_block_size")
     copy_prop("vendor_squashfs_disable_4k_align", "squashfs_disable_4k_align")
     copy_prop("vendor_base_fs_file", "base_fs_file")
+    copy_prop("vendor_avb_enable", "avb_enable")
+    copy_prop("vendor_avb_add_hashtree_footer_args",
+              "avb_add_hashtree_footer_args")
   elif mount_point == "oem":
     copy_prop("fs_type", "fs_type")
     copy_prop("oem_size", "partition_size")
     copy_prop("oem_journal_size", "journal_size")
     copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
-
+  d["partition_name"] = mount_point
   return d
 
 
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/common.py b/tools/releasetools/common.py
index d7f8b16..b8113e9 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(
@@ -400,6 +392,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.
@@ -519,6 +521,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()
 
@@ -530,7 +547,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',
@@ -761,10 +778,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)
@@ -1586,8 +1599,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 d3d4974..dc93a9d 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"
@@ -151,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
@@ -453,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:
@@ -542,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:
@@ -553,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),
@@ -575,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()
@@ -624,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()
 
@@ -787,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:
@@ -806,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",
   }
 
@@ -842,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
@@ -954,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 = []
@@ -1102,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())
 
@@ -1173,6 +1174,9 @@
                                       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(
@@ -1187,8 +1191,8 @@
            "-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()
+    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 package signing.
@@ -1230,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.
@@ -1242,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.
@@ -1261,9 +1265,8 @@
            "-pkeyopt", "digest:sha256"]
   cmd.extend(["-in", payload_sig_file,
               "-out", 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, "openssl sign payload failed"
 
   # 3b. Sign the metadata hash.
@@ -1276,8 +1279,8 @@
            "-pkeyopt", "digest:sha256"]
   cmd.extend(["-in", metadata_sig_file,
               "-out", signed_metadata_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, "openssl sign metadata failed"
 
   # 3c. Insert the signatures back into the payload file.
@@ -1289,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.
@@ -1299,8 +1302,8 @@
   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:
@@ -1477,17 +1480,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:
@@ -1496,8 +1500,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",
   }
 
@@ -1540,17 +1544,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
@@ -1901,8 +1913,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
@@ -1954,7 +1964,7 @@
     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=",
@@ -1962,7 +1972,6 @@
                                  "full_radio",
                                  "full_bootloader",
                                  "wipe_user_data",
-                                 "no_prereq",
                                  "downgrade",
                                  "extra_script=",
                                  "worker_threads=",
@@ -1995,8 +2004,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 c9bd375..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
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 6d68be1..7f69a57 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -280,7 +280,7 @@
       pass
 
     # Skip the care_map as we will regenerate the system/vendor images.
-    elif (info.filename == "META/care_map.txt"):
+    elif info.filename == "META/care_map.txt":
       pass
 
     # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch. This case
@@ -553,9 +553,12 @@
   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)
+      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()
+      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:
@@ -592,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()
@@ -615,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()
@@ -698,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,
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 edf1c4b..e181187 100644
--- a/tools/releasetools/test_rangelib.py
+++ b/tools/releasetools/test_rangelib.py
@@ -125,6 +125,20 @@
     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()),
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..ea1cd22 100755
--- a/tools/warn.py
+++ b/tools/warn.py
@@ -1,563 +1,2360 @@
-#!/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
+  ANALYZER = 4
+  TIDY = 5
+  HARMLESS = 6
+  UNKNOWN = 7
+  SKIP = 8
+  range = range(SKIP + 1)
+  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'],
+      ['hotpink',   'Analyzer',  'Clang-Analyzer 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': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Security warning',
+     'patterns': [r".*: warning: .+\[clang-analyzer-security.*\]"]},
+    {'category': 'make', 'severity': Severity.MEDIUM,
+     'description': 'make: overriding commands/ignoring old commands',
+     'patterns': [r".*: warning: overriding commands for target .+",
+                  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.ANALYZER,
+     'description': 'clang-analyzer Value stored is never read',
+     'patterns': [r".*: warning: Value stored to .+ is never read.*clang-analyzer-deadcode.DeadStores"]},
+    {'category': 'C/C++', 'severity': Severity.LOW,
+     'description': 'Value stored is never read',
+     'patterns': [r".*: warning: Value stored to .+ is never read"]},
+    {'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.ANALYZER,
+     'description': 'clang-analyzer Unreachable code',
+     'patterns': [r".*: warning: This statement is never executed.*UnreachableCode"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Size of malloc may overflow',
+     'patterns': [r".*: warning: .* size of .* may overflow .*MallocOverflow"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Stream pointer might be NULL',
+     'patterns': [r".*: warning: Stream pointer might be NULL .*unix.Stream"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Opened file never closed',
+     'patterns': [r".*: warning: Opened File never closed.*unix.Stream"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer sozeof() on a pointer type',
+     'patterns': [r".*: warning: .*calls sizeof.* on a pointer type.*SizeofPtr"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Pointer arithmetic on non-array variables',
+     'patterns': [r".*: warning: Pointer arithmetic on non-array variables .*PointerArithm"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Subtraction of pointers of different memory chunks',
+     'patterns': [r".*: warning: Subtraction of two pointers .*PointerSub"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Access out-of-bound array element',
+     'patterns': [r".*: warning: Access out-of-bound array element .*ArrayBound"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Out of bound memory access',
+     'patterns': [r".*: warning: Out of bound memory access .*ArrayBoundV2"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Possible lock order reversal',
+     'patterns': [r".*: warning: .* Possible lock order reversal.*PthreadLock"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer Argument is a pointer to uninitialized value',
+     'patterns': [r".*: warning: .* argument is a pointer to uninitialized value .*CallAndMessage"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer cast to struct',
+     'patterns': [r".*: warning: Casting a non-structure type to a structure type .*CastToStruct"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer call path problems',
+     'patterns': [r".*: warning: Call Path : .+"]},
+    {'category': 'C/C++', 'severity': Severity.ANALYZER,
+     'description': 'clang-analyzer 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)