Merge "Remove special x86 flag that disables tail call optimization."
diff --git a/.gitignore b/.gitignore
index c9b568f..f1f4a52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
 *.pyc
 *.swp
+blueprint/
+kati/
+soong/
diff --git a/CleanSpec.mk b/CleanSpec.mk
index f5f7991..edf0179 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -334,6 +334,21 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop)
 
+# Rename dalvik.vm.usejit to debug.dalvik.vm.usejit
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop)
+
+# Revert rename dalvik.vm.usejit to debug.dalvik.vm.usejit
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop)
+
+# Change from interpret-only to verify-at-runtime.
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/default.prop)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 478c966..2f75568 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -106,7 +106,7 @@
 BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
 
 # A human-readable string that descibes this build in detail.
-build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER) $(BUILD_VERSION_TAGS)
+build_desc := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) $(PLATFORM_VERSION) $(BUILD_ID) $(BUILD_NUMBER_FROM_FILE) $(BUILD_VERSION_TAGS)
 $(INSTALLED_BUILD_PROP_TARGET): PRIVATE_BUILD_DESC := $(build_desc)
 
 # The string used to uniquely identify the combined build and product; used by the OTA server.
@@ -114,7 +114,7 @@
   ifneq ($(filter eng.%,$(BUILD_NUMBER)),)
     # Trim down BUILD_FINGERPRINT: the default BUILD_NUMBER makes it easily exceed
     # the Android system property length limit (PROPERTY_VALUE_MAX=92).
-    BF_BUILD_NUMBER := $(USER)$(shell date +%m%d%H%M)
+    BF_BUILD_NUMBER := $(USER)$(shell $(DATE) +%m%d%H%M)
   else
     BF_BUILD_NUMBER := $(BUILD_NUMBER)
   endif
@@ -124,6 +124,9 @@
   $(error BUILD_FINGERPRINT cannot contain spaces: "$(BUILD_FINGERPRINT)")
 endif
 
+$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) > $(PRODUCT_OUT)/build_fingerprint.txt)
+BUILD_FINGERPRINT_FROM_FILE := $$(cat $(PRODUCT_OUT)/build_fingerprint.txt)
+
 # The string used to uniquely identify the system build; used by the OTA server.
 # This purposefully excludes any product-specific variables.
 ifeq (,$(strip $(BUILD_THUMBPRINT)))
@@ -147,7 +150,7 @@
 
   # Dev. branches should have DISPLAY_BUILD_NUMBER set
   ifeq "true" "$(DISPLAY_BUILD_NUMBER)"
-    BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER) $(BUILD_KEYS)
+    BUILD_DISPLAY_ID := $(BUILD_ID).$(BUILD_NUMBER_FROM_FILE) $(BUILD_KEYS)
   else
     BUILD_DISPLAY_ID := $(BUILD_ID) $(BUILD_KEYS)
   endif
@@ -194,14 +197,16 @@
 			PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
 			BUILD_ID="$(BUILD_ID)" \
 			BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \
-			BUILD_NUMBER="$(BUILD_NUMBER)" \
+			DATE="$(DATE_FROM_FILE)" \
+			BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
+			BOARD_BUILD_SYSTEM_ROOT_IMAGE="$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)" \
 			PLATFORM_VERSION="$(PLATFORM_VERSION)" \
 			PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
 			PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \
 			PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \
 			BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
 			TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)" \
-			BUILD_FINGERPRINT="$(BUILD_FINGERPRINT)" \
+			BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
 			$(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT="$(BUILD_THUMBPRINT)") \
 			TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)" \
 			TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \
@@ -242,9 +247,9 @@
 	@echo Target vendor buildinfo: $@
 	@mkdir -p $(dir $@)
 	$(hide) echo > $@
-	$(hide) echo ro.vendor.build.date=`date`>>$@
-	$(hide) echo ro.vendor.build.date.utc=`date +%s`>>$@
-	$(hide) echo ro.vendor.build.fingerprint="$(BUILD_FINGERPRINT)">>$@
+	$(hide) echo ro.vendor.build.date=`$(DATE_FROM_FILE)`>>$@
+	$(hide) echo ro.vendor.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@
+	$(hide) echo ro.vendor.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
 endif
 
 # ----------------------------------------------------------------
@@ -258,9 +263,9 @@
 	@echo Target bootimage buildinfo: $@
 	@mkdir -p $(dir $@)
 	$(hide) echo > $@
-	$(hide) echo ro.bootimage.build.date=`date`>>$@
-	$(hide) echo ro.bootimage.build.date.utc=`date +%s`>>$@
-	$(hide) echo ro.bootimage.build.fingerprint="$(BUILD_FINGERPRINT)">>$@
+	$(hide) echo ro.bootimage.build.date=`$(DATE_FROM_FILE)`>>$@
+	$(hide) echo ro.bootimage.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@
+	$(hide) echo ro.bootimage.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
 
 # -----------------------------------------------------------------
 # sdk-build.prop
@@ -682,7 +687,7 @@
 endif
 
 ifeq ($(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),squashfs)
-INTERNAL_USERIMAGES_DEPS += $(MAKE_SQUASHFS) $(MKSQUASHFSUSERIMG)
+INTERNAL_USERIMAGES_DEPS += $(MAKE_SQUASHFS) $(MKSQUASHFSUSERIMG) $(IMG2SIMG)
 endif
 
 INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS)))
@@ -691,7 +696,7 @@
 INTERNAL_USERIMAGES_DEPS += $(BUILD_VERITY_TREE) $(APPEND2SIMG) $(VERITY_SIGNER)
 endif
 
-SELINUX_FC := $(TARGET_ROOT_OUT)/file_contexts
+SELINUX_FC := $(TARGET_ROOT_OUT)/file_contexts.bin
 INTERNAL_USERIMAGES_DEPS += $(SELINUX_FC)
 
 # $(1): the path of the output dictionary file
@@ -701,6 +706,9 @@
 $(if $(BOARD_SYSTEMIMAGE_PARTITION_SIZE),$(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(1))
 $(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_fs_type=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
 $(if $(BOARD_SYSTEMIMAGE_JOURNAL_SIZE),$(hide) echo "system_journal_size=$(BOARD_SYSTEMIMAGE_JOURNAL_SIZE)" >> $(1))
+$(if $(BOARD_HAS_EXT4_RESERVED_BLOCKS),$(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(1))
+$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_squashfs_compressor=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
+$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
 $(if $(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "userdata_fs_type=$(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
 $(if $(BOARD_USERDATAIMAGE_PARTITION_SIZE),$(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(1))
 $(if $(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "cache_fs_type=$(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
@@ -714,9 +722,16 @@
 $(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(1)
 $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)" >> $(1))
 $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)" >> $(1))
-$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(VERITY_SIGNER)" >> $(1))
+$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(notdir $(VERITY_SIGNER))" >> $(1))
 $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1))
 $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1))
+$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)" >> $(1))
+$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY)" >> $(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 $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)),\
+    $(hide) echo "system_root_image=true" >> $(1);\
+    echo "ramdisk_dir=$(TARGET_ROOT_OUT)" >> $(1))
 $(if $(2),$(hide) $(foreach kv,$(2),echo "$(kv)" >> $(1);))
 endef
 
@@ -759,24 +774,33 @@
 # can be overridden for a particular device by putting a font.png in
 # its private recovery resources.
 
-ifneq (,$(filter xxxhdpi xxhdpi xhdpi,$(recovery_density)))
+ifneq (,$(filter xxxhdpi 560dpi xxhdpi 400dpi xhdpi,$(recovery_density)))
 recovery_font := $(call include-path-for, recovery)/fonts/18x32.png
 else
 recovery_font := $(call include-path-for, recovery)/fonts/12x22.png
 endif
 
-recovery_resources_private := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery/res))
+ifndef TARGET_PRIVATE_RES_DIRS
+TARGET_PRIVATE_RES_DIRS := $(wildcard $(TARGET_DEVICE_DIR)/recovery/res)
+endif
 recovery_resource_deps := $(shell find $(recovery_resources_common) \
-  $(recovery_resources_private) -type f)
+  $(TARGET_PRIVATE_RES_DIRS) -type f)
 ifdef TARGET_RECOVERY_FSTAB
 recovery_fstab := $(TARGET_RECOVERY_FSTAB)
 else
 recovery_fstab := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery.fstab))
 endif
+
+ifneq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
 # Named '.dat' so we don't attempt to use imgdiff for patching it.
 RECOVERY_RESOURCE_ZIP := $(TARGET_OUT)/etc/recovery-resource.dat
+else
+# We carry a full copy of the recovery image. recovery-resource.dat is no
+# longer needed.
+RECOVERY_RESOURCE_ZIP :=
+endif
 
-ifeq ($(recovery_resources_private),)
+ifeq ($(TARGET_PRIVATE_RES_DIRS),)
   $(info No private recovery resources for TARGET_DEVICE $(TARGET_DEVICE))
 endif
 
@@ -825,28 +849,36 @@
   $(hide) mkdir -p $(TARGET_RECOVERY_OUT)
   $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/etc $(TARGET_RECOVERY_ROOT_OUT)/tmp
   @echo Copying baseline ramdisk...
-  $(hide) rsync -a $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT) # "cp -Rf" fails to overwrite broken symlinks on Mac.
+  $(hide) rsync -a --exclude=etc $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT) # "cp -Rf" fails to overwrite broken symlinks on Mac.
   @echo Modifying ramdisk contents...
   $(hide) rm -f $(TARGET_RECOVERY_ROOT_OUT)/init*.rc
   $(hide) cp -f $(recovery_initrc) $(TARGET_RECOVERY_ROOT_OUT)/
   $(hide) rm -f $(TARGET_RECOVERY_ROOT_OUT)/sepolicy
   $(hide) cp -f $(recovery_sepolicy) $(TARGET_RECOVERY_ROOT_OUT)/sepolicy
-  $(hide) cp $(TARGET_ROOT_OUT)/init.recovery.*.rc $(TARGET_RECOVERY_ROOT_OUT)/ | true # Ignore error when the src file doesn't exist.
+  $(hide) cp $(TARGET_ROOT_OUT)/init.recovery.*.rc $(TARGET_RECOVERY_ROOT_OUT)/ || true # Ignore error when the src file doesn't exist.
   $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/res
   $(hide) rm -rf $(TARGET_RECOVERY_ROOT_OUT)/res/*
   $(hide) cp -rf $(recovery_resources_common)/* $(TARGET_RECOVERY_ROOT_OUT)/res
   $(hide) cp -f $(recovery_font) $(TARGET_RECOVERY_ROOT_OUT)/res/images/font.png
-  $(hide) $(foreach item,$(recovery_resources_private), \
-    cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/)
+  $(hide) $(foreach item,$(TARGET_PRIVATE_RES_DIRS), \
+    cp -rf $(item) $(TARGET_RECOVERY_ROOT_OUT)/$(newline))
   $(hide) $(foreach item,$(recovery_fstab), \
     cp -f $(item) $(TARGET_RECOVERY_ROOT_OUT)/etc/recovery.fstab)
   $(hide) cp $(RECOVERY_INSTALL_OTA_KEYS) $(TARGET_RECOVERY_ROOT_OUT)/res/keys
   $(hide) cat $(INSTALLED_DEFAULT_PROP_TARGET) $(recovery_build_prop) \
           > $(TARGET_RECOVERY_ROOT_OUT)/default.prop
+  $(if $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)), \
+    $(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/system_root; \
+            rm -rf $(TARGET_RECOVERY_ROOT_OUT)/system; \
+            ln -sf /system_root/system $(TARGET_RECOVERY_ROOT_OUT)/system) # Mount the system_root_image to /system_root and symlink /system.
   $(hide) $(MKBOOTFS) $(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk)
-  $(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
+  $(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)), \
+    $(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1).unsigned, \
+    $(hide) $(MKBOOTIMG) $(INTERNAL_RECOVERYIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1))
   $(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY)),\
     $(BOOT_SIGNER) /recovery $(1) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1))
+  $(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 $(1).keyblock $(1))
   $(hide) $(call assert-max-image-size,$(1),$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))
   @echo ----- Made recovery image: $(1) --------
 endef
@@ -862,16 +894,18 @@
 		$(RECOVERY_INSTALL_OTA_KEYS)
 		$(call build-recoveryimage-target, $@)
 
+ifneq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
 $(RECOVERY_RESOURCE_ZIP): $(INSTALLED_RECOVERYIMAGE_TARGET)
 	$(hide) mkdir -p $(dir $@)
 	$(hide) find $(TARGET_RECOVERY_ROOT_OUT)/res -type f | sort | zip -0qrj $@ -@
+endif
 
 .PHONY: recoveryimage-nodeps
 recoveryimage-nodeps:
 	@echo "make $@: ignoring dependencies"
 	$(call build-recoveryimage-target, $(INSTALLED_RECOVERYIMAGE_TARGET))
 
-else
+else # ! ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY)))
 INSTALLED_RECOVERYIMAGE_TARGET :=
 RECOVERY_RESOURCE_ZIP :=
 endif
@@ -954,7 +988,15 @@
       $(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) \
       || ( echo "Out of space? the tree size of $(TARGET_OUT) is (MB): " 1>&2 ;\
            du -sm $(TARGET_OUT) 1>&2;\
-           echo "The max is $$(( $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) / 1048576 )) MB." 1>&2 ;\
+           if [ "$(INTERNAL_USERIMAGES_EXT_VARIANT)" == "ext4" ]; then \
+               maxsize=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE); \
+               if [ "$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" == "true" ]; then \
+                   maxsize=$$((maxsize - 4096 * 4096)); \
+               fi; \
+               echo "The max is $$(( maxsize / 1048576 )) MB." 1>&2 ;\
+           else \
+               echo "The max is $$(( $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) / 1048576 )) MB." 1>&2 ;\
+           fi; \
            mkdir -p $(DIST_DIR); cp $(INSTALLED_FILES_FILE) $(DIST_DIR)/installed-files-rescued.txt; \
            exit 1 )
 endef
@@ -971,6 +1013,7 @@
 # we can see how big it's going to be, and include that in the system
 # image size check calculation.
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
+ifneq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
 intermediates := $(call intermediates-dir-for,PACKAGING,recovery_patch)
 RECOVERY_FROM_BOOT_PATCH := $(intermediates)/recovery_from_boot.p
 $(RECOVERY_FROM_BOOT_PATCH): $(INSTALLED_RECOVERYIMAGE_TARGET) \
@@ -980,6 +1023,9 @@
 	@echo "Construct recovery from boot"
 	mkdir -p $(dir $@)
 	PATH=$(HOST_OUT_EXECUTABLES):$$PATH $(HOST_OUT_EXECUTABLES)/imgdiff $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@
+else # $(BOARD_USES_FULL_RECOVERY_IMAGE) == true
+RECOVERY_FROM_BOOT_PATCH := $(INSTALLED_RECOVERYIMAGE_TARGET)
+endif
 endif
 
 
@@ -1239,52 +1285,60 @@
 # -----------------------------------------------------------------
 # host tools needed to build dist and OTA packages
 
-DISTTOOLS :=  $(HOST_OUT_EXECUTABLES)/minigzip \
-	  $(HOST_OUT_EXECUTABLES)/mkbootfs \
-	  $(HOST_OUT_EXECUTABLES)/mkbootimg \
-	  $(HOST_OUT_EXECUTABLES)/fs_config \
-	  $(HOST_OUT_EXECUTABLES)/zipalign \
-	  $(HOST_OUT_EXECUTABLES)/bsdiff \
-	  $(HOST_OUT_EXECUTABLES)/imgdiff \
-	  $(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar \
-	  $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
-	  $(HOST_OUT_JAVA_LIBRARIES)/BootSignature.jar \
-	  $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \
-	  $(HOST_OUT_EXECUTABLES)/make_ext4fs \
-	  $(HOST_OUT_EXECUTABLES)/simg2img \
-	  $(HOST_OUT_EXECUTABLES)/e2fsck \
-	  $(HOST_OUT_EXECUTABLES)/build_verity_tree \
-	  $(HOST_OUT_EXECUTABLES)/verity_signer \
-	  $(HOST_OUT_EXECUTABLES)/append2simg \
-	  $(HOST_OUT_EXECUTABLES)/boot_signer
+OTATOOLS :=  $(HOST_OUT_EXECUTABLES)/minigzip \
+  $(HOST_OUT_EXECUTABLES)/aapt \
+  $(HOST_OUT_EXECUTABLES)/mkbootfs \
+  $(HOST_OUT_EXECUTABLES)/mkbootimg \
+  $(HOST_OUT_EXECUTABLES)/fs_config \
+  $(HOST_OUT_EXECUTABLES)/zipalign \
+  $(HOST_OUT_EXECUTABLES)/bsdiff \
+  $(HOST_OUT_EXECUTABLES)/imgdiff \
+  $(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar \
+  $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
+  $(HOST_OUT_JAVA_LIBRARIES)/BootSignature.jar \
+  $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \
+  $(HOST_OUT_EXECUTABLES)/make_ext4fs \
+  $(HOST_OUT_EXECUTABLES)/simg2img \
+  $(HOST_OUT_EXECUTABLES)/e2fsck \
+  $(HOST_OUT_EXECUTABLES)/build_verity_tree \
+  $(HOST_OUT_EXECUTABLES)/verity_signer \
+  $(HOST_OUT_EXECUTABLES)/append2simg \
+  $(HOST_OUT_EXECUTABLES)/img2simg \
+  $(HOST_OUT_EXECUTABLES)/boot_signer
 
-OTATOOLS := $(DISTTOOLS) \
-	  $(HOST_OUT_EXECUTABLES)/aapt
+# Shared libraries.
+OTATOOLS += \
+  $(HOST_LIBRARY_PATH)/libc++$(HOST_SHLIB_SUFFIX) \
+  $(HOST_LIBRARY_PATH)/liblog$(HOST_SHLIB_SUFFIX) \
+  $(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)/libext2fs_host$(HOST_SHLIB_SUFFIX) \
+  $(HOST_LIBRARY_PATH)/libext2_blkid_host$(HOST_SHLIB_SUFFIX) \
+  $(HOST_LIBRARY_PATH)/libext2_com_err_host$(HOST_SHLIB_SUFFIX) \
+  $(HOST_LIBRARY_PATH)/libext2_e2p_host$(HOST_SHLIB_SUFFIX) \
+  $(HOST_LIBRARY_PATH)/libext2_profile_host$(HOST_SHLIB_SUFFIX) \
+  $(HOST_LIBRARY_PATH)/libext2_quota_host$(HOST_SHLIB_SUFFIX) \
+  $(HOST_LIBRARY_PATH)/libext2_uuid_host$(HOST_SHLIB_SUFFIX)
 
 .PHONY: otatools
 otatools: $(OTATOOLS)
 
 BUILT_OTATOOLS_PACKAGE := $(PRODUCT_OUT)/otatools.zip
-$(BUILT_OTATOOLS_PACKAGE): \
-	intermediate := $(call intermediates-dir-for,PACKAGING,otatools)
-$(BUILT_OTATOOLS_PACKAGE): \
-	zip_root := $(intermediate)/otatools
+$(BUILT_OTATOOLS_PACKAGE): zip_root := $(call intermediates-dir-for,PACKAGING,otatools)/otatools
 
-otatools_lib_path := $(notdir $(HOST_OUT_SHARED_LIBRARIES))
-$(BUILT_OTATOOLS_PACKAGE): \
-		$(OTATOOLS) \
-		$(HOST_OUT_SHARED_LIBRARIES)/libc++.so
+$(BUILT_OTATOOLS_PACKAGE): $(OTATOOLS) | $(ACP)
 	@echo "Package OTA tools: $@"
 	$(hide) rm -rf $@ $(zip_root)
-	$(hide) mkdir -p $(dir $@) $(zip_root)/bin $(zip_root)/framework $(zip_root)/releasetools $(zip_root)/$(otatools_lib_path)
-	$(hide) $(ACP) -p $(OTATOOLS) $(zip_root)/bin
-	$(hide) mv $(zip_root)/bin/*.jar $(zip_root)/framework/
-	$(hide) $(ACP) $(HOST_OUT_SHARED_LIBRARIES)/libc++.so $(zip_root)/$(otatools_lib_path)
+	$(hide) mkdir -p $(dir $@) $(zip_root)/bin $(zip_root)/framework $(zip_root)/releasetools $(zip_root)/system/extras/verity
+	$(call copy-files-with-structure,$(OTATOOLS),$(HOST_OUT)/,$(zip_root))
+	$(hide) $(ACP) $(HOST_OUT_JAVA_LIBRARIES)/VeritySigner.jar $(zip_root)/framework/
+	$(hide) $(ACP) -p system/extras/verity/build_verity_metadata.py $(zip_root)/system/extras/verity/
 	$(hide) $(ACP) -r -d -p build/tools/releasetools/* $(zip_root)/releasetools
 	$(hide) rm -rf $@ $(zip_root)/releasetools/*.pyc
-	$(hide) (cd $(zip_root) && zip -qry $(abspath $@) bin framework releasetools $(otatools_lib_path))
+	$(hide) (cd $(zip_root) && zip -qry $(abspath $@) *)
 	$(hide) zip -qry $(abspath $@) build/target/product/security/
-	$(hide) find device vendor -name \*.pk8 -o -name \*.x509.pem -o -name oem.prop | xargs zip -qry $(abspath $@)
+	$(hide) find device vendor -name \*.pk8 -o -name \*.x509.pem -o -name oem.prop | xargs zip -qry $(abspath $@)>/dev/null || true
 
 .PHONY: otatools-package
 otatools-package: $(BUILT_OTATOOLS_PACKAGE)
@@ -1318,11 +1372,17 @@
 endef
 
 built_ota_tools := \
-	$(call intermediates-dir-for,EXECUTABLES,applypatch,,,$(TARGET_PREFER_32_BIT))/applypatch \
-	$(call intermediates-dir-for,EXECUTABLES,applypatch_static,,,$(TARGET_PREFER_32_BIT))/applypatch_static \
-	$(call intermediates-dir-for,EXECUTABLES,check_prereq,,,$(TARGET_PREFER_32_BIT))/check_prereq \
-	$(call intermediates-dir-for,EXECUTABLES,sqlite3,,,$(TARGET_PREFER_32_BIT))/sqlite3 \
-	$(call intermediates-dir-for,EXECUTABLES,updater,,,$(TARGET_PREFER_32_BIT))/updater
+    $(call intermediates-dir-for,EXECUTABLES,applypatch,,,$(TARGET_PREFER_32_BIT))/applypatch \
+    $(call intermediates-dir-for,EXECUTABLES,sqlite3,,,$(TARGET_PREFER_32_BIT))/sqlite3
+
+# We can't build static executables when SANITIZE_TARGET=address
+ifneq (address,$(SANITIZE_TARGET))
+built_ota_tools += \
+    $(call intermediates-dir-for,EXECUTABLES,check_prereq,,,$(TARGET_PREFER_32_BIT))/check_prereq \
+    $(call intermediates-dir-for,EXECUTABLES,applypatch_static,,,$(TARGET_PREFER_32_BIT))/applypatch_static \
+    $(call intermediates-dir-for,EXECUTABLES,updater,,,$(TARGET_PREFER_32_BIT))/updater
+endif
+
 $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)
 
 $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_API_VERSION := $(RECOVERY_API_VERSION)
@@ -1376,8 +1436,14 @@
 endif
 	@# Components of the boot image
 	$(hide) mkdir -p $(zip_root)/BOOT
+ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+	$(hide) mkdir -p $(zip_root)/ROOT
+	$(hide) $(call package_files-copy-root, \
+		$(TARGET_ROOT_OUT),$(zip_root)/ROOT)
+else
 	$(hide) $(call package_files-copy-root, \
 		$(TARGET_ROOT_OUT),$(zip_root)/BOOT/RAMDISK)
+endif
 ifdef INSTALLED_KERNEL_TARGET
 	$(hide) $(ACP) $(INSTALLED_KERNEL_TARGET) $(zip_root)/BOOT/kernel
 endif
@@ -1417,7 +1483,8 @@
 	$(hide) mkdir -p $(zip_root)/META
 	$(hide) $(ACP) $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt
 	$(hide) if test -e $(tool_extensions)/releasetools.py; then $(ACP) $(tool_extensions)/releasetools.py $(zip_root)/META/; fi
-	$(hide)	echo "$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt
+	$(hide) echo "$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt
+	$(hide) $(ACP) $(SELINUX_FC) $(zip_root)/META/file_contexts.bin
 	$(hide) echo "recovery_api_version=$(PRIVATE_RECOVERY_API_VERSION)" > $(zip_root)/META/misc_info.txt
 	$(hide) echo "fstab_version=$(PRIVATE_RECOVERY_FSTAB_VERSION)" >> $(zip_root)/META/misc_info.txt
 ifdef BOARD_FLASH_BLOCK_SIZE
@@ -1429,6 +1496,9 @@
 ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
 	$(hide) echo "recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
 endif
+ifdef BOARD_HAS_EXT4_RESERVED_BLOCKS
+	$(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(zip_root)/META/misc_info.txt
+endif
 ifdef TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS
 	@# TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS can be empty to indicate that nothing but defaults should be used.
 	$(hide) echo "recovery_mount_options=$(TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)" >> $(zip_root)/META/misc_info.txt
@@ -1449,8 +1519,15 @@
 	# OTA scripts are only interested in fingerprint related properties
 	$(hide) echo "oem_fingerprint_properties=$(OEM_THUMBPRINT_PROPERTIES)" >> $(zip_root)/META/misc_info.txt
 endif
+ifeq ($(SANITIZE_TARGET),address)
+	# We need to create userdata.img with real data because the instrumented libraries are in userdata.img.
+	$(hide) echo "userdata_img_with_data=true" >> $(zip_root)/META/misc_info.txt
+endif
+ifeq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
+	$(hide) echo "full_recovery_image=true" >> $(zip_root)/META/misc_info.txt
+endif
 	$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
-	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
+	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	    ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
 	@# Zip everything up, preserving symlinks
 	$(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .)
@@ -1458,11 +1535,15 @@
 	@# 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 -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt
 	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="VENDOR/" } /^VENDOR\// {print "vendor/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/vendor_filesystem_config.txt
+ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="ROOT/" } /^ROOT\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/root_filesystem_config.txt
+else
 	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/boot_filesystem_config.txt
+endif
 	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt
 	$(hide) (cd $(zip_root) && zip -q ../$(notdir $@) META/*filesystem_config.txt)
-	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
-	    ./build/tools/releasetools/add_img_to_target_files -p $(HOST_OUT) $@
+	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
+	    ./build/tools/releasetools/add_img_to_target_files -v -p $(HOST_OUT) $@
 
 .PHONY: target-files-package
 target-files-package: $(BUILT_TARGET_FILES_PACKAGE)
@@ -1471,11 +1552,27 @@
 $(call dist-for-goals, target-files-package, $(BUILT_TARGET_FILES_PACKAGE))
 endif
 
-ifneq ($(TARGET_PRODUCT),sdk)
-ifeq ($(filter generic%,$(TARGET_DEVICE)),)
-ifneq ($(TARGET_NO_KERNEL),true)
-ifneq ($(recovery_fstab),)
+build_ota_package := true
+ifeq ($(BUILD_OS),darwin)
+build_ota_package := false
+endif
+ifeq ($(SANITIZE_TARGET),address)
+build_ota_package := false
+endif
+ifeq ($(TARGET_PRODUCT),sdk)
+build_ota_package := false
+endif
+ifneq ($(filter generic%,$(TARGET_DEVICE)),)
+build_ota_package := false
+endif
+ifeq ($(TARGET_NO_KERNEL),true)
+build_ota_package := false
+endif
+ifeq ($(recovery_fstab),)
+build_ota_package := false
+endif
 
+ifeq ($(build_ota_package),true)
 # -----------------------------------------------------------------
 # OTA update package
 
@@ -1489,7 +1586,7 @@
 
 $(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
 
-$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS)
+$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE)
 	@echo "Package OTA: $@"
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	   ./build/tools/releasetools/ota_from_target_files -v \
@@ -1502,10 +1599,7 @@
 .PHONY: otapackage
 otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)
 
-endif    # recovery_fstab is defined
-endif    # TARGET_NO_KERNEL != true
-endif    # TARGET_DEVICE != generic*
-endif    # TARGET_PRODUCT != sdk
+endif    # build_ota_package
 
 # -----------------------------------------------------------------
 # The update package
@@ -1518,7 +1612,7 @@
 
 INTERNAL_UPDATE_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
 
-$(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(DISTTOOLS)
+$(INTERNAL_UPDATE_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE)
 	@echo "Package: $@"
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	   ./build/tools/releasetools/img_from_target_files -v \
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 38f04f1..41e808b 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -87,6 +87,7 @@
 # file, tag the module as "gnu".  Search for "*_GPL*", "*_LGPL*" and "*_MPL*"
 # so that we can also find files like MODULE_LICENSE_GPL_AND_AFL
 #
+license_files := $(call find-parent-file,$(LOCAL_PATH),MODULE_LICENSE*)
 gpl_license_file := $(call find-parent-file,$(LOCAL_PATH),MODULE_LICENSE*_GPL* MODULE_LICENSE*_MPL* MODULE_LICENSE*_LGPL*)
 ifneq ($(gpl_license_file),)
   my_module_tags += gnu
@@ -116,6 +117,8 @@
     partition_tag := _VENDOR
   else ifeq (true,$(LOCAL_OEM_MODULE))
     partition_tag := _OEM
+  else ifeq (true,$(LOCAL_ODM_MODULE))
+    partition_tag := _ODM
   else
     # The definition of should-install-to-system will be different depending
     # on which goal (e.g., sdk or just droid) is being built.
@@ -417,10 +420,11 @@
 #                 be up-to-date.
 ifdef LOCAL_IS_HOST_MODULE
 ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-deps,core-libart-hostdex,$(LOCAL_IS_HOST_MODULE))
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-files,core-libart-hostdex,$(LOCAL_IS_HOST_MODULE))
 
 full_shared_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
-full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE)) \
+    $(full_shared_java_libs)
 else
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH :=
 
@@ -643,6 +647,21 @@
 
 INSTALLABLE_FILES.$(LOCAL_INSTALLED_MODULE).MODULE := $(my_register_name)
 
+##########################################################
+# Track module-level dependencies.
+# Use $(LOCAL_MODULE) instead of $(my_register_name) to ignore module's bitness.
+ALL_DEPS.MODULES := $(sort $(ALL_DEPS.MODULES) $(LOCAL_MODULE))
+ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(sort \
+  $(ALL_MODULES.$(LOCAL_MODULE).ALL_DEPS) \
+  $(LOCAL_STATIC_LIBRARIES) \
+  $(LOCAL_WHOLE_STATIC_LIBRARIES) \
+  $(LOCAL_SHARED_LIBRARIES) \
+  $(LOCAL_STATIC_JAVA_LIBRARIES) \
+  $(LOCAL_JAVA_LIBRARIES)\
+  $(LOCAL_JNI_SHARED_LIBRARIES))
+
+ALL_DEPS.$(LOCAL_MODULE).LICENSE := $(sort $(ALL_DEPS.$(LOCAL_MODULE).LICENSE) $(license_files))
+
 ###########################################################
 ## Take care of my_module_tags
 ###########################################################
@@ -679,6 +698,86 @@
 endif
 
 ###########################################################
+# JACK
+###########################################################
+ifdef LOCAL_JACK_ENABLED
+ifdef need_compile_java
+
+full_static_jack_libs := \
+    $(foreach lib,$(LOCAL_STATIC_JAVA_LIBRARIES), \
+      $(call intermediates-dir-for, \
+        JAVA_LIBRARIES,$(lib),$(LOCAL_IS_HOST_MODULE),COMMON)/classes.jack)
+
+ifeq ($(my_prefix),TARGET_)
+ifeq ($(LOCAL_SDK_VERSION),)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,core-libart)
+else
+ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current)
+# LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS.
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,android_stubs_current)
+else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,android_system_stubs_current)
+else
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,sdk_v$(LOCAL_SDK_VERSION))
+endif # current or system_current
+endif # LOCAL_SDK_VERSION
+endif # TARGET_
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JACK_LIBRARIES := $(full_static_jack_libs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VM_ARGS := $(LOCAL_JACK_VM_ARGS)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_EXTRA_ARGS := $(LOCAL_JACK_EXTRA_ARGS)
+
+ifdef LOCAL_IS_HOST_MODULE
+ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,core-libart-hostdex,$(LOCAL_IS_HOST_MODULE))
+full_shared_jack_libs := $(call jack-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_jack_lib_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_lib_deps := $(full_shared_jack_libs)
+endif # USE_CORE_LIB_BOOTCLASSPATH
+else # !LOCAL_IS_HOST_MODULE
+full_shared_jack_libs := $(call jack-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_jack_lib_deps := $(call jack-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+endif # !LOCAL_IS_HOST_MODULE
+full_jack_libs := $(full_shared_jack_libs) $(full_static_jack_libs) $(LOCAL_JACK_CLASSPATH)
+full_jack_lib_deps += $(full_static_jack_libs) $(LOCAL_JACK_CLASSPATH)
+
+# This is set by packages that are linking to other packages that export
+# shared libraries, allowing them to make use of the code in the linked apk.
+ifneq ($(apk_libraries),)
+  link_apk_jack_libraries := \
+      $(foreach lib,$(apk_libraries), \
+        $(call intermediates-dir-for, \
+              APPS,$(lib),,COMMON)/classes.jack)
+
+  # 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_lib_deps += $(link_apk_jack_libraries)
+endif
+
+# This is set by packages that contain instrumentation, allowing them to
+# link against the package they are instrumenting.  Currently only one such
+# package is allowed.
+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_jack_lib_deps += $(link_instr_classes_jack)
+endif
+
+endif  # need_compile_java
+
+# Propagate local configuration options to this target.
+$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_ALL_JACK_LIBRARIES:= $(full_jack_libs)
+$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
+
+endif # LOCAL_JACK_ENABLED
+
+###########################################################
 ## NOTICE files
 ###########################################################
 
diff --git a/core/binary.mk b/core/binary.mk
index 92b08fa..01dab2c 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -24,7 +24,7 @@
   endif
 else
   ifeq ($(LOCAL_SYSTEM_SHARED_LIBRARIES),none)
-      my_system_shared_libraries := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES)
+      my_system_shared_libraries := libc libm
   else
       my_system_shared_libraries := $(LOCAL_SYSTEM_SHARED_LIBRARIES)
   endif
@@ -40,15 +40,20 @@
 my_cflags := $(LOCAL_CFLAGS)
 my_conlyflags := $(LOCAL_CONLYFLAGS)
 my_cppflags := $(LOCAL_CPPFLAGS)
+my_cflags_no_override := $(GLOBAL_CFLAGS_NO_OVERRIDE)
+my_cppflags_no_override := $(GLOBAL_CPPFLAGS_NO_OVERRIDE)
 my_ldflags := $(LOCAL_LDFLAGS)
 my_ldlibs := $(LOCAL_LDLIBS)
 my_asflags := $(LOCAL_ASFLAGS)
 my_cc := $(LOCAL_CC)
+my_cc_wrapper := $(CC_WRAPPER)
 my_cxx := $(LOCAL_CXX)
+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) $(LOCAL_ADDITIONAL_DEPENDENCIES)
+my_export_c_include_dirs := $(LOCAL_EXPORT_C_INCLUDE_DIRS)
 
 ifdef LOCAL_IS_HOST_MODULE
 my_allow_undefined_symbols := true
@@ -77,10 +82,12 @@
     my_ndk_sysroot_lib := $(my_ndk_sysroot)/usr/lib
   endif
 
-  # The bionic linker now has support for gnu style hashes (which are much
-  # faster!), but shipping to older devices requires the old style hash.
+  # 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 and disabling packed relocations.
   #ifeq ($(shell expr $(LOCAL_SDK_VERSION) >= FIRST_SUPPORTED_VERSION),0)
     my_ldflags += -Wl,--hash-style=sysv
+    LOCAL_PACK_MODULE_RELOCATIONS := false
   #endif
 
   # Set up the NDK stl variant. Starting from NDK-r5 the c++ stl resides in a separate location.
@@ -173,6 +180,22 @@
     endif
 endif
 
+my_cpp_std_version := -std=gnu++14
+ifdef LOCAL_SDK_VERSION
+    # The NDK handles this itself.
+    my_cpp_std_version :=
+endif
+
+ifdef LOCAL_IS_HOST_MODULE
+    ifneq ($(my_clang),true)
+        # The host GCC doesn't support C++14 (and is deprecated, so likely
+        # never will). Build these modules with C++11.
+        my_cpp_std_version := -std=gnu++11
+    endif
+endif
+
+my_cppflags := $(my_cpp_std_version) $(my_cppflags)
+
 # Add option to make clang the default for device build
 ifeq ($(USE_CLANG_PLATFORM_BUILD),true)
     ifeq ($(my_clang),)
@@ -184,8 +207,6 @@
 my_static_libraries := $(LOCAL_STATIC_LIBRARIES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_STATIC_LIBRARIES_$(my_32_64_bit_suffix)) $(my_static_libraries)
 my_whole_static_libraries := $(LOCAL_WHOLE_STATIC_LIBRARIES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_WHOLE_STATIC_LIBRARIES_$(my_32_64_bit_suffix)) $(my_whole_static_libraries)
 
-my_cflags := $(filter-out $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)GLOBAL_UNSUPPORTED_CFLAGS),$(my_cflags))
-
 include $(BUILD_SYSTEM)/cxx_stl_setup.mk
 
 # Add static HAL libraries
@@ -197,6 +218,8 @@
 b_lib :=
 endif
 
+my_linker := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LINKER)
+
 include $(BUILD_SYSTEM)/config_sanitizers.mk
 
 ifeq ($(strip $($(LOCAL_2ND_ARCH_VAR_PREFIX)WITHOUT_$(my_prefix)CLANG)),true)
@@ -204,7 +227,7 @@
 endif
 
 # Add in libcompiler_rt for all regular device builds
-ifeq (,$(LOCAL_SDK_VERSION)$(LOCAL_IS_HOST_MODULE)$(WITHOUT_LIBCOMPILER_RT))
+ifeq (,$(LOCAL_SDK_VERSION)$(WITHOUT_LIBCOMPILER_RT))
   my_static_libraries += $(COMPILER_RT_CONFIG_EXTRA_STATIC_LIBRARIES)
 endif
 
@@ -223,6 +246,9 @@
     my_cflags += $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_FDO_OPTIMIZE_CFLAGS)
     my_fdo_build := true
   endif
+  # Disable ccache (or other compiler wrapper).
+  my_cc_wrapper :=
+  my_cxx_wrapper :=
 endif
 
 ###########################################################
@@ -294,24 +320,14 @@
 # clean build of your module after toggling it.
 ifeq ($(NATIVE_COVERAGE),true)
     ifeq ($(my_native_coverage),true)
+        # Note that clang coverage doesn't play nicely with acov out of the box.
+        # Clang apparently generates .gcno files that aren't compatible with
+        # gcov-4.8.  This can be solved by installing gcc-4.6 and invoking lcov
+        # with `--gcov-tool /usr/bin/gcov-4.6`.
+        #
+        # http://stackoverflow.com/questions/17758126/clang-code-coverage-invalid-output
         my_cflags += --coverage -O0
-        ifeq ($(my_clang),true)
-            # b/17574078
-            # We currently don't have a prebuilt libclang_rt.profile-<ARCH>.a,
-            # which clang is hardcoded to link if --coverage is passed in the
-            # link stage.  For now we manually link libprofile_rt (which is the
-            # name it is built as from external/compiler-rt).
-            #
-            # Note that clang coverage doesn't play nicely with acov out of the
-            # box. Clang apparently generates .gcno files that aren't compatible
-            # with gcov-4.8.  This can be solved by installing gcc-4.6 and
-            # invoking lcov with `--gcov-tool /usr/bin/gcov-4.6`.
-            #
-            # http://stackoverflow.com/questions/17758126/clang-code-coverage-invalid-output
-            my_static_libraries += libprofile_rt
-        else
-            my_ldflags += --coverage
-        endif
+        my_ldflags += --coverage
     endif
 else
     my_native_coverage := false
@@ -343,6 +359,7 @@
   else
     my_cc := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)CC)
   endif
+  my_cc := $(my_cc_wrapper) $(my_cc)
 endif
 ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
   my_cc := $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer $(my_syntax_arch) "$(my_cc)"
@@ -359,6 +376,7 @@
   else
     my_cxx := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)CXX)
   endif
+  my_cxx := $(my_cxx_wrapper) $(my_cxx)
 endif
 ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
   my_cxx := $(SYNTAX_TOOLS_PREFIX)/cxx-analyzer $(my_syntax_arch) "$(my_cxx)"
@@ -367,6 +385,7 @@
   my_cxx := $(SYNTAX_TOOLS_PREFIX)/cxx-syntax $(my_syntax_arch) "$(my_cxx)"
 endif
 endif
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_LINKER := $(my_linker)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CXX := $(my_cxx)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CLANG := $(my_clang)
 
@@ -395,7 +414,7 @@
 ## Define arm-vs-thumb-mode flags.
 ###########################################################
 LOCAL_ARM_MODE := $(strip $(LOCAL_ARM_MODE))
-ifeq ($(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH),arm)
+ifeq ($($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH),arm)
 arm_objects_mode := $(if $(LOCAL_ARM_MODE),$(LOCAL_ARM_MODE),arm)
 normal_objects_mode := $(if $(LOCAL_ARM_MODE),$(LOCAL_ARM_MODE),thumb)
 
@@ -441,6 +460,20 @@
 RenderScript_file_stamp := $(intermediates)/RenderScriptCPP.stamp
 renderscript_intermediate := $(intermediates)/renderscript
 
+renderscript_target_api :=
+
+ifneq (,$(LOCAL_RENDERSCRIPT_TARGET_API))
+renderscript_target_api := $(LOCAL_RENDERSCRIPT_TARGET_API)
+else
+ifneq (,$(LOCAL_SDK_VERSION))
+# Set target-api for LOCAL_SDK_VERSIONs other than current.
+ifneq (,$(filter-out current system_current, $(LOCAL_SDK_VERSION)))
+renderscript_target_api := $(LOCAL_SDK_VERSION)
+endif
+endif  # LOCAL_SDK_VERSION is set
+endif  # LOCAL_RENDERSCRIPT_TARGET_API is set
+
+
 ifeq ($(LOCAL_RENDERSCRIPT_CC),)
 LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
 endif
@@ -461,18 +494,21 @@
 renderscript_includes := $(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE)
 endif
 
+bc_dep_files := $(addprefix $(renderscript_intermediate)/, \
+    $(patsubst %.fs,%.d, $(patsubst %.rs,%.d, $(notdir $(renderscript_sources)))))
+
 $(RenderScript_file_stamp): PRIVATE_RS_INCLUDES := $(renderscript_includes)
 $(RenderScript_file_stamp): PRIVATE_RS_CC := $(LOCAL_RENDERSCRIPT_CC)
 $(RenderScript_file_stamp): PRIVATE_RS_FLAGS := $(renderscript_flags)
 $(RenderScript_file_stamp): PRIVATE_RS_SOURCE_FILES := $(renderscript_sources_fullpath)
 $(RenderScript_file_stamp): PRIVATE_RS_OUTPUT_DIR := $(renderscript_intermediate)
+$(RenderScript_file_stamp): PRIVATE_RS_TARGET_API := $(renderscript_target_api)
+$(RenderScript_file_stamp): PRIVATE_DEP_FILES := $(bc_dep_files)
 $(RenderScript_file_stamp): $(renderscript_sources_fullpath) $(LOCAL_RENDERSCRIPT_CC)
 	$(transform-renderscripts-to-cpp-and-bc)
 
-# include the dependency files (.d) generated by llvm-rs-cc.
-renderscript_generated_dep_files := $(addprefix $(renderscript_intermediate)/, \
-    $(patsubst %.fs,%.d, $(patsubst %.rs,%.d, $(notdir $(renderscript_sources)))))
--include $(renderscript_generated_dep_files)
+# include the dependency files (.d/.P) generated by llvm-rs-cc.
+-include $(bc_dep_files:%.d=%.P)
 
 LOCAL_INTERMEDIATE_TARGETS += $(RenderScript_file_stamp)
 
@@ -506,34 +542,44 @@
 ALL_GENERATED_SOURCES += $(my_generated_sources)
 
 ###########################################################
-## Compile the .proto files to .cc and then to .o
+## Compile the .proto files to .cc (or .c) and then to .o
 ###########################################################
 proto_sources := $(filter %.proto,$(my_src_files))
 proto_generated_objects :=
 proto_generated_headers :=
 ifneq ($(proto_sources),)
-proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
-proto_generated_cc_sources_dir := $(generated_sources_dir)/proto
-proto_generated_cc_sources := $(addprefix $(proto_generated_cc_sources_dir)/, \
-    $(patsubst %.proto,%.pb.cc,$(proto_sources_fullpath)))
-proto_generated_headers := $(patsubst %.pb.cc,%.pb.h, $(proto_generated_cc_sources))
+proto_generated_sources_dir := $(generated_sources_dir)/proto
 proto_generated_obj_dir := $(intermediates)/proto
+
+ifneq (,$(filter nanopb-c nanopb-c-enable_malloc, $(LOCAL_PROTOC_OPTIMIZE_TYPE)))
+my_proto_source_suffix := .c
+my_proto_c_includes := external/nanopb-c
+my_protoc_flags := --nanopb_out=$(proto_generated_sources_dir) \
+    --plugin=external/nanopb-c/generator/protoc-gen-nanopb
+else
+my_proto_source_suffix := .cc
+my_proto_c_includes := external/protobuf/src
+my_cflags += -DGOOGLE_PROTOBUF_NO_RTTI
+my_protoc_flags := --cpp_out=$(proto_generated_sources_dir)
+endif
+my_proto_c_includes += $(proto_generated_sources_dir)
+
+proto_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(proto_sources))
+proto_generated_sources := $(addprefix $(proto_generated_sources_dir)/, \
+    $(patsubst %.proto,%.pb$(my_proto_source_suffix),$(proto_sources_fullpath)))
+proto_generated_headers := $(patsubst %.pb$(my_proto_source_suffix),%.pb.h, $(proto_generated_sources))
 proto_generated_objects := $(addprefix $(proto_generated_obj_dir)/, \
     $(patsubst %.proto,%.pb.o,$(proto_sources_fullpath)))
 
-# Auto-export the generated proto source dir.
-LOCAL_EXPORT_C_INCLUDE_DIRS += $(proto_generated_cc_sources_dir)
-
 # Ensure the transform-proto-to-cc rule is only defined once in multilib build.
 ifndef $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined
-$(proto_generated_cc_sources): PRIVATE_PROTO_INCLUDES := $(TOP)
-$(proto_generated_cc_sources): PRIVATE_PROTO_CC_OUTPUT_DIR := $(proto_generated_cc_sources_dir)
-$(proto_generated_cc_sources): PRIVATE_PROTOC_FLAGS := $(LOCAL_PROTOC_FLAGS)
-$(proto_generated_cc_sources): $(proto_generated_cc_sources_dir)/%.pb.cc: %.proto $(PROTOC)
+$(proto_generated_sources): PRIVATE_PROTO_INCLUDES := $(TOP)
+$(proto_generated_sources): PRIVATE_PROTOC_FLAGS := $(LOCAL_PROTOC_FLAGS) $(my_protoc_flags)
+$(proto_generated_sources): $(proto_generated_sources_dir)/%.pb$(my_proto_source_suffix): %.proto $(PROTOC)
 	$(transform-proto-to-cc)
 
 # This is just a dummy rule to make sure gmake doesn't skip updating the dependents.
-$(proto_generated_headers): $(proto_generated_cc_sources_dir)/%.pb.h: $(proto_generated_cc_sources_dir)/%.pb.cc
+$(proto_generated_headers): $(proto_generated_sources_dir)/%.pb.h: $(proto_generated_sources_dir)/%.pb$(my_proto_source_suffix)
 	@echo "Updated header file $@."
 
 $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_proto_defined := true
@@ -541,13 +587,23 @@
 
 $(proto_generated_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(proto_generated_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
-$(proto_generated_objects): $(proto_generated_obj_dir)/%.o: $(proto_generated_cc_sources_dir)/%.cc $(proto_generated_headers)
+$(proto_generated_objects): $(proto_generated_obj_dir)/%.o: $(proto_generated_sources_dir)/%$(my_proto_source_suffix) $(proto_generated_headers)
+ifeq ($(my_proto_source_suffix),.c)
+	$(transform-$(PRIVATE_HOST)c-to-o)
+else
 	$(transform-$(PRIVATE_HOST)cpp-to-o)
+endif
 -include $(proto_generated_objects:%.o=%.P)
 
-my_c_includes += external/protobuf/src $(proto_generated_cc_sources_dir)
-my_cflags += -DGOOGLE_PROTOBUF_NO_RTTI
-ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),full)
+my_c_includes += $(my_proto_c_includes)
+# Auto-export the generated proto source dir.
+my_export_c_include_dirs += $(my_proto_c_includes)
+
+ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c-enable_malloc)
+    my_static_libraries += libprotobuf-c-nano-enable_malloc
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),nanopb-c)
+    my_static_libraries += libprotobuf-c-nano
+else ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),full)
     ifdef LOCAL_SDK_VERSION
         my_static_libraries += libprotobuf-cpp-full
     else
@@ -562,6 +618,50 @@
 endif
 endif  # $(proto_sources) non-empty
 
+###########################################################
+## Compile the .dbus.xml files to c++ headers
+###########################################################
+dbus_if_sources := $(filter %.dbus.xml,$(my_src_files))
+ifneq ($(dbus_if_sources),)
+
+dbus_if_sources_full_path := $(addprefix $(LOCAL_PATH)/,$(dbus_if_sources))
+dbus_service_config := $(filter %dbus-service-config.json,$(my_src_files))
+dbus_service_config_full_path := $(addprefix $(LOCAL_PATH)/,$(dbus_service_config))
+
+dbus_header_prefix := $(generated_sources_dir)/dbus_bindings
+dbus_adaptors_header := $(dbus_header_prefix)/adaptors.h
+dbus_proxies_header := $(dbus_header_prefix)/proxies.h
+dbus_method_names_header := $(dbus_header_prefix)/method_names.h
+
+dbus_generated_source_dependencies := \
+    $(dbus_if_sources_full_path) \
+    $(dbus_service_config_full_path) \
+    $(DBUS_GENERATOR)
+
+# Ensure that we only define build rules once in multilib builds.
+ifndef $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_dbus_bindings_defined
+$(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_dbus_bindings_defined := true
+$(dbus_adaptors_header) : PRIVATE_DBUS_MODULE := $(LOCAL_MODULE)
+$(dbus_adaptors_header) : PRIVATE_DBUS_HEADER_DIRECTORY := $(dbus_header_prefix)
+$(dbus_adaptors_header) : PRIVATE_DBUS_SERVICE_CONFIG := $(dbus_service_config_full_path)
+$(dbus_adaptors_header) : PRIVATE_DBUS_ADAPTORS_HEADER := $(dbus_adaptors_header)
+$(dbus_adaptors_header) : PRIVATE_DBUS_PROXIES_HEADER := $(dbus_proxies_header)
+$(dbus_adaptors_header) : PRIVATE_DBUS_METHOD_NAMES_HEADER := $(dbus_method_names_header)
+$(dbus_adaptors_header) : PRIVATE_DBUS_INTERFACE_DEFINITIONS := $(dbus_if_sources_full_path)
+$(dbus_adaptors_header) : $(dbus_generated_source_dependencies)
+	$(generate-dbus-bindings)
+# These are actually generated by the above recipe, but we'd like to make the
+# dependency chain complete.
+$(dbus_proxies_header) : $(dbus_adaptors_header)
+$(dbus_method_names_header) : $(dbus_adaptors_header)
+endif  # $(my_prefix)_$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_dbus_bindings_defined
+
+my_generated_sources += \
+    $(dbus_adaptors_header) \
+    $(dbus_proxies_header) \
+    $(dbus_method_names_header)
+endif  # $(dbus_if_sources) non-empty
+
 
 ###########################################################
 ## YACC: Compile .y and .yy files to .cpp and the to .o.
@@ -1037,6 +1137,8 @@
 my_cflags += $(LOCAL_CLANG_CFLAGS)
 my_conlyflags += $(LOCAL_CLANG_CONLYFLAGS)
 my_cppflags += $(LOCAL_CLANG_CPPFLAGS)
+my_cflags_no_override += $(GLOBAL_CLANG_CFLAGS_NO_OVERRIDE)
+my_cppflags_no_override += $(GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE)
 my_asflags += $(LOCAL_CLANG_ASFLAGS)
 my_ldflags += $(LOCAL_CLANG_LDFLAGS)
 my_cflags += $(LOCAL_CLANG_CFLAGS_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_CLANG_CFLAGS_$(my_32_64_bit_suffix))
@@ -1056,18 +1158,28 @@
   my_cflags := $(filter-out $(fdo_incompatible_flags),$(my_cflags))
 endif
 
+# No one should ever use this flag. On GCC it's mere presence will disable all
+# warnings, even those that are specified after it (contrary to typical warning
+# flag behavior). This circumvents CFLAGS_NO_OVERRIDE from forcibly enabling the
+# warnings that are *always* bugs.
+my_illegal_flags := -w
+my_cflags := $(filter-out $(my_illegal_flags),$(my_cflags))
+my_cppflags := $(filter-out $(my_illegal_flags),$(my_cppflags))
+my_conlyflags := $(filter-out $(my_illegal_flags),$(my_conlyflags))
+
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_YACCFLAGS := $(LOCAL_YACCFLAGS)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASFLAGS := $(my_asflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CONLYFLAGS := $(my_conlyflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CFLAGS := $(my_cflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CPPFLAGS := $(my_cppflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CFLAGS_NO_OVERRIDE := $(my_cflags_no_override)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CPPFLAGS_NO_OVERRIDE := $(my_cppflags_no_override)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RTTI_FLAG := $(LOCAL_RTTI_FLAG)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEBUG_CFLAGS := $(debug_cflags)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_C_INCLUDES := $(my_c_includes)
 $(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_NO_CRT := $(strip $(LOCAL_NO_CRT) $(LOCAL_NO_CRT_$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)))
 
 # this is really the way to get the files onto the command line instead
 # of using $^, because then LOCAL_ADDITIONAL_DEPENDENCIES doesn't work
@@ -1094,12 +1206,12 @@
 # Export includes
 ###########################################################
 export_includes := $(intermediates)/export_includes
-$(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDE_DIRS)
+$(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(my_export_c_include_dirs)
 # Make sure .pb.h are already generated before any dependent source files get compiled.
 $(export_includes) : $(LOCAL_MODULE_MAKEFILE) $(proto_generated_headers)
 	@echo Export includes file: $< -- $@
 	$(hide) mkdir -p $(dir $@) && rm -f $@
-ifdef LOCAL_EXPORT_C_INCLUDE_DIRS
+ifdef my_export_c_include_dirs
 	$(hide) for d in $(PRIVATE_EXPORT_C_INCLUDE_DIRS); do \
 	        echo "-I $$d" >> $@; \
 	        done
diff --git a/core/ccache.mk b/core/ccache.mk
new file mode 100644
index 0000000..34e5e1c
--- /dev/null
+++ b/core/ccache.mk
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+ifneq ($(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
+
+  # See man page, optimizations to get more cache hits
+  # implies that __DATE__ and __TIME__ are not critical for functionality.
+  # Ignore include file modification time since it will depend on when
+  # the repo was checked out
+  export CCACHE_SLOPPINESS := time_macros,include_file_mtime,file_macro
+
+  # Turn all preprocessor absolute paths into relative paths.
+  # Fixes absolute paths in preprocessed source due to use of -g.
+  # We don't really use system headers much so the rootdir is
+  # fine; ensures these paths are relative for all Android trees
+  # on a workstation.
+  export CCACHE_BASEDIR := /
+
+  # Workaround for ccache with clang.
+  # See http://petereisentraut.blogspot.com/2011/09/ccache-and-clang-part-2.html
+  export CCACHE_CPP2 := true
+
+  CCACHE_HOST_TAG := $(HOST_PREBUILT_TAG)
+  # If we are cross-compiling Windows binaries on Linux
+  # then use the linux ccache binary instead.
+  ifeq ($(HOST_OS)-$(BUILD_OS),windows-linux)
+    CCACHE_HOST_TAG := linux-$(HOST_PREBUILT_ARCH)
+  endif
+  ccache := prebuilts/misc/$(CCACHE_HOST_TAG)/ccache/ccache
+  # Check that the executable is here.
+  ccache := $(strip $(wildcard $(ccache)))
+  ifdef ccache
+    ifndef CC_WRAPPER
+      CC_WRAPPER := $(ccache)
+    endif
+    ifndef CXX_WRAPPER
+      CXX_WRAPPER := $(ccache)
+    endif
+    ccache =
+  endif
+endif
diff --git a/core/clang/HOST_x86.mk b/core/clang/HOST_x86.mk
index 35cfe60..f14a9c3 100644
--- a/core/clang/HOST_x86.mk
+++ b/core/clang/HOST_x86.mk
@@ -76,3 +76,5 @@
 $(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 c546715..1211e73 100644
--- a/core/clang/HOST_x86_64.mk
+++ b/core/clang/HOST_x86_64.mk
@@ -76,3 +76,5 @@
 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/TARGET_arm.mk b/core/clang/TARGET_arm.mk
index 993755f..5ac5477 100644
--- a/core/clang/TARGET_arm.mk
+++ b/core/clang/TARGET_arm.mk
@@ -64,3 +64,10 @@
 $(clang_2nd_arch_prefix)RS_TRIPLE := armv7-none-linux-gnueabi
 $(clang_2nd_arch_prefix)RS_TRIPLE_CFLAGS :=
 $(clang_2nd_arch_prefix)RS_COMPAT_TRIPLE := armv7-none-linux-gnueabi
+
+$(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_RPATH := /data/vendor/lib:/$(TARGET_COPY_OUT_VENDOR)/lib:/data/lib
+$(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 ba6e5f1..5120a6d 100644
--- a/core/clang/TARGET_arm64.mk
+++ b/core/clang/TARGET_arm64.mk
@@ -62,3 +62,10 @@
 RS_TRIPLE := aarch64-linux-android
 RS_TRIPLE_CFLAGS :=
 RS_COMPAT_TRIPLE := aarch64-linux-android
+
+TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-aarch64-android.a
+
+# Address sanitizer clang config
+ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan-arm64-android
+ADDRESS_SANITIZER_RPATH := /data/vendor/lib64:/$(TARGET_COPY_OUT_VENDOR)/lib64:/data/lib64
+ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
diff --git a/core/clang/TARGET_mips.mk b/core/clang/TARGET_mips.mk
index 2360181..19bbaf2 100644
--- a/core/clang/TARGET_mips.mk
+++ b/core/clang/TARGET_mips.mk
@@ -63,3 +63,5 @@
 $(clang_2nd_arch_prefix)RS_TRIPLE := armv7-none-linux-gnueabi
 $(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
diff --git a/core/clang/TARGET_mips64.mk b/core/clang/TARGET_mips64.mk
index 742be4b..104fb70 100644
--- a/core/clang/TARGET_mips64.mk
+++ b/core/clang/TARGET_mips64.mk
@@ -62,3 +62,5 @@
 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
diff --git a/core/clang/TARGET_x86.mk b/core/clang/TARGET_x86.mk
index bbbe6f1..6922f97 100644
--- a/core/clang/TARGET_x86.mk
+++ b/core/clang/TARGET_x86.mk
@@ -69,3 +69,5 @@
 $(clang_2nd_arch_prefix)RS_TRIPLE := armv7-none-linux-gnueabi
 $(clang_2nd_arch_prefix)RS_TRIPLE_CFLAGS := -D__i386__
 $(clang_2nd_arch_prefix)RS_COMPAT_TRIPLE := i686-linux-android
+
+$(clang_2nd_arch_prefix)TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i686-android.a
diff --git a/core/clang/TARGET_x86_64.mk b/core/clang/TARGET_x86_64.mk
index 9f8e8b0..e44382d 100644
--- a/core/clang/TARGET_x86_64.mk
+++ b/core/clang/TARGET_x86_64.mk
@@ -62,3 +62,5 @@
 RS_TRIPLE := aarch64-linux-android
 RS_TRIPLE_CFLAGS := -D__x86_64__
 RS_COMPAT_TRIPLE := x86_64-linux-android
+
+TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-x86_64-android.a
diff --git a/core/clang/arm.mk b/core/clang/arm.mk
index f76a182..6b3d7c1 100644
--- a/core/clang/arm.mk
+++ b/core/clang/arm.mk
@@ -7,7 +7,7 @@
 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
+  CLANG_CONFIG_arm_EXTRA_CFLAGS += -mcpu=krait -mfpu=neon-vfpv4
 endif
 
 ifeq ($(HOST_OS),darwin)
@@ -40,6 +40,5 @@
 define subst-clang-incompatible-arm-flags
   $(subst -march=armv5te,-march=armv5t,\
   $(subst -march=armv5e,-march=armv5,\
-  $(subst -mcpu=cortex-a15,-march=armv7-a,\
-  $(1))))
+  $(1)))
 endef
diff --git a/core/clang/config.mk b/core/clang/config.mk
index 72a880f..e747362 100644
--- a/core/clang/config.mk
+++ b/core/clang/config.mk
@@ -8,6 +8,7 @@
 
 LLVM_PREBUILTS_VERSION := 3.6
 LLVM_PREBUILTS_PATH := prebuilts/clang/$(BUILD_OS)-x86/host/$(LLVM_PREBUILTS_VERSION)/bin
+LLVM_RTLIB_PATH := $(LLVM_PREBUILTS_PATH)/../lib/clang/$(LLVM_PREBUILTS_VERSION)/lib/linux/
 
 CLANG := $(LLVM_PREBUILTS_PATH)/clang$(BUILD_EXECUTABLE_SUFFIX)
 CLANG_CXX := $(LLVM_PREBUILTS_PATH)/clang++$(BUILD_EXECUTABLE_SUFFIX)
@@ -17,18 +18,6 @@
 CLANG_TBLGEN := $(BUILD_OUT_EXECUTABLES)/clang-tblgen$(BUILD_EXECUTABLE_SUFFIX)
 LLVM_TBLGEN := $(BUILD_OUT_EXECUTABLES)/llvm-tblgen$(BUILD_EXECUTABLE_SUFFIX)
 
-# The C/C++ compiler can be wrapped by setting the CC/CXX_WRAPPER vars.
-ifdef CC_WRAPPER
-  ifneq ($(CC_WRAPPER),$(firstword $(CLANG)))
-    CLANG := $(CC_WRAPPER) $(CLANG)
-  endif
-endif
-ifdef CXX_WRAPPER
-  ifneq ($(CXX_WRAPPER),$(firstword $(CLANG_CXX)))
-    CLANG_CXX := $(CXX_WRAPPER) $(CLANG_CXX)
-  endif
-endif
-
 # Clang flags for all host or target rules
 CLANG_CONFIG_EXTRA_ASFLAGS :=
 CLANG_CONFIG_EXTRA_CFLAGS :=
@@ -43,6 +32,16 @@
 CLANG_CONFIG_EXTRA_CFLAGS += \
   -Werror=int-conversion
 
+# Disable overly aggressive warning for macros defined with a leading underscore
+# This happens in AndroidConfig.h, which is included nearly everywhere.
+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 += \
@@ -57,19 +56,26 @@
   -finline-functions \
   -finline-limit=64 \
   -fno-canonical-system-headers \
+  -Wno-clobbered \
+  -fno-devirtualize \
   -fno-tree-sra \
   -fprefetch-loop-arrays \
   -funswitch-loops \
   -Wmaybe-uninitialized \
+  -Wno-error=clobbered \
   -Wno-error=maybe-uninitialized \
+  -Wno-error=unused-but-set-parameter \
+  -Wno-error=unused-but-set-variable \
   -Wno-free-nonheap-object \
   -Wno-literal-suffix \
   -Wno-maybe-uninitialized \
   -Wno-old-style-declaration \
   -Wno-psabi \
-  -Wno-unused-but-set-variable \
   -Wno-unused-but-set-parameter \
-  -Wno-unused-local-typedefs
+  -Wno-unused-but-set-variable \
+  -Wno-unused-local-typedefs \
+  -Wunused-but-set-parameter \
+  -Wunused-but-set-variable
 
 # Clang flags for all host rules
 CLANG_CONFIG_HOST_EXTRA_ASFLAGS :=
@@ -83,6 +89,32 @@
 CLANG_CONFIG_TARGET_EXTRA_CPPFLAGS := -nostdlibinc
 CLANG_CONFIG_TARGET_EXTRA_LDFLAGS :=
 
+CLANG_DEFAULT_UB_CHECKS := \
+  bool \
+  integer-divide-by-zero \
+  return \
+  returns-nonnull-attribute \
+  shift-exponent \
+  unreachable \
+  vla-bound \
+
+# TODO(danalbert): The following checks currently have compiler performance
+# issues.
+# CLANG_DEFAULT_UB_CHECKS += alignment
+# CLANG_DEFAULT_UB_CHECKS += bounds
+# CLANG_DEFAULT_UB_CHECKS += enum
+# CLANG_DEFAULT_UB_CHECKS += float-cast-overflow
+# CLANG_DEFAULT_UB_CHECKS += float-divide-by-zero
+# CLANG_DEFAULT_UB_CHECKS += nonnull-attribute
+# CLANG_DEFAULT_UB_CHECKS += null
+# CLANG_DEFAULT_UB_CHECKS += shift-base
+# CLANG_DEFAULT_UB_CHECKS += signed-integer-overflow
+
+# TODO(danalbert): Fix UB in libc++'s __tree so we can turn this on.
+# https://llvm.org/PR19302
+# http://reviews.llvm.org/D6974
+# CLANG_DEFAULT_UB_CHECKS += object-size
+
 # HOST config
 clang_2nd_arch_prefix :=
 include $(BUILD_SYSTEM)/clang/HOST_$(HOST_ARCH).mk
@@ -103,12 +135,10 @@
 include $(BUILD_SYSTEM)/clang/TARGET_$(TARGET_2ND_ARCH).mk
 endif
 
-# Address sanitizer clang config
-ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan_$(TARGET_ARCH)_android
-ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS := -fsanitize=address -fno-omit-frame-pointer
+ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS := -fno-omit-frame-pointer
 ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS := -Wl,-u,__asan_preinit
 
-ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES := libdl $(ADDRESS_SANITIZER_RUNTIME_LIBRARY)
+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
diff --git a/core/clang/mips.mk b/core/clang/mips.mk
index 08daf40..4a8f812 100644
--- a/core/clang/mips.mk
+++ b/core/clang/mips.mk
@@ -12,8 +12,14 @@
   -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)
diff --git a/core/clang/mips64.mk b/core/clang/mips64.mk
index 612175c..1b72e05 100644
--- a/core/clang/mips64.mk
+++ b/core/clang/mips64.mk
@@ -12,8 +12,14 @@
   -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)
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index cf980d8..7885644 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -54,6 +54,7 @@
 # can have permission to touch it.
 include $(BUILD_SYSTEM)/cleanspec.mk
 INTERNAL_CLEAN_BUILD_VERSION := $(strip $(INTERNAL_CLEAN_BUILD_VERSION))
+INTERNAL_CLEAN_STEPS := $(strip $(INTERNAL_CLEAN_STEPS))
 
 # If the clean_steps.mk file is missing (usually after a clean build)
 # then we won't do anything.
@@ -105,11 +106,18 @@
   _crs_new_cmd :=
   steps :=
 endif
-CURRENT_CLEAN_BUILD_VERSION :=
-CURRENT_CLEAN_STEPS :=
 
 # Write the new state to the file.
 #
+rewrite_clean_steps_file :=
+ifneq ($(CURRENT_CLEAN_BUILD_VERSION)-$(CURRENT_CLEAN_STEPS),$(INTERNAL_CLEAN_BUILD_VERSION)-$(INTERNAL_CLEAN_STEPS))
+rewrite_clean_steps_file := true
+endif
+ifeq ($(wildcard $(clean_steps_file)),)
+# This is the first build.
+rewrite_clean_steps_file := true
+endif
+ifeq ($(rewrite_clean_steps_file),true)
 $(shell \
   mkdir -p $(dir $(clean_steps_file)) && \
   echo "CURRENT_CLEAN_BUILD_VERSION := $(INTERNAL_CLEAN_BUILD_VERSION)" > \
@@ -117,8 +125,12 @@
   echo "CURRENT_CLEAN_STEPS := $(INTERNAL_CLEAN_STEPS)" >> \
       $(clean_steps_file) \
  )
+endif
 
+CURRENT_CLEAN_BUILD_VERSION :=
+CURRENT_CLEAN_STEPS :=
 clean_steps_file :=
+rewrite_clean_steps_file :=
 INTERNAL_CLEAN_STEPS :=
 INTERNAL_CLEAN_BUILD_VERSION :=
 
@@ -137,15 +149,23 @@
 
 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 :=
 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)"
     $(info *** Build configuration changed: "$(PREVIOUS_BUILD_CONFIG)" -> "$(current_build_config)")
@@ -156,15 +176,27 @@
     endif
   endif
 endif  # else, this is the first build, so no need to clean.
-PREVIOUS_BUILD_CONFIG :=
+
+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)) && \
   echo "PREVIOUS_BUILD_CONFIG := $(current_build_config)" > \
+      $(previous_build_config_file) && \
+  echo "PREVIOUS_SANITIZE_TARGET := $(current_sanitize_target)" >> \
       $(previous_build_config_file) \
  )
+endif
+PREVIOUS_BUILD_CONFIG :=
+PREVIOUS_SANITIZE_TARGET :=
 previous_build_config_file :=
 current_build_config :=
 
@@ -221,6 +253,12 @@
 	$(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)))
@@ -240,6 +278,12 @@
 	$(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))
@@ -247,3 +291,73 @@
   $(info *** Done with the cleaning, now starting the real build.)
 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 :=
+
+###########################################################
+# Clean build tools when swithcing between prebuilt host tools (such as in
+# apps_only build) and tools built from source (platform build).
+previous_prebuilt_tools_config_file := $(HOST_OUT)/previous_prebuilt_tools_config.mk
+ifneq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)))
+current_prebuilt_tools := true
+else
+current_prebuilt_tools := false
+endif
+PREVIOUS_PREBUILT_TOOLS :=
+-include $(previous_prebuilt_tools_config_file)
+force_tools_clean :=
+ifdef PREVIOUS_PREBUILT_TOOLS
+ifneq ($(PREVIOUS_PREBUILT_TOOLS),$(current_prebuilt_tools))
+force_tools_clean := true
+endif
+endif # else, this is the first build, so no need to clean.
+
+# Write the new state to the file.
+ifneq ($(PREVIOUS_PREBUILT_TOOLS),$(current_prebuilt_tools))
+$(shell \
+  mkdir -p $(dir $(previous_prebuilt_tools_config_file)) && \
+  echo "PREVIOUS_PREBUILT_TOOLS:=$(current_prebuilt_tools)" > \
+    $(previous_prebuilt_tools_config_file))
+endif
+
+ifeq ($(force_tools_clean),true)
+# For this list of prebuilt tools, see prebuilts/sdk/tools/Android.mk.
+tools_clean_files := \
+  $(HOST_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/signapk_intermediates \
+  $(HOST_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/dx_intermediates \
+  $(HOST_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/shrinkedAndroid_intermediates \
+  $(HOST_OUT)/obj*/EXECUTABLES/aapt_intermediates \
+  $(HOST_OUT)/obj*/EXECUTABLES/aidl_intermediates \
+  $(HOST_OUT)/obj*/EXECUTABLES/zipalign_intermediates \
+  $(HOST_OUT)/obj*/lib/libc++$(HOST_SHLIB_SUFFIX) \
+
+$(info *** build type changed, clean host tools...)
+$(info *** rm -rf $(tools_clean_files))
+$(shell rm -rf $(tools_clean_files))
+endif
+
+###########################################################
+
+.PHONY: clean-jack-files
+clean-jack-files: clean-dex-files
+	$(hide) find $(OUT_DIR) -name "*.jack" | xargs rm -f
+	$(hide) find $(OUT_DIR) -type d -name "jack" | xargs rm -rf
+	@echo "All jack files have been removed."
+
+.PHONY: clean-dex-files
+clean-dex-files:
+	$(hide) find $(OUT_DIR) -name "*.dex" ! -path "*/jack-incremental/*" | xargs rm -f
+	$(hide) for i in `find $(OUT_DIR) -name "*.jar" -o -name "*.apk"` ; do ((unzip -l $$i 2> /dev/null | \
+				grep -q "\.dex$$" && rm -f $$i) || continue ) ; done
+	@echo "All dex files and archives containing dex files have been removed."
+
+.PHONY: clean-jack-incremental
+clean-jack-incremental:
+	$(hide) find $(OUT_DIR) -name "jack-incremental" -type d | xargs rm -rf
+	@echo "All jack incremental dirs have been removed."
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 7837ae3..e5d299c 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -74,6 +74,7 @@
 LOCAL_JAVA_LAYERS_FILE:=
 LOCAL_NO_STANDARD_LIBRARIES:=
 LOCAL_CLASSPATH:=
+LOCAL_JACK_CLASSPATH:=
 LOCAL_DROIDDOC_USE_STANDARD_DOCLET:=
 LOCAL_DROIDDOC_SOURCE_PATH:=
 LOCAL_DROIDDOC_TEMPLATE_DIR:=
@@ -92,11 +93,10 @@
 LOCAL_COPY_HEADERS:=
 LOCAL_FORCE_STATIC_EXECUTABLE:=
 LOCAL_ADDITIONAL_DEPENDENCIES:=
-LOCAL_COMPRESS_MODULE_SYMBOLS:=
 LOCAL_STRIP_MODULE:=
+LOCAL_PACK_MODULE_RELOCATIONS:=
 LOCAL_JNI_SHARED_LIBRARIES:=
 LOCAL_JNI_SHARED_LIBRARIES_ABI:=
-LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS:=
 LOCAL_PREBUILT_JNI_LIBS:=
 LOCAL_JAR_MANIFEST:=
 LOCAL_INSTRUMENTATION_FOR:=
@@ -108,6 +108,11 @@
 LOCAL_ADDITIONAL_JAVA_DIR:=
 LOCAL_ALLOW_UNDEFINED_SYMBOLS:=
 LOCAL_DX_FLAGS:=
+LOCAL_JACK_ENABLED:=$(DEFAULT_JACK_ENABLED) # '' (ie disabled), disabled, full, incremental
+LOCAL_JACK_VM_ARGS := $(DEFAULT_JACK_VM_ARGS)
+LOCAL_JACK_EXTRA_ARGS := $(DEFAULT_JACK_EXTRA_ARGS)
+LOCAL_JACK_FLAGS:=
+LOCAL_JILL_FLAGS:=
 LOCAL_CERTIFICATE:=
 LOCAL_SDK_VERSION:=
 LOCAL_SDK_RES_VERSION:=
@@ -115,6 +120,7 @@
 LOCAL_EMMA_INSTRUMENT:=
 LOCAL_PROGUARD_ENABLED:= # '',full,custom,nosystem,disabled,obfuscation,optimization
 LOCAL_PROGUARD_FLAGS:=
+LOCAL_JACK_PROGUARD_FLAGS:=
 LOCAL_PROGUARD_FLAG_FILES:=
 LOCAL_TEST_MODULE_TO_PROGUARD_WITH:=
 LOCAL_EMMA_COVERAGE_FILTER:=
@@ -136,18 +142,18 @@
 LOCAL_PROTOC_FLAGS:=
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS:=
 LOCAL_NO_CRT:=
+LOCAL_NO_LIBGCC:=
 LOCAL_PROPRIETARY_MODULE:=
 LOCAL_OEM_MODULE:=
+LOCAL_ODM_MODULE:=
 LOCAL_PRIVILEGED_MODULE:=
 LOCAL_MODULE_OWNER:=
 LOCAL_CTS_TEST_PACKAGE:=
 LOCAL_CTS_TEST_RUNNER:=
 LOCAL_CLANG:=
-LOCAL_ADDRESS_SANITIZER:=
 LOCAL_JAR_EXCLUDE_FILES:=
 LOCAL_JAR_PACKAGES:=
 LOCAL_JAR_EXCLUDE_PACKAGES:=
-LOCAL_LINT_FLAGS:=
 LOCAL_SOURCE_FILES_ALL_GENERATED:= # '',true
 # Don't delete the META_INF dir when merging static Java libraries.
 LOCAL_DONT_DELETE_JAR_META_INF:=
@@ -156,7 +162,6 @@
 LOCAL_PREBUILT_MODULE_FILE:=
 LOCAL_POST_LINK_CMD:=
 LOCAL_POST_INSTALL_CMD:=
-LOCAL_DIST_BUNDLED_BINARIES:=
 LOCAL_HAL_STATIC_LIBRARIES:=
 LOCAL_RMTYPEDEFS:=
 LOCAL_NO_SYNTAX_CHECK:=
@@ -173,6 +178,8 @@
 LOCAL_NATIVE_COVERAGE :=
 LOCAL_DPI_VARIANTS:=
 LOCAL_DPI_FILE_STEM:=
+LOCAL_SANITIZE:=
+LOCAL_SANITIZE_RECOVER:=
 
 # arch specific variables
 LOCAL_SRC_FILES_$(TARGET_ARCH):=
@@ -183,7 +190,6 @@
 LOCAL_C_INCLUDES_$(TARGET_ARCH):=
 LOCAL_ASFLAGS_$(TARGET_ARCH):=
 LOCAL_CLANG_ASFLAGS_$(TARGET_ARCH):=
-LOCAL_NO_CRT_$(TARGET_ARCH):=
 LOCAL_LDFLAGS_$(TARGET_ARCH):=
 LOCAL_CLANG_LDFLAGS_$(TARGET_ARCH):=
 LOCAL_SHARED_LIBRARIES_$(TARGET_ARCH):=
@@ -202,7 +208,6 @@
 LOCAL_C_INCLUDES_$(TARGET_2ND_ARCH):=
 LOCAL_ASFLAGS_$(TARGET_2ND_ARCH):=
 LOCAL_CLANG_ASFLAGS_$(TARGET_2ND_ARCH):=
-LOCAL_NO_CRT_$(TARGET_2ND_ARCH):=
 LOCAL_LDFLAGS_$(TARGET_2ND_ARCH):=
 LOCAL_CLANG_LDFLAGS_$(TARGET_2ND_ARCH):=
 LOCAL_SHARED_LIBRARIES_$(TARGET_2ND_ARCH):=
@@ -221,7 +226,6 @@
 LOCAL_C_INCLUDES_$(HOST_ARCH):=
 LOCAL_ASFLAGS_$(HOST_ARCH):=
 LOCAL_CLANG_ASFLAGS_$(HOST_ARCH):=
-LOCAL_NO_CRT_$(HOST_ARCH):=
 LOCAL_LDFLAGS_$(HOST_ARCH):=
 LOCAL_CLANG_LDFLAGS_$(HOST_ARCH):=
 LOCAL_SHARED_LIBRARIES_$(HOST_ARCH):=
@@ -239,7 +243,6 @@
 LOCAL_C_INCLUDES_$(HOST_2ND_ARCH):=
 LOCAL_ASFLAGS_$(HOST_2ND_ARCH):=
 LOCAL_CLANG_ASFLAGS_$(HOST_2ND_ARCH):=
-LOCAL_NO_CRT_$(HOST_2ND_ARCH):=
 LOCAL_LDFLAGS_$(HOST_2ND_ARCH):=
 LOCAL_CLANG_LDFLAGS_$(HOST_2ND_ARCH):=
 LOCAL_SHARED_LIBRARIES_$(HOST_2ND_ARCH):=
diff --git a/core/combo/HOST_darwin-x86.mk b/core/combo/HOST_darwin-x86.mk
index 7fa48ff..85c883c 100644
--- a/core/combo/HOST_darwin-x86.mk
+++ b/core/combo/HOST_darwin-x86.mk
@@ -52,16 +52,6 @@
 $(combo_2nd_arch_prefix)HOST_SHLIB_SUFFIX := .dylib
 $(combo_2nd_arch_prefix)HOST_JNILIB_SUFFIX := .jnilib
 
-# TODO: add AndroidConfig.h for darwin-x86_64
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += \
-    -include $(call select-android-config-h,darwin-x86)
-
-ifneq ($(filter 10.7 10.7.% 10.8 10.8.%, $(build_mac_version)),)
-       $(combo_2nd_arch_prefix)HOST_RUN_RANLIB_AFTER_COPYING := false
-else
-       $(combo_2nd_arch_prefix)HOST_RUN_RANLIB_AFTER_COPYING := true
-       PRE_LION_DYNAMIC_LINKER_OPTIONS := -Wl,-dynamic
-endif
 $(combo_2nd_arch_prefix)HOST_GLOBAL_ARFLAGS := cqs
 
 ############################################################
@@ -84,14 +74,16 @@
         -o $@ \
         -install_name @rpath/$(notdir $@) \
         -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)) \
         $(PRIVATE_LDFLAGS)
 endef
 
 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)) \
         -o $@ \
-        $(PRE_LION_DYNAMIC_LINKER_OPTIONS) -Wl,-headerpad_max_install_names \
+        -Wl,-headerpad_max_install_names \
         $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_LD_DIRS) \
         $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
            $(PRIVATE_HOST_GLOBAL_LDFLAGS) \
diff --git a/core/combo/HOST_darwin-x86_64.mk b/core/combo/HOST_darwin-x86_64.mk
index c06933d..93a1b3e 100644
--- a/core/combo/HOST_darwin-x86_64.mk
+++ b/core/combo/HOST_darwin-x86_64.mk
@@ -52,14 +52,6 @@
 HOST_SHLIB_SUFFIX := .dylib
 HOST_JNILIB_SUFFIX := .jnilib
 
-HOST_GLOBAL_CFLAGS += \
-    -include $(call select-android-config-h,darwin-x86)
-
-ifneq ($(filter 10.7 10.7.% 10.8 10.8.%, $(build_mac_version)),)
-       HOST_RUN_RANLIB_AFTER_COPYING := false
-else
-       HOST_RUN_RANLIB_AFTER_COPYING := true
-endif
 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 93a1287..3acf795 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -29,7 +29,7 @@
 
 # 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
+$(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -m32 -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now
 
 ifneq ($(strip $(BUILD_HOST_static)),)
 # Statically-linked binaries are desirable for sandboxed environment
@@ -40,8 +40,7 @@
   -no-canonical-prefixes \
   -include $(call select-android-config-h,linux-x86)
 
-# Disable new longjmp in glibc 2.11 and later. See bug 2967937. Same for 2.15?
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
+$(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.
@@ -49,7 +48,6 @@
 
 $(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 3685712..b74990b 100644
--- a/core/combo/HOST_linux-x86_64.mk
+++ b/core/combo/HOST_linux-x86_64.mk
@@ -28,7 +28,7 @@
 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
+HOST_GLOBAL_LDFLAGS += -m64 -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now
 
 ifneq ($(strip $(BUILD_HOST_static)),)
 # Statically-linked binaries are desirable for sandboxed environment
@@ -40,8 +40,7 @@
   -no-canonical-prefixes \
   -include $(call select-android-config-h,linux-x86)
 
-# Disable new longjmp in glibc 2.11 and later. See bug 2967937. Same for 2.15?
-HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
+HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector
 
 # Workaround differences in inttypes.h between host and target.
 # See bug 12708004.
diff --git a/core/combo/HOST_windows-x86.mk b/core/combo/HOST_windows-x86.mk
index b71ac16..eb1c49c 100644
--- a/core/combo/HOST_windows-x86.mk
+++ b/core/combo/HOST_windows-x86.mk
@@ -14,19 +14,10 @@
 # limitations under the License.
 #
 
-# Configuration for Linux on x86.
+# Settings to use MinGW as a cross-compiler under Linux
 # Included by combo/select.make
 
-# right now we get these from the environment, but we should
-# pick them from the tree somewhere
-TOOLS_PREFIX := #prebuilt/windows/host/bin/
-TOOLS_EXE_SUFFIX := .exe
-
-# Settings to use MinGW has a cross-compiler under Linux
-ifneq ($(findstring Linux,$(UNAME)),)
-ifdef USE_MINGW
 HOST_ACP_UNAVAILABLE := true
-TOOLS_EXE_SUFFIX :=
 $(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -DUSE_MINGW -DWIN32_LEAN_AND_MEAN
 $(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -Wno-unused-parameter
 $(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += --sysroot=prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32
@@ -36,12 +27,12 @@
 $(combo_2nd_arch_prefix)HOST_C_INCLUDES += prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/include
 $(combo_2nd_arch_prefix)HOST_C_INCLUDES += prebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/lib/gcc/x86_64-w64-mingw32/4.8.3/include
 $(combo_2nd_arch_prefix)HOST_GLOBAL_LD_DIRS += -Lprebuilts/gcc/linux-x86/host/x86_64-w64-mingw32-4.8/x86_64-w64-mingw32/lib32
-endif # USE_MINGW
-endif # Linux
 
 # 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 -D__USE_MINGW_ANSI_STDIO
+$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
+# Use C99-compliant printf functions (%zd).
+$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
 
 $(combo_2nd_arch_prefix)HOST_CC := $(TOOLS_PREFIX)gcc$(TOOLS_EXE_SUFFIX)
 $(combo_2nd_arch_prefix)HOST_CXX := $(TOOLS_PREFIX)g++$(TOOLS_EXE_SUFFIX)
@@ -57,22 +48,6 @@
 $(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -static
 endif # BUILD_HOST_static
 
-# when building under Cygwin, ensure that we use Mingw compilation by default.
-# you can disable this (i.e. to generate Cygwin executables) by defining the
-# USE_CYGWIN variable in your environment, e.g.:
-#
-#   export USE_CYGWIN=1
-#
-# note that the -mno-cygwin flags are not needed when cross-compiling the
-# Windows host tools on Linux
-#
-ifneq ($(findstring CYGWIN,$(UNAME)),)
-ifeq ($(strip $(USE_CYGWIN)),)
-$(combo_2nd_arch_prefix)HOST_GLOBAL_CFLAGS += -mno-cygwin
-$(combo_2nd_arch_prefix)HOST_GLOBAL_LDFLAGS += -mno-cygwin -mconsole
-endif
-endif
-
 ############################################################
 ## Macros after this line are shared by the 64-bit config.
 
@@ -80,7 +55,6 @@
 HOST_EXECUTABLE_SUFFIX := .exe
 
 # $(1): The file to check
-# TODO: find out what format cygwin's stat(1) uses
 define get-file-size
-999999999
+stat --format "%s" "$(1)" | tr -d '\n'
 endef
diff --git a/core/combo/HOST_windows-x86_64.mk b/core/combo/HOST_windows-x86_64.mk
index bd392ea..b38c74c 100644
--- a/core/combo/HOST_windows-x86_64.mk
+++ b/core/combo/HOST_windows-x86_64.mk
@@ -14,29 +14,23 @@
 # limitations under the License.
 #
 
-# Configuration for Windows on x86_64.
+# Settings to use MinGW as a cross-compiler under Linux
 # Included by combo/select.make
 
 # right now we get these from the environment, but we should
 # pick them from the tree somewhere
-TOOLS_PREFIX := #prebuilt/windows/host/bin/
-TOOLS_EXE_SUFFIX := .exe
-
-# Settings to use MinGW has a cross-compiler under Linux
-ifneq ($(findstring Linux,$(UNAME)),)
-ifdef USE_MINGW
-HOST_ACP_UNAVAILABLE := true
-TOOLS_EXE_SUFFIX :=
-HOST_GLOBAL_CFLAGS += -DUSE_MINGW
 TOOLS_PREFIX := /usr/bin/amd64-mingw32msvc-
+
+HOST_ACP_UNAVAILABLE := true
+HOST_GLOBAL_CFLAGS += -DUSE_MINGW
 HOST_C_INCLUDES += /usr/lib/gcc/amd64-mingw32msvc/4.4.2/include
 HOST_GLOBAL_LD_DIRS += -L/usr/amd64-mingw32msvc/lib
-endif # USE_MINGW
-endif # Linux
 
 # Workaround differences in inttypes.h between host and target.
 # See bug 12708004.
-HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS -D__USE_MINGW_ANSI_STDIO
+HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
+# Use C99-compliant printf functions (%zd).
+HOST_GLOBAL_CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
 
 HOST_CC := $(TOOLS_PREFIX)gcc$(TOOLS_EXE_SUFFIX)
 HOST_CXX := $(TOOLS_PREFIX)g++$(TOOLS_EXE_SUFFIX)
@@ -48,19 +42,3 @@
 # Statically-linked binaries are desirable for sandboxed environment
 HOST_GLOBAL_LDFLAGS += -static
 endif # BUILD_HOST_static
-
-# when building under Cygwin, ensure that we use Mingw compilation by default.
-# you can disable this (i.e. to generate Cygwin executables) by defining the
-# USE_CYGWIN variable in your environment, e.g.:
-#
-#   export USE_CYGWIN=1
-#
-# note that the -mno-cygwin flags are not needed when cross-compiling the
-# Windows host tools on Linux
-#
-ifneq ($(findstring CYGWIN,$(UNAME)),)
-ifeq ($(strip $(USE_CYGWIN)),)
-HOST_GLOBAL_CFLAGS += -mno-cygwin
-HOST_GLOBAL_LDFLAGS += -mno-cygwin -mconsole
-endif
-endif
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 8059b2a..7818e3e 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -57,13 +57,13 @@
 $(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$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_CXX := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_AR := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_OBJCOPY := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_LD := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_READELF := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)readelf$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_STRIP := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)strip$(HOST_EXECUTABLE_SUFFIX)
+$(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_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
 
@@ -188,8 +188,6 @@
 $(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_STRIP_MODULE:=true
-
-$(combo_2nd_arch_prefix)TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libm
+$(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 07a1de9..863befe 100644
--- a/core/combo/TARGET_linux-arm64.mk
+++ b/core/combo/TARGET_linux-arm64.mk
@@ -57,13 +57,13 @@
 TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/aarch64-linux-android-
 endif
 
-TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
-TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-TARGET_AR := $(TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-TARGET_LD := $(TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
-TARGET_READELF := $(TARGET_TOOLS_PREFIX)readelf$(HOST_EXECUTABLE_SUFFIX)
-TARGET_STRIP := $(TARGET_TOOLS_PREFIX)strip$(HOST_EXECUTABLE_SUFFIX)
+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_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
 
@@ -114,6 +114,7 @@
 			-Wl,--fatal-warnings \
 			-Wl,-maarch64linux \
 			-Wl,--hash-style=gnu \
+			-Wl,--fix-cortex-a53-843419 \
 			$(arch_variant_ldflags)
 
 # Disable transitive dependency library symbol resolving.
@@ -158,8 +159,6 @@
 TARGET_CRTBEGIN_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
 TARGET_CRTEND_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
 
-TARGET_STRIP_MODULE:=true
-
-TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libm
+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 55566eb..66461d9 100644
--- a/core/combo/TARGET_linux-mips.mk
+++ b/core/combo/TARGET_linux-mips.mk
@@ -57,13 +57,13 @@
 $(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$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_CXX := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_AR := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_OBJCOPY := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_LD := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_READELF := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)readelf$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_STRIP := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)strip$(HOST_EXECUTABLE_SUFFIX)
+$(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_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
 
@@ -162,8 +162,6 @@
 $(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_STRIP_MODULE:=true
-
-$(combo_2nd_arch_prefix)TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libm
+$(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 c6f9f29..7aaded5 100644
--- a/core/combo/TARGET_linux-mips64.mk
+++ b/core/combo/TARGET_linux-mips64.mk
@@ -57,13 +57,13 @@
 TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/mips64el-linux-android-
 endif
 
-TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
-TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-TARGET_AR := $(TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-TARGET_LD := $(TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
-TARGET_READELF := $(TARGET_TOOLS_PREFIX)readelf$(HOST_EXECUTABLE_SUFFIX)
-TARGET_STRIP := $(TARGET_TOOLS_PREFIX)strip$(HOST_EXECUTABLE_SUFFIX)
+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_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
 
@@ -115,6 +115,9 @@
 			-Wl,--fatal-warnings \
 			$(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
@@ -128,7 +131,6 @@
 
 libc_root := bionic/libc
 libm_root := bionic/libm
-libthread_db_root := bionic/libthread_db
 
 
 ## on some hosts, the target cross-compiler is not available so do not run this command
@@ -159,7 +161,7 @@
 	$(KERNEL_HEADERS) \
 	$(libm_root)/include \
 	$(libm_root)/include/mips \
-	$(libthread_db_root)/include
+
 # TODO: perhaps use $(libm_root)/include/mips64 instead of mips ?
 
 TARGET_CRTBEGIN_STATIC_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
@@ -169,8 +171,6 @@
 TARGET_CRTBEGIN_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
 TARGET_CRTEND_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
 
-TARGET_STRIP_MODULE:=true
-
-TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libm
+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 f17a514..0b87920 100644
--- a/core/combo/TARGET_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -23,10 +23,10 @@
 endif
 
 # Decouple NDK library selection with platform compiler version
-$(combo_2nd_arch_prefix)TARGET_NDK_GCC_VERSION := 4.8
+$(combo_2nd_arch_prefix)TARGET_NDK_GCC_VERSION := 4.9
 
 ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := 4.8
+$(combo_2nd_arch_prefix)TARGET_GCC_VERSION := 4.9
 else
 $(combo_2nd_arch_prefix)TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
 endif
@@ -49,13 +49,13 @@
 $(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$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_CXX := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_AR := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_OBJCOPY := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_LD := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_READELF := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)readelf$(HOST_EXECUTABLE_SUFFIX)
-$(combo_2nd_arch_prefix)TARGET_STRIP := $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)strip$(HOST_EXECUTABLE_SUFFIX)
+$(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
 
 ifneq ($(wildcard $($(combo_2nd_arch_prefix)TARGET_CC)),)
 $(combo_2nd_arch_prefix)TARGET_LIBGCC := \
@@ -142,9 +142,7 @@
 $(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_STRIP_MODULE:=true
-
-$(combo_2nd_arch_prefix)TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libm
+$(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 2adb157..bf443b3 100644
--- a/core/combo/TARGET_linux-x86_64.mk
+++ b/core/combo/TARGET_linux-x86_64.mk
@@ -26,7 +26,7 @@
 TARGET_NDK_GCC_VERSION := 4.9
 
 ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
-TARGET_GCC_VERSION := 4.8
+TARGET_GCC_VERSION := 4.9
 else
 TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
 endif
@@ -49,13 +49,13 @@
 TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/x86_64-linux-android-
 endif
 
-TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
-TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-TARGET_AR := $(TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-TARGET_LD := $(TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
-TARGET_READELF := $(TARGET_TOOLS_PREFIX)readelf$(HOST_EXECUTABLE_SUFFIX)
-TARGET_STRIP := $(TARGET_TOOLS_PREFIX)strip$(HOST_EXECUTABLE_SUFFIX)
+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
 
 ifneq ($(wildcard $(TARGET_CC)),)
 TARGET_LIBGCC := \
@@ -151,10 +151,6 @@
 TARGET_CRTBEGIN_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_so.o
 TARGET_CRTEND_SO_O := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtend_so.o
 
-TARGET_STRIP_MODULE:=true
-
-TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libm
-
 TARGET_LINKER := /system/bin/linker64
 
 TARGET_GLOBAL_YASM_FLAGS := -f elf64 -m amd64
diff --git a/core/combo/arch/arm/armv7-a-neon.mk b/core/combo/arch/arm/armv7-a-neon.mk
index d535afc..99f17aa 100644
--- a/core/combo/arch/arm/armv7-a-neon.mk
+++ b/core/combo/arch/arm/armv7-a-neon.mk
@@ -16,14 +16,23 @@
 	# Fake an ARM compiler flag as these processors support LPAE which GCC/clang
 	# don't advertise.
 	arch_variant_cflags += -D__ARM_FEATURE_LPAE=1
+	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
 ifeq ($(strip $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)),cortex-a7)
 	arch_variant_cflags := -mcpu=cortex-a7
+	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
@@ -31,6 +40,3 @@
 arch_variant_cflags += \
     -mfloat-abi=softfp \
     -mfpu=neon
-
-arch_variant_ldflags := \
-	-Wl,--fix-cortex-a8
diff --git a/core/combo/arch/mips/mips32-fp.mk b/core/combo/arch/mips/mips32-fp.mk
index 8320e93..912ff63 100644
--- a/core/combo/arch/mips/mips32-fp.mk
+++ b/core/combo/arch/mips/mips32-fp.mk
@@ -7,6 +7,7 @@
     -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 2b4f714..09b3bc2 100644
--- a/core/combo/arch/mips/mips32r2-fp-xburst.mk
+++ b/core/combo/arch/mips/mips32r2-fp-xburst.mk
@@ -9,7 +9,8 @@
     -mfp32 \
     -modd-spreg \
     -mno-fused-madd \
-    -Wa,-mmxu
+    -Wa,-mmxu \
+    -mno-synci
 
 arch_variant_ldflags := \
     -Wl,-melf32ltsmip
diff --git a/core/combo/include/arch/darwin-x86/AndroidConfig.h b/core/combo/include/arch/darwin-x86/AndroidConfig.h
deleted file mode 100644
index 6ddfdb1..0000000
--- a/core/combo/include/arch/darwin-x86/AndroidConfig.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-/*
- * Android config -- "Darwin".  Used for X86 Mac OS X.
- */
-#ifndef _ANDROID_CONFIG_H
-#define _ANDROID_CONFIG_H
-
-/*
- * ===========================================================================
- *                              !!! IMPORTANT !!!
- * ===========================================================================
- *
- * This file is included by ALL C/C++ source files.  Don't put anything in
- * here unless you are absolutely certain it can't go anywhere else.
- *
- * Any C++ stuff must be wrapped with "#ifdef __cplusplus".  Do not use "//"
- * comments.
- */
-
-/*
- * Add any extra platform-specific defines here.
- */
-#define _THREAD_SAFE
-
-/*
- * Define if we have <malloc.h> header
- */
-/* #define HAVE_MALLOC_H */
-
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '/'
-
-/*
- * Define if the strlcpy() function exists on the system.
- */
-#define HAVE_STRLCPY 1
-
-/*
- * Define if <stdint.h> exists.
- */
-#define HAVE_STDINT_H 1
-
-/*
- * Define if printf() supports %zd for size_t arguments
- */
-#define HAVE_PRINTF_ZD 1
-
-#endif /*_ANDROID_CONFIG_H*/
diff --git a/core/combo/include/arch/linux-arm/AndroidConfig.h b/core/combo/include/arch/linux-arm/AndroidConfig.h
index b1c963e..030a628 100644
--- a/core/combo/include/arch/linux-arm/AndroidConfig.h
+++ b/core/combo/include/arch/linux-arm/AndroidConfig.h
@@ -33,33 +33,8 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
 
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '/'
-
-/*
- * Define if the strlcpy() function exists on the system.
- */
-#define HAVE_STRLCPY 1
-
-/*
- * Define if <stdint.h> exists.
- */
-#define HAVE_STDINT_H 1
-
-/*
- * Define if printf() supports %zd for size_t arguments
- */
-#define HAVE_PRINTF_ZD 1
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/core/combo/include/arch/linux-arm64/AndroidConfig.h b/core/combo/include/arch/linux-arm64/AndroidConfig.h
index c1e9e59..a969ab7 100644
--- a/core/combo/include/arch/linux-arm64/AndroidConfig.h
+++ b/core/combo/include/arch/linux-arm64/AndroidConfig.h
@@ -33,33 +33,8 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
 
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '/'
-
-/*
- * Define if the strlcpy() function exists on the system.
- */
-#define HAVE_STRLCPY 1
-
-/*
- * Define if <stdint.h> exists.
- */
-#define HAVE_STDINT_H 1
-
-/*
- * Define if printf() supports %zd for size_t arguments
- */
-#define HAVE_PRINTF_ZD 1
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/core/combo/include/arch/linux-mips/AndroidConfig.h b/core/combo/include/arch/linux-mips/AndroidConfig.h
index ac0c9e1..6e46f8a 100644
--- a/core/combo/include/arch/linux-mips/AndroidConfig.h
+++ b/core/combo/include/arch/linux-mips/AndroidConfig.h
@@ -33,38 +33,8 @@
  */
 
 /*
- * Define this if you build against MSVCRT.DLL
- */
-/* #define HAVE_MS_C_RUNTIME */
-
-/*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
 
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '/'
-
-/*
- * Define if the strlcpy() function exists on the system.
- */
-#define HAVE_STRLCPY 1
-
-/*
- * Define if <stdint.h> exists.
- */
-#define HAVE_STDINT_H 1
-
-/*
- * Define if printf() supports %zd for size_t arguments
- */
-#define HAVE_PRINTF_ZD 1
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/core/combo/include/arch/linux-mips64/AndroidConfig.h b/core/combo/include/arch/linux-mips64/AndroidConfig.h
index b86c676..d4143a7 100644
--- a/core/combo/include/arch/linux-mips64/AndroidConfig.h
+++ b/core/combo/include/arch/linux-mips64/AndroidConfig.h
@@ -33,33 +33,8 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
 
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '/'
-
-/*
- * Define if the strlcpy() function exists on the system.
- */
-#define HAVE_STRLCPY 1
-
-/*
- * Define if <stdint.h> exists.
- */
-#define HAVE_STDINT_H 1
-
-/*
- * Define if printf() supports %zd for size_t arguments
- */
-#define HAVE_PRINTF_ZD 1
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/core/combo/include/arch/linux-x86/AndroidConfig.h b/core/combo/include/arch/linux-x86/AndroidConfig.h
index a2897bc..b8e4217 100644
--- a/core/combo/include/arch/linux-x86/AndroidConfig.h
+++ b/core/combo/include/arch/linux-x86/AndroidConfig.h
@@ -40,24 +40,4 @@
 #define _FILE_OFFSET_BITS 64
 #define _LARGEFILE_SOURCE 1
 
-/*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H
-
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '/'
-
-/*
- * Define if <stdint.h> exists.
- */
-#define HAVE_STDINT_H 1
-
-/*
- * Define if printf() supports %zd for size_t arguments
- */
-#define HAVE_PRINTF_ZD 1
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/core/combo/include/arch/target_linux-x86/AndroidConfig.h b/core/combo/include/arch/target_linux-x86/AndroidConfig.h
index 676913c..90d5f00 100644
--- a/core/combo/include/arch/target_linux-x86/AndroidConfig.h
+++ b/core/combo/include/arch/target_linux-x86/AndroidConfig.h
@@ -19,33 +19,8 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
 
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '/'
-
-/*
- * Define if the strlcpy() function exists on the system.
- */
-#define HAVE_STRLCPY 1
-
-/*
- * Define if <stdint.h> exists.
- */
-#define HAVE_STDINT_H 1
-
-/*
- * Define if printf() supports %zd for size_t arguments
- */
-#define HAVE_PRINTF_ZD 1
-
 #endif /* _ANDROID_CONFIG_H */
diff --git a/core/combo/include/arch/windows/AndroidConfig.h b/core/combo/include/arch/windows/AndroidConfig.h
index e7eb837..60268c8 100644
--- a/core/combo/include/arch/windows/AndroidConfig.h
+++ b/core/combo/include/arch/windows/AndroidConfig.h
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-/*
- * Android config -- "CYGWIN_NT-5.1".
- *
- * Cygwin has pthreads, but GDB seems to get confused if you use it to
- * create threads.  By "confused", I mean it freezes up the first time the
- * debugged process creates a thread, even if you use CreateThread.  The
- * mere presence of pthreads linkage seems to cause problems.
- */
 #ifndef _ANDROID_CONFIG_H
 #define _ANDROID_CONFIG_H
 
@@ -37,27 +29,6 @@
  * comments.
  */
 
-/* MingW doesn't define __BEGIN_DECLS / __END_DECLS. */
-
-#ifndef __BEGIN_DECLS
-#  ifdef __cplusplus
-#    define __BEGIN_DECLS extern "C" {
-#  else
-#    define __BEGIN_DECLS
-#  endif
-#endif
-
-#ifndef __END_DECLS
-#  ifdef __cplusplus
-#    define __END_DECLS }
-#  else
-#    define __END_DECLS
-#  endif
-#endif
-
-/* TODO: replace references to this. */
-#define HAVE_WIN32_IPC
-
 #ifdef __CYGWIN__
 #error "CYGWIN is unsupported for platform builds"
 #endif
@@ -68,11 +39,6 @@
 #define HAVE_MS_C_RUNTIME
 
 /*
- * Define this if we want to use WinSock.
- */
-#define HAVE_WINSOCK
-
-/*
  * We need to choose between 32-bit and 64-bit off_t.  All of our code should
  * agree on the same size.  For desktop systems, use 64-bit values,
  * because some of our libraries (e.g. wxWidgets) expect to be built that way.
@@ -87,18 +53,4 @@
 #define _WIN32 1
 #define _WIN32_WINNT 0x0500     /* admit to using >= Win2K */
 
-#define HAVE_WINDOWS_PATHS      /* needed by simulator */
-
-/*
- * The default path separator for the platform
- */
-#define OS_PATH_SEPARATOR '\\'
-
-/*
- * Various definitions missing in MinGW
- */
-#ifdef USE_MINGW
-#define S_IRGRP 0
-#endif
-
 #endif /*_ANDROID_CONFIG_H*/
diff --git a/core/combo/javac.mk b/core/combo/javac.mk
index fb43ea4..e3838a6 100644
--- a/core/combo/javac.mk
+++ b/core/combo/javac.mk
@@ -26,12 +26,7 @@
 endif
 
 # Whatever compiler is on this system.
-ifeq ($(BUILD_OS), windows)
-    COMMON_JAVAC := development/host/windows/prebuilt/javawrap.exe -J-Xmx256m \
-        $(common_jdk_flags)
-else
-    COMMON_JAVAC := $(JAVACC) -J-Xmx1024M $(common_jdk_flags)
-endif
+COMMON_JAVAC := $(JAVACC) -J-Xmx1024M $(common_jdk_flags)
 
 # Eclipse.
 ifeq ($(CUSTOM_JAVA_COMPILER), eclipse)
diff --git a/core/combo/mac_version.mk b/core/combo/mac_version.mk
index 6defba7..638e3a0 100644
--- a/core/combo/mac_version.mk
+++ b/core/combo/mac_version.mk
@@ -9,7 +9,7 @@
 
 build_mac_version := $(shell sw_vers -productVersion)
 
-mac_sdk_versions_supported :=  10.6 10.7 10.8 10.9
+mac_sdk_versions_supported :=  10.8 10.9 10.10
 ifneq ($(strip $(MAC_SDK_VERSION)),)
 mac_sdk_version := $(MAC_SDK_VERSION)
 ifeq ($(filter $(mac_sdk_version),$(mac_sdk_versions_supported)),)
@@ -19,7 +19,7 @@
 $(error Stop.)
 endif
 else
-mac_sdk_versions_installed := $(shell xcodebuild -showsdks | grep macosx | sort | sed -e "s/.*macosx//g")
+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))
diff --git a/core/combo/select.mk b/core/combo/select.mk
index 01f9322..df12e7e 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -47,62 +47,3 @@
 
 # Now include the combo for this specific target.
 include $(BUILD_COMBOS)/$(combo_target)$(combo_os_arch).mk
-
-ifneq ($(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
-
-  # See man page, optimizations to get more cache hits
-  # implies that __DATE__ and __TIME__ are not critical for functionality.
-  # Ignore include file modification time since it will depend on when
-  # the repo was checked out
-  export CCACHE_SLOPPINESS := time_macros,include_file_mtime,file_macro
-
-  # Turn all preprocessor absolute paths into relative paths.
-  # Fixes absolute paths in preprocessed source due to use of -g.
-  # We don't really use system headers much so the rootdir is
-  # fine; ensures these paths are relative for all Android trees
-  # on a workstation.
-  export CCACHE_BASEDIR := /
-
-  # Workaround for ccache with clang.
-  # See http://petereisentraut.blogspot.com/2011/09/ccache-and-clang-part-2.html
-  export CCACHE_CPP2 := true
-
-  CCACHE_HOST_TAG := $(HOST_PREBUILT_TAG)
-  # If we are cross-compiling Windows binaries on Linux
-  # then use the linux ccache binary instead.
-  ifeq ($(HOST_OS)-$(BUILD_OS),windows-linux)
-    CCACHE_HOST_TAG := linux-$(HOST_PREBUILT_ARCH)
-  endif
-  ccache := prebuilts/misc/$(CCACHE_HOST_TAG)/ccache/ccache
-  # Check that the executable is here.
-  ccache := $(strip $(wildcard $(ccache)))
-  ifdef ccache
-    ifndef CC_WRAPPER
-      CC_WRAPPER := $(ccache)
-    endif
-    ifndef CXX_WRAPPER
-      CXX_WRAPPER := $(ccache)
-    endif
-    ccache =
-  endif
-endif
-
-# Stash the original values of CC and CXX so we can still use the non-wrapped
-# values later.
-$(combo_2nd_arch_prefix)CC_BARE := $($(combo_var_prefix)CC)
-$(combo_2nd_arch_prefix)CXX_BARE := $($(combo_var_prefix)CXX)
-
-# The C/C++ compiler can be wrapped by setting the CC/CXX_WRAPPER vars.
-ifdef CC_WRAPPER
-  ifneq ($(CC_WRAPPER),$(firstword $($(combo_var_prefix)CC)))
-    $(combo_var_prefix)CC := $(CC_WRAPPER) $($(combo_var_prefix)CC)
-  endif
-endif
-ifdef CXX_WRAPPER
-  ifneq ($(CXX_WRAPPER),$(firstword $($(combo_var_prefix)CXX)))
-    $(combo_var_prefix)CXX := $(CXX_WRAPPER) $($(combo_var_prefix)CXX)
-  endif
-endif
diff --git a/core/config.mk b/core/config.mk
index 0b76b53..78a43ec 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -85,6 +85,8 @@
 BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
 BUILD_NATIVE_BENCHMARK := $(BUILD_SYSTEM)/native_benchmark.mk
 BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
+BUILD_FUZZ_TEST := $(BUILD_SYSTEM)/fuzz_test.mk
+BUILD_HOST_FUZZ_TEST := $(BUILD_SYSTEM)/host_fuzz_test.mk
 
 BUILD_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/shared_test_lib.mk
 BUILD_HOST_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/host_shared_test_lib.mk
@@ -104,7 +106,7 @@
 # lines being executed, instead of a short message about
 # the kind of operation being done.
 SHOW_COMMANDS:= $(filter showcommands,$(MAKECMDGOALS))
-
+hide := $(if $(SHOW_COMMANDS),,@)
 
 # ###############################################################
 # Set common values
@@ -114,13 +116,18 @@
 COMMON_GLOBAL_CFLAGS:= -DANDROID -fmessage-length=0 -W -Wall -Wno-unused -Winit-self -Wpointer-arith
 COMMON_RELEASE_CFLAGS:= -DNDEBUG -UDEBUG
 
-COMMON_GLOBAL_CPPFLAGS:= $(COMMON_GLOBAL_CFLAGS) -Wsign-promo -std=gnu++11
+COMMON_GLOBAL_CPPFLAGS:= $(COMMON_GLOBAL_CFLAGS) -Wsign-promo
 COMMON_RELEASE_CPPFLAGS:= $(COMMON_RELEASE_CFLAGS)
 
-GLOBAL_CFLAGS_NO_OVERRIDE :=  \
+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 \
+
 GLOBAL_CPPFLAGS_NO_OVERRIDE :=
 
 # Set the extensions used for various packages
@@ -131,8 +138,11 @@
 # 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
 
-# TODO: do symbol compression
-TARGET_COMPRESS_MODULE_SYMBOLS := false
+ifdef TMPDIR
+JAVA_TMPDIR_ARG := -Djava.io.tmpdir=$(TMPDIR)
+else
+JAVA_TMPDIR_ARG :=
+endif
 
 # ###############################################################
 # Include sub-configuration files
@@ -153,6 +163,23 @@
 # are specific to the user's build configuration.
 include $(BUILD_SYSTEM)/envsetup.mk
 
+# ---------------------------------------------------------------
+# 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)\"
+COMMON_GLOBAL_CPPFLAGS += -Wno-builtin-macro-redefined -D__DATE__="\"$(BUILD_DATETIME_C_DATE)\"" -D__TIME__=\"$(BUILD_DATETIME_C_TIME)\"
+endif
+
 # The build system exposes several variables for where to find the kernel
 # headers:
 #   TARGET_DEVICE_KERNEL_HEADERS is automatically created for the current
@@ -249,6 +276,8 @@
 include $(BUILD_SYSTEM)/combo/select.mk
 endif
 
+include $(BUILD_SYSTEM)/ccache.mk
+
 ifdef TARGET_PREFER_32_BIT
 TARGET_PREFER_32_BIT_APPS := true
 TARGET_PREFER_32_BIT_EXECUTABLES := true
@@ -368,6 +397,11 @@
 
 # ---------------------------------------------------------------
 # Generic tools.
+JACK := $(HOST_OUT_EXECUTABLES)/jack
+JACK_JAR := $(HOST_OUT_JAVA_LIBRARIES)/jack.jar
+JACK_LAUNCHER_JAR := $(HOST_OUT_JAVA_LIBRARIES)/jack-launcher.jar
+JILL_JAR := $(HOST_OUT_JAVA_LIBRARIES)/jill.jar
+JACK_MULTIDEX_DEFAULT_PREPROCESSOR := frameworks/multidex/library/resources/JACK-INF/legacyMultidexInstallation.jpp
 
 LEX := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/flex/flex-2.5.39
 # The default PKGDATADIR built in the prebuilt bison is a relative path
@@ -384,6 +418,7 @@
 AAPT := $(HOST_OUT_EXECUTABLES)/aapt$(HOST_EXECUTABLE_SUFFIX)
 AIDL := $(HOST_OUT_EXECUTABLES)/aidl$(HOST_EXECUTABLE_SUFFIX)
 PROTOC := $(HOST_OUT_EXECUTABLES)/aprotoc$(HOST_EXECUTABLE_SUFFIX)
+DBUS_GENERATOR := $(HOST_OUT_EXECUTABLES)/dbus-binding-generator
 SIGNAPK_JAR := $(HOST_OUT_JAVA_LIBRARIES)/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)
 MKBOOTFS := $(HOST_OUT_EXECUTABLES)/mkbootfs$(HOST_EXECUTABLE_SUFFIX)
 MINIGZIP := $(HOST_OUT_EXECUTABLES)/minigzip$(HOST_EXECUTABLE_SUFFIX)
@@ -406,16 +441,52 @@
 MAKE_F2FS := $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)
 MKF2FSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh
 SIMG2IMG := $(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX)
+IMG2SIMG := $(HOST_OUT_EXECUTABLES)/img2simg$(HOST_EXECUTABLE_SUFFIX)
 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
+
+ifeq ($(ANDROID_COMPILE_WITH_JACK),true)
+DEFAULT_JACK_ENABLED:=full
+else
+DEFAULT_JACK_ENABLED:=
+endif
+ifneq ($(strip $(ANDROID_JACK_VM)),)
+JACK_VM := $(ANDROID_JACK_VM)
+else
+JACK_VM := java
+endif
+# call jack
+#
+# $(1): vm arguments
+# $(2): jack perf arguments
+ifneq (,$(strip $(filter dist,$(MAKECMDGOALS))))
+JACK_SERVER_LOG_COMMAND := mkdir -p $(DIST_DIR)/logs/; SERVER_LOG=$(DIST_DIR)/logs/jack-server.log
+endif
+define call-jack
+$(JACK_SERVER_LOG_COMMAND) JACK_VM_COMMAND="$(JACK_VM) $(1) $(JAVA_TMPDIR_ARG) -jar $(JACK_LAUNCHER_JAR) " JACK_JAR="$(JACK_JAR)" $(JACK) $(2)
+endef
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VM_ARGS := $(DEFAULT_JACK_VM_ARGS)
+ifneq ($(ANDROID_JACK_VM_ARGS),)
+DEFAULT_JACK_VM_ARGS := $(ANDROID_JACK_VM_ARGS)
+else
+DEFAULT_JACK_VM_ARGS := -Dfile.encoding=UTF-8 -Xms2560m -XX:+TieredCompilation
+endif
+ifneq ($(ANDROID_JACK_EXTRA_ARGS),)
+DEFAULT_JACK_EXTRA_ARGS := $(ANDROID_JACK_EXTRA_ARGS)
+else
+DEFAULT_JACK_EXTRA_ARGS := @$(BUILD_SYSTEM)/jack-default.args
+endif
+# Turn off jack warnings by default.
+DEFAULT_JACK_EXTRA_ARGS += --verbose error
+
+JILL := java -jar $(JILL_JAR)
 PROGUARD := external/proguard/bin/proguard.sh
 JAVATAGS := build/tools/java-event-log-tags.py
 LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc$(HOST_EXECUTABLE_SUFFIX)
 BCC_COMPAT := $(HOST_OUT_EXECUTABLES)/bcc_compat$(HOST_EXECUTABLE_SUFFIX)
-LINT := prebuilts/sdk/tools/lint
 RMTYPEDEFS := $(HOST_OUT_EXECUTABLES)/rmtypedefs
 APPEND2SIMG := $(HOST_OUT_EXECUTABLES)/append2simg
 VERITY_SIGNER := $(HOST_OUT_EXECUTABLES)/verity_signer
@@ -428,6 +499,10 @@
 # dx is java behind a shell script; no .exe necessary.
 DX := $(HOST_OUT_EXECUTABLES)/dx
 ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign$(HOST_EXECUTABLE_SUFFIX)
+
+# relocation packer
+RELOCATION_PACKER := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/relocation_packer/relocation_packer
+
 FINDBUGS_DIR := external/owasp/sanitizer/tools/findbugs/bin
 FINDBUGS := $(FINDBUGS_DIR)/findbugs
 EMMA_JAR := external/emma/lib/emma$(COMMON_JAVA_PACKAGE_SUFFIX)
@@ -437,12 +512,7 @@
 
 YACC_HEADER_SUFFIX:= .hpp
 
-# Don't use column under Windows, cygwin or not
-ifeq ($(HOST_OS),windows)
-COLUMN:= cat
-else
 COLUMN:= column
-endif
 
 HOST_JDK_TOOLS_JAR:= $(shell $(BUILD_SYSTEM)/find-jdk-tools-jar.sh)
 
@@ -539,7 +609,7 @@
 
 # allow overriding default Java libraries on a per-target basis
 ifeq ($(TARGET_DEFAULT_JAVA_LIBRARIES),)
-  TARGET_DEFAULT_JAVA_LIBRARIES := core-libart core-junit ext framework
+  TARGET_DEFAULT_JAVA_LIBRARIES := core-libart core-junit ext framework okhttp
 endif
 
 # Flags for DEX2OAT
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index a1964a9..8d285b1 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -2,31 +2,126 @@
 ## Perform configuration steps for sanitizers.
 ##############################################
 
-# Configure SANITIZE_HOST.
-ifdef LOCAL_IS_HOST_MODULE
-ifeq ($(SANITIZE_HOST),true)
-ifneq ($(strip $(LOCAL_CLANG)),false)
-ifneq ($(strip $(LOCAL_ADDRESS_SANITIZER)),false)
-    LOCAL_ADDRESS_SANITIZER := true
-endif
-endif
-endif
+my_sanitize := $(strip $(LOCAL_SANITIZE))
+
+# Don't apply sanitizers to NDK code.
+ifdef LOCAL_SDK_VERSION
+  my_sanitize := never
 endif
 
-# Configure address sanitizer.
-ifeq ($(strip $(LOCAL_ADDRESS_SANITIZER)),true)
-  my_clang := true
+# Configure SANITIZE_HOST / SANITIZE_TARGET.
+ifeq ($(my_sanitize),)
+  ifdef LOCAL_IS_HOST_MODULE
+    my_sanitize := $(strip $(SANITIZE_HOST))
+  else
+    my_sanitize := $(strip $(SANITIZE_TARGET))
+  endif
+
+  # SANITIZE_HOST=true is a deprecated way to say SANITIZE_HOST=address.
+  ifeq ($(my_sanitize),true)
+    my_sanitize := address
+  endif
+
+  # SANITIZE_HOST is only in effect if the module is already using clang (host
+  # modules that haven't set `LOCAL_CLANG := false` and device modules that
+  # have set `LOCAL_CLANG := true`.
+  ifneq ($(my_clang),true)
+    my_sanitize :=
+  endif
+endif
+
+ifeq ($(my_sanitize),never)
+  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)),)
+  ifeq ($(my_32_64_bit_suffix),32)
+    ifeq ($(my_module_multilib),both)
+        my_sanitize := $(filter-out thread,$(my_sanitize))
+    else
+        $(error $(LOCAL_PATH): $(LOCAL_MODULE): TSAN cannot be used for 32-bit modules.)
+    endif
+  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)),)
+  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
+
+# Sanitizers can only be used with clang.
+ifneq ($(my_clang),true)
+  ifneq ($(my_sanitize),)
+    $(error $(LOCAL_PATH): $(LOCAL_MODULE): Use of sanitizers requires LOCAL_CLANG := true)
+  endif
+endif
+
+ifneq ($(filter default-ub,$(my_sanitize)),)
+  my_sanitize := $(CLANG_DEFAULT_UB_CHECKS)
+endif
+
+ifneq ($(my_sanitize),)
+  fsanitize_arg := $(subst $(space),$(comma),$(my_sanitize)),
+  my_cflags += -fsanitize=$(fsanitize_arg)
+
+  ifdef LOCAL_IS_HOST_MODULE
+    my_cflags += -fno-sanitize-recover=all
+    my_ldflags += -fsanitize=$(fsanitize_arg)
+    my_ldlibs += -lrt -ldl
+  else
+    my_cflags += -fsanitize-undefined-trap-on-error
+    my_cflags += -ftrap-function=abort
+    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)
   my_ldflags += $(ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS)
   ifdef LOCAL_IS_HOST_MODULE
-      my_ldflags += -fsanitize=address
-      # -nodefaultlibs (provided with libc++) prevents the driver from linking
-      # libraries needed with -fsanitize=address. http://b/18650275
-      my_ldlibs += -ldl -lpthread
+    # -nodefaultlibs (provided with libc++) prevents the driver from linking
+    # libraries needed with -fsanitize=address. http://b/18650275 (WAI)
+    my_ldlibs += -lm -lpthread
+    my_ldflags += -Wl,--no-as-needed
   else
-      my_shared_libraries += $(ADDRESS_SANITIZER_CONFIG_EXTRA_SHARED_LIBRARIES)
-      my_static_libraries += $(ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES)
+    my_cflags += -mllvm -asan-globals=0
+    # 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)
+    my_ldflags += -Wl,-rpath,$($(LOCAL_2ND_ARCH_VAR_PREFIX)ADDRESS_SANITIZER_RPATH)
+
+    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
+
+ifneq ($(filter undefined,$(my_sanitize)),)
+  ifndef LOCAL_IS_HOST_MODULE
+    $(error ubsan is not yet supported on the target)
+  endif
+endif
+
+ifneq ($(strip $(LOCAL_SANITIZE_RECOVER)),)
+  recover_arg := $(subst $(space),$(comma),$(LOCAL_SANITIZE_RECOVER)),
+  my_cflags += -fsanitize-recover=$(recover_arg)
+endif
diff --git a/core/configure_local_jack.mk b/core/configure_local_jack.mk
new file mode 100644
index 0000000..98b13d2
--- /dev/null
+++ b/core/configure_local_jack.mk
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+ifdef ANDROID_FORCE_JACK_ENABLED
+LOCAL_JACK_ENABLED := $(ANDROID_FORCE_JACK_ENABLED)
+endif
+LOCAL_JACK_ENABLED := $(strip $(LOCAL_JACK_ENABLED))
+ifneq ($(LOCAL_JACK_ENABLED),full)
+ifneq ($(LOCAL_JACK_ENABLED),incremental)
+ifdef LOCAL_JACK_ENABLED
+ifneq ($(LOCAL_JACK_ENABLED),disabled)
+$(error $(LOCAL_PATH): invalid LOCAL_JACK_ENABLED "$(LOCAL_JACK_ENABLED)" for $(LOCAL_MODULE))
+endif
+endif
+LOCAL_JACK_ENABLED :=
+endif
+endif
diff --git a/core/cxx_stl_setup.mk b/core/cxx_stl_setup.mk
index 265d8cb..f150714 100644
--- a/core/cxx_stl_setup.mk
+++ b/core/cxx_stl_setup.mk
@@ -8,22 +8,34 @@
 ifeq ($(strip $(LOCAL_CXX_STL)),default)
     ifndef LOCAL_SDK_VERSION
         # Platform code. Select the appropriate STL.
-        ifndef USE_MINGW
-            my_cxx_stl := libc++
-            ifdef LOCAL_IS_HOST_MODULE
-                ifneq (,$(BUILD_HOST_static))
-                    my_cxx_stl := libc++_static
-                endif
+        my_cxx_stl := libc++
+        ifdef LOCAL_IS_HOST_MODULE
+            ifneq (,$(BUILD_HOST_static))
+                my_cxx_stl := libc++_static
             endif
-        else
-            # libc++ is not supported on mingw.
-            my_cxx_stl := libstdc++
+
+            ifdef USE_MINGW
+                # libc++ is not supported on mingw.
+                my_cxx_stl := libstdc++
+            endif
         endif
     else
         my_cxx_stl := ndk
     endif
 else
     my_cxx_stl := $(strip $(LOCAL_CXX_STL))
+    ifdef LOCAL_SDK_VERSION
+        # The NDK has historically used LOCAL_NDK_STL_VARIANT to specify the
+        # STL. An Android.mk that specifies both LOCAL_CXX_STL and
+        # LOCAL_SDK_VERSION will incorrectly try (and most likely fail) to use
+        # the platform STL in an NDK binary. Emit an error to direct the user
+        # toward the correct option.
+        #
+        # Note that we could also accept LOCAL_CXX_STL as an alias for
+        # LOCAL_NDK_STL_VARIANT (and in fact soong does use the same name), but
+        # the two options use different names for the STLs.
+        $(error $(LOCAL_PATH): $(LOCAL_MODULE): Must use LOCAL_NDK_STL_VARIANT rather than LOCAL_CXX_STL for NDK binaries)
+    endif
 endif
 
 # Yes, this is actually what the clang driver does.
@@ -49,8 +61,15 @@
 ifneq ($(filter $(my_cxx_stl),libc++ libc++_static),)
     my_cflags += -D_USING_LIBCXX
     my_c_includes += external/libcxx/include
-    ifeq ($(my_cxx_stl),libc++)
-        my_shared_libraries += libc++
+
+    # Note that the structure of this means that LOCAL_CXX_STL := libc++ will
+    # use the static libc++ for static executables.
+    ifeq ($(my_link_type),dynamic)
+        ifeq ($(my_cxx_stl),libc++)
+            my_shared_libraries += libc++
+        else
+            my_static_libraries += libc++_static
+        endif
     else
         my_static_libraries += libc++_static
     endif
@@ -60,19 +79,20 @@
         my_ldflags += -nodefaultlibs
         my_ldlibs += -lpthread -lm
         my_ldlibs += $($(my_prefix)$(HOST_OS)_$(my_link_type)_gcclibs)
-    endif
-else ifneq ($(filter $(my_cxx_stl),stlport stlport_static),)
-    ifndef LOCAL_IS_HOST_MODULE
-        my_c_includes += external/stlport/stlport bionic/libstdc++/include \
-                         bionic
-        ifeq ($(my_cxx_stl),stlport)
-            my_shared_libraries += libstdc++ libstlport
+    else
+        ifeq (arm,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
+            my_static_libraries += libunwind_llvm
+            my_ldflags += -Wl,--exclude-libs,libunwind_llvm.a
+        endif
+
+        ifeq ($(my_link_type),static)
+            my_static_libraries += libm libc libdl
         else
-            my_static_libraries += libstdc++ libstlport_static
+            my_shared_libraries += libdl
         endif
     endif
 else ifeq ($(my_cxx_stl),ndk)
-    # Using an NDK STL. Handled farther up in this file.
+    # Using an NDK STL. Handled in binary.mk.
     ifndef LOCAL_IS_HOST_MODULE
         my_system_shared_libraries += libstdc++
     endif
@@ -91,5 +111,5 @@
         my_ldlibs += $($(my_prefix)$(HOST_OS)_$(my_link_type)_gcclibs)
     endif
 else
-    $(error $(my_cxx_stl) is not a supported STL.)
+    $(error $(LOCAL_PATH): $(LOCAL_MODULE): $(my_cxx_stl) is not a supported STL.)
 endif
diff --git a/core/definitions.mk b/core/definitions.mk
index f59b78e..dd84b8a 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -139,7 +139,7 @@
 ###########################################################
 
 define all-makefiles-under
-$(wildcard $(1)/*/Android.mk)
+$(sort $(wildcard $(1)/*/Android.mk))
 endef
 
 ###########################################################
@@ -171,7 +171,7 @@
 
 # $(1): List of directories to look for under this directory
 define all-named-subdir-makefiles
-$(wildcard $(addsuffix /Android.mk, $(addprefix $(call my-dir)/,$(1))))
+$(sort $(wildcard $(addsuffix /Android.mk, $(addprefix $(call my-dir)/,$(1)))))
 endef
 
 ###########################################################
@@ -403,6 +403,14 @@
 endef
 
 ###########################################################
+## Reverse order of a list
+###########################################################
+
+define reverse-list
+$(if $(1),$(call reverse-list,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
+endef
+
+###########################################################
 ## The intermediates directory.  Where object files go for
 ## a given target.  We could technically get away without
 ## the "_intermediates" suffix on the directory, but it's
@@ -602,6 +610,36 @@
 endef
 
 ###########################################################
+## Convert "core ext framework" to "out/.../classes.jack ..."
+## $(1): library list
+## $(2): Non-empty if IS_HOST_MODULE
+###########################################################
+
+# $(1): library name
+# $(2): Non-empty if IS_HOST_MODULE
+define _jack-lib-full-classes
+$(call _java-lib-dir,$(1),$(2))/classes.jack
+endef
+
+# $(1): library name list
+# $(2): Non-empty if IS_HOST_MODULE
+define jack-lib-files
+$(foreach lib,$(1),$(call _jack-lib-full-classes,$(lib),$(2)))
+endef
+
+# $(1): library name
+# $(2): Non-empty if IS_HOST_MODULE
+define _jack-lib-full-dep
+$(call _jack-lib-full-classes,$(1),$(2))
+endef
+
+# $(1): library name list
+# $(2): Non-empty if IS_HOST_MODULE
+define jack-lib-deps
+$(foreach lib,$(1),$(call _jack-lib-full-dep,$(lib),$(2)))
+endef
+
+###########################################################
 ## Run rot13 on a string
 ## $(1): the string.  Must be one line.
 ###########################################################
@@ -764,51 +802,12 @@
 define pretty
 @echo $1
 endef
-hide := @
 else
 define pretty
 endef
-hide :=
 endif
 
 ###########################################################
-## Dump the variables that are associated with targets
-###########################################################
-
-define dump-module-variables
-@echo all_dependencies=$^
-@echo PRIVATE_YACCFLAGS=$(PRIVATE_YACCFLAGS);
-@echo PRIVATE_CFLAGS=$(PRIVATE_CFLAGS);
-@echo PRIVATE_CPPFLAGS=$(PRIVATE_CPPFLAGS);
-@echo PRIVATE_DEBUG_CFLAGS=$(PRIVATE_DEBUG_CFLAGS);
-@echo PRIVATE_C_INCLUDES=$(PRIVATE_C_INCLUDES);
-@echo PRIVATE_LDFLAGS=$(PRIVATE_LDFLAGS);
-@echo PRIVATE_LDLIBS=$(PRIVATE_LDLIBS);
-@echo PRIVATE_ARFLAGS=$(PRIVATE_ARFLAGS);
-@echo PRIVATE_AAPT_FLAGS=$(PRIVATE_AAPT_FLAGS);
-@echo PRIVATE_DX_FLAGS=$(PRIVATE_DX_FLAGS);
-@echo PRIVATE_JAVACFLAGS=$(PRIVATE_JAVACFLAGS);
-@echo PRIVATE_JAVA_LIBRARIES=$(PRIVATE_JAVA_LIBRARIES);
-@echo PRIVATE_ALL_SHARED_LIBRARIES=$(PRIVATE_ALL_SHARED_LIBRARIES);
-@echo PRIVATE_ALL_STATIC_LIBRARIES=$(PRIVATE_ALL_STATIC_LIBRARIES);
-@echo PRIVATE_ALL_WHOLE_STATIC_LIBRARIES=$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES);
-@echo PRIVATE_ALL_OBJECTS=$(PRIVATE_ALL_OBJECTS);
-@echo PRIVATE_NO_CRT=$(PRIVATE_NO_CRT);
-endef
-
-###########################################################
-## Commands for using sed to replace given variable values
-###########################################################
-
-define transform-variables
-@mkdir -p $(dir $@)
-@echo "Sed: $(if $(PRIVATE_MODULE),$(PRIVATE_MODULE),$@) <= $<"
-$(hide) sed $(foreach var,$(REPLACE_VARS),-e "s/{{$(var)}}/$(subst /,\/,$(PWD)/$($(var)))/g") $< >$@
-$(hide) if [ "$(suffix $@)" = ".sh" ]; then chmod a+rx $@; fi
-endef
-
-
-###########################################################
 ## Commands for munging the dependency files GCC generates
 ###########################################################
 # $(1): the input .d file
@@ -829,8 +828,8 @@
 ###########################################################
 
 define transform-l-to-cpp
-@mkdir -p $(dir $@)
 @echo "Lex: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
 $(hide) $(LEX) -o$@ $<
 endef
 
@@ -843,8 +842,8 @@
 ###########################################################
 
 define transform-y-to-cpp
-@mkdir -p $(dir $@)
 @echo "Yacc: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
 $(YACC) $(PRIVATE_YACCFLAGS) -o $@ $<
 touch $(@:$1=$(YACC_HEADER_SUFFIX))
 echo '#ifndef '$(@F:$1=_h) > $(@:$1=.h)
@@ -871,6 +870,8 @@
   $(PRIVATE_RS_FLAGS) \
   $(foreach inc,$(PRIVATE_RS_INCLUDES),$(addprefix -I , $(inc))) \
   $(PRIVATE_RS_SOURCE_FILES)
+  $(foreach d,$(PRIVATE_DEP_FILES),\
+    $(call transform-d-to-p-args,$(d),$(d:%.d=%.P))$(newline))
 $(hide) mkdir -p $(dir $@)
 $(hide) touch $@
 endef
@@ -902,9 +903,12 @@
   -d $(PRIVATE_RS_OUTPUT_DIR) \
   -a $@ -MD \
   -reflect-c++ \
+  $(addprefix -target-api , $(PRIVATE_RS_TARGET_API)) \
   $(PRIVATE_RS_FLAGS) \
   $(addprefix -I , $(PRIVATE_RS_INCLUDES)) \
   $(PRIVATE_RS_SOURCE_FILES)
+  $(foreach d,$(PRIVATE_DEP_FILES),\
+    $(call transform-d-to-p-args,$(d),$(d:%.d=%.P))$(newline))
 $(hide) mkdir -p $(dir $@)
 $(hide) touch $@
 endef
@@ -953,15 +957,30 @@
 endef
 
 ######################################################################
-## Commands for running protoc to compile .proto into .pb.cc and .pb.h
+## Commands for running protoc to compile .proto into .pb.cc (or.pb.c) and .pb.h
 ######################################################################
 define transform-proto-to-cc
-@mkdir -p $(dir $@)
 @echo "Protoc: $@ <= $<"
+@mkdir -p $(dir $@)
 $(hide) $(PROTOC) \
 	$(addprefix --proto_path=, $(PRIVATE_PROTO_INCLUDES)) \
 	$(PRIVATE_PROTOC_FLAGS) \
-	--cpp_out=$(PRIVATE_PROTO_CC_OUTPUT_DIR) $<
+	$<
+endef
+
+
+######################################################################
+## Commands for running protoc to compile .proto into .pb.cc and .pb.h
+######################################################################
+define generate-dbus-bindings
+@echo "Generating DBus bindings for $(PRIVATE_DBUS_MODULE)"
+@mkdir -p $(PRIVATE_DBUS_HEADER_DIRECTORY)
+$(hide) $(DBUS_GENERATOR) \
+	--service-config=$(PRIVATE_DBUS_SERVICE_CONFIG) \
+	--adaptor=$(PRIVATE_DBUS_ADAPTORS_HEADER) \
+	--proxy=$(PRIVATE_DBUS_PROXIES_HEADER) \
+	--method-names=$(PRIVATE_DBUS_METHOD_NAMES_HEADER) \
+	$(PRIVATE_DBUS_INTERFACE_DEFINITIONS)
 endef
 
 
@@ -970,8 +989,8 @@
 ###########################################################
 
 define transform-cpp-to-o
-@mkdir -p $(dir $@)
 @echo "target $(PRIVATE_ARM_MODE) C++: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
 $(hide) $(PRIVATE_CXX) \
 	$(addprefix -I , $(PRIVATE_C_INCLUDES)) \
 	$(shell cat $(PRIVATE_IMPORT_INCLUDES)) \
@@ -990,8 +1009,8 @@
 	$(PRIVATE_CFLAGS) \
 	$(PRIVATE_CPPFLAGS) \
 	$(PRIVATE_DEBUG_CFLAGS) \
-	$(GLOBAL_CFLAGS_NO_OVERRIDE) \
-	$(GLOBAL_CPPFLAGS_NO_OVERRIDE) \
+	$(PRIVATE_CFLAGS_NO_OVERRIDE) \
+	$(PRIVATE_CPPFLAGS_NO_OVERRIDE) \
 	-MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
 $(transform-d-to-p)
 endef
@@ -1028,7 +1047,7 @@
     $(PRIVATE_CFLAGS) \
     $(PRIVATE_CONLYFLAGS) \
     $(PRIVATE_DEBUG_CFLAGS) \
-    $(GLOBAL_CFLAGS_NO_OVERRIDE))
+    $(PRIVATE_CFLAGS_NO_OVERRIDE))
 endef
 
 define transform-s-to-o-no-deps
@@ -1077,8 +1096,8 @@
 ###########################################################
 
 define transform-host-cpp-to-o
-@mkdir -p $(dir $@)
 @echo "host C++: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
 $(hide) $(PRIVATE_CXX) \
 	$(addprefix -I , $(PRIVATE_C_INCLUDES)) \
 	$(shell cat $(PRIVATE_IMPORT_INCLUDES)) \
@@ -1095,6 +1114,8 @@
 	$(PRIVATE_CFLAGS) \
 	$(PRIVATE_CPPFLAGS) \
 	$(PRIVATE_DEBUG_CFLAGS) \
+	$(PRIVATE_CFLAGS_NO_OVERRIDE) \
+	$(PRIVATE_CPPFLAGS_NO_OVERRIDE) \
 	-MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
 $(transform-d-to-p)
 endef
@@ -1121,6 +1142,7 @@
 	    $(PRIVATE_HOST_GLOBAL_CONLYFLAGS) \
 	 ) \
 	$(1) \
+	$(PRIVATE_CFLAGS_NO_OVERRIDE) \
 	-MD -MF $(patsubst %.o,%.d,$@) -o $@ $<
 endef
 
@@ -1283,13 +1305,13 @@
 # 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) ($@)"
 @mkdir -p $(dir $@)
 @rm -f $@
 $(extract-and-include-target-whole-static-libs)
-@echo "target StaticLib: $(PRIVATE_MODULE) ($@)"
 $(call split-long-arguments,$($(PRIVATE_2ND_ARCH_VAR_PREFIX)TARGET_AR) \
     $($(PRIVATE_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_ARFLAGS) \
-    $(PRIVATE_ARFLAGS) $@,$(filter %.o, $^))
+    $(PRIVATE_ARFLAGS) $@,$(PRIVATE_ALL_OBJECTS))
 endef
 
 ###########################################################
@@ -1332,13 +1354,13 @@
 # Explicitly delete the archive first so that ar doesn't
 # try to add to an existing archive.
 define transform-host-o-to-static-lib
+@echo "host StaticLib: $(PRIVATE_MODULE) ($@)"
 @mkdir -p $(dir $@)
 @rm -f $@
 $(extract-and-include-host-whole-static-libs)
-@echo "host StaticLib: $(PRIVATE_MODULE) ($@)"
 $(call split-long-arguments,$($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_AR) \
     $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_ARFLAGS) \
-    $(PRIVATE_ARFLAGS) $@,$(filter %.o, $^))
+    $(PRIVATE_ARFLAGS) $@,$(PRIVATE_ALL_OBJECTS))
 endef
 
 
@@ -1353,6 +1375,7 @@
 $(hide) $(PRIVATE_CXX) \
 	-Wl,-rpath-link=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES) \
 	-Wl,-rpath,\$$ORIGIN/../$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)) \
+	-Wl,-rpath,\$$ORIGIN/$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)) \
 	-shared -Wl,-soname,$(notdir $@) \
 	$($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_LD_DIRS) \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
@@ -1367,6 +1390,7 @@
 	$(call normalize-host-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)) \
 	-o $@ \
 	$(PRIVATE_LDLIBS)
@@ -1374,14 +1398,14 @@
 endif
 
 define transform-host-o-to-shared-lib
-@mkdir -p $(dir $@)
 @echo "host SharedLib: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(transform-host-o-to-shared-lib-inner)
 endef
 
 define transform-host-o-to-package
-@mkdir -p $(dir $@)
 @echo "host Package: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(transform-host-o-to-shared-lib-inner)
 endef
 
@@ -1396,7 +1420,7 @@
 	-Wl,--gc-sections \
 	$(if $(filter true,$(PRIVATE_CLANG)),-shared,-Wl$(comma)-shared) \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
-	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_SO_O)) \
+	$(PRIVATE_TARGET_CRTBEGIN_SO_O) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
@@ -1404,21 +1428,21 @@
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
-	$(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \
+	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBGCOV)) \
+	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBPROFILE_RT)) \
+	$(PRIVATE_TARGET_LIBATOMIC) \
+	$(PRIVATE_TARGET_LIBGCC) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
-	$(PRIVATE_TARGET_LIBATOMIC) \
-	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBGCOV)) \
-	$(PRIVATE_TARGET_LIBGCC) \
-	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTEND_SO_O)) \
+	$(PRIVATE_TARGET_CRTEND_SO_O) \
 	$(PRIVATE_LDLIBS)
 endef
 
 define transform-o-to-shared-lib
-@mkdir -p $(dir $@)
 @echo "target SharedLib: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(transform-o-to-shared-lib-inner)
 endef
 
@@ -1433,20 +1457,29 @@
 endif
 
 define transform-to-stripped
-@mkdir -p $(dir $@)
 @echo "target 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-symbols
-@mkdir -p $(dir $@)
 @echo "target Strip (keep symbols): $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(hide) $(PRIVATE_OBJCOPY) \
     `$(PRIVATE_READELF) -S $< | awk '/.debug_/ {print "-R " $$2}' | xargs` \
     $(TARGET_STRIP_KEEP_SYMBOLS_EXTRA) $< $@
 endef
 
+###########################################################
+## Commands for packing a target executable or library
+###########################################################
+
+define pack-elf-relocations
+@echo "target Pack Relocations: $(PRIVATE_MODULE) ($@)"
+$(copy-file-to-target)
+$(hide) $(RELOCATION_PACKER) $@
+endef
 
 ###########################################################
 ## Commands for running gcc to link an executable
@@ -1455,12 +1488,12 @@
 define transform-o-to-executable-inner
 $(hide) $(PRIVATE_CXX) -pie \
 	-nostdlib -Bdynamic \
-	-Wl,-dynamic-linker,$($(PRIVATE_2ND_ARCH_VAR_PREFIX)TARGET_LINKER) \
+	-Wl,-dynamic-linker,$(PRIVATE_LINKER) \
 	-Wl,--gc-sections \
 	-Wl,-z,nocopyreloc \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
 	-Wl,-rpath-link=$(PRIVATE_TARGET_OUT_INTERMEDIATE_LIBRARIES) \
-	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O)) \
+	$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
@@ -1468,21 +1501,21 @@
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
-	$(if $(TARGET_BUILD_APPS),$(PRIVATE_TARGET_LIBGCC)) \
+	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBGCOV)) \
+	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBPROFILE_RT)) \
+	$(PRIVATE_TARGET_LIBATOMIC) \
+	$(PRIVATE_TARGET_LIBGCC) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
-	$(PRIVATE_TARGET_LIBATOMIC) \
-	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBGCOV)) \
-	$(PRIVATE_TARGET_LIBGCC) \
-	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTEND_O)) \
+	$(PRIVATE_TARGET_CRTEND_O) \
 	$(PRIVATE_LDLIBS)
 endef
 
 define transform-o-to-executable
-@mkdir -p $(dir $@)
 @echo "target Executable: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(transform-o-to-executable-inner)
 endef
 
@@ -1504,7 +1537,7 @@
 	-Wl,--gc-sections \
 	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
-	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_STATIC_O)) \
+	$(PRIVATE_TARGET_CRTBEGIN_STATIC_O) \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_ALL_OBJECTS) \
@@ -1515,17 +1548,18 @@
 	-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))) \
-	$(PRIVATE_TARGET_LIBATOMIC) \
 	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBGCOV)) \
+	$(if $(filter true,$(NATIVE_COVERAGE)),$(PRIVATE_TARGET_LIBPROFILE_RT)) \
+	$(PRIVATE_TARGET_LIBATOMIC) \
 	$(call normalize-target-libraries,$(filter %libcompiler_rt.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \
 	$(PRIVATE_TARGET_LIBGCC) \
 	-Wl,--end-group \
-	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTEND_O))
+	$(PRIVATE_TARGET_CRTEND_O)
 endef
 
 define transform-o-to-static-executable
-@mkdir -p $(dir $@)
 @echo "target StaticExecutable: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(transform-o-to-static-executable-inner)
 endef
 
@@ -1554,9 +1588,11 @@
 	$(call normalize-host-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)) \
 	-Wl,-rpath-link=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES) \
 	-Wl,-rpath,\$$ORIGIN/../$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)) \
+	-Wl,-rpath,\$$ORIGIN/$(notdir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_OUT_SHARED_LIBRARIES)) \
 	$($(PRIVATE_2ND_ARCH_VAR_PREFIX)HOST_GLOBAL_LD_DIRS) \
 	$(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 		$(PRIVATE_HOST_GLOBAL_LDFLAGS) \
@@ -1568,8 +1604,8 @@
 endif
 
 define transform-host-o-to-executable
-@mkdir -p $(dir $@)
 @echo "host Executable: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(transform-host-o-to-executable-inner)
 endef
 
@@ -1578,9 +1614,6 @@
 ## Commands for running javac to make .class files
 ###########################################################
 
-#@echo "Source intermediates dir: $(PRIVATE_SOURCE_INTERMEDIATES_DIR)"
-#@echo "Source intermediates: $$(find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java')"
-
 # TODO: Right now we generate the asset resources twice, first as part
 # of generating the Java classes, then at the end when packaging the final
 # assets.  This should be changed to do one of two things: (1) Don't generate
@@ -1606,17 +1639,13 @@
     $(addprefix -G , $(PRIVATE_PROGUARD_OPTIONS_FILE)) \
     $(addprefix --min-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
     $(addprefix --target-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
-    $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-code , $(PLATFORM_SDK_VERSION))) \
-    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-name , $(PLATFORM_VERSION)-$(BUILD_NUMBER))) \
+    $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,--version-code $(PLATFORM_SDK_VERSION)) \
+    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,--version-name $(PLATFORM_VERSION)-$(BUILD_NUMBER_FROM_FILE)) \
     $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
     $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR))
 endef
 
-ifeq ($(HOST_OS),windows)
-xlint_unchecked :=
-else
 xlint_unchecked := -Xlint:unchecked
-endif
 
 ifeq (true, $(ENABLE_INCREMENTALJAVAC))
 incremental_dex := --incremental
@@ -1695,7 +1724,7 @@
 $(call unzip-jar-files,$(PRIVATE_STATIC_JAVA_LIBRARIES),$(PRIVATE_CLASS_INTERMEDIATES_DIR))
 $(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list)
 $(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
-          find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \
+          find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \
 fi
 $(hide) tr ' ' '\n' < $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list \
     | sort -u > $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
@@ -1730,7 +1759,7 @@
         $(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)/' \
+    $(hide) sed -e "s/%BUILD_NUMBER%/$(BUILD_NUMBER_FROM_FILE)/" \
             $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \
         jar -cfm $@ $(dir $@)/manifest.mf \
             -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) ., \
@@ -1743,6 +1772,147 @@
 $(call compile-java,$(TARGET_JAVAC),$(PRIVATE_BOOTCLASSPATH))
 endef
 
+# Invoke Jack to compile java from source to dex and jack files.
+#
+# Some historical notes:
+# - below we write the list of java files to java-source-list to avoid argument
+#   list length problems with Cygwin
+# - we filter out duplicate java file names because Jack doesn't like them.
+define jack-java-to-dex
+$(hide) rm -f $@
+$(hide) rm -f $(PRIVATE_CLASSES_JACK)
+$(hide) rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR)
+$(hide) mkdir -p $(dir $@)
+$(hide) mkdir -p $(dir $(PRIVATE_CLASSES_JACK))
+$(hide) mkdir -p $(PRIVATE_JACK_INTERMEDIATES_DIR)
+$(if $(PRIVATE_JACK_INCREMENTAL_DIR),$(hide) mkdir -p $(PRIVATE_JACK_INCREMENTAL_DIR))
+$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list)
+$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
+          find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list; \
+fi
+$(hide) tr ' ' '\n' < $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list \
+    | sort -u > $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq
+$(if $(PRIVATE_JACK_PROGUARD_FLAGS), \
+    $(hide) echo -basedirectory $(CURDIR) > $@.flags; \
+    echo $(PRIVATE_JACK_PROGUARD_FLAGS) >> $@.flags; \
+)
+$(if $(PRIVATE_EXTRA_JAR_ARGS),
+    $(hide) mkdir -p $@.res.tmp
+    $(hide) $(call create-empty-package-at,$@.res.tmp.zip)
+    $(hide) $(call add-java-resources-to,$@.res.tmp.zip)
+    $(hide) $(call unzip-jar-files,$@.res.tmp.zip,$@.res.tmp)
+    $(hide) rm $@.res.tmp.zip)
+$(hide) if [ -s $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
+    export tmpEcjArg="@$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq"; \
+else \
+    export tmpEcjArg=""; \
+fi; \
+$(call call-jack,$(PRIVATE_JACK_VM_ARGS),$(PRIVATE_JACK_EXTRA_ARGS)) \
+    $(strip $(PRIVATE_JACK_FLAGS)) \
+    $(strip $(PRIVATE_JACK_DEBUG_FLAGS)) \
+    $(if $(NO_OPTIMIZE_DX), \
+        -D jack.dex.optimize="false") \
+    $(if $(PRIVATE_RMTYPEDEFS), \
+        -D jack.android.remove-typedef="true") \
+    $(addprefix --classpath ,$(strip \
+        $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES) $(PRIVATE_ALL_JACK_LIBRARIES)))) \
+    $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
+    $(if $(PRIVATE_EXTRA_JAR_ARGS),--import-resource $@.res.tmp) \
+    -D jack.import.resource.policy=keep-first \
+    -D jack.import.type.policy=keep-first \
+    --output-jack $(PRIVATE_CLASSES_JACK) \
+    -D jack.java.source.version=1.7 \
+    $(if $(PRIVATE_JACK_INCREMENTAL_DIR),--incremental-folder $(PRIVATE_JACK_INCREMENTAL_DIR)) \
+    --output-dex $(PRIVATE_JACK_INTERMEDIATES_DIR) \
+    $(addprefix --config-jarjar ,$(strip $(PRIVATE_JARJAR_RULES))) \
+    $(if $(PRIVATE_JACK_PROGUARD_FLAGS),--config-proguard $@.flags) \
+    $$tmpEcjArg \
+    || ( rm -rf $(PRIVATE_CLASSES_JACK); rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR); exit 41 )
+$(hide) mv $(PRIVATE_JACK_INTERMEDIATES_DIR)/classes*.dex $(dir $@)
+$(hide) rm -f $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list
+$(if $(PRIVATE_EXTRA_JAR_ARGS),$(hide) rm -rf $@.res.tmp)
+$(hide) mv $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq $(PRIVATE_JACK_INTERMEDIATES_DIR).java-source-list
+$(if $(PRIVATE_JAR_PACKAGES), $(hide) echo unsupported options PRIVATE_JAR_PACKAGES in $@; exit 53)
+$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) echo unsupported options JAR_EXCLUDE_PACKAGES in $@; exit 53)
+$(if $(PRIVATE_JAR_MANIFEST), $(hide) echo unsupported options JAR_MANIFEST in $@; exit 53)
+endef
+
+define transform-jar-to-jack
+	$(hide) mkdir -p $(dir $@)
+	$(JILL) $(PRIVATE_JILL_FLAGS) --output $@.tmpjill.jack $<
+	$(hide) mkdir -p $@.tmpjill.res
+	$(hide) $(call unzip-jar-files,$<,$@.tmpjill.res)
+	$(hide) find $@.tmpjill.res -iname "*.class" -delete
+	$(hide) $(call call-jack,$(PRIVATE_JACK_VM_ARGS),$(PRIVATE_JACK_EXTRA_ARGS)) \
+        -D jack.import.resource.policy=keep-first \
+        -D jack.import.type.policy=keep-first \
+	    --import $@.tmpjill.jack \
+	    --import-resource $@.tmpjill.res \
+	    --output-jack $@
+	$(hide) rm -rf $@.tmpjill.res
+	$(hide) rm $@.tmpjill.jack
+endef
+
+
+# Invoke Jack to compile java from source to jack files without shrink or obfuscation.
+#
+# Some historical notes:
+# - below we write the list of java files to java-source-list to avoid argument
+#   list length problems with Cygwin
+# - we filter out duplicate java file names because Jack doesn't like them.
+define java-to-jack
+$(hide) rm -f $@
+$(hide) rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR)
+$(hide) mkdir -p $(dir $@)
+$(hide) mkdir -p $(PRIVATE_JACK_INTERMEDIATES_DIR)
+$(if $(PRIVATE_JACK_INCREMENTAL_DIR),$(hide) mkdir -p $(PRIVATE_JACK_INCREMENTAL_DIR))
+$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list)
+$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
+          find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list; \
+fi
+$(hide) tr ' ' '\n' < $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list \
+    | sort -u > $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq
+$(if $(PRIVATE_JACK_PROGUARD_FLAGS), \
+    $(hide) echo -basedirectory $(CURDIR) > $@.flags; \
+    echo $(PRIVATE_JACK_PROGUARD_FLAGS) >> $@.flags; \
+)
+$(if $(PRIVATE_EXTRA_JAR_ARGS),
+	$(hide) mkdir -p $@.res.tmp
+	$(hide) $(call create-empty-package-at,$@.res.tmp.zip)
+	$(hide) $(call add-java-resources-to,$@.res.tmp.zip)
+	$(hide) unzip -qo $@.res.tmp.zip -d $@.res.tmp
+	$(hide) rm $@.res.tmp.zip)
+$(hide) if [ -s $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
+    export tmpEcjArg="@$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq"; \
+else \
+    export tmpEcjArg=""; \
+fi; \
+$(call call-jack,$(PRIVATE_JACK_VM_ARGS),$(PRIVATE_JACK_EXTRA_ARGS)) \
+    $(strip $(PRIVATE_JACK_FLAGS)) \
+    $(strip $(PRIVATE_JACK_DEBUG_FLAGS)) \
+    $(if $(NO_OPTIMIZE_DX), \
+        -D jack.dex.optimize="false") \
+    $(addprefix --classpath ,$(strip \
+        $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES) $(PRIVATE_ALL_JACK_LIBRARIES)))) \
+    $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
+    $(if $(PRIVATE_EXTRA_JAR_ARGS),--import-resource $@.res.tmp) \
+    -D jack.import.resource.policy=keep-first \
+    -D jack.import.type.policy=keep-first \
+    -D jack.java.source.version=1.7 \
+    $(if $(PRIVATE_JACK_INCREMENTAL_DIR),--incremental-folder $(PRIVATE_JACK_INCREMENTAL_DIR)) \
+    --output-jack $@ \
+    $(addprefix --config-jarjar ,$(strip $(PRIVATE_JARJAR_RULES))) \
+    $(if $(PRIVATE_JACK_PROGUARD_FLAGS),--config-proguard $@.flags) \
+    $$tmpEcjArg \
+    || ( rm -f $@ ; exit 41 )
+$(hide) rm -f $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list
+$(if $(PRIVATE_EXTRA_JAR_ARGS),$(hide) rm -rf $@.res.tmp)
+$(hide) mv $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq $(PRIVATE_JACK_INTERMEDIATES_DIR).java-source-list
+$(if $(PRIVATE_JAR_PACKAGES), $(hide) echo unsupported options PRIVATE_JAR_PACKAGES in $@; exit 53)
+$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) echo unsupported options JAR_EXCLUDE_PACKAGES in $@; exit 53)
+$(if $(PRIVATE_JAR_MANIFEST), $(hide) echo unsupported options JAR_MANIFEST in $@; exit 53)
+endef
+
 # Override the above definitions if we want to do incremetal javac
 ifeq (true, $(ENABLE_INCREMENTALJAVAC))
 define compile-java
@@ -1791,7 +1961,7 @@
         $(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)/' \
+    $(hide) sed -e "s/%BUILD_NUMBER%/$(BUILD_NUMBER_FROM_FILE)/" \
             $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \
         jar -cfm $@ $(dir $@)/manifest.mf \
             -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) ., \
@@ -1814,13 +1984,12 @@
 
 #TODO: use a smaller -Xmx value for most libraries;
 #      only core.jar and framework.jar need a heap this big.
-# Avoid the memory arguments on Windows, dx fails to load for some reason with them.
 define transform-classes.jar-to-dex
 @echo "target Dex: $(PRIVATE_MODULE)"
 @mkdir -p $(dir $@)
 $(hide) rm -f $(dir $@)classes*.dex
 $(hide) $(DX) \
-    $(if $(findstring windows,$(HOST_OS)),,-JXms16M -JXmx2048M) \
+    -JXms16M -JXmx2048M \
     --dex --output=$(dir $@) \
     $(incremental_dex) \
     $(if $(NO_OPTIMIZE_DX), \
@@ -1836,12 +2005,31 @@
 # Create a mostly-empty .jar file that we'll add to later.
 # The MacOS jar tool doesn't like creating empty jar files,
 # so we need to give it something.
+# $(1) package to create
+define create-empty-package-at
+@mkdir -p $(dir $(1))
+$(hide) touch $(dir $(1))dummy
+$(hide) (cd $(dir $(1)) && jar cf $(notdir $(1)) dummy)
+$(hide) zip -qd $(1) dummy
+$(hide) rm $(dir $(1))dummy
+endef
+
+# Create a mostly-empty .jar file that we'll add to later.
+# The MacOS jar tool doesn't like creating empty jar files,
+# so we need to give it something.
 define create-empty-package
-@mkdir -p $(dir $@)
-$(hide) touch $(dir $@)zipdummy
-$(hide) (cd $(dir $@) && jar cf $(notdir $@) zipdummy)
-$(hide) zip -qd $@ zipdummy
-$(hide) rm $(dir $@)zipdummy
+@mkdir -p $(dir $(1))
+$(hide) touch $(dir $(1))zipdummy
+$(hide) (cd $(dir $(1)) && jar cf $(notdir $(1)) zipdummy)
+$(hide) zip -qd $(1) zipdummy
+$(hide) rm $(dir $(1))zipdummy
+endef
+
+# Create a mostly-empty .jar file that we'll add to later.
+# The MacOS jar tool doesn't like creating empty jar files,
+# so we need to give it something.
+define create-empty-package
+$(call create-empty-package-at,$@)
 endef
 
 # Copy an arhchive file and delete any class files and empty folders inside.
@@ -1875,8 +2063,8 @@
     $(addprefix --min-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
     $(addprefix --target-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
     $(if $(filter --product,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --product , $(TARGET_AAPT_CHARACTERISTICS))) \
-    $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-code , $(PLATFORM_SDK_VERSION))) \
-    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-name , $(PLATFORM_VERSION)-$(BUILD_NUMBER))) \
+    $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,--version-code $(PLATFORM_SDK_VERSION)) \
+    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,--version-name $(PLATFORM_VERSION)-$(BUILD_NUMBER_FROM_FILE)) \
     $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
     $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
     -F $@
@@ -1896,7 +2084,8 @@
 $(foreach abi,$(PRIVATE_JNI_SHARED_LIBRARIES_ABI),\
   $(call _add-jni-shared-libs-to-package-per-abi,$(abi),\
     $(patsubst $(abi):%,%,$(filter $(abi):%,$(PRIVATE_JNI_SHARED_LIBRARIES)))))
-$(hide) (cd $(dir $@) && zip -r $(PRIVATE_JNI_SHARED_LIBRARIES_ZIP_OPTIONS) $(notdir $@) lib)
+$(hide) (cd $(dir $@) && zip -r \
+    $(if $(filter true, $(PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES)),-0,) $(notdir $@) lib)
 $(hide) rm -rf $(dir $@)lib
 endef
 
@@ -1914,6 +2103,19 @@
 @rm -f $(1).jar-arg-list
 endef
 
+# Add resources carried by static Jack libraries.
+#
+define add-carried-jack-resources
+ $(hide) if [ -d $(PRIVATE_JACK_INTERMEDIATES_DIR) ] ; then \
+    jack_res_jar_flags=$$(find $(PRIVATE_JACK_INTERMEDIATES_DIR) -type f \
+        | sed -e "s?^$(PRIVATE_JACK_INTERMEDIATES_DIR)/? -C $(PRIVATE_JACK_INTERMEDIATES_DIR) ?"); \
+    if [ -n "$$jack_res_jar_flags" ] ; then \
+        echo $$jack_res_jar_flags >$(dir $@)jack_res_jar_flags; \
+        jar uf $@ $$jack_res_jar_flags; \
+    fi; \
+fi
+endef
+
 # Sign a package using the specified key/cert.
 #
 define sign-package
@@ -1930,12 +2132,22 @@
 $(hide) mv $@ $@.unaligned
 $(hide) $(ZIPALIGN) \
     -f \
-    $(if $(findstring true, $(PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES)),-p ,) \
+    $(if $(filter true, $(PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES)),-p,) \
     4 \
     $@.unaligned $@.aligned
 $(hide) mv $@.aligned $@
 endef
 
+define uncompress-shared-libs
+$(hide) rm -rf $(dir $@)/tmpworkdir
+$(hide) mv $@ $@.compressed
+$(hide) mkdir $(dir $@)/tmpworkdir
+$(hide) unzip $@.compressed 'lib/*.so' -d $(dir $@)/tmpworkdir
+$(hide) ( cd $(dir $@)/tmpworkdir && zip -D -r -0 ../$(notdir $@).compressed lib )
+$(hide) mv $@.compressed $@
+$(hide) rm -rf $(dir $@)/tmpworkdir
+endef
+
 define install-dex-debug
 $(hide) if [ -f "$(PRIVATE_INTERMEDIATES_DIR)/classes.dex" ]; then \
 	    mkdir -p $(TOP)/dalvik/DEBUG-FILES; \
@@ -2073,31 +2285,16 @@
 $(copy-file-to-target-strip-comments)
 endef
 
-###########################################################
-## On some platforms (MacOS), after copying a static
-## library, ranlib must be run to update an internal
-## timestamp!?!?!
-###########################################################
-
-ifeq ($(HOST_RUN_RANLIB_AFTER_COPYING),true)
-define transform-host-ranlib-copy-hack
-    $(hide) ranlib $@ || true
+# Copy a list of files/directories to target location, with sub dir structure preserved.
+# For example $(HOST_OUT_EXECUTABLES)/aapt -> $(staging)/bin/aapt .
+# $(1): the source list of files/directories.
+# $(2): the path prefix to strip. In the above example it would be $(HOST_OUT).
+# $(3): the target location.
+define copy-files-with-structure
+$(foreach t,$(1),\
+  $(eval s := $(patsubst $(2)%,%,$(t)))\
+  $(hide) mkdir -p $(dir $(3)/$(s)); cp -Rf $(t) $(3)/$(s)$(newline))
 endef
-else
-define transform-host-ranlib-copy-hack
-@true
-endef
-endif
-
-ifeq ($(TARGET_RUN_RANLIB_AFTER_COPYING),true)
-define transform-ranlib-copy-hack
-    $(hide) ranlib $@
-endef
-else
-define transform-ranlib-copy-hack
-@true
-endef
-endif
 
 
 ###########################################################
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 8b555e0..e0dde01 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -35,7 +35,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) $(AAPT)
+$$(_dbj_jar_no_dex) : $$(_dbj_src_jar) | $(ACP)
 	$$(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 bee5d40..1bd0bd7 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -3,8 +3,13 @@
 #
 ####################################
 
+# Default to debug version to help find bugs.
+# Set USE_DEX2OAT_DEBUG to false for only building non-debug versions.
+ifeq ($(USE_DEX2OAT_DEBUG),false)
 DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oat$(HOST_EXECUTABLE_SUFFIX)
-DEX2OATD := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
+else
+DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
+endif
 
 # By default, do not run rerun dex2oat if the tool changes.
 # Comment out the | to force dex2oat to rerun on after all changes.
@@ -13,9 +18,6 @@
 DEX2OAT_DEPENDENCY += |
 DEX2OAT_DEPENDENCY += $(DEX2OAT)
 
-DEX2OATD_DEPENDENCY := $(DEX2OAT_DEPENDENCY)
-DEX2OATD_DEPENDENCY += $(DEX2OATD)
-
 # Use the first preloaded-classes file in PRODUCT_COPY_FILES.
 PRELOADED_CLASSES := $(call word-colon,1,$(firstword \
     $(filter %system/etc/preloaded-classes,$(PRODUCT_COPY_FILES))))
@@ -24,13 +26,6 @@
 COMPILED_CLASSES := $(call word-colon,1,$(firstword \
     $(filter %system/etc/compiled-classes,$(PRODUCT_COPY_FILES))))
 
-# Default to debug version to help find bugs.
-# Set USE_DEX2OAT_DEBUG to false for only building non-debug versions.
-ifneq ($(USE_DEX2OAT_DEBUG), false)
-DEX2OAT = $(DEX2OATD)
-DEX2OAT_DEPENDENCY = $(DEX2OATD_DEPENDENCY)
-endif
-
 # start of image reserved address space
 LIBART_IMG_HOST_BASE_ADDRESS   := 0x60000000
 LIBART_IMG_TARGET_BASE_ADDRESS := 0x70000000
@@ -62,7 +57,7 @@
 # $(1): the arch name.
 # $(2): the full path (including file name) of the corresponding .jar or .apk.
 define get-odex-file-path
-$(dir $(2))$(1)/$(basename $(notdir $(2))).odex
+$(dir $(2))oat/$(1)/$(basename $(notdir $(2))).odex
 endef
 
 # Returns the path to the image file (such as "/system/framework/<arch>/boot.art"
@@ -105,7 +100,7 @@
 	--instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
 	--instruction-set-variant=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT) \
 	--instruction-set-features=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
-	--include-patch-information --runtime-arg -Xnorelocate --no-include-debug-symbols \
+	--include-patch-information --runtime-arg -Xnorelocate --no-generate-debug-info \
 	--abort-on-hard-verifier-error \
 	$(PRIVATE_DEX_PREOPT_FLAGS)
 endef
diff --git a/core/dex_preopt_libart_boot.mk b/core/dex_preopt_libart_boot.mk
index 2569d73..afd61eb 100644
--- a/core/dex_preopt_libart_boot.mk
+++ b/core/dex_preopt_libart_boot.mk
@@ -62,5 +62,5 @@
 		--instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
 		--instruction-set-variant=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT) \
 		--instruction-set-features=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
-		--android-root=$(PRODUCT_OUT)/system --include-patch-information --runtime-arg -Xnorelocate --no-include-debug-symbols \
+		--android-root=$(PRODUCT_OUT)/system --include-patch-information --runtime-arg -Xnorelocate --no-generate-debug-info \
 		$(PRODUCT_DEX_PREOPT_BOOT_FLAGS) $(COMPILED_CLASSES_FLAGS)
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
index 0e8cbdf..5d0b5bf 100644
--- a/core/dpi_specific_apk.mk
+++ b/core/dpi_specific_apk.mk
@@ -25,34 +25,47 @@
 $(built_dpi_apk): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_INSTRUMENTATION_FOR)
 $(built_dpi_apk): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)
 $(built_dpi_apk): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abis)
-$(built_dpi_apk): PRIVATE_DEX_FILE := $(built_dex)
-# Note that PRIVATE_CLASS_INTERMEDIATES_DIR points to the base apk's intermediate dir.
-$(built_dpi_apk): PRIVATE_CLASS_INTERMEDIATES_DIR := $(intermediates)/classes
-$(built_dpi_apk): PRIVATE_EXTRA_JAR_ARGS := $(extra_jar_args)
 $(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): 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): $(built_dex)
+else
+$(built_dpi_apk): PRIVATE_DEX_FILE :=
+endif # full_classes_jar
+
 # Set up dependenncies and the build recipe.
 $(built_dpi_apk) : $(R_file_stamp)
 $(built_dpi_apk) : $(all_library_res_package_export_deps)
-$(built_dpi_apk) : $(built_dex)
 $(built_dpi_apk) : $(private_key) $(certificate) $(SIGNAPK_JAR)
 $(built_dpi_apk) : $(AAPT) | $(ZIPALIGN)
 $(built_dpi_apk) : $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)
 	@echo "target Package: $(PRIVATE_MODULE) ($@)"
-	$(create-empty-package)
+	$(if $(PRIVATE_SOURCE_ARCHIVE),\
+	  $(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@),\
+	  $(create-empty-package))
 	$(add-assets-to-package)
 ifneq ($(jni_shared_libraries),)
 	$(add-jni-shared-libs-to-package)
 endif
-ifneq ($(full_classes_jar),)
+ifeq ($(full_classes_jar),)
+# We don't build jar, need to add the Java resources here.
+	$(if $(PRIVATE_EXTRA_JAR_ARGS),$(call add-java-resources-to,$@))
+else
 	$(add-dex-to-package)
+ifdef LOCAL_JACK_ENABLED
+	$(add-carried-jack-resources)
 endif
-	$(add-carried-java-resources)
-ifneq ($(extra_jar_args),)
-	$(add-java-resources-to-package)
 endif
 	$(sign-package)
 	$(align-package)
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 41f135c..aae2aba 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -107,7 +107,7 @@
 define prepare-doc-source-list
 $(hide) mkdir -p $(dir $(1))
 $(call dump-words-to-file, $(2), $(1))
-$(hide) for d in $(3) ; do find $$d -name '*.java' >> $(1) 2> /dev/null ; done ; true
+$(hide) for d in $(3) ; do find $$d -name '*.java' -and -not -name '.*' >> $(1) 2> /dev/null ; done ; true
 endef
 
 ifeq (a,b)
@@ -131,8 +131,8 @@
 	$(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX)
 
 $(full_target): PRIVATE_DOCLETPATH := $(HOST_OUT_JAVA_LIBRARIES)/jsilver$(COMMON_JAVA_PACKAGE_SUFFIX):$(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX)
-$(full_target): PRIVATE_CURRENT_BUILD := -hdf page.build $(BUILD_ID)-$(BUILD_NUMBER)
-$(full_target): PRIVATE_CURRENT_TIME :=  -hdf page.now "$(shell date "+%d %b %Y %k:%M")"
+$(full_target): PRIVATE_CURRENT_BUILD := -hdf page.build $(BUILD_ID)-$(BUILD_NUMBER_FROM_FILE)
+$(full_target): PRIVATE_CURRENT_TIME :=  -hdf page.now "$$($(DATE_FROM_FILE) "+%d %b %Y %k:%M")"
 $(full_target): PRIVATE_CUSTOM_TEMPLATE_DIR := $(LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR)
 $(full_target): PRIVATE_IN_CUSTOM_ASSET_DIR := $(LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR)/$(LOCAL_DROIDDOC_CUSTOM_ASSET_DIR)
 $(full_target): PRIVATE_OUT_ASSET_DIR := $(out_dir)/$(LOCAL_DROIDDOC_ASSET_DIR)
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index cf06a3d..38c0cbe 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -39,27 +39,37 @@
 ###################################
 
 ###########################################################
-## Compress
+## Pack relocation tables
 ###########################################################
-compress_input := $(linked_module)
+relocation_packer_input := $(linked_module)
+relocation_packer_output := $(intermediates)/PACKED/$(my_built_module_stem)
 
-ifeq ($(strip $(LOCAL_COMPRESS_MODULE_SYMBOLS)),)
-  LOCAL_COMPRESS_MODULE_SYMBOLS := $(strip $(TARGET_COMPRESS_MODULE_SYMBOLS))
+my_pack_module_relocations := $(LOCAL_PACK_MODULE_RELOCATIONS)
+
+ifeq ($(my_pack_module_relocations),)
+  my_pack_module_relocations := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_PACK_MODULE_RELOCATIONS)
 endif
 
-ifeq ($(LOCAL_COMPRESS_MODULE_SYMBOLS),true)
-$(error Symbol compression not yet supported.)
-compress_output := $(intermediates)/COMPRESSED-$(my_built_module_stem)
+# 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)
+  my_pack_module_relocations := false
+endif
 
-#TODO: write the real $(STRIPPER) rule.
-#TODO: define a rule to build TARGET_SYMBOL_FILTER_FILE, and
-#      make it depend on ALL_ORIGINAL_DYNAMIC_BINARIES.
-$(compress_output): $(compress_input) $(TARGET_SYMBOL_FILTER_FILE) | $(ACP)
-	@echo "target Compress Symbols: $(PRIVATE_MODULE) ($@)"
-	$(copy-file-to-target)
+# TODO (dimitry): Relocation packer is not yet available for darwin
+ifneq ($(HOST_OS),linux)
+  my_pack_module_relocations := false
+endif
+
+ifeq (true,$(my_pack_module_relocations))
+# Pack relocations
+$(relocation_packer_output): $(relocation_packer_input) | $(ACP)
+	$(pack-elf-relocations)
 else
-# Skip this step.
-compress_output := $(compress_input)
+$(relocation_packer_output): $(relocation_packer_input) | $(ACP)
+	@echo "target Unpacked: $(PRIVATE_MODULE) ($@)"
+	$(copy-file-to-target)
 endif
 
 ###########################################################
@@ -70,7 +80,7 @@
 else
 my_unstripped_path := $(LOCAL_UNSTRIPPED_PATH)
 endif
-symbolic_input := $(compress_output)
+symbolic_input := $(relocation_packer_output)
 symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
 $(symbolic_output) : $(symbolic_input) | $(ACP)
 	@echo "target Symbolic: $(PRIVATE_MODULE) ($@)"
@@ -85,7 +95,7 @@
 
 my_strip_module := $(LOCAL_STRIP_MODULE)
 ifeq ($(my_strip_module),)
-  my_strip_module := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_STRIP_MODULE)
+  my_strip_module := true
 endif
 
 $(strip_output): PRIVATE_STRIP := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_STRIP)
@@ -131,8 +141,7 @@
 endif
 endif # my_strip_module
 
-
 $(cleantarget): PRIVATE_CLEAN_FILES += \
     $(linked_module) \
     $(symbolic_output) \
-    $(compress_output)
+    $(strip_output)
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 43774ea..c76e9a6 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -22,7 +22,7 @@
 # NOTE: This will be overridden in product_config.mk if make
 # was invoked with a PRODUCT-xxx-yyy goal.
 ifeq ($(TARGET_PRODUCT),)
-TARGET_PRODUCT := full
+TARGET_PRODUCT := aosp_arm
 endif
 
 
@@ -48,9 +48,6 @@
 ifneq (,$(findstring Macintosh,$(UNAME)))
   HOST_OS := darwin
 endif
-ifneq (,$(findstring CYGWIN,$(UNAME)))
-  HOST_OS := windows
-endif
 
 # BUILD_OS is the real host doing the build.
 BUILD_OS := $(HOST_OS)
@@ -72,6 +69,10 @@
   HOST_ARCH := x86_64
   HOST_2ND_ARCH := x86
   HOST_IS_64_BIT := true
+else
+ifneq (,$(findstring x86,$(UNAME)))
+$(error Building on a 32-bit x86 host is not supported: $(UNAME)!)
+endif
 endif
 
 BUILD_ARCH := $(HOST_ARCH)
@@ -96,17 +97,14 @@
 HOST_PREBUILT_ARCH := x86
 # This is the standard way to name a directory containing prebuilt host
 # objects. E.g., prebuilt/$(HOST_PREBUILT_TAG)/cc
-ifeq ($(HOST_OS),windows)
-  HOST_PREBUILT_TAG := windows
-else
-  HOST_PREBUILT_TAG := $(HOST_OS)-$(HOST_PREBUILT_ARCH)
-endif
+HOST_PREBUILT_TAG := $(BUILD_OS)-$(HOST_PREBUILT_ARCH)
 
 # TARGET_COPY_OUT_* are all relative to the staging directory, ie PRODUCT_OUT.
 # Define them here so they can be used in product config files.
 TARGET_COPY_OUT_SYSTEM := system
 TARGET_COPY_OUT_DATA := data
 TARGET_COPY_OUT_OEM := oem
+TARGET_COPY_OUT_ODM := odm
 TARGET_COPY_OUT_ROOT := root
 TARGET_COPY_OUT_RECOVERY := recovery
 ###########################################
@@ -130,10 +128,6 @@
 $(error must be empty or one of: eng user userdebug)
 endif
 
-# Build host as 32-bit for SDK build.
-ifneq ($(filter $(MAKECMDGOALS),win_sdk sdk),)
-HOST_PREFER_32_BIT := true
-endif
 ifdef USE_MINGW
 # We only build sdk host tools in the MinGW windows build.
 # Build it as 32-bit as well.
@@ -255,6 +249,7 @@
 $(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES := $($(HOST_2ND_ARCH_VAR_PREFIX)HOST_OUT_INTERMEDIATES)/lib
 $(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)
 
 # The default host library path.
 # It always points to the path where we build libraries in the default bitness.
@@ -273,14 +268,20 @@
 TARGET_OUT_COMMON_GEN := $(TARGET_COMMON_OUT_ROOT)/gen
 
 TARGET_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM)
+ifeq ($(SANITIZE_TARGET),address)
+target_out_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_DATA)
+else
+target_out_shared_libraries_base := $(TARGET_OUT)
+endif
+
 TARGET_OUT_EXECUTABLES := $(TARGET_OUT)/bin
 TARGET_OUT_OPTIONAL_EXECUTABLES := $(TARGET_OUT)/xbin
 ifeq ($(TARGET_IS_64_BIT),true)
 # /system/lib always contains 32-bit libraries,
 # and /system/lib64 (if present) always contains 64-bit libraries.
-TARGET_OUT_SHARED_LIBRARIES := $(TARGET_OUT)/lib64
+TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib64
 else
-TARGET_OUT_SHARED_LIBRARIES := $(TARGET_OUT)/lib
+TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib
 endif
 TARGET_OUT_JAVA_LIBRARIES := $(TARGET_OUT)/framework
 TARGET_OUT_APPS := $(TARGET_OUT)/app
@@ -296,7 +297,7 @@
 TARGET_2ND_ARCH_MODULE_SUFFIX := $(HOST_2ND_ARCH_MODULE_SUFFIX)
 $(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
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES := $(TARGET_OUT)/lib
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SHARED_LIBRARIES := $(target_out_shared_libraries_base)/lib
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_EXECUTABLES := $(TARGET_OUT_EXECUTABLES)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_APPS := $(TARGET_OUT_APPS)
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_APPS_PRIVILEGED := $(TARGET_OUT_APPS_PRIVILEGED)
@@ -324,12 +325,18 @@
 TARGET_OUT_CACHE := $(PRODUCT_OUT)/cache
 
 TARGET_OUT_VENDOR := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)
+ifeq ($(SANITIZE_TARGET),address)
+target_out_vendor_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_DATA)/vendor
+else
+target_out_vendor_shared_libraries_base := $(TARGET_OUT_VENDOR)
+endif
+
 TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR)/bin
 TARGET_OUT_VENDOR_OPTIONAL_EXECUTABLES := $(TARGET_OUT_VENDOR)/xbin
 ifeq ($(TARGET_IS_64_BIT),true)
-TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib64
+TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib64
 else
-TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(TARGET_OUT_VENDOR)/lib
+TARGET_OUT_VENDOR_SHARED_LIBRARIES := $(target_out_vendor_shared_libraries_base)/lib
 endif
 TARGET_OUT_VENDOR_JAVA_LIBRARIES := $(TARGET_OUT_VENDOR)/framework
 TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR)/app
@@ -341,7 +348,7 @@
 
 TARGET_OUT_OEM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_OEM)
 TARGET_OUT_OEM_EXECUTABLES := $(TARGET_OUT_OEM)/bin
-ifneq ($(filter %64,$(TARGET_ARCH)),)
+ifeq ($(TARGET_IS_64_BIT),true)
 TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib64
 else
 TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib
@@ -355,6 +362,20 @@
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_SHARED_LIBRARIES := $(TARGET_OUT_OEM)/lib
 $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_OEM_APPS := $(TARGET_OUT_OEM_APPS)
 
+TARGET_OUT_ODM := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ODM)
+TARGET_OUT_ODM_EXECUTABLES := $(TARGET_OUT_ODM)/bin
+ifeq ($(TARGET_IS_64_BIT),true)
+TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib64
+else
+TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib
+endif
+TARGET_OUT_ODM_APPS := $(TARGET_OUT_ODM)/app
+TARGET_OUT_ODM_ETC := $(TARGET_OUT_ODM)/etc
+
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_EXECUTABLES := $(TARGET_OUT_ODM_EXECUTABLES)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_SHARED_LIBRARIES := $(TARGET_OUT_ODM)/lib
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS := $(TARGET_OUT_ODM_APPS)
+
 TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols
 TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin
 TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib
diff --git a/core/executable.mk b/core/executable.mk
index 4dd9a23..0ce400c 100644
--- a/core/executable.mk
+++ b/core/executable.mk
@@ -6,6 +6,17 @@
 # LOCAL_MODULE_PATH_32 and LOCAL_MODULE_PATH_64 or LOCAL_MODULE_STEM_32 and
 # LOCAL_MODULE_STEM_64
 
+my_skip_this_target :=
+ifeq (address,$(strip $(SANITIZE_TARGET)))
+  ifeq (true,$(LOCAL_FORCE_STATIC_EXECUTABLE))
+    my_skip_this_target := true
+  else ifeq (false, $(LOCAL_CLANG))
+    my_skip_this_target := true
+  endif
+endif
+
+ifneq (true,$(my_skip_this_target))
+
 my_prefix := TARGET_
 include $(BUILD_SYSTEM)/multilib.mk
 
@@ -71,3 +82,5 @@
 LOCAL_NO_2ND_ARCH_MODULE_SUFFIX :=
 
 my_module_arch_supported :=
+
+endif
diff --git a/core/executable_internal.mk b/core/executable_internal.mk
index ebb6867..1d576a2 100644
--- a/core/executable_internal.mk
+++ b/core/executable_internal.mk
@@ -35,12 +35,23 @@
 
 # Define PRIVATE_ variables from global vars
 my_target_global_ld_dirs := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LD_DIRS)
+my_target_libprofile_rt := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBPROFILE_RT)
 my_target_libgcov := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCOV)
+ifeq ($(LOCAL_NO_LIBGCC),true)
+my_target_libgcc :=
+else
 my_target_libgcc := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCC)
+endif
 my_target_libatomic := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBATOMIC)
+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)
+endif
 ifdef LOCAL_SDK_VERSION
 # Make sure the prebuilt NDK paths are put ahead of the TARGET_GLOBAL_LD_DIRS,
 # so we don't have race condition when the system libraries (such as libc, libstdc++) are also built in the tree.
@@ -55,6 +66,7 @@
 endif
 $(linked_module): PRIVATE_TARGET_GLOBAL_LD_DIRS := $(my_target_global_ld_dirs)
 $(linked_module): PRIVATE_TARGET_GLOBAL_LDFLAGS := $(my_target_global_ldflags)
+$(linked_module): PRIVATE_TARGET_LIBPROFILE_RT := $(my_target_libprofile_rt)
 $(linked_module): PRIVATE_TARGET_LIBGCOV := $(my_target_libgcov)
 $(linked_module): PRIVATE_TARGET_LIBGCC := $(my_target_libgcc)
 $(linked_module): PRIVATE_TARGET_LIBATOMIC := $(my_target_libatomic)
diff --git a/core/fuzz_test.mk b/core/fuzz_test.mk
new file mode 100644
index 0000000..065cc03
--- /dev/null
+++ b/core/fuzz_test.mk
@@ -0,0 +1,34 @@
+###########################################
+## A thin wrapper around BUILD_EXECUTABLE
+## Common flags for fuzz tests are added.
+###########################################
+
+ifdef LOCAL_SDK_VERSION
+    $(error $(LOCAL_PATH): $(LOCAL_MODULE): NDK fuzz tests are not supported.)
+endif
+
+LOCAL_CFLAGS += -fsanitize-coverage=edge,indirect-calls,8bit-counters
+LOCAL_STATIC_LIBRARIES += libLLVMFuzzer
+
+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
+
+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_MULTILIB
+ifndef LOCAL_32_BIT_ONLY
+LOCAL_MULTILIB := both
+endif
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk
index f8264ee..4814d70 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -34,11 +34,13 @@
 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
+full_classes_jack := $(intermediates.COMMON)/classes.jack
 built_dex := $(intermediates.COMMON)/classes.dex
 
 LOCAL_INTERMEDIATE_TARGETS += \
     $(full_classes_compiled_jar) \
     $(full_classes_jarjar_jar) \
+    $(full_classes_jack) \
     $(full_classes_jar) \
     $(built_dex)
 
@@ -61,6 +63,7 @@
 	PRIVATE_CLASS_INTERMEDIATES_DIR := $(intermediates.COMMON)/classes
 $(LOCAL_INTERMEDIATE_TARGETS): \
 	PRIVATE_SOURCE_INTERMEDIATES_DIR := $(LOCAL_INTERMEDIATE_SOURCE_DIR)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RMTYPEDEFS :=
 
 $(cleantarget): PRIVATE_CLEAN_FILES += $(intermediates.COMMON)
 
@@ -69,7 +72,6 @@
 $(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): PRIVATE_RMTYPEDEFS :=
 $(full_classes_compiled_jar): \
         $(java_sources) \
         $(java_resource_sources) \
@@ -96,6 +98,7 @@
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 
+ifndef LOCAL_JACK_ENABLED
 $(built_dex): PRIVATE_INTERMEDIATES_DIR := $(intermediates.COMMON)
 $(built_dex): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
 $(built_dex): $(full_classes_jar) $(DX)
@@ -109,6 +112,42 @@
 	$(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
+
+ifeq ($(LOCAL_JACK_ENABLED),incremental)
+$(LOCAL_INTERMEDIATE_TARGETS): \
+	PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-incremental
+else
+$(LOCAL_INTERMEDIATE_TARGETS): \
+	PRIVATE_JACK_INCREMENTAL_DIR :=
+endif
+$(LOCAL_INTERMEDIATE_TARGETS):  PRIVATE_JACK_DEBUG_FLAGS := -g
+
+$(built_dex): PRIVATE_CLASSES_JACK := $(full_classes_jack)
+$(built_dex): PRIVATE_JACK_FLAGS := $(LOCAL_JACK_FLAGS)
+$(built_dex): $(java_sources) $(java_resource_sources) $(full_jack_lib_deps) \
+        $(jar_manifest_file) $(proto_java_sources_file_stamp) $(LOCAL_MODULE_MAKEFILE) \
+        $(LOCAL_MODULE_MAKEFILE) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JACK_JAR) $(JACK_LAUNCHER_JAR)
+	@echo Building with Jack: $@
+	$(jack-java-to-dex)
+
+# $(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).
+$(full_classes_jack): $(built_dex)
+	$(hide) touch $@
+
+$(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE := $(built_dex)
+$(LOCAL_BUILT_MODULE): $(built_dex) $(java_resource_sources)
+	@echo "Host Jar: $(PRIVATE_MODULE) ($@)"
+	$(create-empty-package)
+	$(add-dex-to-package)
+	$(add-carried-jack-resources)
+
+endif # LOCAL_JACK_ENABLED
+
 USE_CORE_LIB_BOOTCLASSPATH :=
 
 endif
diff --git a/core/host_dalvik_static_java_library.mk b/core/host_dalvik_static_java_library.mk
index 9e5aaa3..90bcc12 100644
--- a/core/host_dalvik_static_java_library.mk
+++ b/core/host_dalvik_static_java_library.mk
@@ -21,11 +21,37 @@
 #
 ifeq ($(HOST_OS),linux)
 
+LOCAL_UNINSTALLABLE_MODULE := true
+LOCAL_IS_STATIC_JAVA_LIBRARY := true
 USE_CORE_LIB_BOOTCLASSPATH := true
 LOCAL_JAVA_LIBRARIES += 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_java_library.mk
+# proguard is not supported
+# *.proto files are not supported
+$(full_classes_jack): PRIVATE_JACK_FLAGS := $(LOCAL_JACK_FLAGS)
+$(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_lib_deps) \
+        $(jar_manifest_file) $(layers_file) $(LOCAL_MODULE_MAKEFILE) \
+        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(LOCAL_JARJAR_RULES) \
+        $(JACK_JAR) $(JACK_LAUNCHER_JAR)
+	@echo Building with Jack: $@
+	$(java-to-jack)
 
 USE_CORE_LIB_BOOTCLASSPATH :=
-
+LOCAL_IS_STATIC_JAVA_LIBRARY :=
 endif
diff --git a/core/host_executable_internal.mk b/core/host_executable_internal.mk
index ffb35d2..0c0ac3d 100644
--- a/core/host_executable_internal.mk
+++ b/core/host_executable_internal.mk
@@ -27,6 +27,9 @@
 
 include $(BUILD_SYSTEM)/binary.mk
 
+my_host_libprofile_rt := $($(LOCAL_2ND_ARCH_VAR_PREFIX)HOST_LIBPROFILE_RT)
+$(LOCAL_BUILT_MODULE): PRIVATE_HOST_LIBPROFILE_RT := $(my_host_libprofile_rt)
+
 $(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
new file mode 100644
index 0000000..e917959
--- /dev/null
+++ b/core/host_fuzz_test.mk
@@ -0,0 +1,9 @@
+################################################
+## A thin wrapper around BUILD_HOST_EXECUTABLE
+## Common flags for host fuzz tests are added.
+################################################
+
+LOCAL_CFLAGS += -fsanitize-coverage=edge,indirect-calls,8bit-counters
+LOCAL_STATIC_LIBRARIES += libLLVMFuzzer
+
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/core/host_java_library.mk b/core/host_java_library.mk
index b751c5f..47189d7 100644
--- a/core/host_java_library.mk
+++ b/core/host_java_library.mk
@@ -43,6 +43,8 @@
 include $(BUILD_SYSTEM)/base_rules.mk
 #######################################
 
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RMTYPEDEFS :=
+
 ifeq (true,$(LOCAL_EMMA_INSTRUMENT))
 $(full_classes_emma_jar): PRIVATE_EMMA_COVERAGE_FILE := $(intermediates.COMMON)/coverage.em
 $(full_classes_emma_jar): PRIVATE_EMMA_INTERMEDIATES_DIR := $(emma_intermediates_dir)
@@ -58,13 +60,13 @@
 $(full_classes_emma_jar) : $(full_classes_compiled_jar) | $(EMMA_JAR)
 	$(transform-classes.jar-to-emma)
 
-$(LOCAL_BUILT_MODULE) : $(full_classes_emma_jar)
+$(built_javalib_jar) : $(full_classes_emma_jar)
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 
 else # LOCAL_EMMA_INSTRUMENT
-# Directly build into LOCAL_BUILT_MODULE.
-full_classes_compiled_jar := $(LOCAL_BUILT_MODULE)
+# Directly build into $(built_javalib_jar).
+full_classes_compiled_jar := $(built_javalib_jar)
 endif # LOCAL_EMMA_INSTRUMENT
 
 $(full_classes_compiled_jar): PRIVATE_JAVAC_DEBUG_FLAGS := -g
@@ -78,7 +80,6 @@
 $(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): PRIVATE_RMTYPEDEFS :=
 $(full_classes_compiled_jar): \
         $(java_sources) \
         $(java_resource_sources) \
diff --git a/core/host_java_library_common.mk b/core/host_java_library_common.mk
index cd9e679..d077634 100644
--- a/core/host_java_library_common.mk
+++ b/core/host_java_library_common.mk
@@ -23,6 +23,22 @@
 LOCAL_IS_HOST_MODULE := true
 LOCAL_BUILT_MODULE_STEM := javalib.jar
 
+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 :=
 
@@ -39,9 +55,6 @@
 endif
 endif
 
-intermediates := $(call local-intermediates-dir)
-intermediates.COMMON := $(call local-intermediates-dir,COMMON)
-
 LOCAL_INTERMEDIATE_SOURCE_DIR := $(intermediates.COMMON)/src
 LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES))
 
diff --git a/core/host_shared_library.mk b/core/host_shared_library.mk
index 438a9ce..e840780 100644
--- a/core/host_shared_library.mk
+++ b/core/host_shared_library.mk
@@ -6,8 +6,8 @@
 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
+# libraries default to building for both architecturess
+my_module_multilib := both
 endif
 endif
 endif
diff --git a/core/host_shared_library_internal.mk b/core/host_shared_library_internal.mk
index f1b3311..645098a 100644
--- a/core/host_shared_library_internal.mk
+++ b/core/host_shared_library_internal.mk
@@ -40,6 +40,9 @@
 
 include $(BUILD_SYSTEM)/binary.mk
 
+my_host_libprofile_rt := $($(LOCAL_2ND_ARCH_VAR_PREFIX)HOST_LIBPROFILE_RT)
+$(LOCAL_BUILD_MODULE): PRIVATE_HOST_LIBPROFILE_RT := $(my_host_libprofile_rt)
+
 $(LOCAL_BUILT_MODULE): \
         $(all_objects) \
         $(all_libraries) \
diff --git a/core/host_static_library.mk b/core/host_static_library.mk
index 74ac2ea..52c42ef 100644
--- a/core/host_static_library.mk
+++ b/core/host_static_library.mk
@@ -6,8 +6,8 @@
 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
+# libraries default to building for both architecturess
+my_module_multilib := both
 endif
 endif
 endif
diff --git a/core/jack-default.args b/core/jack-default.args
new file mode 100644
index 0000000..8d70a82
--- /dev/null
+++ b/core/jack-default.args
@@ -0,0 +1,5 @@
+-D sched.runner=multi-threaded
+-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
diff --git a/core/java.mk b/core/java.mk
index cd90f03..f295973 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -112,6 +112,10 @@
 full_classes_jar := $(intermediates.COMMON)/classes.jar
 built_dex := $(intermediates.COMMON)/classes.dex
 endif
+# final Jack library, shrinked and obfuscated if it must be
+full_classes_jack := $(intermediates.COMMON)/classes.jack
+# intermediate Jack library without shrink and obfuscation
+noshrob_classes_jack := $(intermediates.COMMON)/classes.noshrob.jack
 
 LOCAL_INTERMEDIATE_TARGETS += \
     $(full_classes_compiled_jar) \
@@ -120,6 +124,8 @@
     $(full_classes_jar) \
     $(full_classes_proguard_jar) \
     $(built_dex_intermediate) \
+    $(full_classes_jack) \
+    $(noshrob_classes_jack) \
     $(built_dex) \
     $(full_classes_stubs_jar)
 
@@ -180,6 +186,9 @@
 LOCAL_RENDERSCRIPT_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE)
 endif
 
+bc_files := $(patsubst %.fs,%.bc, $(patsubst %.rs,%.bc, $(notdir $(renderscript_sources))))
+bc_dep_files := $(addprefix $(renderscript_intermediate.COMMON)/,$(patsubst %.bc,%.d,$(bc_files)))
+
 $(RenderScript_file_stamp): PRIVATE_RS_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES)
 $(RenderScript_file_stamp): PRIVATE_RS_CC := $(LOCAL_RENDERSCRIPT_CC)
 $(RenderScript_file_stamp): PRIVATE_RS_FLAGS := $(renderscript_flags)
@@ -188,11 +197,14 @@
 # automatically found by the java compiling function transform-java-to-classes.jar.
 $(RenderScript_file_stamp): PRIVATE_RS_OUTPUT_DIR := $(renderscript_intermediate.COMMON)
 $(RenderScript_file_stamp): PRIVATE_RS_TARGET_API := $(renderscript_target_api)
+$(RenderScript_file_stamp): PRIVATE_DEP_FILES := $(bc_dep_files)
 $(RenderScript_file_stamp): $(renderscript_sources_fullpath) $(LOCAL_RENDERSCRIPT_CC)
 	$(transform-renderscripts-to-java-and-bc)
 
+# include the dependency files (.d/.P) generated by llvm-rs-cc.
+-include $(bc_dep_files:%.d=%.P)
+
 ifneq ($(LOCAL_RENDERSCRIPT_COMPATIBILITY),)
-bc_files := $(patsubst %.fs,%.bc, $(patsubst %.rs,%.bc, $(notdir $(renderscript_sources))))
 
 
 ifeq ($(filter $(RSCOMPAT_32BIT_ONLY_API_LEVELS),$(renderscript_target_api)),)
@@ -239,7 +251,7 @@
 $(rs_compatibility_jni_libs): $(RenderScript_file_stamp) $(RS_PREBUILT_CLCORE) \
     $(rs_support_lib) $(rs_support_io_lib) $(rs_jni_lib) $(rs_compiler_rt)
 $(rs_compatibility_jni_libs): $(BCC_COMPAT)
-$(rs_compatibility_jni_libs): PRIVATE_CXX := $(TARGET_CXX)
+$(rs_compatibility_jni_libs): PRIVATE_CXX := $(CXX_WRAPPER) $(TARGET_CXX)
 $(rs_compatibility_jni_libs): $(renderscript_intermediate)/librs.%.so: \
     $(renderscript_intermediate.bc_folder)%.bc
 	$(transform-bc-to-so)
@@ -248,11 +260,6 @@
 
 endif
 
-# include the dependency files (.d) generated by llvm-rs-cc.
-renderscript_generated_dep_files := $(addprefix $(renderscript_intermediate.COMMON)/, \
-    $(patsubst %.fs,%.d, $(patsubst %.rs,%.d, $(notdir $(renderscript_sources)))))
--include $(renderscript_generated_dep_files)
-
 LOCAL_INTERMEDIATE_TARGETS += $(RenderScript_file_stamp)
 # Make sure the generated resource will be added to the apk.
 LOCAL_RESOURCE_DIR := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/renderscript/res $(LOCAL_RESOURCE_DIR)
@@ -321,6 +328,7 @@
 	PRIVATE_CLASS_INTERMEDIATES_DIR := $(intermediates.COMMON)/classes
 $(LOCAL_INTERMEDIATE_TARGETS): \
 	PRIVATE_SOURCE_INTERMEDIATES_DIR := $(LOCAL_INTERMEDIATE_SOURCE_DIR)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RMTYPEDEFS := $(LOCAL_RMTYPEDEFS)
 
 # Since we're using intermediates.COMMON, make sure that it gets cleaned
 # properly.
@@ -337,7 +345,7 @@
 # - This extra copy, with the dependency on LOCAL_BUILT_MODULE allows the
 #   PRIVATE_ vars to be preserved.
 $(full_classes_stubs_jar): PRIVATE_SOURCE_FILE := $(full_classes_jar)
-$(full_classes_stubs_jar) : $(LOCAL_BUILT_MODULE) | $(ACP)
+$(full_classes_stubs_jar) : $(full_classes_jar) | $(ACP)
 	@echo Copying $(PRIVATE_SOURCE_FILE)
 	$(hide) $(ACP) -fp $(PRIVATE_SOURCE_FILE) $@
 ALL_MODULES.$(LOCAL_MODULE).STUBS := $(full_classes_stubs_jar)
@@ -360,7 +368,6 @@
 $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := $(LOCAL_JAR_EXCLUDE_FILES)
 $(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := $(LOCAL_JAR_PACKAGES)
 $(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES := $(LOCAL_JAR_EXCLUDE_PACKAGES)
-$(full_classes_compiled_jar): PRIVATE_RMTYPEDEFS := $(LOCAL_RMTYPEDEFS)
 $(full_classes_compiled_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF)
 $(full_classes_compiled_jar): \
         $(java_sources) \
@@ -423,50 +430,57 @@
     $(error invalid value for LOCAL_PROGUARD_ENABLED: $(LOCAL_PROGUARD_ENABLED))
 endif
 proguard_dictionary := $(intermediates.COMMON)/proguard_dictionary
-proguard_flags := $(addprefix -libraryjars ,$(full_shared_java_libs)) \
+# jack already has the libraries in its classpath and doesn't support jars
+legacy_proguard_flags := $(addprefix -libraryjars ,$(full_shared_java_libs))
+common_proguard_flags :=  \
                   -forceprocessing \
                   -printmapping $(proguard_dictionary)
 
 ifeq ($(filter nosystem,$(LOCAL_PROGUARD_ENABLED)),)
-proguard_flags += -include $(BUILD_SYSTEM)/proguard.flags
+common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.flags
 ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-proguard_flags += -include $(BUILD_SYSTEM)/proguard.emma.flags
+common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.emma.flags
 endif
 # If this is a test package, add proguard keep flags for tests.
 ifneq ($(LOCAL_INSTRUMENTATION_FOR)$(filter tests,$(LOCAL_MODULE_TAGS)),)
-proguard_flags += -include $(BUILD_SYSTEM)/proguard_tests.flags
+common_proguard_flags += -include $(BUILD_SYSTEM)/proguard_tests.flags
 ifeq ($(filter shrinktests,$(LOCAL_PROGUARD_ENABLED)),)
-proguard_flags += -dontshrink # don't shrink tests by default
+common_proguard_flags += -dontshrink # don't shrink tests by default
 endif # shrinktests
 endif # test package
 ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)
 # By default no obfuscation
-proguard_flags += -dontobfuscate
+common_proguard_flags += -dontobfuscate
 endif  # No obfuscation
 ifeq ($(filter optimization,$(LOCAL_PROGUARD_ENABLED)),)
 # By default no optimization
-proguard_flags += -dontoptimize
+common_proguard_flags += -dontoptimize
 endif  # No optimization
 
 ifdef LOCAL_INSTRUMENTATION_FOR
 ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)
 # If no obfuscation, link in the instrmented package's classes.jar as a library.
 # link_instr_classes_jar is defined in base_rule.mk
-proguard_flags += -libraryjars $(link_instr_classes_jar)
+# jack already has this library in its classpath and doesn't support jars
+legacy_proguard_flags += -libraryjars $(link_instr_classes_jar)
 else # obfuscation
 # If obfuscation is enabled, the main app must be obfuscated too.
 # We need to run obfuscation using the main app's dictionary,
 # and treat the main app's class.jar as injars instead of libraryjars.
-proguard_flags := -injars  $(link_instr_classes_jar) \
+legacy_proguard_flags := -injars  $(link_instr_classes_jar) \
     -outjars $(intermediates.COMMON)/proguard.$(LOCAL_INSTRUMENTATION_FOR).jar \
     -include $(link_instr_intermediates_dir.COMMON)/proguard_options \
     -applymapping $(link_instr_intermediates_dir.COMMON)/proguard_dictionary \
     -verbose \
-    $(proguard_flags)
+    $(legacy_proguard_flags)
+# not supported with jack
+ifdef LOCAL_JACK_ENABLED
+    $(error $(LOCAL_MODULE): Build with jack of instrumentation when obfuscating is not yet supported)
+endif
 
 # Sometimes (test + main app) uses different keep rules from the main app -
 # apply the main app's dictionary anyway.
-proguard_flags += -ignorewarnings
+legacy_proguard_flags += -ignorewarnings
 
 # Make sure we run Proguard on the main app first
 $(full_classes_proguard_jar) : $(link_instr_intermediates_dir.COMMON)/proguard.classes.jar
@@ -484,7 +498,7 @@
 extra_input_jar :=
 endif
 $(full_classes_proguard_jar): PRIVATE_EXTRA_INPUT_JAR := $(extra_input_jar)
-$(full_classes_proguard_jar): PRIVATE_PROGUARD_FLAGS := $(proguard_flags) $(LOCAL_PROGUARD_FLAGS)
+$(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) $(proguard_flag_files) | $(ACP) $(PROGUARD)
 	$(call transform-jar-to-proguard)
 
@@ -495,7 +509,7 @@
 
 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)
@@ -511,6 +525,8 @@
 endif
 $(built_dex_intermediate): $(full_classes_proguard_jar) $(DX)
 	$(transform-classes.jar-to-dex)
+endif # LOCAL_JACK_ENABLED is disabled
+
 $(built_dex): $(built_dex_intermediate) | $(ACP)
 	@echo Copying: $@
 	$(hide) mkdir -p $(dir $@)
@@ -521,17 +537,14 @@
 endif
 
 findbugs_xml := $(intermediates.COMMON)/findbugs.xml
-$(findbugs_xml) : PRIVATE_JAR_FILE := $(full_classes_jar)
 $(findbugs_xml) : PRIVATE_AUXCLASSPATH := $(addprefix -auxclasspath ,$(strip \
 								$(call normalize-path-list,$(filter %.jar,\
 										$(full_java_libs)))))
-# We can't depend directly on full_classes_jar because the PRIVATE_
-# vars won't be set up correctly.
-$(findbugs_xml) : $(LOCAL_BUILT_MODULE)
+$(findbugs_xml) : $(full_classes_jar)
 	@echo Findbugs: $@
 	$(hide) $(FINDBUGS) -textui -effort:min -xml:withMessages \
 		$(PRIVATE_AUXCLASSPATH) \
-		$(PRIVATE_JAR_FILE) \
+		$< \
 		> $@
 
 ALL_FINDBUGS_FILES += $(findbugs_xml)
@@ -548,3 +561,72 @@
 $(LOCAL_MODULE)-findbugs : $(findbugs_html)
 
 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)
+$(LOCAL_INTERMEDIATE_TARGETS): \
+	PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-incremental
+else
+$(LOCAL_INTERMEDIATE_TARGETS): \
+	PRIVATE_JACK_INCREMENTAL_DIR :=
+endif
+
+ifdef full_classes_jar
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_DEBUG_FLAGS := -g
+
+ifdef LOCAL_PROGUARD_ENABLED
+
+ifndef LOCAL_JACK_PROGUARD_FLAGS
+    LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
+endif
+LOCAL_JACK_PROGUARD_FLAGS += $(addprefix -include , $(proguard_flag_files))
+ifdef LOCAL_TEST_MODULE_TO_PROGUARD_WITH
+    $(error $(LOCAL_MODULE): Build with jack when LOCAL_TEST_MODULE_TO_PROGUARD_WITH is defined is not yet implemented)
+endif
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_PROGUARD_FLAGS := $(common_proguard_flags) $(LOCAL_JACK_PROGUARD_FLAGS)
+else  # LOCAL_PROGUARD_ENABLED not defined
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_PROGUARD_FLAGS :=
+endif # LOCAL_PROGUARD_ENABLED defined
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_FLAGS := $(LOCAL_JACK_FLAGS)
+
+jack_all_deps := $(java_sources) $(java_resource_sources) $(full_jack_lib_deps) \
+        $(jar_manifest_file) $(layers_file) $(RenderScript_file_stamp) $(proguard_flag_files) \
+        $(proto_java_sources_file_stamp) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(LOCAL_JARJAR_RULES) \
+        $(LOCAL_MODULE_MAKEFILE) $(JACK_JAR) $(JACK_LAUNCHER_JAR)
+
+ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
+$(full_classes_jack): $(jack_all_deps)
+	@echo Building with Jack: $@
+	$(java-to-jack)
+
+else #LOCAL_IS_STATIC_JAVA_LIBRARY
+$(built_dex_intermediate): PRIVATE_CLASSES_JACK := $(full_classes_jack)
+
+$(built_dex_intermediate): $(jack_all_deps)
+	@echo Building with Jack: $@
+	$(jack-java-to-dex)
+
+# $(full_classes_jack) is just by-product of $(built_dex_intermediate).
+# The dummy command was added because, without it, make misses the fact the $(built_dex) also
+# change $(full_classes_jack).
+$(full_classes_jack): $(built_dex_intermediate)
+	$(hide) touch $@
+
+endif #LOCAL_IS_STATIC_JAVA_LIBRARY
+
+$(noshrob_classes_jack): PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-noshrob-rsc
+ifeq ($(LOCAL_JACK_ENABLED),incremental)
+$(noshrob_classes_jack): PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-noshrob-incremental
+else
+$(noshrob_classes_jack): PRIVATE_JACK_INCREMENTAL_DIR :=
+endif
+$(noshrob_classes_jack): PRIVATE_JACK_PROGUARD_FLAGS :=
+$(noshrob_classes_jack): $(jack_all_deps)
+	@echo Building with Jack: $@
+	$(java-to-jack)
+endif  # full_classes_jar is defined
+endif # LOCAL_JACK_ENABLED
diff --git a/core/java_library.mk b/core/java_library.mk
index b4e3eaa..5a2d19b 100644
--- a/core/java_library.mk
+++ b/core/java_library.mk
@@ -24,10 +24,20 @@
 
 LOCAL_BUILT_MODULE_STEM := 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
+endif
+endif
+
 intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
 # This file will be the one that other modules should depend on.
-common_javalib.jar := $(intermediates.COMMON)/$(LOCAL_BUILT_MODULE_STEM)
+common_javalib.jar := $(intermediates.COMMON)/javalib.jar
 LOCAL_INTERMEDIATE_TARGETS += $(common_javalib.jar)
 
 ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
@@ -59,7 +69,11 @@
 	@echo "target Static Jar: $(PRIVATE_MODULE) ($@)"
 	$(copy-file-to-target)
 
-$(LOCAL_BUILT_MODULE): $(common_javalib.jar)
+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
@@ -69,8 +83,15 @@
 $(common_javalib.jar): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
 $(common_javalib.jar) : $(built_dex) $(java_resource_sources)
 	@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
 
 ifdef LOCAL_DEX_PREOPT
 ifneq ($(dexpreopt_boot_jar_module),) # boot jar
diff --git a/core/main.mk b/core/main.mk
index 0e058af..3c5a554 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -29,7 +29,7 @@
 # TOPDIR is the normal variable you should use, because
 # if we are executing relative to the current directory
 # it can be "", whereas TOP must be "." which causes
-# pattern matching probles when make strips off the
+# pattern matching problems when make strips off the
 # trailing "./" from paths in various places.
 #ifeq ($(TOP),.)
 #TOPDIR :=
@@ -38,8 +38,6 @@
 #endif
 
 # Check for broken versions of make.
-# (Allow any version under Cygwin since we don't actually build the platform there.)
-ifeq (,$(findstring CYGWIN,$(shell uname -sm)))
 ifneq (1,$(strip $(shell expr $(MAKE_VERSION) \>= 3.81)))
 $(warning ********************************************************************************)
 $(warning *  You are using version $(MAKE_VERSION) of make.)
@@ -48,7 +46,6 @@
 $(warning ********************************************************************************)
 $(error stopping)
 endif
-endif
 
 # Absolute path of the present working direcotry.
 # This overrides the shell variable $PWD, which does not necessarily points to
@@ -86,6 +83,8 @@
 dont_bother := true
 endif
 
+ORIGINAL_MAKECMDGOALS := $(MAKECMDGOALS)
+
 # Targets that provide quick help on the build system.
 include $(BUILD_SYSTEM)/help.mk
 
@@ -93,6 +92,24 @@
 # and host information.
 include $(BUILD_SYSTEM)/config.mk
 
+ifeq ($(USE_NINJA),true)
+include build/core/ninja.mk
+else # !USE_NINJA
+
+# Write the build number to a file so it can be read back in
+# without changing the command line every time.  Avoids rebuilds
+# when using ninja.
+$(shell mkdir -p $(OUT_DIR) && \
+    echo -n $(BUILD_NUMBER) > $(OUT_DIR)/build_number.txt && \
+    echo -n $(BUILD_DATETIME) > $(OUT_DIR)/build_date.txt)
+BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
+BUILD_DATETIME_FROM_FILE := $$(cat $(OUT_DIR)/build_date.txt)
+ifeq ($(HOST_OS),darwin)
+DATE_FROM_FILE := date -r $(BUILD_DATETIME_FROM_FILE)
+else
+DATE_FROM_FILE := date -d @$(BUILD_DATETIME_FROM_FILE)
+endif
+
 # CTS-specific config.
 -include cts/build/config.mk
 
@@ -111,7 +128,6 @@
 
 $(info Checking build tools versions...)
 
-ifneq ($(HOST_OS),windows)
 # check for a case sensitive file system
 ifneq (a,$(shell mkdir -p $(OUT_DIR) ; \
                 echo a > $(OUT_DIR)/casecheck.txt; \
@@ -123,7 +139,6 @@
 $(warning ************************************************************)
 $(error Case-insensitive filesystems not supported)
 endif
-endif
 
 # Make sure that there are no spaces in the absolute path; the
 # build system can't deal with them.
@@ -175,7 +190,7 @@
 #
 # For Java 1.7, we require OpenJDK on linux and Oracle JDK on Mac OS.
 requires_openjdk := false
-ifeq ($(HOST_OS), linux)
+ifeq ($(BUILD_OS),linux)
 requires_openjdk := true
 endif
 
@@ -388,10 +403,10 @@
           ro.setupwizard.mode=OPTIONAL
 endif
 ifndef is_sdk_build
-  # Don't even verify the image on eng builds to speed startup
-  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.image-dex2oat-filter=verify-none
-  # Don't compile apps on eng builds to speed startup
-  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.dex2oat-filter=interpret-only
+  # Don't verify or compile the image on eng builds to speed startup.
+  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.image-dex2oat-filter=verify-at-runtime
+  # Don't verify or compile apps on eng builds to speed startup.
+  ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.dex2oat-filter=verify-at-runtime
 endif
   ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.usejit=true
 endif
@@ -459,11 +474,6 @@
 include $(TOPDIR)sdk/build/windows_sdk_whitelist.mk
 include $(TOPDIR)development/build/windows_sdk_whitelist.mk
 
-# Exclude tools/acp when cross-compiling windows under linux
-ifeq ($(findstring Linux,$(UNAME)),)
-subdirs += build/tools/acp
-endif
-
 else	# !SDK_ONLY
 #
 # Typical build; include any Android.mk files we can find.
@@ -875,7 +885,8 @@
 all_modules: $(ALL_MODULES)
 else
 # BUILD_MODULES_IN_PATHS is a list of paths relative to the top of the tree
-module_path_patterns := $(foreach p, $(BUILD_MODULES_IN_PATHS),\
+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))))
@@ -1008,13 +1019,13 @@
 tests : host-tests target-tests
 
 # 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)
 ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
 droidcore : target-tests host-tests
 endif
 endif
-
-.PHONY: lintall
+endif
 
 ifneq (,$(filter samplecode, $(MAKECMDGOALS)))
 .PHONY: samplecode
@@ -1059,3 +1070,4 @@
 .PHONY: nothing
 nothing:
 	@echo Successfully read the makefiles.
+endif # !USE_NINJA
diff --git a/core/multilib.mk b/core/multilib.mk
index a3ced65..e0615b2 100644
--- a/core/multilib.mk
+++ b/core/multilib.mk
@@ -13,3 +13,11 @@
 $(error $(LOCAL_PATH): Invalid LOCAL_MULTILIB specified for module $(LOCAL_MODULE))
 endif
 endif # my_module_multilib defined
+
+# Windows is a special case. Linux and Darwin are both multilib builds, but we
+# don't have a 64-bit Windows build, so make sure it's not a multilib build.
+ifdef LOCAL_IS_HOST_MODULE
+ifeq ($(HOST_OS),windows)
+my_module_multilib := 32
+endif
+endif
diff --git a/core/native_benchmark.mk b/core/native_benchmark.mk
index 431e40a..e5ca451 100644
--- a/core/native_benchmark.mk
+++ b/core/native_benchmark.mk
@@ -3,7 +3,7 @@
 ## Common flags for native benchmarks are added.
 ###########################################
 
-LOCAL_STATIC_LIBRARIES += libbenchmark
+LOCAL_STATIC_LIBRARIES += libbenchmark libbase
 
 ifndef LOCAL_MODULE_PATH
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
diff --git a/core/ninja.mk b/core/ninja.mk
new file mode 100644
index 0000000..de133c5
--- /dev/null
+++ b/core/ninja.mk
@@ -0,0 +1,55 @@
+KATI ?= $(HOST_OUT_EXECUTABLES)/ckati
+
+KATI_OUTPUTS := $(PRODUCT_OUT)/build.ninja $(PRODUCT_OUT)/ninja.sh
+NINJA_GOALS := fastincremental generateonly droid showcommands
+
+ANDROID_TARGETS := $(filter-out $(KATI_OUTPUTS) $(NINJA_GOALS),$(ORIGINAL_MAKECMDGOALS))
+
+ifeq (,$(NINJA_STATUS))
+NINJA_STATUS := [%p %s/%t]$(space)
+endif
+
+ifneq (,$(filter showcommands,$(ORIGINAL_MAKECMDGOALS)))
+NINJA_ARGS += "-v"
+PHONY: showcommands
+showcommands: droid
+endif
+
+ifeq (,$(filter generateonly,$(ORIGINAL_MAKECMDGOALS)))
+fastincremental droid $(ANDROID_TARGETS): ninja.intermediate
+	@#empty
+
+.INTERMEDIATE: ninja.intermediate
+ninja.intermediate: $(KATI_OUTPUTS)
+	@echo Starting build with ninja
+	$(hide) PATH=prebuilts/ninja/$(HOST_PREBUILT_TAG)/:$$PATH NINJA_STATUS="$(NINJA_STATUS)" $(PRODUCT_OUT)/ninja.sh -C $(TOP) $(NINJA_ARGS) $(ANDROID_TARGETS)
+else
+generateonly droid $(ANDROID_TARGETS): $(KATI_OUTPUTS)
+	@#empty
+endif
+
+ifeq (,$(filter fastincremental,$(ORIGINAL_MAKECMDGOALS)))
+KATI_FORCE := FORCE
+endif
+
+$(KATI_OUTPUTS): kati.intermediate $(KATI_FORCE)
+
+.INTERMEDIATE: kati.intermediate
+kati.intermediate: $(KATI)
+	@echo Running kati to generate build.ninja...
+	@#TODO: use separate ninja file for mm or single target build
+	$(hide) $(KATI) --ninja --ninja_dir=$(PRODUCT_OUT) --ignore_optional_include=$(OUT_DIR)/%.P --detect_android_echo --use_find_emulator -f build/core/main.mk $(ANDROID_TARGETS) USE_NINJA=false
+
+KATI_CXX := $(CLANG_CXX) $(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)
+KATI_LD += -static
+endif
+
+KATI_INTERMEDIATES_PATH := $(HOST_OUT_INTERMEDIATES)/EXECUTABLES/ckati_intermediates
+KATI_BIN_PATH := $(HOST_OUT_EXECUTABLES)
+include build/kati/Makefile.ckati
+
+.PHONY: FORCE
+FORCE:
diff --git a/core/notice_files.mk b/core/notice_files.mk
index e63cd84..43a5435 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -43,7 +43,7 @@
       # javalib.jar is the default name for the build module (and isn't meaningful)
       # If that's what we have, substitute the module name instead.  These files
       # aren't included on the device, so this name is synthetic anyway.
-      ifeq ($(module_leaf),javalib.jar)
+      ifneq ($(filter javalib.jar classes.jack,$(module_leaf)),)
         module_leaf := $(LOCAL_MODULE).jar
       endif
       module_installed_filename := \
diff --git a/core/package_internal.mk b/core/package_internal.mk
index e389b04..4f3c339 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -57,6 +57,10 @@
 endif
 LOCAL_MODULE_CLASS := APPS
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
 # Package LOCAL_MODULE_TAGS default to optional
 LOCAL_MODULE_TAGS := $(strip $(LOCAL_MODULE_TAGS))
 ifeq ($(LOCAL_MODULE_TAGS),)
@@ -162,6 +166,13 @@
 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
 # No emma for test apks.
@@ -271,6 +282,18 @@
 # 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)
+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
@@ -369,7 +392,6 @@
 $(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)
 # PRIVATE_JNI_SHARED_LIBRARIES_ABI is a list of ABI names.
 $(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abis)
-$(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES_ZIP_OPTIONS := $(LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS)
 $(LOCAL_BUILT_MODULE): PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES := $(LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES)
 ifneq ($(TARGET_BUILD_APPS),)
     # Include all resources for unbundled apps.
@@ -389,22 +411,32 @@
 $(LOCAL_BUILT_MODULE): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
 $(LOCAL_BUILT_MODULE): $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)
 	@echo "target Package: $(PRIVATE_MODULE) ($@)"
+ifdef LOCAL_JACK_ENABLED
+	$(create-empty-package)
+else
 	$(if $(PRIVATE_SOURCE_ARCHIVE),\
 	  $(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@),\
 	  $(create-empty-package))
+endif
 	$(add-assets-to-package)
 ifneq ($(jni_shared_libraries),)
 	$(add-jni-shared-libs-to-package)
 endif
-ifneq ($(full_classes_jar),)
+ifeq ($(full_classes_jar),)
+# We don't build jar, need to add the Java resources here.
+	$(if $(PRIVATE_EXTRA_JAR_ARGS),$(call add-java-resources-to,$@))
+else
 	$(add-dex-to-package)
 endif
-	$(sign-package)
+ifdef LOCAL_JACK_ENABLED
+	$(add-carried-jack-resources)
+endif
 ifdef LOCAL_DEX_PREOPT
 ifneq (nostripping,$(LOCAL_DEX_PREOPT))
 	$(call dexpreopt-remove-classes.dex,$@)
 endif
 endif
+	$(sign-package)
 	@# Alignment must happen after all other zip operations.
 	$(align-package)
 
@@ -478,39 +510,6 @@
 
 PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME)
 
-# Dist the files that can be bundled in system.img.
-# They include the jni shared libraries and the apk with jni libraries stripped.
-ifeq ($(LOCAL_DIST_BUNDLED_BINARIES),true)
-ifneq ($(filter $(LOCAL_PACKAGE_NAME),$(TARGET_BUILD_APPS)),)
-ifneq ($(strip $(jni_shared_libraries)),)
-dist_subdir := bundled_$(LOCAL_PACKAGE_NAME)
-$(foreach f, $(jni_shared_libraries), \
-  $(call dist-for-goals, apps_only, $(f):$(dist_subdir)/$(notdir $(f))))
-
-apk_jni_stripped := $(intermediates)/jni_stripped/package.apk
-$(apk_jni_stripped): PRIVATE_JNI_SHARED_LIBRARIES := $(notdir $(jni_shared_libraries))
-$(apk_jni_stripped) : $(LOCAL_BUILT_MODULE) | $(ZIPALIGN)
-	@rm -rf $(dir $@) && mkdir -p $(dir $@)
-	$(hide) cp $< $@
-	$(hide) zip -d $@ $(foreach f,$(PRIVATE_JNI_SHARED_LIBRARIES),\*/$(f))
-	$(align-package)
-
-$(call dist-for-goals, apps_only, $(apk_jni_stripped):$(dist_subdir)/$(LOCAL_PACKAGE_NAME).apk)
-
-endif  # jni_shared_libraries
-endif  # apps_only build
-endif  # LOCAL_DIST_BUNDLED_BINARIES
-
-# Lint phony targets
-.PHONY: lint-$(LOCAL_PACKAGE_NAME)
-lint-$(LOCAL_PACKAGE_NAME): PRIVATE_PATH := $(LOCAL_PATH)
-lint-$(LOCAL_PACKAGE_NAME): PRIVATE_LINT_FLAGS := $(LOCAL_LINT_FLAGS)
-lint-$(LOCAL_PACKAGE_NAME) :
-	@echo lint $(PRIVATE_PATH)
-	$(LINT) $(PRIVATE_LINT_FLAGS) $(PRIVATE_PATH)
-
-lintall : lint-$(LOCAL_PACKAGE_NAME)
-
 endif # skip_definition
 
 # Reset internal variables.
diff --git a/core/pathmap.mk b/core/pathmap.mk
index 2532707..38306f4 100644
--- a/core/pathmap.mk
+++ b/core/pathmap.mk
@@ -16,7 +16,14 @@
 
 #
 # A central place to define mappings to paths, to avoid hard-coding
-# them in Android.mk files.
+# them in Android.mk files. Not meant for header file include directories,
+# despite the fact that it was historically used for that!
+#
+# If you want this for a library's header files, use LOCAL_EXPORT_C_INCLUDES
+# instead. Then users of the library don't have to do anything --- they'll
+# have the correct header files added to their include path automatically.
+#
+
 #
 # TODO: Allow each project to define stuff like this before the per-module
 #       Android.mk files are included, so we don't need to have a big central
@@ -30,16 +37,12 @@
     camera:system/media/camera/include \
     frameworks-base:frameworks/base/include \
     frameworks-native:frameworks/native/include \
-    libc:bionic/libc/include \
     libhardware:hardware/libhardware/include \
     libhardware_legacy:hardware/libhardware_legacy/include \
     libhost:build/libs/host/include \
-    libm:bionic/libm/include \
     libnativehelper:libnativehelper/include \
     libpagemap:system/extras/libpagemap/include \
     libril:hardware/ril/include \
-    libstdc++:bionic/libstdc++/include \
-    mkbootimg:system/core/mkbootimg \
     opengl-tests-includes:frameworks/native/opengl/tests/include \
     recovery:bootable/recovery \
     system-core:system/core/include \
diff --git a/core/post_clean.mk b/core/post_clean.mk
index 0273ff2..7fafe4a 100644
--- a/core/post_clean.mk
+++ b/core/post_clean.mk
@@ -88,7 +88,7 @@
 $(shell echo 'MODULES_WITH_AIDL_FILES := $(MODULES_WITH_AIDL_FILES)' >> $(current_aidl_config))
 
 # Now current becomes previous.
-$(shell mv -f $(current_aidl_config) $(previous_aidl_config))
+$(shell cmp $(current_aidl_config) $(previous_aidl_config) > /dev/null 2>&1 || mv -f $(current_aidl_config) $(previous_aidl_config))
 
 MODULES_WITH_AIDL_FILES :=
 modules_with_aidl_files :=
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index 47e21ef..d367828 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -43,6 +43,11 @@
     # Strip but not try to add debuglink
     LOCAL_STRIP_MODULE := no_debuglink
   endif
+
+  ifeq ($(LOCAL_IS_HOST_MODULE)$(LOCAL_PACK_MODULE_RELOCATIONS),)
+    # Do not pack relocations by default
+    LOCAL_PACK_MODULE_RELOCATIONS := false
+  endif
 endif
 
 ifneq ($(filter STATIC_LIBRARIES SHARED_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
@@ -63,20 +68,20 @@
 LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_MODULE).apk
 endif
 
-ifneq ($(filter true no_debuglink,$(LOCAL_STRIP_MODULE)),)
+ifneq ($(filter true no_debuglink,$(LOCAL_STRIP_MODULE) $(LOCAL_PACK_MODULE_RELOCATIONS)),)
   ifdef LOCAL_IS_HOST_MODULE
-    $(error Cannot strip host module LOCAL_PATH=$(LOCAL_PATH))
+    $(error Cannot strip/pack host module LOCAL_PATH=$(LOCAL_PATH))
   endif
   ifeq ($(filter SHARED_LIBRARIES EXECUTABLES,$(LOCAL_MODULE_CLASS)),)
-    $(error Can strip only shared libraries or executables LOCAL_PATH=$(LOCAL_PATH))
+    $(error Can strip/pack only shared libraries or executables LOCAL_PATH=$(LOCAL_PATH))
   endif
   ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),)
-    $(error Cannot strip scripts LOCAL_PATH=$(LOCAL_PATH))
+    $(error Cannot strip/pack scripts LOCAL_PATH=$(LOCAL_PATH))
   endif
   include $(BUILD_SYSTEM)/dynamic_binary.mk
   built_module := $(linked_module)
 
-else  # LOCAL_STRIP_MODULE not true
+else  # LOCAL_STRIP_MODULE and LOCAL_PACK_MODULE_RELOCATIONS not true
   include $(BUILD_SYSTEM)/base_rules.mk
   built_module := $(LOCAL_BUILT_MODULE)
 
@@ -193,17 +198,21 @@
 $(built_module) : PRIVATE_PAGE_ALIGN_JNI_SHARED_LIBRARIES := $(LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES)
 $(built_module) : $(my_prebuilt_src_file) | $(ACP) $(ZIPALIGN) $(SIGNAPK_JAR)
 	$(transform-prebuilt-to-target)
+ifneq ($(LOCAL_CERTIFICATE),PRESIGNED)
+	@# Only strip out files if we can re-sign the package.
 ifdef extracted_jni_libs
 	$(hide) zip -d $@ 'lib/*.so'  # strip embedded JNI libraries.
 endif
-ifneq ($(LOCAL_CERTIFICATE),PRESIGNED)
-	$(sign-package)
-endif
 ifdef LOCAL_DEX_PREOPT
 ifneq (nostripping,$(LOCAL_DEX_PREOPT))
 	$(call dexpreopt-remove-classes.dex,$@)
 endif
 endif
+	$(sign-package)
+endif
+ifeq ($(LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES),true)
+	$(uncompress-shared-libs)
+endif
 	$(align-package)
 
 ###############################
@@ -256,13 +265,6 @@
 else
 $(built_module) : $(my_prebuilt_src_file) | $(ACP)
 	$(transform-prebuilt-to-target)
-ifneq ($(prebuilt_module_is_a_library),)
-  ifneq ($(LOCAL_IS_HOST_MODULE),)
-	$(transform-host-ranlib-copy-hack)
-  else
-	$(transform-ranlib-copy-hack)
-  endif
-endif
 endif
 endif # LOCAL_MODULE_CLASS != APPS
 
@@ -300,6 +302,14 @@
 $(built_module) : $(common_javalib_jar)
 endif # TARGET JAVA_LIBRARIES
 
+ifeq ($(LOCAL_MODULE_CLASS),JAVA_LIBRARIES)
+$(intermediates.COMMON)/classes.jack : PRIVATE_JILL_FLAGS:=$(LOCAL_JILL_FLAGS)
+$(intermediates.COMMON)/classes.jack : $(my_prebuilt_src_file) $(LOCAL_MODULE_MAKEFILE) \
+        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JILL_JAR) $(JACK_JAR) $(JACK_LAUNCHER_JAR)
+	$(transform-jar-to-jack)
+
+endif # JAVA_LIBRARIES
+
 $(built_module) : $(LOCAL_MODULE_MAKEFILE) $(LOCAL_ADDITIONAL_DEPENDENCIES)
 
 my_prebuilt_src_file :=
diff --git a/core/product.mk b/core/product.mk
index d3df582..ac5f854 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -229,7 +229,6 @@
 	TARGET_DEVICE_KERNEL_HEADERS \
 	TARGET_PRODUCT_KERNEL_HEADERS \
 	TARGET_BOOTLOADER_BOARD_NAME \
-	TARGET_COMPRESS_MODULE_SYMBOLS \
 	TARGET_NO_BOOTLOADER \
 	TARGET_NO_KERNEL \
 	TARGET_NO_RECOVERY \
@@ -271,6 +270,7 @@
 _product_stash_var_list += \
 	GLOBAL_CFLAGS_NO_OVERRIDE \
 	GLOBAL_CPPFLAGS_NO_OVERRIDE \
+	GLOBAL_CLANG_CFLAGS_NO_OVERRIDE \
 
 #
 # Stash values of the variables in _product_stash_var_list.
diff --git a/core/shared_library_internal.mk b/core/shared_library_internal.mk
index 1fda794..1507502 100644
--- a/core/shared_library_internal.mk
+++ b/core/shared_library_internal.mk
@@ -40,11 +40,21 @@
 
 # Define PRIVATE_ variables from global vars
 my_target_global_ld_dirs := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_LD_DIRS)
+my_target_libprofile_rt := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBPROFILE_RT)
 my_target_libgcov := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCOV)
+ifeq ($(LOCAL_NO_LIBGCC),true)
+my_target_libgcc :=
+else
 my_target_libgcc := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBGCC)
+endif
 my_target_libatomic := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBATOMIC)
+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)
+endif
 ifdef LOCAL_SDK_VERSION
 # Make sure the prebuilt NDK paths are put ahead of the TARGET_GLOBAL_LD_DIRS,
 # so we don't have race condition when the system libraries (such as libc, libstdc++) are also built in the tree.
@@ -58,6 +68,7 @@
 endif
 $(linked_module): PRIVATE_TARGET_GLOBAL_LD_DIRS := $(my_target_global_ld_dirs)
 $(linked_module): PRIVATE_TARGET_GLOBAL_LDFLAGS := $(my_target_global_ldflags)
+$(linked_module): PRIVATE_TARGET_LIBPROFILE_RT := $(my_target_libprofile_rt)
 $(linked_module): PRIVATE_TARGET_LIBGCOV := $(my_target_libgcov)
 $(linked_module): PRIVATE_TARGET_LIBGCC := $(my_target_libgcc)
 $(linked_module): PRIVATE_TARGET_LIBATOMIC := $(my_target_libatomic)
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index 02078e0..69d6ebf 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -56,8 +56,20 @@
 ifneq ($(LOCAL_PROGUARD_ENABLED),custom)
   proguard_options_file := $(intermediates.COMMON)/proguard_options
 endif
+
 LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
 
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+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
+
 endif  # LOCAL_RESOURCE_DIR
 
 all_res_assets := $(all_resources)
@@ -114,9 +126,11 @@
 	$(hide) find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name R.java | xargs cat > $@
 
 $(LOCAL_BUILT_MODULE): $(R_file_stamp)
-ifneq ($(full_classes_jar),)
+ifdef LOCAL_JACK_ENABLED
+$(noshrob_classes_jack): $(R_file_stamp)
+$(full_classes_jack): $(R_file_stamp)
+endif # LOCAL_JACK_ENABLED
 $(full_classes_compiled_jar): $(R_file_stamp)
-endif
 
 endif  # need_compile_res
 
diff --git a/core/tasks/build_custom_images.mk b/core/tasks/build_custom_images.mk
new file mode 100644
index 0000000..8ebf89b
--- /dev/null
+++ b/core/tasks/build_custom_images.mk
@@ -0,0 +1,64 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Build additional images requested by the product makefile.
+# This script gives the ability to build multiple additional images and you can
+# configure what modules/files to include in each image.
+# 1. Define PRODUCT_CUSTOM_IMAGE_MAKEFILES in your product makefile.
+#    PRODUCT_CUSTOM_IMAGE_MAKEFILES is a list of makefiles.
+#    Each makefile configures an image.
+#    For image configuration makefile foo/bar/xyz.mk, the built image file name
+#    will be xyz.img. So make sure they won't conflict.
+# 2. In each image's configuration makefile, you can define variables:
+#   - CUSTOM_IMAGE_MOUNT_POINT, the mount point, such as "oem", "odm" etc.
+#   - CUSTOM_IMAGE_PARTITION_SIZE
+#   - CUSTOM_IMAGE_FILE_SYSTEM_TYPE
+#   - CUSTOM_IMAGE_DICT_FILE, a text file defines a dictionary accepted by
+#     BuildImage() in tools/releasetools/build_image.py.
+#   - CUSTOM_IMAGE_MODULES, a list of module names you want to include in
+#     the image; Not only the module itself will be installed to proper path in
+#     the image, you can also piggyback additional files/directories with the
+#     module's LOCAL_PICKUP_FILES.
+#   - CUSTOM_IMAGE_COPY_FILES, a list of "<src>:<dest>" to be copied to the
+#     image. <dest> is relativ to the root of the image.
+#   - CUSTOM_IMAGE_SELINUX, set to "true" if the image supports selinux.
+#   - CUSTOM_IMAGE_SUPPORT_VERITY, set to "true" if the product supports verity.
+#   - CUSTOM_IMAGE_VERITY_BLOCK_DEVICE
+#
+# To build all those images, run "make custom_images".
+
+ifneq ($(filter $(MAKECMDGOALS),custom_images),)
+
+.PHONY: custom_images
+
+custom_image_parameter_variables := \
+  CUSTOM_IMAGE_MOUNT_POINT \
+  CUSTOM_IMAGE_PARTITION_SIZE \
+  CUSTOM_IMAGE_FILE_SYSTEM_TYPE \
+  CUSTOM_IMAGE_DICT_FILE \
+  CUSTOM_IMAGE_MODULES \
+  CUSTOM_IMAGE_COPY_FILES \
+  CUSTOM_IMAGE_SELINUX \
+  CUSTOM_IMAGE_SUPPORT_VERITY \
+  CUSTOM_IMAGE_VERITY_BLOCK_DEVICE \
+
+# We don't expect product makefile to inherit/override PRODUCT_CUSTOM_IMAGE_MAKEFILES,
+# so we don't put it in the _product_var_list.
+$(foreach mk, $(PRODUCT_CUSTOM_IMAGE_MAKEFILES),\
+  $(eval my_custom_imag_makefile := $(mk))\
+  $(eval include $(BUILD_SYSTEM)/tasks/tools/build_custom_image.mk))
+
+endif
diff --git a/core/tasks/check_boot_jars/check_boot_jars.py b/core/tasks/check_boot_jars/check_boot_jars.py
index 89d9ee8..5a0ec40 100755
--- a/core/tasks/check_boot_jars/check_boot_jars.py
+++ b/core/tasks/check_boot_jars/check_boot_jars.py
@@ -64,10 +64,10 @@
 def main(argv):
   if len(argv) < 2:
     print __doc__
-    sys.exit(1)
+    return 1
 
   if not LoadWhitelist(argv[0]):
-    sys.exit(1)
+    return 1
 
   passed = True
   for jar in argv[1:]:
@@ -80,4 +80,4 @@
 
 
 if __name__ == '__main__':
-  main(sys.argv[1:])
+  sys.exit(main(sys.argv[1:]))
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 2ce5dbc..4c82ada 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -50,6 +50,10 @@
 	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 += \
@@ -61,7 +65,7 @@
 
 CTS_TEST_JAR_LIST := \
         cts-junit \
-	CtsJdwp
+        CtsJdwp
 
 # Depend on the full package paths rather than the phony targets to avoid
 # rebuilding the packages every time.
@@ -82,8 +86,10 @@
     $(eval $(call copy-one-file, $(built), $(installed)))\
     $(eval CTS_CASE_LIST_APKS += $(installed))))
 
+CTS_SHARED_LIBS :=
+
 DEFAULT_TEST_PLAN := $(cts_dir)/$(cts_name)/resource/plans
-$(cts_dir)/all_cts_files_stamp: $(CTS_CORE_CASES) $(CTS_TEST_CASES) $(CTS_CASE_LIST_APKS) $(JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(VMTESTSTF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(CTS_TF_README_PATH) $(ACP) $(CTS_TEST_JAR_FILES)
+$(cts_dir)/all_cts_files_stamp: $(CTS_CORE_CASES) $(CTS_TEST_CASES) $(CTS_CASE_LIST_APKS) $(JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(VMTESTSTF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(CTS_TF_README_PATH) $(ACP) $(CTS_TEST_JAR_FILES) $(CTS_SHARED_LIBS)
 # Make necessary directory for CTS
 	$(hide) mkdir -p $(TMP_DIR)
 	$(hide) mkdir -p $(PRIVATE_DIR)/docs
@@ -93,6 +99,7 @@
 # Copy executable and JARs to CTS directory
 	$(hide) $(ACP) -fp $(VMTESTSTF_JAR) $(PRIVATE_DIR)/repository/testcases
 	$(hide) $(ACP) -fp $(HOSTTESTLIB_JAR) $(CTS_HOST_LIBRARY_JARS) $(TF_JAR) $(CTS_TF_JAR) $(CTS_TF_EXEC_PATH) $(CTS_TF_README_PATH) $(PRIVATE_DIR)/tools
+	$(hide) $(call copy-files-with-structure, $(CTS_SHARED_LIBS),$(HOST_OUT)/,$(PRIVATE_DIR))
 # Change mode of the executables
 	$(foreach jar,$(CTS_TEST_JAR_LIST),$(call copy-testcase-jar,$(jar)))
 	$(foreach testcase,$(CTS_TEST_CASES),$(call copy-testcase,$(testcase)))
@@ -128,8 +135,10 @@
 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 := $(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
+GEN_CLASSPATH := \
+    $(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 \
@@ -154,6 +163,7 @@
 	$(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
@@ -161,7 +171,7 @@
 # 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 build/core/tasks/cts.mk | $(ACP)
+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)
@@ -202,7 +212,16 @@
 	$(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,\
+		$(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.json,\
 		$(TARGET_ARCH),libcore/expectations)
 
 $(CTS_TESTCASES_OUT)/android.core.tests.libcore.package.libcore.xml: $(CTS_CORE_XMLS_DEPS)
@@ -317,6 +336,13 @@
 		$(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
diff --git a/core/tasks/deps_licenses.mk b/core/tasks/deps_licenses.mk
new file mode 100644
index 0000000..bb20fa0
--- /dev/null
+++ b/core/tasks/deps_licenses.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Print modules and their transitive dependencies with license files.
+# To invoke, run "make deps-license PROJ_PATH=<proj-path-patterns> DEP_PATH=<dep-path-patterns>".
+# PROJ_PATH restricts the paths of the source modules; DEP_PATH restricts the paths of the dependency modules.
+# Both can be makefile patterns supported by makefile function $(filter).
+# Example: "make deps-license packages/app/% external/%" prints all modules in packages/app/ with their dpendencies in external/.
+# The printout lines look like "<module_name> :: <module_paths> :: <license_files>".
+
+ifneq (,$(filter deps-license,$(MAKECMDGOALS)))
+ifndef PROJ_PATH
+$(error To "make deps-license" you must specify PROJ_PATH and DEP_PATH.)
+endif
+ifndef DEP_PATH
+$(error To "make deps-license" you must specify PROJ_PATH and DEP_PATH.)
+endif
+
+# Expand a module's dependencies transitively.
+# $(1): the variable name to hold the result.
+# $(2): the initial module name.
+define get-module-all-dependencies
+$(eval _gmad_new := $(sort $(filter-out $($(1)),\
+  $(foreach m,$(2),$(ALL_DEPS.$(m).ALL_DEPS)))))\
+$(if $(_gmad_new),$(eval $(1) += $(_gmad_new))\
+  $(call get-module-all-dependencies,$(1),$(_gmad_new)))
+endef
+
+define print-deps-license
+$(foreach m, $(ALL_DEPS.MODULES),\
+  $(eval m_p := $(sort $(ALL_MODULES.$(m).PATH) $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).PATH)))\
+  $(if $(filter $(PROJ_PATH),$(m_p)),\
+    $(eval deps :=)\
+    $(eval $(call get-module-all-dependencies,deps,$(m)))\
+    $(info $(m) :: $(m_p) :: $(ALL_DEPS.$(m).LICENSE))\
+    $(foreach d,$(deps),\
+      $(eval d_p := $(sort $(ALL_MODULES.$(d).PATH) $(ALL_MODULES.$(d)$(TARGET_2ND_ARCH_MODULE_SUFFIX).PATH)))\
+      $(if $(filter $(DEP_PATH),$(d_p)),\
+        $(info $(space)$(space)$(space)$(space)$(d) :: $(d_p) :: $(ALL_DEPS.$(d).LICENSE))))))
+endef
+
+.PHONY: deps-license
+deps-license:
+	@$(call print-deps-license)
+
+endif
diff --git a/core/tasks/tools/build_custom_image.mk b/core/tasks/tools/build_custom_image.mk
new file mode 100644
index 0000000..e59ed42
--- /dev/null
+++ b/core/tasks/tools/build_custom_image.mk
@@ -0,0 +1,115 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+# Define rule to build one custom image.
+# Input variables: my_custom_imag_makefile
+
+$(call clear-var-list, $(custom_image_parameter_variables))
+
+include $(my_custom_imag_makefile)
+
+my_custom_image_name := $(basename $(notdir $(my_custom_imag_makefile)))
+
+intermediates := $(call intermediates-dir-for,PACKAGING,$(my_custom_image_name))
+my_built_custom_image := $(intermediates)/$(my_custom_image_name).img
+my_staging_dir := $(intermediates)/$(CUSTOM_IMAGE_MOUNT_POINT)
+
+# Collect CUSTOM_IMAGE_MODULES's installd files and their PICKUP_FILES.
+my_built_modules :=
+my_copy_pairs :=
+my_pickup_files :=
+
+$(foreach m,$(CUSTOM_IMAGE_MODULES),\
+  $(eval _pickup_files := $(strip $(ALL_MODULES.$(m).PICKUP_FILES)\
+    $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).PICKUP_FILES)))\
+  $(eval _built_files := $(strip $(ALL_MODULES.$(m).BUILT_INSTALLED)\
+    $(ALL_MODULES.$(m)$(TARGET_2ND_ARCH_MODULE_SUFFIX).BUILT_INSTALLED)))\
+  $(if $(_pickup_files)$(_built_files),,\
+    $(warning Unknown installed file for module '$(m)'))\
+  $(eval my_pickup_files += $(_pickup_files))\
+  $(foreach i, $(_built_files),\
+    $(eval bui_ins := $(subst :,$(space),$(i)))\
+    $(eval ins := $(word 2,$(bui_ins)))\
+    $(if $(filter $(TARGET_OUT_ROOT)/%,$(ins)),\
+      $(eval bui := $(word 1,$(bui_ins)))\
+      $(eval my_built_modules += $(bui))\
+      $(eval my_copy_dest := $(patsubst $(PRODUCT_OUT)/%,%,$(ins)))\
+      $(eval my_copy_dest := $(subst /,$(space),$(my_copy_dest)))\
+      $(eval my_copy_dest := $(wordlist 2,999,$(my_copy_dest)))\
+      $(eval my_copy_dest := $(subst $(space),/,$(my_copy_dest)))\
+      $(eval my_copy_pairs += $(bui):$(my_staging_dir)/$(my_copy_dest)))\
+  ))
+
+# Collect CUSTOM_IMAGE_COPY_FILES.
+my_image_copy_files :=
+$(foreach f,$(CUSTOM_IMAGE_COPY_FILES),\
+  $(eval pair := $(subst :,$(space),$(f)))\
+  $(eval src := $(word 1,$(pair)))\
+  $(eval my_image_copy_files += $(src))\
+  $(eval my_copy_pairs += $(src):$(my_staging_dir)/$(word 2,$(pair))))
+
+$(my_built_custom_image): PRIVATE_INTERMEDIATES := $(intermediates)
+$(my_built_custom_image): PRIVATE_MOUNT_POINT := $(CUSTOM_IMAGE_MOUNT_POINT)
+$(my_built_custom_image): PRIVATE_PARTITION_SIZE := $(CUSTOM_IMAGE_PARTITION_SIZE)
+$(my_built_custom_image): PRIVATE_FILE_SYSTEM_TYPE := $(CUSTOM_IMAGE_FILE_SYSTEM_TYPE)
+$(my_built_custom_image): PRIVATE_STAGING_DIR := $(my_staging_dir)
+$(my_built_custom_image): PRIVATE_COPY_PAIRS := $(my_copy_pairs)
+$(my_built_custom_image): PRIVATE_PICKUP_FILES := $(my_pickup_files)
+$(my_built_custom_image): PRIVATE_SELINUX := $(CUSTOM_IMAGE_SELINUX)
+$(my_built_custom_image): PRIVATE_SUPPORT_VERITY := $(CUSTOM_IMAGE_SUPPORT_VERITY)
+$(my_built_custom_image): PRIVATE_VERITY_KEY := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)
+$(my_built_custom_image): PRIVATE_VERITY_BLOCK_DEVICE := $(CUSTOM_IMAGE_VERITY_BLOCK_DEVICE)
+$(my_built_custom_image): PRIVATE_DICT_FILE := $(CUSTOM_IMAGE_DICT_FILE)
+$(my_built_custom_image): $(INTERNAL_USERIMAGES_DEPS) $(my_built_modules) $(my_image_copy_files) \
+  $(CUSTOM_IMAGE_DICT_FILE)
+	@echo "Build image $@"
+	$(hide) rm -rf $(PRIVATE_INTERMEDIATES) && mkdir -p $(PRIVATE_INTERMEDIATES)
+	$(hide) rm -rf $(PRIVATE_STAGING_DIR) && mkdir -p $(PRIVATE_STAGING_DIR)
+	# Copy all the files.
+	$(hide) $(foreach p,$(PRIVATE_COPY_PAIRS),\
+	          $(eval pair := $(subst :,$(space),$(p)))\
+	          mkdir -p $(dir $(word 2,$(pair)));\
+	          cp -Rf $(word 1,$(pair)) $(word 2,$(pair));)
+	$(if $($(PRIVATE_PICKUP_FILES)),$(hide) cp -Rf $(PRIVATE_PICKUP_FILES) $(PRIVATE_STAGING_DIR))
+	# Generate the dict.
+	$(hide) echo "# For all accepted properties, see BuildImage() in tools/releasetools/build_image.py" > $(PRIVATE_INTERMEDIATES)/image_info.txt
+	$(hide) echo "mount_point=$(PRIVATE_MOUNT_POINT)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt
+	$(hide) echo "fs_type=$(PRIVATE_FILE_SYSTEM_TYPE)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt
+	$(hide) echo "partition_size=$(PRIVATE_PARTITION_SIZE)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt
+	$(if $(PRIVATE_SELINUX),$(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
+	$(if $(PRIVATE_SUPPORT_VERITY),\
+	  $(hide) echo "verity=$(PRIVATE_SUPPORT_VERITY)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt;\
+	    echo "verity_key=$(PRIVATE_VERITY_KEY)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt;\
+	    echo "verity_signer_cmd=$(VERITY_SIGNER)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt;\
+	    echo "verity_block_device=$(PRIVATE_VERITY_BLOCK_DEVICE)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
+	$(if $(PRIVATE_DICT_FILE),\
+	  $(hide) echo "# Properties from $(PRIVATE_DICT_FILE)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt;\
+	    cat $(PRIVATE_DICT_FILE) >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
+	# Generate the image.
+	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
+	  ./build/tools/releasetools/build_image.py \
+	  $(PRIVATE_STAGING_DIR) $(PRIVATE_INTERMEDIATES)/image_info.txt $@
+
+my_installed_custom_image := $(PRODUCT_OUT)/$(notdir $(my_built_custom_image))
+$(my_installed_custom_image) : $(my_built_custom_image)
+	$(call copy-file-to-new-target-with-cp)
+
+.PHONY: $(my_custom_image_name)
+custom_images $(my_custom_image_name) : $(my_installed_custom_image)
+
+# Archive the built image.
+$(call dist-for-goals, $(my_custom_image_name) custom_images,$(my_installed_custom_image))
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index f3b2297..170e20b 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -24,6 +24,7 @@
 #     DEFAULT_APP_TARGET_SDK
 #     BUILD_ID
 #     BUILD_NUMBER
+#     BUILD_DATETIME
 #
 
 # Look for an optional file containing overrides of the defaults,
@@ -89,6 +90,18 @@
   BUILD_ID := UNKNOWN
 endif
 
+ifeq "" "$(BUILD_DATETIME)"
+  # Used to reproduce builds by setting the same time. Must be the number
+  # of seconds since the Epoch.
+  BUILD_DATETIME := $(shell date +%s)
+endif
+
+ifneq (,$(findstring Darwin,$(shell uname -sm)))
+DATE := date -r $(BUILD_DATETIME)
+else
+DATE := date -d @$(BUILD_DATETIME)
+endif
+
 ifeq "" "$(BUILD_NUMBER)"
   # BUILD_NUMBER should be set to the source control value that
   # represents the current state of the source code.  E.g., a
@@ -99,5 +112,5 @@
   # If no BUILD_NUMBER is set, create a useful "I am an engineering build
   # from this date/time" value.  Make it start with a non-digit so that
   # anyone trying to parse it as an integer will probably get "0".
-  BUILD_NUMBER := eng.$(USER).$(shell date +%Y%m%d.%H%M%S)
+  BUILD_NUMBER := eng.$(USER).$(shell $(DATE) +%Y%m%d.%H%M%S)
 endif
diff --git a/envsetup.sh b/envsetup.sh
index f93c07d..3c29e88 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -15,6 +15,7 @@
 - jgrep:   Greps on all local Java files.
 - resgrep: Greps on all local res/*.xml files.
 - mangrep: Greps on all local AndroidManifest.xml files.
+- mgrep:   Greps on all local Makefiles files.
 - sepgrep: Greps on all local sepolicy files.
 - sgrep:   Greps on all local source files.
 - godir:   Go to the directory containing a file.
@@ -29,7 +30,7 @@
     T=$(gettop)
     local A
     A=""
-    for i in `cat $T/build/envsetup.sh | sed -n "/^[ \t]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
+    for i in `cat $T/build/envsetup.sh | sed -n "/^[[:blank:]]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
       A="$A $i"
     done
     echo $A
@@ -175,7 +176,7 @@
             ;;
     esac
 
-    export ANDROID_DEV_SCRIPTS=$T/development/scripts:$T/prebuilts/devtools/tools
+    export ANDROID_DEV_SCRIPTS=$T/development/scripts:$T/prebuilts/devtools/tools:$T/external/selinux/prebuilts/bin
     export ANDROID_BUILD_PATHS=$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_TOOLCHAIN:$ANDROID_TOOLCHAIN_2ND_ARCH:$ANDROID_KERNEL_TOOLCHAIN_PATH$ANDROID_DEV_SCRIPTS:
 
     # If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH
@@ -197,6 +198,7 @@
     fi
 
     export PATH=$ANDROID_BUILD_PATHS$PATH
+    export PYTHONPATH=$T/system/core:$PYTHONPATH
 
     unset ANDROID_JAVA_TOOLCHAIN
     unset ANDROID_PRE_BUILD_PATHS
@@ -347,7 +349,7 @@
     if [ "x$TARGET_PRODUCT" != x ] ; then
         default_value=$TARGET_PRODUCT
     else
-        default_value=full
+        default_value=aosp_arm
     fi
 
     export TARGET_PRODUCT=
@@ -594,10 +596,10 @@
         return
     fi
 
-    local product=full
+    local product=aosp_arm
     case $arch in
-      x86)    product=full_x86;;
-      mips)   product=full_mips;;
+      x86)    product=aosp_x86;;
+      mips)   product=aosp_mips;;
       armv5)  product=generic_armv5;;
       arm64)  product=aosp_arm64;;
       x86_64) product=aosp_x86_64;;
@@ -672,6 +674,7 @@
         $DRV make -C $T -f build/core/main.mk $@
     else
         echo "Couldn't locate the top of the tree.  Try setting TOP."
+        return 1
     fi
 }
 
@@ -710,8 +713,10 @@
         local M=`echo $M|sed 's:'$T'/::'`
         if [ ! "$T" ]; then
             echo "Couldn't locate the top of the tree.  Try setting TOP."
+            return 1
         elif [ ! "$M" ]; then
             echo "Couldn't locate a makefile from the current directory."
+            return 1
         else
             for ARG in $@; do
                 case $ARG in
@@ -774,6 +779,7 @@
         ONE_SHOT_MAKEFILE="$MAKEFILE" $DRV make -C $T -f build/core/main.mk $DASH_ARGS $MODULES $ARGS
     else
         echo "Couldn't locate the top of the tree.  Try setting TOP."
+        return 1
     fi
 }
 
@@ -786,6 +792,7 @@
   else
     if [ ! "$T" ]; then
       echo "Couldn't locate the top of the tree.  Try setting TOP."
+      return 1
     fi
     local MY_PWD=`PWD= /bin/pwd|sed 's:'$T'/::'`
     $DRV make -C $T -f build/core/main.mk $@ all_modules BUILD_MODULES_IN_PATHS="$MY_PWD"
@@ -825,6 +832,7 @@
     $DRV make -C $T -f build/core/main.mk $DASH_ARGS $ARGS all_modules BUILD_MODULES_IN_PATHS="$MODULE_PATHS"
   else
     echo "Couldn't locate the top of the tree.  Try setting TOP."
+    return 1
   fi
 }
 
@@ -1420,9 +1428,9 @@
     local retval=$?
     if [ $retval -ne 0 ]
     then
-        echo -e "\e[0;31mFAILURE\e[00m"
+        echo $'\E'"[0;31mFAILURE\e[00m"
     else
-        echo -e "\e[0;32mSUCCESS\e[00m"
+        echo $'\E'"[0;32mSUCCESS\e[00m"
     fi
     return $retval
 }
@@ -1444,9 +1452,9 @@
     local secs=$(($tdiff % 60))
     local ncolors=$(tput colors 2>/dev/null)
     if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
-        color_failed="\e[0;31m"
-        color_success="\e[0;32m"
-        color_reset="\e[00m"
+        color_failed=$'\E'"[0;31m"
+        color_success=$'\E'"[0;32m"
+        color_reset=$'\E'"[00m"
     else
         color_failed=""
         color_success=""
@@ -1454,9 +1462,9 @@
     fi
     echo
     if [ $ret -eq 0 ] ; then
-        echo -n -e "${color_success}#### make completed successfully "
+        echo -n "${color_success}#### make completed successfully "
     else
-        echo -n -e "${color_failed}#### make failed to build some targets "
+        echo -n "${color_failed}#### make failed to build some targets "
     fi
     if [ $hours -gt 0 ] ; then
         printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs
@@ -1465,7 +1473,7 @@
     elif [ $secs -gt 0 ] ; then
         printf "(%s seconds)" $secs
     fi
-    echo -e " ####${color_reset}"
+    echo " ####${color_reset}"
     echo
     return $ret
 }
@@ -1481,8 +1489,8 @@
 fi
 
 # Execute the contents of any vendorsetup.sh files we can find.
-for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null` \
-         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null`
+for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
+         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
 do
     echo "including $f"
     . $f
diff --git a/libs/host/Android.mk b/libs/host/Android.mk
index cab878b..821f9b8 100644
--- a/libs/host/Android.mk
+++ b/libs/host/Android.mk
@@ -5,9 +5,6 @@
 LOCAL_SRC_FILES:= \
     CopyFile.c
 
-ifeq ($(HOST_OS),cygwin)
-LOCAL_CFLAGS += -DWIN32_EXE
-endif
 ifeq ($(HOST_OS),darwin)
 LOCAL_CFLAGS += -DMACOSX_RSRC
 endif
@@ -16,13 +13,12 @@
 
 LOCAL_MODULE:= libhost
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_CXX_STL := none
 
 # acp uses libhost, so we can't use
 # acp to install libhost.
 LOCAL_ACP_UNAVAILABLE:= true
 
-LOCAL_ADDRESS_SANITIZER := false
-
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 # Include toolchain prebuilt modules if they exist.
diff --git a/libs/host/CopyFile.c b/libs/host/CopyFile.c
index 855a565..b2a3e7f 100644
--- a/libs/host/CopyFile.c
+++ b/libs/host/CopyFile.c
@@ -24,11 +24,8 @@
 #include <errno.h>
 #include <assert.h>
 
-#ifdef HAVE_MS_C_RUNTIME
-#  define  mkdir(path,mode)   _mkdir(path)
-#endif
-
 #if defined(_WIN32)
+#  define mkdir(path,mode)   _mkdir(path)
 #  define S_ISLNK(s) 0
 #  define lstat stat
 #  ifndef EACCESS   /* seems to be missing from the Mingw headers */
@@ -183,7 +180,7 @@
             DBUG(("---   unable to set perms on '%s' to 0%o: %s\n",
                 dst, pSrcStat->st_mode & ~(S_IFMT), strerror(errno)));
         }
-#ifndef HAVE_MS_C_RUNTIME
+#ifndef _WIN32
         /*
          * Set the owner.
          */
@@ -261,7 +258,7 @@
         /* if "force" is set, try removing the destination file and retry */
         if (options & COPY_FORCE) {
             if (unlink(dst) != 0) {
-#ifdef HAVE_MS_C_RUNTIME
+#ifdef _WIN32
 				/* MSVCRT.DLL unlink will fail with EACCESS if the file is set read-only */
 				/* so try to change its mode, and unlink again                           */
 				if (errno == EACCESS) {
@@ -274,7 +271,7 @@
                 (void) close(srcFd);
                 return -1;
             }
-#ifdef HAVE_MS_C_RUNTIME
+#ifdef _WIN32
         Open_File:
 #endif			
             dstFd = open(dst, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
@@ -546,57 +543,6 @@
         statResult = stat(src, &srcStat);
     statErrno = errno;        /* preserve across .exe attempt */
 
-#ifdef WIN32_EXE
-    /*
-     * Here's the interesting part.  Under Cygwin, if you have a file
-     * called "foo.exe", stat("foo", ...) will succeed, but open("foo", ...)
-     * will fail.  We need to figure out what its name is supposed to be
-     * so we can create the correct destination file.
-     *
-     * If we don't have the "-e" flag set, we want "acp foo bar" to fail,
-     * not automatically find "foo.exe".  That way, if we really were
-     * trying to copy "foo", it doesn't grab something we don't want.
-     */
-    if (isCmdLine && statResult == 0) {
-        int tmpFd;
-        tmpFd = open(src, O_RDONLY | O_BINARY, 0);
-        if (tmpFd < 0) {
-            statResult = -1;
-            statErrno = ENOENT;
-        } else {
-            (void) close(tmpFd);
-        }
-    }
-
-    /*
-     * If we didn't find the file, try it again with ".exe".
-     */
-    if (isCmdLine && statResult < 0 && statErrno == ENOENT && (options & COPY_TRY_EXE)) {
-        srcExe = malloc(strlen(src) + 4 +1);
-        strcpy(srcExe, src);
-        strcat(srcExe, ".exe");
-
-        if (options & COPY_NO_DEREFERENCE)
-            statResult = lstat(srcExe, &srcStat);
-        else
-            statResult = stat(srcExe, &srcStat);
-
-        if (statResult == 0 && !S_ISREG(srcStat.st_mode))
-            statResult = -1;        /* fail, use original statErrno below */
-
-        if (statResult == 0) {
-            /* found a .exe, copy that instead */
-            dstExe = malloc(strlen(dst) + 4 +1);
-            strcpy(dstExe, dst);
-            strcat(dstExe, ".exe");
-
-            src = srcExe;
-            dst = dstExe;
-        } else {
-            DBUG(("---  couldn't find '%s' either\n", srcExe));
-        }
-    }
-#endif
     if (statResult < 0) {
         if (statErrno == ENOENT)
             fprintf(stderr, "acp: file '%s' does not exist\n", src);
diff --git a/libs/host/include/host/Directories.h b/libs/host/include/host/Directories.h
deleted file mode 100644
index fccce46..0000000
--- a/libs/host/include/host/Directories.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef HOST_MKDIRS_H
-#define HOST_MKDIRS_H
-
-#include <string>
-
-std::string parent_dir(const std::string& path);
-
-extern "C" int mkdirs(const char* path);
-
-#endif // HOST_MKDIRS_H
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index e06c985..393492b 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -76,22 +76,6 @@
 TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
 
 BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
-BOARD_SEPOLICY_UNION += \
-        bootanim.te \
-        device.te \
-        domain.te \
-        file.te \
-        file_contexts \
-        goldfish_setup.te \
-        goldfish_logcat.te \
-        property.te \
-        property_contexts \
-        qemu_props.te \
-        qemud.te \
-        rild.te \
-        shell.te \
-        surfaceflinger.te \
-        system_server.te
 
 ifeq ($(TARGET_PRODUCT),sdk)
   # include an expanded selection of fonts for the SDK.
diff --git a/target/board/generic/sepolicy/file_contexts b/target/board/generic/sepolicy/file_contexts
index 444a47f..e626d9d 100644
--- a/target/board/generic/sepolicy/file_contexts
+++ b/target/board/generic/sepolicy/file_contexts
@@ -1,9 +1,12 @@
-/dev/block/mtdblock0       u:object_r:system_block_device:s0
-/dev/block/mtdblock1       u:object_r:userdata_block_device:s0
-/dev/block/mtdblock2       u:object_r:cache_block_device:s0
-/dev/qemu_.*		u:object_r:qemu_device:s0
-/dev/socket/qemud	u:object_r:qemud_socket:s0
-/system/bin/qemud	u:object_r:qemud_exec:s0
-/sys/qemu_trace(/.*)?	--	u:object_r:sysfs_writable:s0
+/dev/block/mtdblock0         u:object_r:system_block_device:s0
+/dev/block/mtdblock1         u:object_r:userdata_block_device:s0
+/dev/block/mtdblock2         u:object_r:cache_block_device:s0
+/dev/goldfish_pipe           u:object_r:qemu_device:s0
+/dev/qemu_.*                 u:object_r:qemu_device:s0
+/dev/socket/qemud            u:object_r:qemud_socket:s0
+/dev/ttyGF[0-9]*             u:object_r:serial_device:s0
+/dev/ttyS2                   u:object_r:console_device:s0
+/system/bin/qemud            u:object_r:qemud_exec:s0
+/sys/qemu_trace(/.*)?   --   u:object_r:sysfs_writable:s0
 /system/etc/init.goldfish.sh u:object_r:goldfish_setup_exec:s0
-/system/bin/qemu-props	     u:object_r:qemu_props_exec:s0
+/system/bin/qemu-props       u:object_r:qemu_props_exec:s0
diff --git a/target/board/generic/sepolicy/goldfish_logcat.te b/target/board/generic/sepolicy/goldfish_logcat.te
deleted file mode 100644
index a785355..0000000
--- a/target/board/generic/sepolicy/goldfish_logcat.te
+++ /dev/null
@@ -1,10 +0,0 @@
-# goldfish-logcat service:  runs logcat -Q
-type goldfish_logcat, domain;
-
-domain_auto_trans(init, logcat_exec, goldfish_logcat)
-
-# Read from logd.
-read_logd(goldfish_logcat)
-
-# Write to /dev/ttyS2
-allow goldfish_logcat serial_device:chr_file { write open };
diff --git a/target/board/generic/sepolicy/goldfish_setup.te b/target/board/generic/sepolicy/goldfish_setup.te
index 584731e..3fb79e7 100644
--- a/target/board/generic/sepolicy/goldfish_setup.te
+++ b/target/board/generic/sepolicy/goldfish_setup.te
@@ -13,6 +13,12 @@
 allow goldfish_setup self:udp_socket create_socket_perms;
 
 # Set net.eth0.dns*, debug.sf.nobootanimation
-unix_socket_connect(goldfish_setup, property, init)
-allow goldfish_setup system_prop:property_service set;
-allow goldfish_setup debug_prop:property_service set;
+set_prop(goldfish_setup, system_prop)
+set_prop(goldfish_setup, debug_prop)
+
+# Set ro.radio.noril
+set_prop(goldfish_setup, radio_noril_prop)
+
+# Stop ril-daemon service (by setting ctl.stop to ril-daemon, which
+# transforms to a permission check on ctl.ril-daemon).
+set_prop(goldfish_setup, ctl_rildaemon_prop)
diff --git a/target/board/generic/sepolicy/logd.te b/target/board/generic/sepolicy/logd.te
new file mode 100644
index 0000000..b3e60d7
--- /dev/null
+++ b/target/board/generic/sepolicy/logd.te
@@ -0,0 +1,11 @@
+# goldfish logcat service:  runs logcat -Q in logd domain
+
+# See global logd.te, these only set for eng & userdebug, allow for all builds
+
+domain_auto_trans(init, logcat_exec, logd)
+
+# Read from logd.
+read_logd(logd)
+
+# Write to /dev/ttyS2 and /dev/ttyGF2.
+allow logd serial_device:chr_file { write open };
diff --git a/target/board/generic/sepolicy/property.te b/target/board/generic/sepolicy/property.te
index b3d15f8..b316d08 100644
--- a/target/board/generic/sepolicy/property.te
+++ b/target/board/generic/sepolicy/property.te
@@ -1 +1,2 @@
 type qemu_prop, property_type;
+type radio_noril_prop, property_type;
diff --git a/target/board/generic/sepolicy/property_contexts b/target/board/generic/sepolicy/property_contexts
index 5f741f8..09b9b06 100644
--- a/target/board/generic/sepolicy/property_contexts
+++ b/target/board/generic/sepolicy/property_contexts
@@ -1 +1,2 @@
 qemu.                   u:object_r:qemu_prop:s0
+radio.noril             u:object_r:radio_noril_prop:s0
diff --git a/target/board/generic/sepolicy/qemu_props.te b/target/board/generic/sepolicy/qemu_props.te
index 05c7461..4a91c4c 100644
--- a/target/board/generic/sepolicy/qemu_props.te
+++ b/target/board/generic/sepolicy/qemu_props.te
@@ -5,5 +5,6 @@
 init_daemon_domain(qemu_props)
 
 # Set properties.
-unix_socket_connect(qemu_props, property, init)
-allow qemu_props { qemu_prop dalvik_prop config_prop }:property_service set;
+set_prop(qemu_props, qemu_prop)
+set_prop(qemu_props, dalvik_prop)
+set_prop(qemu_props, config_prop)
diff --git a/target/board/generic/sepolicy/qemud.te b/target/board/generic/sepolicy/qemud.te
index 41f2065..eee21c4 100644
--- a/target/board/generic/sepolicy/qemud.te
+++ b/target/board/generic/sepolicy/qemud.te
@@ -4,5 +4,5 @@
 
 init_daemon_domain(qemud)
 
-# Access /dev/ttyS1.
+# Access /dev/ttyS1 and /dev/ttyGF1.
 allow qemud serial_device:chr_file rw_file_perms;
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index 8afd5a8..0c4d59c 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -76,9 +76,11 @@
 USE_OPENGL_RENDERER := true
 
 TARGET_USERIMAGES_USE_EXT4 := true
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 943718400
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1258291200
 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/board/generic_mips/BoardConfig.mk b/target/board/generic_mips/BoardConfig.mk
index ff5a4e4..13d1c9f 100644
--- a/target/board/generic_mips/BoardConfig.mk
+++ b/target/board/generic_mips/BoardConfig.mk
@@ -53,7 +53,7 @@
 USE_OPENGL_RENDERER := true
 
 TARGET_USERIMAGES_USE_EXT4 := true
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 838860800
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1073741824
 BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
 BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
 BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
@@ -61,19 +61,3 @@
 TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
 
 BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
-BOARD_SEPOLICY_UNION += \
-        bootanim.te \
-        device.te \
-        domain.te \
-        file.te \
-        file_contexts \
-        goldfish_setup.te \
-        goldfish_logcat.te \
-        property.te \
-        property_contexts \
-        qemu_props.te \
-        qemud.te \
-        rild.te \
-        shell.te \
-        surfaceflinger.te \
-        system_server.te
diff --git a/target/board/generic_mips64/BoardConfig.mk b/target/board/generic_mips64/BoardConfig.mk
index 2097635..8e8a68b 100644
--- a/target/board/generic_mips64/BoardConfig.mk
+++ b/target/board/generic_mips64/BoardConfig.mk
@@ -65,9 +65,13 @@
 USE_OPENGL_RENDERER := true
 
 TARGET_USERIMAGES_USE_EXT4 := true
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1101004800
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 734003200
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1342177280  # 1.25 GB swag, 20% more than before
+BOARD_USERDATAIMAGE_PARTITION_SIZE := 1610612736  # 1.5 GB, lots of space for running tests
 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
+
+DEX_PREOPT_DEFAULT := nostripping
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 78b7590..d5f0531 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -45,21 +45,3 @@
 BOARD_SEPOLICY_DIRS += \
         build/target/board/generic/sepolicy \
         build/target/board/generic_x86/sepolicy
-
-BOARD_SEPOLICY_UNION += \
-        device.te \
-        domain.te \
-        file.te \
-        file_contexts \
-        healthd.te \
-        installd.te \
-        goldfish_setup.te \
-        goldfish_logcat.te \
-        property.te \
-        property_contexts \
-        qemu_props.te \
-        qemud.te \
-        rild.te \
-        shell.te \
-        system_server.te \
-        zygote.te
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
index 295ee2b..62753a2 100755
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -47,3 +47,7 @@
 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 \
+        build/target/board/generic_x86/sepolicy
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index ac5902c..69edc72 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -59,7 +59,6 @@
     $(LOCAL_DIR)/aosp_arm64.mk \
     $(LOCAL_DIR)/aosp_mips64.mk \
     $(LOCAL_DIR)/aosp_x86_64.mk \
-    $(LOCAL_DIR)/full_x86_64.mk \
     $(LOCAL_DIR)/sdk_phone_armv7.mk \
     $(LOCAL_DIR)/sdk_phone_x86.mk \
     $(LOCAL_DIR)/sdk_phone_mips.mk \
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index ea8ec06..6232295 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -19,6 +19,12 @@
 # build quite specifically for the emulator, and might not be
 # entirely appropriate to inherit from for on-device configurations.
 
+# This is for enabling ethernet support for ranchu.
+# Consider removing this after RIL support is provided in ranchu.
+# Having this permission file on the target requires additional
+# dhcpcd_eth0 service defined in the init.ranchu.rc.
+PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.ethernet.xml:system/etc/permissions/android.hardware.ethernet.xml
+
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
diff --git a/target/product/aosp_mips64.mk b/target/product/aosp_mips64.mk
index 3a6026c..d485677 100644
--- a/target/product/aosp_mips64.mk
+++ b/target/product/aosp_mips64.mk
@@ -13,6 +13,26 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-$(call inherit-product, $(SRC_TARGET_DIR)/product/full_mips64.mk)
 
+# This is a build configuration for a full-featured build of the
+# Open-Source part of the tree. It's geared toward a US-centric
+# mips64 build quite specifically for the emulator, and might not be
+# entirely appropriate to inherit from for on-device configurations.
+
+# This is for enabling ethernet support for ranchu.
+# Consider removing this after RIL support is provided in ranchu.
+# Having this permission file on the target requires additional
+# dhcpcd_eth0 service defined in the init.ranchu.rc.
+PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.ethernet.xml:system/etc/permissions/android.hardware.ethernet.xml
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_mips64/device.mk)
+
+include $(SRC_TARGET_DIR)/product/emulator.mk
+
+# Overrides
 PRODUCT_NAME := aosp_mips64
+PRODUCT_DEVICE := generic_mips64
+PRODUCT_BRAND := Android
+PRODUCT_MODEL := AOSP on MIPS64 Emulator
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index 5a12c08..6c01e5a 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -13,6 +13,39 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-$(call inherit-product, $(SRC_TARGET_DIR)/product/full_x86_64.mk)
 
+# This is a build configuration for a full-featured build of the
+# Open-Source part of the tree. It's geared toward a US-centric
+# build quite specifically for the emulator, and might not be
+# entirely appropriate to inherit from for on-device configurations.
+
+# If running on an emulator or some other device that has a LAN connection
+# that isn't a wifi connection. This will instruct init.rc to enable the
+# network connection so that you can use it with ADB
+
+# This is for enabling ethernet support for ranchu.
+# Consider removing this after RIL support is provided in ranchu.
+# Having this permission file on the target requires additional
+# dhcpcd_eth0 service defined in the init.ranchu.rc.
+PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.ethernet.xml:system/etc/permissions/android.hardware.ethernet.xml
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
+
+include $(SRC_TARGET_DIR)/product/emulator.mk
+
+ifdef NET_ETH0_STARTONBOOT
+  PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
+endif
+
+# Ensure we package the BIOS files too.
+PRODUCT_PACKAGES += \
+	bios.bin \
+	vgabios-cirrus.bin \
+
+# Overrides
 PRODUCT_NAME := aosp_x86_64
+PRODUCT_DEVICE := generic_x86_64
+PRODUCT_BRAND := Android
+PRODUCT_MODEL := AOSP on IA x86_64 Emulator
diff --git a/target/product/base.mk b/target/product/base.mk
index 0d052b5..85c01a2 100644
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -95,7 +95,6 @@
     monkey \
     mtpd \
     ndc \
-    netcfg \
     netd \
     ping \
     ping6 \
diff --git a/target/product/core.mk b/target/product/core.mk
index 519dbb8..d32acbc 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -22,7 +22,8 @@
 
 PRODUCT_PACKAGES += \
     BasicDreams \
-    Browser \
+    BookmarkProvider \
+    Browser2 \
     Calculator \
     Calendar \
     CalendarProvider \
diff --git a/target/product/core_base.mk b/target/product/core_base.mk
index 6c29482..03d33e1 100644
--- a/target/product/core_base.mk
+++ b/target/product/core_base.mk
@@ -41,13 +41,14 @@
     libstagefright_soft_amrdec \
     libstagefright_soft_amrnbenc \
     libstagefright_soft_amrwbenc \
+    libstagefright_soft_avcdec \
+    libstagefright_soft_avcenc \
     libstagefright_soft_flacenc \
     libstagefright_soft_g711dec \
     libstagefright_soft_gsmdec \
-    libstagefright_soft_h264dec \
-    libstagefright_soft_h264enc \
     libstagefright_soft_hevcdec \
     libstagefright_soft_mp3dec \
+    libstagefright_soft_mpeg2dec \
     libstagefright_soft_mpeg4dec \
     libstagefright_soft_mpeg4enc \
     libstagefright_soft_opusdec \
diff --git a/target/product/embedded.mk b/target/product/embedded.mk
index 96c0b77..468fbe5 100644
--- a/target/product/embedded.mk
+++ b/target/product/embedded.mk
@@ -25,6 +25,7 @@
     debuggerd \
     dumpstate \
     dumpsys \
+    fastboot \
     gralloc.default \
     grep \
     gzip \
@@ -51,7 +52,6 @@
     libpower \
     libsigchain \
     libstdc++ \
-    libstlport \
     libsurfaceflinger \
     libsurfaceflinger_ddmconnection \
     libsysutils \
@@ -70,11 +70,12 @@
     surfaceflinger \
     toolbox \
     toybox \
+    tzdatacheck \
 
 # SELinux packages
 PRODUCT_PACKAGES += \
     sepolicy \
-    file_contexts \
+    file_contexts.bin \
     seapp_contexts \
     property_contexts \
     mac_permissions.xml \
diff --git a/target/product/full_base.mk b/target/product/full_base.mk
index d8dad79..3004002 100644
--- a/target/product/full_base.mk
+++ b/target/product/full_base.mk
@@ -46,9 +46,6 @@
 # Put en_US first in the list, so make it default.
 PRODUCT_LOCALES := en_US
 
-# Include drawables for all densities
-PRODUCT_AAPT_CONFIG := normal
-
 # Get some sounds
 $(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
 
diff --git a/target/product/full_base_telephony.mk b/target/product/full_base_telephony.mk
index 2fd2ce8..9a2c63a 100644
--- a/target/product/full_base_telephony.mk
+++ b/target/product/full_base_telephony.mk
@@ -19,9 +19,6 @@
 # build quite specifically for the emulator, and might not be
 # entirely appropriate to inherit from for on-device configurations.
 
-PRODUCT_PACKAGES := \
-    VoiceDialer
-
 PRODUCT_PROPERTY_OVERRIDES := \
     keyguard.no_require_sim=true \
     ro.com.android.dataroaming=true
diff --git a/target/product/full_mips64.mk b/target/product/full_mips64.mk
deleted file mode 100644
index e813e41..0000000
--- a/target/product/full_mips64.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2013 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 a build configuration for a full-featured build of the
-# Open-Source part of the tree. It's geared toward a US-centric
-# mips64 build quite specifically for the emulator, and might not be
-# entirely appropriate to inherit from for on-device configurations.
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_mips64/device.mk)
-
-include $(SRC_TARGET_DIR)/product/emulator.mk
-
-# Overrides
-PRODUCT_NAME := full_mips64
-PRODUCT_DEVICE := generic_mips64
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on MIPS64 Emulator
diff --git a/target/product/full_x86_64.mk b/target/product/full_x86_64.mk
deleted file mode 100755
index 051a86e..0000000
--- a/target/product/full_x86_64.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# 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 a build configuration for a full-featured build of the
-# Open-Source part of the tree. It's geared toward a US-centric
-# build quite specifically for the emulator, and might not be
-# entirely appropriate to inherit from for on-device configurations.
-
-# If running on an emulator or some other device that has a LAN connection
-# that isn't a wifi connection. This will instruct init.rc to enable the
-# network connection so that you can use it with ADB
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
-
-include $(SRC_TARGET_DIR)/product/emulator.mk
-
-ifdef NET_ETH0_STARTONBOOT
-  PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
-endif
-
-# Ensure we package the BIOS files too.
-PRODUCT_PACKAGES += \
-	bios.bin \
-	vgabios-cirrus.bin \
-
-# Overrides
-PRODUCT_NAME := full_x86_64
-PRODUCT_DEVICE := generic_x86_64
-PRODUCT_BRAND := Android
-PRODUCT_MODEL := AOSP on IA x86_64 Emulator
diff --git a/tools/acp/Android.mk b/tools/acp/Android.mk
index 2b41bc1..e31ad3a 100644
--- a/tools/acp/Android.mk
+++ b/tools/acp/Android.mk
@@ -9,9 +9,6 @@
 LOCAL_SRC_FILES := \
     acp.c
 
-ifeq ($(HOST_OS),cygwin)
-LOCAL_CFLAGS += -DWIN32_EXE
-endif
 ifeq ($(HOST_OS),darwin)
 LOCAL_CFLAGS += -DMACOSX_RSRC
 endif
@@ -23,6 +20,5 @@
 LOCAL_MODULE := acp
 LOCAL_ACP_UNAVAILABLE := true
 LOCAL_CXX_STL := none
-LOCAL_ADDRESS_SANITIZER := false
 
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh
index dcd9ab5..910894d 100755
--- a/tools/buildinfo.sh
+++ b/tools/buildinfo.sh
@@ -10,13 +10,16 @@
 echo "ro.build.version.codename=$PLATFORM_VERSION_CODENAME"
 echo "ro.build.version.all_codenames=$PLATFORM_VERSION_ALL_CODENAMES"
 echo "ro.build.version.release=$PLATFORM_VERSION"
-echo "ro.build.date=`date`"
-echo "ro.build.date.utc=`date +%s`"
+echo "ro.build.date=`$DATE`"
+echo "ro.build.date.utc=`$DATE +%s`"
 echo "ro.build.type=$TARGET_BUILD_TYPE"
 echo "ro.build.user=$USER"
 echo "ro.build.host=`hostname`"
 echo "ro.build.tags=$BUILD_VERSION_TAGS"
 echo "ro.build.flavor=$TARGET_BUILD_FLAVOR"
+if [ -n "$BOARD_BUILD_SYSTEM_ROOT_IMAGE" ] ; then
+  echo "ro.build.system_root_image=$BOARD_BUILD_SYSTEM_ROOT_IMAGE"
+fi
 echo "ro.product.model=$PRODUCT_MODEL"
 echo "ro.product.brand=$PRODUCT_BRAND"
 echo "ro.product.name=$PRODUCT_NAME"
diff --git a/tools/droiddoc/templates-sac/assets/css/default.css b/tools/droiddoc/templates-sac/assets/css/default.css
index c1a0c19..3e4b539 100644
--- a/tools/droiddoc/templates-sac/assets/css/default.css
+++ b/tools/droiddoc/templates-sac/assets/css/default.css
@@ -408,7 +408,7 @@
 .content-header.just-links {
   margin-bottom:0;
   padding-bottom:0;}
-    
+ 
 .content-header h1 {
   color:#000;
   margin:0;
@@ -420,8 +420,12 @@
   border-top: 1px solid #ccc;
   margin-top: 10px;
   padding-top:10px;
-  height: 30px; }
+  height: 30px;
+}
 
+.content-footer-sac {
+  border-top: 1px solid #ccc;
+}
 .content-footer .col-9 {
   margin-left:0;
 }
@@ -4457,6 +4461,11 @@
   float:right;
 }
 
+.feedback {
+  float:right !important;
+  margin: 0 0 0 10px;
+  font-size: 14px;
+}
 
 
 /************* HOME/LANDING PAGE *****************/
diff --git a/tools/droiddoc/templates-sac/customizations.cs b/tools/droiddoc/templates-sac/customizations.cs
index 6bdfe36..e489b63 100644
--- a/tools/droiddoc/templates-sac/customizations.cs
+++ b/tools/droiddoc/templates-sac/customizations.cs
@@ -355,7 +355,7 @@
 def:custom_footerlinks() ?>
   <p>
     <a href="<?cs var:toroot ?>source/index.html">About Android</a>&nbsp;&nbsp;|&nbsp;
-    <a href="<?cs var:toroot ?>source/community/index.html">Community</a>&nbsp;&nbsp;|&nbsp;
+    <a href="<?cs var:toroot ?>source/community.html">Community</a>&nbsp;&nbsp;|&nbsp;
     <a href="<?cs var:toroot ?>legal.html">Legal</a>&nbsp;&nbsp;|&nbsp;
   </p><?cs 
 /def ?>
diff --git a/tools/droiddoc/templates-sac/docpage.cs b/tools/droiddoc/templates-sac/docpage.cs
index 3e5c24f..3d120b6 100644
--- a/tools/droiddoc/templates-sac/docpage.cs
+++ b/tools/droiddoc/templates-sac/docpage.cs
@@ -34,7 +34,7 @@
             ru-lang="Предыдущий"
             ko-lang="이전"
             ja-lang="前へ"
-            es-lang="Anterior"               
+            es-lang="Anterior"
             >Previous</a>
         <a href="#" class="next-page-link hide"
             zh-TW-lang="下一堂課"
@@ -42,7 +42,7 @@
             ru-lang="Следующий"
             ko-lang="다음"
             ja-lang="次へ"
-            es-lang="Siguiente"               
+            es-lang="Siguiente"
             >Next</a>
         <a href="#" class="start-class-link hide"
             zh-TW-lang="開始上課"
@@ -50,7 +50,7 @@
             ru-lang="Начало работы"
             ko-lang="시작하기"
             ja-lang="開始する"
-            es-lang="Empezar"               
+            es-lang="Empezar"
             >Get started</a>
       </div>
     <?cs elif:!page.trainingcourse ?>
@@ -61,7 +61,7 @@
             ru-lang="Предыдущий"
             ko-lang="이전"
             ja-lang="前へ"
-            es-lang="Anterior"               
+            es-lang="Anterior"
             >Previous</a>
         <a href="#" class="next-page-link hide"
             zh-TW-lang="下一堂課"
@@ -69,7 +69,7 @@
             ru-lang="Следующий"
             ko-lang="다음"
             ja-lang="次へ"
-            es-lang="Siguiente"               
+            es-lang="Siguiente"
             >Next</a>
       </div>
     <?cs /if ?><?cs # end if training ?>
@@ -87,7 +87,6 @@
         <?cs /if ?>
           <h1 itemprop="name" style="margin-bottom:0;"><?cs var:page.title ?></h1>
           <p itemprop="description"><?cs var:page.landing.intro ?></p>
-          
           <p><a class="next-page-link topic-start-link"></a></p>
         <?cs if:page.landing.image ?>
         </div>
@@ -112,22 +111,16 @@
   <?cs # THIS IS THE MAIN DOC CONTENT ?>
   <div id="jd-content">
 
-
     <div class="jd-descr" itemprop="articleBody">
     <?cs call:tag_list(root.descr) ?>
     </div>
-      
-      <div class="content-footer <?cs 
-                    if:fullpage ?>wrap<?cs
-                    else ?>layout-content-row<?cs /if ?>" 
+
+      <div class="content-footer-sac"
                     itemscope itemtype="http://schema.org/SiteNavigationElement">
         <div class="layout-content-col <?cs 
                     if:fullpage ?>col-16<?cs 
                     elif:training||guide ?>col-8<?cs 
                     else ?>col-9<?cs /if ?>" style="padding-top:4px">
-          <?cs if:!page.noplus ?><?cs if:fullpage ?><style>#___plusone_0 {float:right !important;}</style><?cs /if ?>
-            <div class="g-plusone" data-size="medium"></div>
-          <?cs /if ?>
         </div>
         <?cs if:!fullscreen ?>
         <div class="paging-links layout-content-col col-4">
@@ -138,7 +131,7 @@
                 ru-lang="Предыдущий"
                 ko-lang="이전"
                 ja-lang="前へ"
-                es-lang="Anterior"               
+                es-lang="Anterior"
                 >Previous</a>
             <a href="#" class="next-page-link hide"
                 zh-TW-lang="下一堂課"
@@ -146,23 +139,20 @@
                 ru-lang="Следующий"
                 ko-lang="다음"
                 ja-lang="次へ"
-                es-lang="Siguiente"               
+                es-lang="Siguiente"
                 >Next</a>
           <?cs /if ?>
         </div>
         <?cs /if ?>
       </div>
-      
       <?cs # for training classes, provide a different kind of link when the next page is a different class ?>
       <?cs if:training && !page.article ?>
       <div class="layout-content-row content-footer next-class" style="display:none" itemscope itemtype="http://schema.org/SiteNavigationElement">
           <a href="#" class="next-class-link hide">Next class: </a>
       </div>
       <?cs /if ?>
-
-  </div> <!-- end jd-content -->
-
-<?cs include:"footer.cs" ?>
+    </div> <!-- end jd-content -->
+  <?cs include:"footer.cs" ?>
 </div><!-- end doc-content -->
 
 <?cs include:"trailer.cs" ?>
diff --git a/tools/droiddoc/templates-sac/footer.cs b/tools/droiddoc/templates-sac/footer.cs
index 6979ca0..ea22605 100644
--- a/tools/droiddoc/templates-sac/footer.cs
+++ b/tools/droiddoc/templates-sac/footer.cs
@@ -1,4 +1,9 @@
 <div id="footer" class="wrap" <?cs if:fullpage ?>style="width:940px"<?cs /if ?>>
+  <style>.feedback { float: right !Important }</style>
+  <div class="feedback">
+    <a href="#" class="button" onclick=" try {
+      userfeedback.api.startFeedback({'productId':'715571','authuser':'1'});return false;}catch(e){}">Send Feedback</a>
+  </div>
   <div id="copyright">
     <?cs call:custom_cc_copyright() ?>
   </div>
diff --git a/tools/droiddoc/templates-sac/head_tag.cs b/tools/droiddoc/templates-sac/head_tag.cs
index 9fca488..b672b25 100644
--- a/tools/droiddoc/templates-sac/head_tag.cs
+++ b/tools/droiddoc/templates-sac/head_tag.cs
@@ -7,7 +7,7 @@
 <title><?cs 
   if:page.title ?><?cs 
     var:page.title ?> | <?cs
-  /if ?>Android Developers</title>
+  /if ?>Android Open Source Project</title>
 
 <!-- STYLESHEETS -->
 <link rel="stylesheet"
@@ -46,6 +46,8 @@
 <script src="<?cs var:toroot ?>navtree_data.js" async type="text/javascript"></script>
 <?cs /if ?>
 
+<script type="text/javascript" src="//www.gstatic.com/feedback/api.js"></script>
+
 <script type="text/javascript">
   var _gaq = _gaq || [];
   _gaq.push(['_setAccount', 'UA-45455297-1']);
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
index 02deabb..34a3522 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -13,11 +13,73 @@
 # limitations under the License.
 
 LOCAL_PATH := $(call my-dir)
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := fs_config.c
 LOCAL_MODULE := fs_config
-LOCAL_STATIC_LIBRARIES := libselinux
-LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SHARED_LIBRARIES := libcutils libselinux
+LOCAL_CFLAGS := -Werror
 
 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
+ANDROID_FS_CONFIG_H := android_filesystem_config.h
+
+ifneq ($(TARGET_ANDROID_FILESYSTEM_CONFIG_H),)
+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))".)
+endif
+
+my_fs_config_h := $(TARGET_ANDROID_FILESYSTEM_CONFIG_H)
+else ifneq ($(wildcard $(TARGET_DEVICE_DIR)/$(ANDROID_FS_CONFIG_H)),)
+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_SHARED_LIBRARIES := libcutils
+LOCAL_CFLAGS := -Werror -Wno-error=\#warnings
+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)
+
+LOCAL_MODULE := fs_config_dirs
+LOCAL_MODULE_CLASS := ETC
+include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+	@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)
+
+LOCAL_MODULE := fs_config_files
+LOCAL_MODULE_CLASS := ETC
+include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE): $(fs_config_generate_bin)
+	@mkdir -p $(dir $@)
+	$< -F -o $@
+
+ANDROID_FS_CONFIG_H :=
+my_fs_config_h :=
+fs_config_generate_bin :=
diff --git a/tools/fs_config/default/android_filesystem_config.h b/tools/fs_config/default/android_filesystem_config.h
new file mode 100644
index 0000000..820b04a
--- /dev/null
+++ b/tools/fs_config/default/android_filesystem_config.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This file is used to enhance the properties of the filesystem
+** images generated by build tools (mkbootfs and mkyaffs2image) and
+** by the device side of adb.
+*/
+
+/*
+** Resorting to the default file means someone requested fs_config_dirs or
+** fs_config_files in their device configuration without providing an
+** associated header.
+*/
+#warning No device-supplied android_filesystem_config.h, using empty default.
+
+/* Rules for directories.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root.
+*/
+
+#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS 1 /* opt out of specifying */
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+
+#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES 1 /* opt out of specifying */
diff --git a/tools/fs_config/fs_config.c b/tools/fs_config/fs_config.c
index f594c1e..fac3d93 100644
--- a/tools/fs_config/fs_config.c
+++ b/tools/fs_config/fs_config.c
@@ -24,7 +24,6 @@
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
-#include <selinux/android.h>
 
 #include "private/android_filesystem_config.h"
 
diff --git a/tools/fs_config/fs_config_generate.c b/tools/fs_config/fs_config_generate.c
new file mode 100644
index 0000000..c06213f
--- /dev/null
+++ b/tools/fs_config/fs_config_generate.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <private/android_filesystem_config.h>
+
+/*
+ * This program expects android_device_dirs and android_device_files
+ * to be defined in the supplied android_filesystem_config.h file in
+ * the device/<vendor>/<product> $(TARGET_DEVICE_DIR). Then generates
+ * the binary format used in the /system/etc/fs_config_dirs and
+ * the /system/etc/fs_config_files to be used by the runtimes.
+ */
+#include "android_filesystem_config.h"
+
+#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+  static const struct fs_path_config android_device_dirs[] = {
+};
+#endif
+
+#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES
+static const struct fs_path_config android_device_files[] = {
+#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+    { 0, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" },
+#endif
+    { 0, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_files" },
+};
+#endif
+
+static void usage() {
+  fprintf(stderr,
+    "Generate binary content for fs_config_dirs (-D) and fs_config_files (-F)\n"
+    "from device-specific android_filesystem_config.h override\n\n"
+    "Usage: fs_config_generate -D|-F [-o output-file]\n");
+}
+
+int main(int argc, char** argv) {
+  const struct fs_path_config *pc;
+  const struct fs_path_config *end;
+  bool dir = false, file = false;
+  FILE *fp = stdout;
+  int opt;
+
+  while((opt = getopt(argc, argv, "DFho:")) != -1) {
+    switch(opt) {
+    case 'D':
+      if (file) {
+        fprintf(stderr, "Must specify only -D or -F\n");
+        usage();
+        exit(EXIT_FAILURE);
+      }
+      dir = true;
+      break;
+    case 'F':
+      if (dir) {
+        fprintf(stderr, "Must specify only -F or -D\n");
+        usage();
+        exit(EXIT_FAILURE);
+      }
+      file = true;
+      break;
+    case 'o':
+      if (fp != stdout) {
+        fprintf(stderr, "Specify only one output file\n");
+        usage();
+        exit(EXIT_FAILURE);
+      }
+      fp = fopen(optarg, "wb");
+      if (fp == NULL) {
+        fprintf(stderr, "Can not open \"%s\"\n", optarg);
+        exit(EXIT_FAILURE);
+      }
+      break;
+    case 'h':
+      usage();
+      exit(EXIT_SUCCESS);
+    default:
+      usage();
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if (!file && !dir) {
+    fprintf(stderr, "Must specify either -F or -D\n");
+    usage();
+    exit(EXIT_FAILURE);
+  }
+
+  if (dir) {
+    pc = android_device_dirs;
+    end = &android_device_dirs[sizeof(android_device_dirs) / sizeof(android_device_dirs[0])];
+  } else {
+    pc = android_device_files;
+    end = &android_device_files[sizeof(android_device_files) / sizeof(android_device_files[0])];
+  }
+  for(; (pc < end) && pc->prefix; pc++) {
+    char buffer[512];
+    ssize_t len = fs_config_generate(buffer, sizeof(buffer), pc);
+    if (len < 0) {
+      fprintf(stderr, "Entry too large\n");
+      exit(EXIT_FAILURE);
+    }
+    if (fwrite(buffer, 1, len, fp) != (size_t)len) {
+      fprintf(stderr, "Write failure\n");
+      exit(EXIT_FAILURE);
+    }
+  }
+  fclose(fp);
+
+  return 0;
+}
diff --git a/tools/fs_get_stats/Android.mk b/tools/fs_get_stats/Android.mk
index c9b4a05..4501c1f 100644
--- a/tools/fs_get_stats/Android.mk
+++ b/tools/fs_get_stats/Android.mk
@@ -6,4 +6,6 @@
 
 LOCAL_MODULE := fs_get_stats
 
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/java-event-log-tags.py b/tools/java-event-log-tags.py
index 846d9cf..f364751 100755
--- a/tools/java-event-log-tags.py
+++ b/tools/java-event-log-tags.py
@@ -129,7 +129,7 @@
     out += "_"
   return out
 
-javaTypes = ["ERROR", "int", "long", "String", "Object[]"]
+javaTypes = ["ERROR", "int", "long", "String", "Object[]", "float"]
 for t in tagfile.tags:
   methodName = javaName("write_" + t.tagname)
   if t.description:
diff --git a/tools/post_process_props.py b/tools/post_process_props.py
index fa6106f..9dcaadf 100755
--- a/tools/post_process_props.py
+++ b/tools/post_process_props.py
@@ -37,11 +37,12 @@
   # (this is for userdebug builds)
   if prop.get("ro.debuggable") == "1":
     val = prop.get("persist.sys.usb.config")
-    if val == "":
-      val = "adb"
-    else:
-      val = val + ",adb"
-    prop.put("persist.sys.usb.config", val)
+    if "adb" not in val:
+      if val == "":
+        val = "adb"
+      else:
+        val = val + ",adb"
+      prop.put("persist.sys.usb.config", val)
   # UsbDeviceManager expects a value here.  If it doesn't get it, it will
   # default to "adb". That might not the right policy there, but it's better
   # to be explicit.
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index e98e4b6..bc2667d 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -30,16 +30,10 @@
 
 import errno
 import os
-import re
 import shutil
-import subprocess
 import tempfile
 import zipfile
 
-# missing in Python 2.4 and before
-if not hasattr(os, "SEEK_SET"):
-  os.SEEK_SET = 0
-
 import build_image
 import common
 
@@ -58,22 +52,20 @@
     return
 
   def output_sink(fn, data):
-     ofile = open(os.path.join(OPTIONS.input_tmp,"SYSTEM",fn), "w")
-     ofile.write(data)
-     ofile.close()
+    ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
+    ofile.write(data)
+    ofile.close()
 
   if OPTIONS.rebuild_recovery:
-    print("Building new recovery patch")
-    common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img, boot_img,
-                             info_dict=OPTIONS.info_dict)
+    print "Building new recovery patch"
+    common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
+                             boot_img, info_dict=OPTIONS.info_dict)
 
   block_list = common.MakeTempFile(prefix="system-blocklist-", suffix=".map")
   imgname = BuildSystem(OPTIONS.input_tmp, OPTIONS.info_dict,
                         block_list=block_list)
-  with open(imgname, "rb") as f:
-    common.ZipWriteStr(output_zip, prefix + "system.img", f.read())
-  with open(block_list, "rb") as f:
-    common.ZipWriteStr(output_zip, prefix + "system.map", f.read())
+  common.ZipWrite(output_zip, imgname, prefix + "system.img")
+  common.ZipWrite(output_zip, block_list, prefix + "system.map")
 
 
 def BuildSystem(input_dir, info_dict, block_list=None):
@@ -93,11 +85,9 @@
 
   block_list = common.MakeTempFile(prefix="vendor-blocklist-", suffix=".map")
   imgname = BuildVendor(OPTIONS.input_tmp, OPTIONS.info_dict,
-                     block_list=block_list)
-  with open(imgname, "rb") as f:
-    common.ZipWriteStr(output_zip, prefix + "vendor.img", f.read())
-  with open(block_list, "rb") as f:
-    common.ZipWriteStr(output_zip, prefix + "vendor.map", f.read())
+                        block_list=block_list)
+  common.ZipWrite(output_zip, imgname, prefix + "vendor.img")
+  common.ZipWrite(output_zip, block_list, prefix + "vendor.map")
 
 
 def BuildVendor(input_dir, info_dict, block_list=None):
@@ -117,18 +107,18 @@
   try:
     os.symlink(os.path.join(input_dir, what.upper()),
                os.path.join(input_dir, what))
-  except OSError, e:
-      # bogus error on my mac version?
-      #   File "./build/tools/releasetools/img_from_target_files", line 86, in AddSystem
-      #     os.path.join(OPTIONS.input_tmp, "system"))
-      # OSError: [Errno 17] File exists
-    if (e.errno == errno.EEXIST):
+  except OSError as e:
+    # bogus error on my mac version?
+    #   File "./build/tools/releasetools/img_from_target_files"
+    #     os.path.join(OPTIONS.input_tmp, "system"))
+    # OSError: [Errno 17] File exists
+    if e.errno == errno.EEXIST:
       pass
 
   image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
   fstab = info_dict["fstab"]
   if fstab:
-    image_props["fs_type" ] = fstab["/" + what].fs_type
+    image_props["fs_type"] = fstab["/" + what].fs_type
 
   if what == "system":
     fs_config_prefix = ""
@@ -137,31 +127,37 @@
 
   fs_config = os.path.join(
       input_dir, "META/" + fs_config_prefix + "filesystem_config.txt")
-  if not os.path.exists(fs_config): fs_config = None
+  if not os.path.exists(fs_config):
+    fs_config = None
 
-  fc_config = os.path.join(input_dir, "BOOT/RAMDISK/file_contexts")
-  if not os.path.exists(fc_config): fc_config = None
+  # Override values loaded from info_dict.
+  if fs_config:
+    image_props["fs_config"] = fs_config
+  if block_list:
+    image_props["block_list"] = block_list
 
   succ = build_image.BuildImage(os.path.join(input_dir, what),
-                                image_props, img,
-                                fs_config=fs_config,
-                                fc_config=fc_config,
-                                block_list=block_list)
+                                image_props, img)
   assert succ, "build " + what + ".img image failed"
 
   return img
 
 
 def AddUserdata(output_zip, prefix="IMAGES/"):
-  """Create an empty userdata image and store it in output_zip."""
+  """Create a userdata image and store it in output_zip.
+
+  In most case we just create and store an empty userdata.img;
+  But the invoker can also request to create userdata.img with real
+  data from the target files, by setting "userdata_img_with_data=true"
+  in OPTIONS.info_dict.
+  """
 
   prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "userdata.img")
   if os.path.exists(prebuilt_path):
     print "userdata.img already exists in %s, no need to rebuild..." % (prefix,)
     return
 
-  image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict,
-                                                    "data")
+  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
@@ -172,23 +168,31 @@
 
   # The name of the directory it is making an image out of matters to
   # mkyaffs2image.  So we create a temp dir, and within it we create an
-  # empty dir named "data", and build the image from that.
+  # empty dir named "data", or a symlink to the DATA dir,
+  # and build the image from that.
   temp_dir = tempfile.mkdtemp()
   user_dir = os.path.join(temp_dir, "data")
-  os.mkdir(user_dir)
+  empty = (OPTIONS.info_dict.get("userdata_img_with_data") != "true")
+  if empty:
+    # Create an empty dir.
+    os.mkdir(user_dir)
+  else:
+    # Symlink to the DATA dir.
+    os.symlink(os.path.join(OPTIONS.input_tmp, "DATA"),
+               user_dir)
+
   img = tempfile.NamedTemporaryFile()
 
   fstab = OPTIONS.info_dict["fstab"]
   if fstab:
-    image_props["fs_type" ] = fstab["/data"].fs_type
+    image_props["fs_type"] = fstab["/data"].fs_type
   succ = build_image.BuildImage(user_dir, image_props, img.name)
   assert succ, "build userdata.img image failed"
 
   common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict)
-  output_zip.write(img.name, prefix + "userdata.img")
+  common.ZipWrite(output_zip, img.name, prefix + "userdata.img")
   img.close()
-  os.rmdir(user_dir)
-  os.rmdir(temp_dir)
+  shutil.rmtree(temp_dir)
 
 
 def AddCache(output_zip, prefix="IMAGES/"):
@@ -199,8 +203,7 @@
     print "cache.img already exists in %s, no need to rebuild..." % (prefix,)
     return
 
-  image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict,
-                                                    "cache")
+  image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "cache")
   # The build system has to explicitly request for cache.img.
   if "fs_type" not in image_props:
     return
@@ -217,12 +220,12 @@
 
   fstab = OPTIONS.info_dict["fstab"]
   if fstab:
-    image_props["fs_type" ] = fstab["/cache"].fs_type
+    image_props["fs_type"] = fstab["/cache"].fs_type
   succ = build_image.BuildImage(user_dir, image_props, img.name)
   assert succ, "build cache.img image failed"
 
   common.CheckSize(img.name, "cache.img", OPTIONS.info_dict)
-  output_zip.write(img.name, prefix + "cache.img")
+  common.ZipWrite(output_zip, img.name, prefix + "cache.img")
   img.close()
   os.rmdir(user_dir)
   os.rmdir(temp_dir)
@@ -243,12 +246,9 @@
   except KeyError:
     has_vendor = False
 
-  OPTIONS.info_dict = common.LoadInfoDict(input_zip)
-  if "selinux_fc" in OPTIONS.info_dict:
-    OPTIONS.info_dict["selinux_fc"] = os.path.join(
-        OPTIONS.input_tmp, "BOOT", "RAMDISK", "file_contexts")
+  OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)
 
-  input_zip.close()
+  common.ZipClose(input_zip)
   output_zip = zipfile.ZipFile(filename, "a",
                                compression=zipfile.ZIP_DEFLATED)
 
@@ -293,11 +293,10 @@
   banner("cache")
   AddCache(output_zip)
 
-  output_zip.close()
+  common.ZipClose(output_zip)
 
 def main(argv):
-
-  def option_handler(o, a):
+  def option_handler(o, _):
     if o in ("-a", "--add_missing"):
       OPTIONS.add_missing = True
     elif o in ("-r", "--rebuild_recovery",):
@@ -306,12 +305,10 @@
       return False
     return True
 
-  args = common.ParseOptions(argv, __doc__,
-                             extra_opts="ar",
-                             extra_long_opts=["add_missing",
-                                              "rebuild_recovery",
-                                              ],
-                             extra_option_handler=option_handler)
+  args = common.ParseOptions(
+      argv, __doc__, extra_opts="ar",
+      extra_long_opts=["add_missing", "rebuild_recovery"],
+      extra_option_handler=option_handler)
 
 
   if len(args) != 1:
@@ -325,7 +322,7 @@
   try:
     common.CloseInheritedPipes()
     main(sys.argv[1:])
-  except common.ExternalError, e:
+  except common.ExternalError as e:
     print
     print "   ERROR: %s" % (e,)
     print
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 5cf0f2d..199783d 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -16,21 +16,22 @@
 
 from collections import deque, OrderedDict
 from hashlib import sha1
+import common
 import heapq
 import itertools
 import multiprocessing
 import os
-import pprint
 import re
 import subprocess
-import sys
 import threading
 import tempfile
 
-from rangelib import *
+from rangelib import RangeSet
+
 
 __all__ = ["EmptyImage", "DataImage", "BlockImageDiff"]
 
+
 def compute_patch(src, tgt, imgdiff=False):
   srcfd, srcfile = tempfile.mkstemp(prefix="src-")
   tgtfd, tgtfile = tempfile.mkstemp(prefix="tgt-")
@@ -69,19 +70,33 @@
     except OSError:
       pass
 
-class EmptyImage(object):
+
+class Image(object):
+  def ReadRangeSet(self, ranges):
+    raise NotImplementedError
+
+  def TotalSha1(self, include_clobbered_blocks=False):
+    raise NotImplementedError
+
+
+class EmptyImage(Image):
   """A zero-length image."""
   blocksize = 4096
   care_map = RangeSet()
+  clobbered_blocks = RangeSet()
+  extended = RangeSet()
   total_blocks = 0
   file_map = {}
   def ReadRangeSet(self, ranges):
     return ()
-  def TotalSha1(self):
+  def TotalSha1(self, include_clobbered_blocks=False):
+    # EmptyImage always carries empty clobbered_blocks, so
+    # include_clobbered_blocks can be ignored.
+    assert self.clobbered_blocks.size() == 0
     return sha1().hexdigest()
 
 
-class DataImage(object):
+class DataImage(Image):
   """An image wrapped around a single string of data."""
 
   def __init__(self, data, trim=False, pad=False):
@@ -105,6 +120,8 @@
 
     self.total_blocks = len(self.data) / self.blocksize
     self.care_map = RangeSet(data=(0, self.total_blocks))
+    self.clobbered_blocks = RangeSet()
+    self.extended = RangeSet()
 
     zero_blocks = []
     nonzero_blocks = []
@@ -125,10 +142,11 @@
   def ReadRangeSet(self, ranges):
     return [self.data[s*self.blocksize:e*self.blocksize] for (s, e) in ranges]
 
-  def TotalSha1(self):
-    if not hasattr(self, "sha1"):
-      self.sha1 = sha1(self.data).hexdigest()
-    return self.sha1
+  def TotalSha1(self, include_clobbered_blocks=False):
+    # DataImage always carries empty clobbered_blocks, so
+    # include_clobbered_blocks can be ignored.
+    assert self.clobbered_blocks.size() == 0
+    return sha1(self.data).hexdigest()
 
 
 class Transfer(object):
@@ -140,8 +158,11 @@
     self.style = style
     self.intact = (getattr(tgt_ranges, "monotonic", False) and
                    getattr(src_ranges, "monotonic", False))
-    self.goes_before = {}
-    self.goes_after = {}
+
+    # We use OrderedDict rather than dict so that the output is repeatable;
+    # otherwise it would depend on the hash values of the Transfer objects.
+    self.goes_before = OrderedDict()
+    self.goes_after = OrderedDict()
 
     self.stash_before = []
     self.use_stash = []
@@ -153,6 +174,12 @@
     return (sum(sr.size() for (_, sr) in self.stash_before) -
             sum(sr.size() for (_, sr) in self.use_stash))
 
+  def ConvertToNew(self):
+    assert self.style != "new"
+    self.use_stash = []
+    self.style = "new"
+    self.src_ranges = RangeSet()
+
   def __str__(self):
     return (str(self.id) + ": <" + str(self.src_ranges) + " " + self.style +
             " to " + str(self.tgt_ranges) + ">")
@@ -174,6 +201,10 @@
 #      (Typically a domain is a file, and the key in file_map is the
 #      pathname.)
 #
+#    clobbered_blocks: a RangeSet containing which blocks contain data
+#      but may be altered by the FS. They need to be excluded when
+#      verifying the partition integrity.
+#
 #    ReadRangeSet(): a function that takes a RangeSet and returns the
 #      data contained in the image blocks of that RangeSet.  The data
 #      is returned as a list or tuple of strings; concatenating the
@@ -183,7 +214,8 @@
 #
 #    TotalSha1(): a function that returns (as a hex string) the SHA-1
 #      hash of all the data in the image (ie, all the blocks in the
-#      care_map)
+#      care_map minus clobbered_blocks, or including the clobbered
+#      blocks if include_clobbered_blocks is True).
 #
 # When creating a BlockImageDiff, the src image may be None, in which
 # case the list of transfers produced will never read from the
@@ -193,9 +225,13 @@
   def __init__(self, tgt, src=None, threads=None, version=3):
     if threads is None:
       threads = multiprocessing.cpu_count() // 2
-      if threads == 0: threads = 1
+      if threads == 0:
+        threads = 1
     self.threads = threads
     self.version = version
+    self.transfers = []
+    self.src_basenames = {}
+    self.src_numpatterns = {}
 
     assert version in (1, 2, 3)
 
@@ -238,13 +274,17 @@
       self.ReverseBackwardEdges()
       self.ImproveVertexSequence()
 
+    # Ensure the runtime stash size is under the limit.
+    if self.version >= 2 and common.OPTIONS.cache_size is not None:
+      self.ReviseStashSize()
+
     # Double-check our work.
     self.AssertSequenceGood()
 
     self.ComputePatches(prefix)
     self.WriteTransfers(prefix)
 
-  def HashBlocks(self, source, ranges):
+  def HashBlocks(self, source, ranges): # pylint: disable=no-self-use
     data = source.ReadRangeSet(ranges)
     ctx = sha1()
 
@@ -297,7 +337,7 @@
       free_string = []
 
       if self.version == 1:
-        src_string = xf.src_ranges.to_string_raw()
+        src_str = xf.src_ranges.to_string_raw()
       elif self.version >= 2:
 
         #   <# blocks> <src ranges>
@@ -307,7 +347,7 @@
         #   <# blocks> - <stash refs...>
 
         size = xf.src_ranges.size()
-        src_string = [str(size)]
+        src_str = [str(size)]
 
         unstashed_src_ranges = xf.src_ranges
         mapped_stashes = []
@@ -319,10 +359,16 @@
           sr = xf.src_ranges.map_within(sr)
           mapped_stashes.append(sr)
           if self.version == 2:
-            src_string.append("%d:%s" % (sid, sr.to_string_raw()))
+            src_str.append("%d:%s" % (sid, sr.to_string_raw()))
+            # A stash will be used only once. We need to free the stash
+            # immediately after the use, instead of waiting for the automatic
+            # clean-up at the end. Because otherwise it may take up extra space
+            # and lead to OTA failures.
+            # Bug: 23119955
+            free_string.append("free %d\n" % (sid,))
           else:
             assert sh in stashes
-            src_string.append("%s:%s" % (sh, sr.to_string_raw()))
+            src_str.append("%s:%s" % (sh, sr.to_string_raw()))
             stashes[sh] -= 1
             if stashes[sh] == 0:
               free_string.append("free %s\n" % (sh))
@@ -330,17 +376,17 @@
           heapq.heappush(free_stash_ids, sid)
 
         if unstashed_src_ranges:
-          src_string.insert(1, unstashed_src_ranges.to_string_raw())
+          src_str.insert(1, unstashed_src_ranges.to_string_raw())
           if xf.use_stash:
             mapped_unstashed = xf.src_ranges.map_within(unstashed_src_ranges)
-            src_string.insert(2, mapped_unstashed.to_string_raw())
+            src_str.insert(2, mapped_unstashed.to_string_raw())
             mapped_stashes.append(mapped_unstashed)
             self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)
         else:
-          src_string.insert(1, "-")
+          src_str.insert(1, "-")
           self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)
 
-        src_string = " ".join(src_string)
+        src_str = " ".join(src_str)
 
       # all versions:
       #   zero <rangeset>
@@ -353,14 +399,14 @@
       #   move <src rangeset> <tgt rangeset>
       #
       # version 2:
-      #   bsdiff patchstart patchlen <tgt rangeset> <src_string>
-      #   imgdiff patchstart patchlen <tgt rangeset> <src_string>
-      #   move <tgt rangeset> <src_string>
+      #   bsdiff patchstart patchlen <tgt rangeset> <src_str>
+      #   imgdiff patchstart patchlen <tgt rangeset> <src_str>
+      #   move <tgt rangeset> <src_str>
       #
       # version 3:
-      #   bsdiff patchstart patchlen srchash tgthash <tgt rangeset> <src_string>
-      #   imgdiff patchstart patchlen srchash tgthash <tgt rangeset> <src_string>
-      #   move hash <tgt rangeset> <src_string>
+      #   bsdiff patchstart patchlen srchash tgthash <tgt rangeset> <src_str>
+      #   imgdiff patchstart patchlen srchash tgthash <tgt rangeset> <src_str>
+      #   move hash <tgt rangeset> <src_str>
 
       tgt_size = xf.tgt_ranges.size()
 
@@ -380,12 +426,18 @@
           elif self.version == 2:
             out.append("%s %s %s\n" % (
                 xf.style,
-                xf.tgt_ranges.to_string_raw(), src_string))
+                xf.tgt_ranges.to_string_raw(), src_str))
           elif self.version >= 3:
+            # take into account automatic stashing of overlapping blocks
+            if xf.src_ranges.overlaps(xf.tgt_ranges):
+              temp_stash_usage = stashed_blocks + xf.src_ranges.size()
+              if temp_stash_usage > max_stashed_blocks:
+                max_stashed_blocks = temp_stash_usage
+
             out.append("%s %s %s %s\n" % (
                 xf.style,
                 self.HashBlocks(self.tgt, xf.tgt_ranges),
-                xf.tgt_ranges.to_string_raw(), src_string))
+                xf.tgt_ranges.to_string_raw(), src_str))
           total += tgt_size
       elif xf.style in ("bsdiff", "imgdiff"):
         performs_read = True
@@ -398,14 +450,20 @@
         elif self.version == 2:
           out.append("%s %d %d %s %s\n" % (
               xf.style, xf.patch_start, xf.patch_len,
-              xf.tgt_ranges.to_string_raw(), src_string))
+              xf.tgt_ranges.to_string_raw(), src_str))
         elif self.version >= 3:
+          # take into account automatic stashing of overlapping blocks
+          if xf.src_ranges.overlaps(xf.tgt_ranges):
+            temp_stash_usage = stashed_blocks + xf.src_ranges.size()
+            if temp_stash_usage > max_stashed_blocks:
+              max_stashed_blocks = temp_stash_usage
+
           out.append("%s %d %d %s %s %s %s\n" % (
               xf.style,
               xf.patch_start, xf.patch_len,
               self.HashBlocks(self.src, xf.src_ranges),
               self.HashBlocks(self.tgt, xf.tgt_ranges),
-              xf.tgt_ranges.to_string_raw(), src_string))
+              xf.tgt_ranges.to_string_raw(), src_str))
         total += tgt_size
       elif xf.style == "zero":
         assert xf.tgt_ranges
@@ -414,28 +472,37 @@
           out.append("%s %s\n" % (xf.style, to_zero.to_string_raw()))
           total += to_zero.size()
       else:
-        raise ValueError, "unknown transfer style '%s'\n" % (xf.style,)
+        raise ValueError("unknown transfer style '%s'\n" % xf.style)
 
       if free_string:
         out.append("".join(free_string))
 
+      if self.version >= 2 and common.OPTIONS.cache_size is not None:
+        # Sanity check: abort if we're going to need more stash space than
+        # the allowed size (cache_size * threshold). There are two purposes
+        # of having a threshold here. a) Part of the cache may have been
+        # occupied by some recovery logs. b) It will buy us some time to deal
+        # with the oversize issue.
+        cache_size = common.OPTIONS.cache_size
+        stash_threshold = common.OPTIONS.stash_threshold
+        max_allowed = cache_size * stash_threshold
+        assert max_stashed_blocks * self.tgt.blocksize < max_allowed, \
+               'Stash size %d (%d * %d) exceeds the limit %d (%d * %.2f)' % (
+                   max_stashed_blocks * self.tgt.blocksize, max_stashed_blocks,
+                   self.tgt.blocksize, max_allowed, cache_size,
+                   stash_threshold)
 
-      # sanity check: abort if we're going to need more than 512 MB if
-      # stash space
-      assert max_stashed_blocks * self.tgt.blocksize < (512 << 20)
+    # Zero out extended blocks as a workaround for bug 20881595.
+    if self.tgt.extended:
+      out.append("zero %s\n" % (self.tgt.extended.to_string_raw(),))
 
+    # We erase all the blocks on the partition that a) don't contain useful
+    # data in the new image and b) will not be touched by dm-verity.
     all_tgt = RangeSet(data=(0, self.tgt.total_blocks))
-    if performs_read:
-      # if some of the original data is used, then at the end we'll
-      # erase all the blocks on the partition that don't contain data
-      # in the new image.
-      new_dontcare = all_tgt.subtract(self.tgt.care_map)
-      if new_dontcare:
-        out.append("erase %s\n" % (new_dontcare.to_string_raw(),))
-    else:
-      # if nothing is read (ie, this is a full OTA), then we can start
-      # by erasing the entire partition.
-      out.insert(0, "erase %s\n" % (all_tgt.to_string_raw(),))
+    all_tgt_minus_extended = all_tgt.subtract(self.tgt.extended)
+    new_dontcare = all_tgt_minus_extended.subtract(self.tgt.care_map)
+    if new_dontcare:
+      out.append("erase %s\n" % (new_dontcare.to_string_raw(),))
 
     out.insert(0, "%d\n" % (self.version,))   # format version number
     out.insert(1, str(total) + "\n")
@@ -450,8 +517,84 @@
         f.write(i)
 
     if self.version >= 2:
-      print("max stashed blocks: %d  (%d bytes)\n" % (
-          max_stashed_blocks, max_stashed_blocks * self.tgt.blocksize))
+      max_stashed_size = max_stashed_blocks * self.tgt.blocksize
+      OPTIONS = common.OPTIONS
+      if OPTIONS.cache_size is not None:
+        max_allowed = OPTIONS.cache_size * OPTIONS.stash_threshold
+        print("max stashed blocks: %d  (%d bytes), "
+              "limit: %d bytes (%.2f%%)\n" % (
+              max_stashed_blocks, max_stashed_size, max_allowed,
+              max_stashed_size * 100.0 / max_allowed))
+      else:
+        print("max stashed blocks: %d  (%d bytes), limit: <unknown>\n" % (
+              max_stashed_blocks, max_stashed_size))
+
+  def ReviseStashSize(self):
+    print("Revising stash size...")
+    stashes = {}
+
+    # Create the map between a stash and its def/use points. For example, for a
+    # given stash of (idx, sr), stashes[idx] = (sr, def_cmd, use_cmd).
+    for xf in self.transfers:
+      # Command xf defines (stores) all the stashes in stash_before.
+      for idx, sr in xf.stash_before:
+        stashes[idx] = (sr, xf)
+
+      # Record all the stashes command xf uses.
+      for idx, _ in xf.use_stash:
+        stashes[idx] += (xf,)
+
+    # Compute the maximum blocks available for stash based on /cache size and
+    # the threshold.
+    cache_size = common.OPTIONS.cache_size
+    stash_threshold = common.OPTIONS.stash_threshold
+    max_allowed = cache_size * stash_threshold / self.tgt.blocksize
+
+    stashed_blocks = 0
+
+    # Now go through all the commands. Compute the required stash size on the
+    # fly. If a command requires excess stash than available, it deletes the
+    # stash by replacing the command that uses the stash with a "new" command
+    # instead.
+    for xf in self.transfers:
+      replaced_cmds = []
+
+      # xf.stash_before generates explicit stash commands.
+      for idx, sr in xf.stash_before:
+        if stashed_blocks + sr.size() > max_allowed:
+          # We cannot stash this one for a later command. Find out the command
+          # that will use this stash and replace the command with "new".
+          use_cmd = stashes[idx][2]
+          replaced_cmds.append(use_cmd)
+          print("  %s replaced due to an explicit stash of %d blocks." % (
+              use_cmd, sr.size()))
+        else:
+          stashed_blocks += sr.size()
+
+      # xf.use_stash generates free commands.
+      for _, sr in xf.use_stash:
+        stashed_blocks -= sr.size()
+
+      # "move" and "diff" may introduce implicit stashes in BBOTA v3. Prior to
+      # ComputePatches(), they both have the style of "diff".
+      if xf.style == "diff" and self.version >= 3:
+        assert xf.tgt_ranges and xf.src_ranges
+        if xf.src_ranges.overlaps(xf.tgt_ranges):
+          if stashed_blocks + xf.src_ranges.size() > max_allowed:
+            replaced_cmds.append(xf)
+            print("  %s replaced due to an implicit stash of %d blocks." % (
+                xf, xf.src_ranges.size()))
+
+      # Replace the commands in replaced_cmds with "new"s.
+      for cmd in replaced_cmds:
+        # It no longer uses any commands in "use_stash". Remove the def points
+        # for all those stashes.
+        for idx, sr in cmd.use_stash:
+          def_cmd = stashes[idx][1]
+          assert (idx, sr) in def_cmd.stash_before
+          def_cmd.stash_before.remove((idx, sr))
+
+        cmd.ConvertToNew()
 
   def ComputePatches(self, prefix):
     print("Reticulating splines...")
@@ -524,11 +667,13 @@
 
       patches = [None] * patch_num
 
+      # TODO: Rewrite with multiprocessing.ThreadPool?
       lock = threading.Lock()
       def diff_worker():
         while True:
           with lock:
-            if not diff_q: return
+            if not diff_q:
+              return
             tgt_size, src, tgt, xf, patchnum = diff_q.pop()
           patch = compute_patch(src, tgt, imgdiff=(xf.style == "imgdiff"))
           size = len(patch)
@@ -540,7 +685,7 @@
                     xf.tgt_name + " (from " + xf.src_name + ")")))
 
       threads = [threading.Thread(target=diff_worker)
-                 for i in range(self.threads)]
+                 for _ in range(self.threads)]
       for th in threads:
         th.start()
       while threads:
@@ -667,8 +812,6 @@
     stash_size = 0
 
     for xf in self.transfers:
-      lost = 0
-      size = xf.src_ranges.size()
       for u in xf.goes_before.copy():
         # xf should go before u
         if xf.order < u.order:
@@ -734,7 +877,8 @@
       # Put all sinks at the end of the sequence.
       while True:
         sinks = [u for u in G if not u.outgoing]
-        if not sinks: break
+        if not sinks:
+          break
         for u in sinks:
           s2.appendleft(u)
           del G[u]
@@ -744,14 +888,16 @@
       # Put all the sources at the beginning of the sequence.
       while True:
         sources = [u for u in G if not u.incoming]
-        if not sources: break
+        if not sources:
+          break
         for u in sources:
           s1.append(u)
           del G[u]
           for iu in u.outgoing:
             del iu.incoming[u]
 
-      if not G: break
+      if not G:
+        break
 
       # Find the "best" vertex to put next.  "Best" is the one that
       # maximizes the net difference in source blocks saved we get by
@@ -789,7 +935,8 @@
     print("Generating digraph...")
     for a in self.transfers:
       for b in self.transfers:
-        if a is b: continue
+        if a is b:
+          continue
 
         # If the blocks written by A are read by B, then B needs to go before A.
         i = a.tgt_ranges.intersect(b.src_ranges)
@@ -804,7 +951,6 @@
           a.goes_after[b] = size
 
   def FindTransfers(self):
-    self.transfers = []
     empty = RangeSet()
     for tgt_fn, tgt_ranges in self.tgt.file_map.items():
       if tgt_fn == "__ZERO":
@@ -816,6 +962,12 @@
                  "zero", self.transfers)
         continue
 
+      elif tgt_fn == "__COPY":
+        # "__COPY" domain includes all the blocks not contained in any
+        # file and that need to be copied unconditionally to the target.
+        Transfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
+        continue
+
       elif tgt_fn in self.src.file_map:
         # Look for an exact pathname match in the source.
         Transfer(tgt_fn, tgt_fn, tgt_ranges, self.src.file_map[tgt_fn],
@@ -844,9 +996,6 @@
       Transfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
 
   def AbbreviateSourceNames(self):
-    self.src_basenames = {}
-    self.src_numpatterns = {}
-
     for k in self.src.file_map.keys():
       b = os.path.basename(k)
       self.src_basenames[b] = k
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 55f0058..bf5d9dd 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -22,6 +22,7 @@
 """
 import os
 import os.path
+import re
 import subprocess
 import sys
 import commands
@@ -31,17 +32,18 @@
 FIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7"
 
 def RunCommand(cmd):
-  """ Echo and run the given command
+  """Echo and run the given command.
 
   Args:
     cmd: the command represented as a list of strings.
   Returns:
-    The exit code.
+    A tuple of the output and the exit code.
   """
   print "Running: ", " ".join(cmd)
-  p = subprocess.Popen(cmd)
-  p.communicate()
-  return p.returncode
+  p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+  output, _ = p.communicate()
+  print "%s" % (output.rstrip(),)
+  return (output, p.returncode)
 
 def GetVerityTreeSize(partition_size):
   cmd = "build_verity_tree -s %d"
@@ -72,14 +74,15 @@
   """
   success, verity_tree_size = GetVerityTreeSize(partition_size)
   if not success:
-    return 0;
+    return 0
   success, verity_metadata_size = GetVerityMetadataSize(partition_size)
   if not success:
     return 0
   return partition_size - verity_tree_size - verity_metadata_size
 
 def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict):
-  cmd = ("build_verity_tree -A %s %s %s" % (FIXED_SALT, sparse_image_path, verity_image_path))
+  cmd = "build_verity_tree -A %s %s %s" % (
+      FIXED_SALT, sparse_image_path, verity_image_path)
   print cmd
   status, output = commands.getstatusoutput(cmd)
   if status:
@@ -92,14 +95,10 @@
 
 def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt,
                         block_device, signer_path, key):
-  cmd = ("system/extras/verity/build_verity_metadata.py %s %s %s %s %s %s %s" %
-              (image_size,
-              verity_metadata_path,
-              root_hash,
-              salt,
-              block_device,
-              signer_path,
-              key))
+  cmd_template = (
+      "system/extras/verity/build_verity_metadata.py %s %s %s %s %s %s %s")
+  cmd = cmd_template % (image_size, verity_metadata_path, root_hash, salt,
+                        block_device, signer_path, key)
   print cmd
   status, output = commands.getstatusoutput(cmd)
   if status:
@@ -125,10 +124,13 @@
     return False
   return True
 
-def BuildVerifiedImage(data_image_path, verity_image_path, verity_metadata_path):
-  if not Append2Simg(data_image_path, verity_metadata_path, "Could not append verity metadata!"):
+def BuildVerifiedImage(data_image_path, verity_image_path,
+                       verity_metadata_path):
+  if not Append2Simg(data_image_path, verity_metadata_path,
+                     "Could not append verity metadata!"):
     return False
-  if not Append2Simg(data_image_path, verity_image_path, "Could not append verity tree!"):
+  if not Append2Simg(data_image_path, verity_image_path,
+                     "Could not append verity tree!"):
     return False
   return True
 
@@ -142,7 +144,7 @@
     else:
       return True, unsparse_image_path
   inflate_command = ["simg2img", sparse_image_path, unsparse_image_path]
-  exit_code = RunCommand(inflate_command)
+  (_, exit_code) = RunCommand(inflate_command)
   if exit_code != 0:
     os.remove(unsparse_image_path)
     return False, None
@@ -153,7 +155,8 @@
 
   Args:
     out_file: the location to write the verifiable image at
-    prop_dict: a dictionary of properties required for image creation and verification
+    prop_dict: a dictionary of properties required for image creation and
+               verification
   Returns:
     True on success, False otherwise.
   """
@@ -178,13 +181,8 @@
   # build the metadata blocks
   root_hash = prop_dict["verity_root_hash"]
   salt = prop_dict["verity_salt"]
-  if not BuildVerityMetadata(image_size,
-                              verity_metadata_path,
-                              root_hash,
-                              salt,
-                              block_dev,
-                              signer_path,
-                              signer_key):
+  if not BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt,
+                             block_dev, signer_path, signer_key):
     shutil.rmtree(tempdir_name, ignore_errors=True)
     return False
 
@@ -198,33 +196,52 @@
   shutil.rmtree(tempdir_name, ignore_errors=True)
   return True
 
-def BuildImage(in_dir, prop_dict, out_file,
-               fs_config=None,
-               fc_config=None,
-               block_list=None):
+def BuildImage(in_dir, prop_dict, out_file):
   """Build an image to out_file from in_dir with property prop_dict.
 
   Args:
     in_dir: path of input directory.
     prop_dict: property dictionary.
     out_file: path of the output image file.
-    fs_config: path to the fs_config file (typically
-      META/filesystem_config.txt).  If None then the configuration in
-      the local client will be used.
-    fc_config: path to the SELinux file_contexts file.  If None then
-      the value from prop_dict['selinux_fc'] will be used.
 
   Returns:
     True iff the image is built successfully.
   """
+  # system_root_image=true: build a system.img that combines the contents of
+  # /system and the ramdisk, and can be mounted at the root of the file system.
+  origin_in = in_dir
+  fs_config = prop_dict.get("fs_config")
+  if (prop_dict.get("system_root_image") == "true"
+      and prop_dict["mount_point"] == "system"):
+    in_dir = tempfile.mkdtemp()
+    # Change the mount point to "/"
+    prop_dict["mount_point"] = "/"
+    if fs_config:
+      # We need to merge the fs_config files of system and ramdisk.
+      fd, merged_fs_config = tempfile.mkstemp(prefix="root_fs_config",
+                                              suffix=".txt")
+      os.close(fd)
+      with open(merged_fs_config, "w") as fw:
+        if "ramdisk_fs_config" in prop_dict:
+          with open(prop_dict["ramdisk_fs_config"]) as fr:
+            fw.writelines(fr.readlines())
+        with open(fs_config) as fr:
+          fw.writelines(fr.readlines())
+      fs_config = merged_fs_config
+
   build_command = []
   fs_type = prop_dict.get("fs_type", "")
   run_fsck = False
 
+  fs_spans_partition = True
+  if fs_type.startswith("squash"):
+    fs_spans_partition = False
+
   is_verity_partition = "verity_block_device" in prop_dict
   verity_supported = prop_dict.get("verity") == "true"
-  # adjust the partition size to make room for the hashes if this is to be verified
-  if verity_supported and is_verity_partition:
+  # Adjust the partition size to make room for the hashes if this is to be
+  # verified.
+  if verity_supported and is_verity_partition and fs_spans_partition:
     partition_size = int(prop_dict.get("partition_size"))
     adjusted_size = AdjustPartitionSizeForVerity(partition_size)
     if not adjusted_size:
@@ -244,23 +261,24 @@
       build_command.extend(["-j", prop_dict["journal_size"]])
     if "timestamp" in prop_dict:
       build_command.extend(["-T", str(prop_dict["timestamp"])])
-    if fs_config is not None:
+    if fs_config:
       build_command.extend(["-C", fs_config])
-    if block_list is not None:
-      build_command.extend(["-B", block_list])
+    if "block_list" in prop_dict:
+      build_command.extend(["-B", prop_dict["block_list"]])
     build_command.extend(["-L", prop_dict["mount_point"]])
-    if fc_config is not None:
-      build_command.append(fc_config)
-    elif "selinux_fc" in prop_dict:
+    if "selinux_fc" in prop_dict:
       build_command.append(prop_dict["selinux_fc"])
   elif fs_type.startswith("squash"):
     build_command = ["mksquashfsimage.sh"]
     build_command.extend([in_dir, out_file])
+    build_command.extend(["-s"])
     build_command.extend(["-m", prop_dict["mount_point"]])
-    if fc_config is not None:
-      build_command.extend(["-c", fc_config])
-    elif "selinux_fc" in prop_dict:
+    if "selinux_fc" in prop_dict:
       build_command.extend(["-c", prop_dict["selinux_fc"]])
+    if "squashfs_compressor" in prop_dict:
+      build_command.extend(["-z", prop_dict["squashfs_compressor"]])
+    if "squashfs_compressor_opt" in prop_dict:
+      build_command.extend(["-zo", prop_dict["squashfs_compressor_opt"]])
   elif fs_type.startswith("f2fs"):
     build_command = ["mkf2fsuserimg.sh"]
     build_command.extend([out_file, prop_dict["partition_size"]])
@@ -274,10 +292,72 @@
       build_command.append(prop_dict["selinux_fc"])
       build_command.append(prop_dict["mount_point"])
 
-  exit_code = RunCommand(build_command)
+  if in_dir != origin_in:
+    # Construct a staging directory of the root file system.
+    ramdisk_dir = prop_dict.get("ramdisk_dir")
+    if ramdisk_dir:
+      shutil.rmtree(in_dir)
+      shutil.copytree(ramdisk_dir, in_dir, symlinks=True)
+    staging_system = os.path.join(in_dir, "system")
+    shutil.rmtree(staging_system, ignore_errors=True)
+    shutil.copytree(origin_in, staging_system, symlinks=True)
+
+  reserved_blocks = prop_dict.get("has_ext4_reserved_blocks") == "true"
+  ext4fs_output = None
+
+  try:
+    if reserved_blocks and fs_type.startswith("ext4"):
+      (ext4fs_output, exit_code) = RunCommand(build_command)
+    else:
+      (_, exit_code) = RunCommand(build_command)
+  finally:
+    if in_dir != origin_in:
+      # Clean up temporary directories and files.
+      shutil.rmtree(in_dir, ignore_errors=True)
+      if fs_config:
+        os.remove(fs_config)
   if exit_code != 0:
     return False
 
+  # Bug: 21522719, 22023465
+  # There are some reserved blocks on ext4 FS (lesser of 4096 blocks and 2%).
+  # We need to deduct those blocks from the available space, since they are
+  # not writable even with root privilege. It only affects devices using
+  # file-based OTA and a kernel version of 3.10 or greater (currently just
+  # sprout).
+  if reserved_blocks and fs_type.startswith("ext4"):
+    assert ext4fs_output is not None
+    ext4fs_stats = re.compile(
+        r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'
+        r'(?P<total_blocks>[0-9]+) blocks')
+    m = ext4fs_stats.match(ext4fs_output.strip().split('\n')[-1])
+    used_blocks = int(m.groupdict().get('used_blocks'))
+    total_blocks = int(m.groupdict().get('total_blocks'))
+    reserved_blocks = min(4096, int(total_blocks * 0.02))
+    adjusted_blocks = total_blocks - reserved_blocks
+    if used_blocks > adjusted_blocks:
+      mount_point = prop_dict.get("mount_point")
+      print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, "
+            "reserved: %d blocks, available: %d blocks)" % (
+                mount_point, total_blocks, used_blocks, reserved_blocks,
+                adjusted_blocks))
+      return False
+
+  if not fs_spans_partition:
+    mount_point = prop_dict.get("mount_point")
+    partition_size = int(prop_dict.get("partition_size"))
+    image_size = os.stat(out_file).st_size
+    if image_size > partition_size:
+      print("Error: %s image size of %d is larger than partition size of "
+            "%d" % (mount_point, image_size, partition_size))
+      return False
+    if verity_supported and is_verity_partition:
+      if 2 * image_size - AdjustPartitionSizeForVerity(image_size) > partition_size:
+        print "Error: No more room on %s to fit verity data" % mount_point
+        return False
+    prop_dict["original_partition_size"] = prop_dict["partition_size"]
+    prop_dict["partition_size"] = str(image_size)
+
   # create the verified image if this is to be verified
   if verity_supported and is_verity_partition:
     if not MakeVerityEnabledImage(out_file, prop_dict):
@@ -290,7 +370,7 @@
 
     # Run e2fsck on the inflated image file
     e2fsck_command = ["e2fsck", "-f", "-n", unsparse_image]
-    exit_code = RunCommand(e2fsck_command)
+    (_, exit_code) = RunCommand(e2fsck_command)
 
     os.remove(unsparse_image)
 
@@ -329,11 +409,18 @@
   d["mount_point"] = mount_point
   if mount_point == "system":
     copy_prop("fs_type", "fs_type")
-    # Copy the generic sysetem fs type first, override with specific one if available.
+    # Copy the generic sysetem fs type first, override with specific one if
+    # available.
     copy_prop("system_fs_type", "fs_type")
     copy_prop("system_size", "partition_size")
     copy_prop("system_journal_size", "journal_size")
     copy_prop("system_verity_block_device", "verity_block_device")
+    copy_prop("system_root_image", "system_root_image")
+    copy_prop("ramdisk_dir", "ramdisk_dir")
+    copy_prop("ramdisk_fs_config", "ramdisk_fs_config")
+    copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
+    copy_prop("system_squashfs_compressor", "squashfs_compressor")
+    copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
   elif mount_point == "data":
     # Copy the generic fs type first, override with specific one if available.
     copy_prop("fs_type", "fs_type")
@@ -347,10 +434,12 @@
     copy_prop("vendor_size", "partition_size")
     copy_prop("vendor_journal_size", "journal_size")
     copy_prop("vendor_verity_block_device", "verity_block_device")
+    copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
   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")
 
   return d
 
@@ -379,25 +468,32 @@
   out_file = argv[2]
 
   glob_dict = LoadGlobalDict(glob_dict_file)
-  image_filename = os.path.basename(out_file)
-  mount_point = ""
-  if image_filename == "system.img":
-    mount_point = "system"
-  elif image_filename == "userdata.img":
-    mount_point = "data"
-  elif image_filename == "cache.img":
-    mount_point = "cache"
-  elif image_filename == "vendor.img":
-    mount_point = "vendor"
-  elif image_filename == "oem.img":
-    mount_point = "oem"
+  if "mount_point" in glob_dict:
+    # The caller knows the mount point and provides a dictionay needed by
+    # BuildImage().
+    image_properties = glob_dict
   else:
-    print >> sys.stderr, "error: unknown image file name ", image_filename
-    exit(1)
+    image_filename = os.path.basename(out_file)
+    mount_point = ""
+    if image_filename == "system.img":
+      mount_point = "system"
+    elif image_filename == "userdata.img":
+      mount_point = "data"
+    elif image_filename == "cache.img":
+      mount_point = "cache"
+    elif image_filename == "vendor.img":
+      mount_point = "vendor"
+    elif image_filename == "oem.img":
+      mount_point = "oem"
+    else:
+      print >> sys.stderr, "error: unknown image file name ", image_filename
+      exit(1)
 
-  image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
+    image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
+
   if not BuildImage(in_dir, image_properties, out_file):
-    print >> sys.stderr, "error: failed to build %s from %s" % (out_file, in_dir)
+    print >> sys.stderr, "error: failed to build %s from %s" % (out_file,
+                                                                in_dir)
     exit(1)
 
 
diff --git a/tools/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures
new file mode 120000
index 0000000..9f62aa3
--- /dev/null
+++ b/tools/releasetools/check_target_files_signatures
@@ -0,0 +1 @@
+check_target_files_signatures.py
\ No newline at end of file
diff --git a/tools/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures.py
similarity index 96%
rename from tools/releasetools/check_target_files_signatures
rename to tools/releasetools/check_target_files_signatures.py
index b2f46c1..dd57033 100755
--- a/tools/releasetools/check_target_files_signatures
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -49,14 +49,8 @@
 import re
 import shutil
 import subprocess
-import tempfile
 import zipfile
 
-try:
-  from hashlib import sha1 as sha1
-except ImportError:
-  from sha import sha as sha1
-
 import common
 
 # Work around a bug in python's zipfile module that prevents opening
@@ -127,7 +121,7 @@
   def FindLocalCerts(self):
     to_load = []
     for top in OPTIONS.local_cert_dirs:
-      for dirpath, dirnames, filenames in os.walk(top):
+      for dirpath, _, filenames in os.walk(top):
         certs = [os.path.join(dirpath, i)
                  for i in filenames if i.endswith(".x509.pem")]
         if certs:
@@ -172,6 +166,10 @@
 class APK(object):
   def __init__(self, full_filename, filename):
     self.filename = filename
+    self.certs = None
+    self.shared_uid = None
+    self.package = None
+
     Push(filename+":")
     try:
       self.RecordCerts(full_filename)
@@ -212,7 +210,7 @@
 
     for line in manifest.split("\n"):
       line = line.strip()
-      m = re.search('A: (\S*?)(?:\(0x[0-9a-f]+\))?="(.*?)" \(Raw', line)
+      m = re.search(r'A: (\S*?)(?:\(0x[0-9a-f]+\))?="(.*?)" \(Raw', line)
       if m:
         name = m.group(1)
         if name == "android:sharedUserId":
@@ -232,13 +230,16 @@
   def __init__(self):
     self.max_pkg_len = 30
     self.max_fn_len = 20
+    self.apks = None
+    self.apks_by_basename = None
+    self.certmap = None
 
   def LoadZipFile(self, filename):
     d, z = common.UnzipTemp(filename, '*.apk')
     try:
       self.apks = {}
       self.apks_by_basename = {}
-      for dirpath, dirnames, filenames in os.walk(d):
+      for dirpath, _, filenames in os.walk(d):
         for fn in filenames:
           if fn.endswith(".apk"):
             fullname = os.path.join(dirpath, fn)
@@ -323,8 +324,8 @@
     """Look for instances where a given package that exists in both
     self and other have different certs."""
 
-    all = set(self.apks.keys())
-    all.update(other.apks.keys())
+    all_apks = set(self.apks.keys())
+    all_apks.update(other.apks.keys())
 
     max_pkg_len = max(self.max_pkg_len, other.max_pkg_len)
 
@@ -434,7 +435,7 @@
   try:
     r = main(sys.argv[1:])
     sys.exit(r)
-  except common.ExternalError, e:
+  except common.ExternalError as e:
     print
     print "   ERROR: %s" % (e,)
     print
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 39c9b3d..d56c0fd 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -30,44 +30,47 @@
 import zipfile
 
 import blockimgdiff
-from rangelib import *
+import rangelib
 
-try:
-  from hashlib import sha1 as sha1
-except ImportError:
-  from sha import sha as sha1
+from hashlib import sha1 as sha1
 
-# missing in Python 2.4 and before
-if not hasattr(os, "SEEK_SET"):
-  os.SEEK_SET = 0
 
-class Options(object): pass
-OPTIONS = Options()
-
-DEFAULT_SEARCH_PATH_BY_PLATFORM = {
-    "linux2": "out/host/linux-x86",
-    "darwin": "out/host/darwin-x86",
+class Options(object):
+  def __init__(self):
+    platform_search_path = {
+        "linux2": "out/host/linux-x86",
+        "darwin": "out/host/darwin-x86",
     }
-OPTIONS.search_path = DEFAULT_SEARCH_PATH_BY_PLATFORM.get(sys.platform, None)
 
-OPTIONS.signapk_path = "framework/signapk.jar"  # Relative to search_path
-OPTIONS.extra_signapk_args = []
-OPTIONS.java_path = "java"  # Use the one on the path by default.
-OPTIONS.java_args = "-Xmx2048m" # JVM Args
-OPTIONS.public_key_suffix = ".x509.pem"
-OPTIONS.private_key_suffix = ".pk8"
-OPTIONS.verbose = False
-OPTIONS.tempfiles = []
-OPTIONS.device_specific = None
-OPTIONS.extras = {}
-OPTIONS.info_dict = None
+    self.search_path = platform_search_path.get(sys.platform, None)
+    self.signapk_path = "framework/signapk.jar"  # Relative to search_path
+    self.extra_signapk_args = []
+    self.java_path = "java"  # Use the one on the path by default.
+    self.java_args = "-Xmx2048m" # JVM Args
+    self.public_key_suffix = ".x509.pem"
+    self.private_key_suffix = ".pk8"
+    # use otatools built boot_signer by default
+    self.boot_signer_path = "boot_signer"
+    self.verbose = False
+    self.tempfiles = []
+    self.device_specific = None
+    self.extras = {}
+    self.info_dict = None
+    self.worker_threads = None
+    # Stash size cannot exceed cache_size * threshold.
+    self.cache_size = None
+    self.stash_threshold = 0.8
+
+
+OPTIONS = Options()
 
 
 # Values for "certificate" in apkcerts that mean special things.
 SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL")
 
 
-class ExternalError(RuntimeError): pass
+class ExternalError(RuntimeError):
+  pass
 
 
 def Run(args, **kwargs):
@@ -94,19 +97,19 @@
       pass
 
 
-def LoadInfoDict(input):
+def LoadInfoDict(input_file, input_dir=None):
   """Read and parse the META/misc_info.txt key/value pairs from the
   input target files and return a dict."""
 
   def read_helper(fn):
-    if isinstance(input, zipfile.ZipFile):
-      return input.read(fn)
+    if isinstance(input_file, zipfile.ZipFile):
+      return input_file.read(fn)
     else:
-      path = os.path.join(input, *fn.split("/"))
+      path = os.path.join(input_file, *fn.split("/"))
       try:
         with open(path) as f:
           return f.read()
-      except IOError, e:
+      except IOError as e:
         if e.errno == errno.ENOENT:
           raise KeyError(fn)
   d = {}
@@ -122,14 +125,16 @@
 
   if "mkyaffs2_extra_flags" not in d:
     try:
-      d["mkyaffs2_extra_flags"] = read_helper("META/mkyaffs2-extra-flags.txt").strip()
+      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("META/recovery-api-version.txt").strip()
+      d["recovery_api_version"] = read_helper(
+          "META/recovery-api-version.txt").strip()
     except KeyError:
       raise ValueError("can't find recovery API version in input target-files")
 
@@ -143,12 +148,42 @@
   if "fstab_version" not in d:
     d["fstab_version"] = "1"
 
+  # A few properties are stored as links to the files in the out/ directory.
+  # It works fine with the build system. However, they are no longer available
+  # when (re)generating from target_files zip. If input_dir is not None, we
+  # are doing repacking. Redirect those properties to the actual files in the
+  # unzipped directory.
+  if input_dir is not None:
+    # We carry a copy of file_contexts.bin under META/. If not available,
+    # search BOOT/RAMDISK/. Note that sometimes we may need a different file
+    # to build images than the one running on device, such as when enabling
+    # system_root_image. In that case, we must have the one for image
+    # generation copied to META/.
+    fc_config = os.path.join(input_dir, "META", "file_contexts.bin")
+    if d.get("system_root_image") == "true":
+      assert os.path.exists(fc_config)
+    if not os.path.exists(fc_config):
+      fc_config = os.path.join(input_dir, "BOOT", "RAMDISK", "file_contexts.bin")
+      if not os.path.exists(fc_config):
+        fc_config = None
+
+    if fc_config:
+      d["selinux_fc"] = fc_config
+
+    # Similarly we need to redirect "ramdisk_dir" and "ramdisk_fs_config".
+    if d.get("system_root_image") == "true":
+      d["ramdisk_dir"] = os.path.join(input_dir, "ROOT")
+      d["ramdisk_fs_config"] = os.path.join(
+          input_dir, "META", "root_filesystem_config.txt")
+
   try:
     data = read_helper("META/imagesizes.txt")
     for line in data.split("\n"):
-      if not line: continue
+      if not line:
+        continue
       name, value = line.split(" ", 1)
-      if not value: continue
+      if not value:
+        continue
       if name == "blocksize":
         d[name] = value
       else:
@@ -170,7 +205,8 @@
   makeint("boot_size")
   makeint("fstab_version")
 
-  d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"])
+  d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"],
+                                 d.get("system_root_image", False))
   d["build.prop"] = LoadBuildProp(read_helper)
   return d
 
@@ -186,15 +222,22 @@
   d = {}
   for line in lines:
     line = line.strip()
-    if not line or line.startswith("#"): continue
+    if not line or line.startswith("#"):
+      continue
     if "=" in line:
       name, value = line.split("=", 1)
       d[name] = value
   return d
 
-def LoadRecoveryFSTab(read_helper, fstab_version):
+def LoadRecoveryFSTab(read_helper, fstab_version, system_root_image=False):
   class Partition(object):
-    pass
+    def __init__(self, mount_point, fs_type, device, length, device2, context):
+      self.mount_point = mount_point
+      self.fs_type = fs_type
+      self.device = device
+      self.length = length
+      self.device2 = device2
+      self.context = context
 
   try:
     data = read_helper("RECOVERY/RAMDISK/etc/recovery.fstab")
@@ -206,72 +249,84 @@
     d = {}
     for line in data.split("\n"):
       line = line.strip()
-      if not line or line.startswith("#"): continue
+      if not line or line.startswith("#"):
+        continue
       pieces = line.split()
-      if not (3 <= len(pieces) <= 4):
+      if not 3 <= len(pieces) <= 4:
         raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
-
-      p = Partition()
-      p.mount_point = pieces[0]
-      p.fs_type = pieces[1]
-      p.device = pieces[2]
-      p.length = 0
       options = None
       if len(pieces) >= 4:
         if pieces[3].startswith("/"):
-          p.device2 = pieces[3]
+          device2 = pieces[3]
           if len(pieces) >= 5:
             options = pieces[4]
         else:
-          p.device2 = None
+          device2 = None
           options = pieces[3]
       else:
-        p.device2 = None
+        device2 = None
 
+      mount_point = pieces[0]
+      length = 0
       if options:
         options = options.split(",")
         for i in options:
           if i.startswith("length="):
-            p.length = int(i[7:])
+            length = int(i[7:])
           else:
-              print "%s: unknown option \"%s\"" % (p.mount_point, i)
+            print "%s: unknown option \"%s\"" % (mount_point, i)
 
-      d[p.mount_point] = p
+      d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[1],
+                                 device=pieces[2], length=length,
+                                 device2=device2)
 
   elif fstab_version == 2:
     d = {}
     for line in data.split("\n"):
       line = line.strip()
-      if not line or line.startswith("#"): continue
+      if not line or line.startswith("#"):
+        continue
+      # <src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
       pieces = line.split()
       if len(pieces) != 5:
         raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
 
       # Ignore entries that are managed by vold
       options = pieces[4]
-      if "voldmanaged=" in options: continue
+      if "voldmanaged=" in options:
+        continue
 
       # It's a good line, parse it
-      p = Partition()
-      p.device = pieces[0]
-      p.mount_point = pieces[1]
-      p.fs_type = pieces[2]
-      p.device2 = None
-      p.length = 0
-
+      length = 0
       options = options.split(",")
       for i in options:
         if i.startswith("length="):
-          p.length = int(i[7:])
+          length = int(i[7:])
         else:
           # Ignore all unknown options in the unified fstab
           continue
 
-      d[p.mount_point] = p
+      mount_flags = pieces[3]
+      # Honor the SELinux context if present.
+      context = None
+      for i in mount_flags.split(","):
+        if i.startswith("context="):
+          context = i
+
+      mount_point = pieces[1]
+      d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[2],
+                                 device=pieces[0], length=length,
+                                 device2=None, context=context)
 
   else:
     raise ValueError("Unknown fstab_version: \"%d\"" % (fstab_version,))
 
+  # / is used for the system mount point when the root directory is included in
+  # system. Other areas assume system is always at "/system" so point /system
+  # at /.
+  if system_root_image:
+    assert not d.has_key("/system") and d.has_key("/")
+    d["/system"] = d["/"]
   return d
 
 
@@ -279,34 +334,47 @@
   for k, v in sorted(d.items()):
     print "%-25s = (%s) %s" % (k, type(v).__name__, v)
 
-def BuildBootableImage(sourcedir, fs_config_file, info_dict=None):
-  """Take a kernel, cmdline, and ramdisk directory from the input (in
-  'sourcedir'), and turn them into a boot image.  Return the image
-  data, or None if sourcedir does not appear to contains files for
-  building the requested image."""
 
-  if (not os.access(os.path.join(sourcedir, "RAMDISK"), os.F_OK) or
-      not os.access(os.path.join(sourcedir, "kernel"), os.F_OK)):
+def _BuildBootableImage(sourcedir, fs_config_file, info_dict=None,
+                        has_ramdisk=False):
+  """Build a bootable image from the specified sourcedir.
+
+  Take a kernel, cmdline, and optionally a ramdisk directory from the input (in
+  'sourcedir'), and turn them into a boot image.  Return the image data, or
+  None if sourcedir does not appear to contains files for building the
+  requested image."""
+
+  def make_ramdisk():
+    ramdisk_img = tempfile.NamedTemporaryFile()
+
+    if os.access(fs_config_file, os.F_OK):
+      cmd = ["mkbootfs", "-f", fs_config_file,
+             os.path.join(sourcedir, "RAMDISK")]
+    else:
+      cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
+    p1 = Run(cmd, stdout=subprocess.PIPE)
+    p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
+
+    p2.wait()
+    p1.wait()
+    assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (sourcedir,)
+    assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (sourcedir,)
+
+    return ramdisk_img
+
+  if not os.access(os.path.join(sourcedir, "kernel"), os.F_OK):
+    return None
+
+  if has_ramdisk and not os.access(os.path.join(sourcedir, "RAMDISK"), os.F_OK):
     return None
 
   if info_dict is None:
     info_dict = OPTIONS.info_dict
 
-  ramdisk_img = tempfile.NamedTemporaryFile()
   img = tempfile.NamedTemporaryFile()
 
-  if os.access(fs_config_file, os.F_OK):
-    cmd = ["mkbootfs", "-f", fs_config_file, os.path.join(sourcedir, "RAMDISK")]
-  else:
-    cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
-  p1 = Run(cmd, stdout=subprocess.PIPE)
-  p2 = Run(["minigzip"],
-           stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
-
-  p2.wait()
-  p1.wait()
-  assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (targetname,)
-  assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (targetname,)
+  if has_ramdisk:
+    ramdisk_img = make_ramdisk()
 
   # use MKBOOTIMG from environ, or "mkbootimg" if empty or not set
   mkbootimg = os.getenv('MKBOOTIMG') or "mkbootimg"
@@ -337,8 +405,15 @@
   if args and args.strip():
     cmd.extend(shlex.split(args))
 
-  cmd.extend(["--ramdisk", ramdisk_img.name,
-              "--output", img.name])
+  if has_ramdisk:
+    cmd.extend(["--ramdisk", ramdisk_img.name])
+
+  img_unsigned = None
+  if info_dict.get("vboot", None):
+    img_unsigned = tempfile.NamedTemporaryFile()
+    cmd.extend(["--output", img_unsigned.name])
+  else:
+    cmd.extend(["--output", img.name])
 
   p = Run(cmd, stdout=subprocess.PIPE)
   p.communicate()
@@ -347,15 +422,34 @@
 
   if info_dict.get("verity_key", None):
     path = "/" + os.path.basename(sourcedir).lower()
-    cmd = ["boot_signer", path, img.name, info_dict["verity_key"] + ".pk8", info_dict["verity_key"] + ".x509.pem", img.name]
+    cmd = [OPTIONS.boot_signer_path, path, img.name,
+           info_dict["verity_key"] + ".pk8",
+           info_dict["verity_key"] + ".x509.pem", img.name]
     p = Run(cmd, stdout=subprocess.PIPE)
     p.communicate()
     assert p.returncode == 0, "boot_signer of %s image failed" % path
 
+  # Sign the image if vboot is non-empty.
+  elif info_dict.get("vboot", None):
+    path = "/" + os.path.basename(sourcedir).lower()
+    img_keyblock = tempfile.NamedTemporaryFile()
+    cmd = [info_dict["vboot_signer_cmd"], info_dict["futility"],
+           img_unsigned.name, info_dict["vboot_key"] + ".vbpubk",
+           info_dict["vboot_key"] + ".vbprivk", img_keyblock.name,
+           img.name]
+    p = Run(cmd, stdout=subprocess.PIPE)
+    p.communicate()
+    assert p.returncode == 0, "vboot_signer of %s image failed" % path
+
+    # Clean up the temp files.
+    img_unsigned.close()
+    img_keyblock.close()
+
   img.seek(os.SEEK_SET, 0)
   data = img.read()
 
-  ramdisk_img.close()
+  if has_ramdisk:
+    ramdisk_img.close()
   img.close()
 
   return data
@@ -363,11 +457,11 @@
 
 def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
                      info_dict=None):
-  """Return a File object (with name 'name') with the desired bootable
-  image.  Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name
-  'prebuilt_name', otherwise look for it under 'unpack_dir'/IMAGES,
-  otherwise construct it from the source files in
-  'unpack_dir'/'tree_subdir'."""
+  """Return a File object with the desired bootable image.
+
+  Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name 'prebuilt_name',
+  otherwise look for it under 'unpack_dir'/IMAGES, otherwise construct it from
+  the source files in 'unpack_dir'/'tree_subdir'."""
 
   prebuilt_path = os.path.join(unpack_dir, "BOOTABLE_IMAGES", prebuilt_name)
   if os.path.exists(prebuilt_path):
@@ -380,10 +474,18 @@
     return File.FromLocalFile(name, prebuilt_path)
 
   print "building image from target_files %s..." % (tree_subdir,)
+
+  if info_dict is None:
+    info_dict = OPTIONS.info_dict
+
+  # With system_root_image == "true", we don't pack ramdisk into the boot image.
+  has_ramdisk = (info_dict.get("system_root_image", None) != "true" or
+                 prebuilt_name != "boot.img")
+
   fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt"
-  data = BuildBootableImage(os.path.join(unpack_dir, tree_subdir),
-                            os.path.join(unpack_dir, fs_config),
-                            info_dict)
+  data = _BuildBootableImage(os.path.join(unpack_dir, tree_subdir),
+                             os.path.join(unpack_dir, fs_config),
+                             info_dict, has_ramdisk)
   if data:
     return File(name, data)
   return None
@@ -453,7 +555,7 @@
               stdin=devnull.fileno(),
               stdout=devnull.fileno(),
               stderr=subprocess.PIPE)
-      stdout, stderr = p.communicate()
+      _, stderr = p.communicate()
       if p.returncode == 0:
         # Encrypted key with empty string as password.
         key_passwords[k] = ''
@@ -512,7 +614,7 @@
     raise ExternalError("signapk.jar failed: return code %s" % (p.returncode,))
 
   if align:
-    p = Run(["zipalign", "-f", str(align), sign_name, output_name])
+    p = Run(["zipalign", "-f", "-p", str(align), sign_name, output_name])
     p.communicate()
     if p.returncode != 0:
       raise ExternalError("zipalign failed: return code %s" % (p.returncode,))
@@ -524,20 +626,23 @@
   any, for the given target.  Raise exception if the data is too big.
   Print a warning if the data is nearing the maximum size."""
 
-  if target.endswith(".img"): target = target[:-4]
+  if target.endswith(".img"):
+    target = target[:-4]
   mount_point = "/" + target
 
   fs_type = None
   limit = None
   if info_dict["fstab"]:
-    if mount_point == "/userdata": mount_point = "/data"
+    if mount_point == "/userdata":
+      mount_point = "/data"
     p = info_dict["fstab"][mount_point]
     fs_type = p.fs_type
     device = p.device
     if "/" in device:
       device = device[device.rfind("/")+1:]
     limit = info_dict.get(device + "_size", None)
-  if not fs_type or not limit: return
+  if not fs_type or not limit:
+    return
 
   if fs_type == "yaffs2":
     # image size should be increased by 1/64th to account for the
@@ -562,7 +667,8 @@
   certmap = {}
   for line in tf_zip.read("META/apkcerts.txt").split("\n"):
     line = line.strip()
-    if not line: continue
+    if not line:
+      continue
     m = re.match(r'^name="(.*)"\s+certificate="(.*)"\s+'
                  r'private_key="(.*)"$', line)
     if m:
@@ -620,15 +726,14 @@
         argv, "hvp:s:x:" + extra_opts,
         ["help", "verbose", "path=", "signapk_path=", "extra_signapk_args=",
          "java_path=", "java_args=", "public_key_suffix=",
-         "private_key_suffix=", "device_specific=", "extra="] +
+         "private_key_suffix=", "boot_signer_path=", "device_specific=",
+         "extra="] +
         list(extra_long_opts))
-  except getopt.GetoptError, err:
+  except getopt.GetoptError as err:
     Usage(docstring)
     print "**", str(err), "**"
     sys.exit(2)
 
-  path_specified = False
-
   for o, a in opts:
     if o in ("-h", "--help"):
       Usage(docstring)
@@ -649,6 +754,8 @@
       OPTIONS.public_key_suffix = a
     elif o in ("--private_key_suffix",):
       OPTIONS.private_key_suffix = a
+    elif o in ("--boot_signer_path",):
+      OPTIONS.boot_signer_path = a
     elif o in ("-s", "--device_specific"):
       OPTIONS.device_specific = a
     elif o in ("-x", "--extra"):
@@ -707,7 +814,8 @@
         if i not in current or not current[i]:
           missing.append(i)
       # Are all the passwords already in the file?
-      if not missing: return current
+      if not missing:
+        return current
 
       for i in missing:
         current[i] = ""
@@ -721,7 +829,7 @@
 
       current = self.UpdateAndReadFile(current)
 
-  def PromptResult(self, current):
+  def PromptResult(self, current): # pylint: disable=no-self-use
     """Prompt the user to enter a value (password) for each key in
     'current' whose value is fales.  Returns a new dict with all the
     values.
@@ -732,9 +840,10 @@
         result[k] = v
       else:
         while True:
-          result[k] = getpass.getpass("Enter password for %s key> "
-                                      % (k,)).strip()
-          if result[k]: break
+          result[k] = getpass.getpass(
+              "Enter password for %s key> " % k).strip()
+          if result[k]:
+            break
     return result
 
   def UpdateAndReadFile(self, current):
@@ -742,14 +851,13 @@
       return self.PromptResult(current)
 
     f = open(self.pwfile, "w")
-    os.chmod(self.pwfile, 0600)
+    os.chmod(self.pwfile, 0o600)
     f.write("# Enter key passwords between the [[[ ]]] brackets.\n")
     f.write("# (Additional spaces are harmless.)\n\n")
 
     first_line = None
-    sorted = [(not v, k, v) for (k, v) in current.iteritems()]
-    sorted.sort()
-    for i, (_, k, v) in enumerate(sorted):
+    sorted_list = sorted([(not v, k, v) for (k, v) in current.iteritems()])
+    for i, (_, k, v) in enumerate(sorted_list):
       f.write("[[[  %s  ]]] %s\n" % (v, k))
       if not v and first_line is None:
         # position cursor on first line with no password.
@@ -763,34 +871,118 @@
 
   def ReadFile(self):
     result = {}
-    if self.pwfile is None: return result
+    if self.pwfile is None:
+      return result
     try:
       f = open(self.pwfile, "r")
       for line in f:
         line = line.strip()
-        if not line or line[0] == '#': continue
+        if not line or line[0] == '#':
+          continue
         m = re.match(r"^\[\[\[\s*(.*?)\s*\]\]\]\s*(\S+)$", line)
         if not m:
           print "failed to parse password file: ", line
         else:
           result[m.group(2)] = m.group(1)
       f.close()
-    except IOError, e:
+    except IOError as e:
       if e.errno != errno.ENOENT:
         print "error reading password file: ", str(e)
     return result
 
 
-def ZipWriteStr(zip, filename, data, perms=0644, compression=None):
-  # use a fixed timestamp so the output is repeatable.
-  zinfo = zipfile.ZipInfo(filename=filename,
-                          date_time=(2009, 1, 1, 0, 0, 0))
-  if compression is None:
-    zinfo.compress_type = zip.compression
+def ZipWrite(zip_file, filename, arcname=None, perms=0o644,
+             compress_type=None):
+  import datetime
+
+  # http://b/18015246
+  # Python 2.7's zipfile implementation wrongly thinks that zip64 is required
+  # for files larger than 2GiB. We can work around this by adjusting their
+  # limit. Note that `zipfile.writestr()` will not work for strings larger than
+  # 2GiB. The Python interpreter sometimes rejects strings that large (though
+  # it isn't clear to me exactly what circumstances cause this).
+  # `zipfile.write()` must be used directly to work around this.
+  #
+  # This mess can be avoided if we port to python3.
+  saved_zip64_limit = zipfile.ZIP64_LIMIT
+  zipfile.ZIP64_LIMIT = (1 << 32) - 1
+
+  if compress_type is None:
+    compress_type = zip_file.compression
+  if arcname is None:
+    arcname = filename
+
+  saved_stat = os.stat(filename)
+
+  try:
+    # `zipfile.write()` doesn't allow us to pass ZipInfo, so just modify the
+    # file to be zipped and reset it when we're done.
+    os.chmod(filename, perms)
+
+    # Use a fixed timestamp so the output is repeatable.
+    epoch = datetime.datetime.fromtimestamp(0)
+    timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
+    os.utime(filename, (timestamp, timestamp))
+
+    zip_file.write(filename, arcname=arcname, compress_type=compress_type)
+  finally:
+    os.chmod(filename, saved_stat.st_mode)
+    os.utime(filename, (saved_stat.st_atime, saved_stat.st_mtime))
+    zipfile.ZIP64_LIMIT = saved_zip64_limit
+
+
+def ZipWriteStr(zip_file, zinfo_or_arcname, data, perms=None,
+                compress_type=None):
+  """Wrap zipfile.writestr() function to work around the zip64 limit.
+
+  Even with the ZIP64_LIMIT workaround, it won't allow writing a string
+  longer than 2GiB. It gives 'OverflowError: size does not fit in an int'
+  when calling crc32(bytes).
+
+  But it still works fine to write a shorter string into a large zip file.
+  We should use ZipWrite() whenever possible, and only use ZipWriteStr()
+  when we know the string won't be too long.
+  """
+
+  saved_zip64_limit = zipfile.ZIP64_LIMIT
+  zipfile.ZIP64_LIMIT = (1 << 32) - 1
+
+  if not isinstance(zinfo_or_arcname, zipfile.ZipInfo):
+    zinfo = zipfile.ZipInfo(filename=zinfo_or_arcname)
+    zinfo.compress_type = zip_file.compression
+    if perms is None:
+      perms = 0o100644
   else:
-    zinfo.compress_type = compression
-  zinfo.external_attr = perms << 16
-  zip.writestr(zinfo, data)
+    zinfo = zinfo_or_arcname
+
+  # If compress_type is given, it overrides the value in zinfo.
+  if compress_type is not None:
+    zinfo.compress_type = compress_type
+
+  # If perms is given, it has a priority.
+  if perms is not None:
+    # If perms doesn't set the file type, mark it as a regular file.
+    if perms & 0o770000 == 0:
+      perms |= 0o100000
+    zinfo.external_attr = perms << 16
+
+  # Use a fixed timestamp so the output is repeatable.
+  zinfo.date_time = (2009, 1, 1, 0, 0, 0)
+
+  zip_file.writestr(zinfo, data)
+  zipfile.ZIP64_LIMIT = saved_zip64_limit
+
+
+def ZipClose(zip_file):
+  # http://b/18015246
+  # zipfile also refers to ZIP64_LIMIT during close() when it writes out the
+  # central directory.
+  saved_zip64_limit = zipfile.ZIP64_LIMIT
+  zipfile.ZIP64_LIMIT = (1 << 32) - 1
+
+  zip_file.close()
+
+  zipfile.ZIP64_LIMIT = saved_zip64_limit
 
 
 class DeviceSpecificParams(object):
@@ -805,7 +997,8 @@
 
     if self.module is None:
       path = OPTIONS.device_specific
-      if not path: return
+      if not path:
+        return
       try:
         if os.path.isdir(path):
           info = imp.find_module("releasetools", [path])
@@ -895,7 +1088,7 @@
     return t
 
   def AddToZip(self, z, compression=None):
-    ZipWriteStr(z, self.name, self.data, compression=compression)
+    ZipWriteStr(z, self.name, self.data, compress_type=compression)
 
 DIFF_PROGRAM_BY_EXT = {
     ".gz" : "imgdiff",
@@ -943,7 +1136,8 @@
       err = []
       def run():
         _, e = p.communicate()
-        if e: err.append(e)
+        if e:
+          err.append(e)
       th = threading.Thread(target=run)
       th.start()
       th.join(timeout=300)   # 5 mins
@@ -1010,7 +1204,7 @@
           print "%8.2f sec %8d / %8d bytes (%6.2f%%) %s" % (
               dur, len(patch), tf.size, 100.0 * len(patch) / tf.size, name)
       lock.release()
-    except Exception, e:
+    except Exception as e:
       print e
       raise
 
@@ -1023,13 +1217,17 @@
     threads.pop().join()
 
 
-class BlockDifference:
-  def __init__(self, partition, tgt, src=None, check_first_block=False, version=None):
+class BlockDifference(object):
+  def __init__(self, partition, tgt, src=None, check_first_block=False,
+               version=None):
     self.tgt = tgt
     self.src = src
     self.partition = partition
     self.check_first_block = check_first_block
 
+    # Due to http://b/20939131, check_first_block is disabled temporarily.
+    assert not self.check_first_block
+
     if version is None:
       version = 1
       if OPTIONS.info_dict:
@@ -1054,25 +1252,30 @@
     else:
       script.Print("Patching %s image after verification." % (self.partition,))
 
-    if progress: script.ShowProgress(progress, 0)
+    if progress:
+      script.ShowProgress(progress, 0)
     self._WriteUpdate(script, output_zip)
+    self._WritePostInstallVerifyScript(script)
 
   def WriteVerifyScript(self, script):
     partition = self.partition
     if not self.src:
       script.Print("Image %s will be patched unconditionally." % (partition,))
     else:
+      ranges = self.src.care_map.subtract(self.src.clobbered_blocks)
+      ranges_str = ranges.to_string_raw()
       if self.version >= 3:
-        script.AppendExtra(('if block_image_verify("%s", '
+        script.AppendExtra(('if (range_sha1("%s", "%s") == "%s" || '
+                            'block_image_verify("%s", '
                             'package_extract_file("%s.transfer.list"), '
-                            '"%s.new.dat", "%s.patch.dat") then') %
-                           (self.device, partition, partition, partition))
+                            '"%s.new.dat", "%s.patch.dat")) then') % (
+                            self.device, ranges_str, self.src.TotalSha1(),
+                            self.device, partition, partition, partition))
       else:
-        script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' %
-                            (self.device, self.src.care_map.to_string_raw(),
-                            self.src.TotalSha1()))
+        script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
+                           self.device, ranges_str, self.src.TotalSha1()))
       script.Print('Verified %s image...' % (partition,))
-      script.AppendExtra('else');
+      script.AppendExtra('else')
 
       # When generating incrementals for the system and vendor partitions,
       # explicitly check the first block (which contains the superblock) of
@@ -1091,23 +1294,56 @@
       script.AppendExtra(('abort("%s partition has unexpected contents");\n'
                           'endif;') % (partition,))
 
-  def _WriteUpdate(self, script, output_zip):
+  def _WritePostInstallVerifyScript(self, script):
     partition = self.partition
-    with open(self.path + ".transfer.list", "rb") as f:
-      ZipWriteStr(output_zip, partition + ".transfer.list", f.read())
-    with open(self.path + ".new.dat", "rb") as f:
-      ZipWriteStr(output_zip, partition + ".new.dat", f.read())
-    with open(self.path + ".patch.dat", "rb") as f:
-      ZipWriteStr(output_zip, partition + ".patch.dat", f.read(),
-                         compression=zipfile.ZIP_STORED)
+    script.Print('Verifying the updated %s image...' % (partition,))
+    # Unlike pre-install verification, clobbered_blocks should not be ignored.
+    ranges = self.tgt.care_map
+    ranges_str = ranges.to_string_raw()
+    script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
+                       self.device, ranges_str,
+                       self.tgt.TotalSha1(include_clobbered_blocks=True)))
 
-    call = (('block_image_update("%s", '
-             'package_extract_file("%s.transfer.list"), '
-             '"%s.new.dat", "%s.patch.dat");\n') %
-            (self.device, partition, partition, partition))
-    script.AppendExtra(script._WordWrap(call))
+    # Bug: 20881595
+    # Verify that extended blocks are really zeroed out.
+    if self.tgt.extended:
+      ranges_str = self.tgt.extended.to_string_raw()
+      script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
+                         self.device, ranges_str,
+                         self._HashZeroBlocks(self.tgt.extended.size())))
+      script.Print('Verified the updated %s image.' % (partition,))
+      script.AppendExtra(
+          'else\n'
+          '  abort("%s partition has unexpected non-zero contents after OTA '
+          'update");\n'
+          'endif;' % (partition,))
+    else:
+      script.Print('Verified the updated %s image.' % (partition,))
 
-  def _HashBlocks(self, source, ranges):
+    script.AppendExtra(
+        'else\n'
+        '  abort("%s partition has unexpected contents after OTA update");\n'
+        'endif;' % (partition,))
+
+  def _WriteUpdate(self, script, output_zip):
+    ZipWrite(output_zip,
+             '{}.transfer.list'.format(self.path),
+             '{}.transfer.list'.format(self.partition))
+    ZipWrite(output_zip,
+             '{}.new.dat'.format(self.path),
+             '{}.new.dat'.format(self.partition))
+    ZipWrite(output_zip,
+             '{}.patch.dat'.format(self.path),
+             '{}.patch.dat'.format(self.partition),
+             compress_type=zipfile.ZIP_STORED)
+
+    call = ('block_image_update("{device}", '
+            'package_extract_file("{partition}.transfer.list"), '
+            '"{partition}.new.dat", "{partition}.patch.dat");\n'.format(
+                device=self.device, partition=self.partition))
+    script.AppendExtra(script.WordWrap(call))
+
+  def _HashBlocks(self, source, ranges): # pylint: disable=no-self-use
     data = source.ReadRangeSet(ranges)
     ctx = sha1()
 
@@ -1116,9 +1352,21 @@
 
     return ctx.hexdigest()
 
+  def _HashZeroBlocks(self, num_blocks): # pylint: disable=no-self-use
+    """Return the hash value for all zero blocks."""
+    zero_block = '\x00' * 4096
+    ctx = sha1()
+    for _ in range(num_blocks):
+      ctx.update(zero_block)
+
+    return ctx.hexdigest()
+
+  # TODO(tbao): Due to http://b/20939131, block 0 may be changed without
+  # remounting R/W. Will change the checking to a finer-grained way to
+  # mask off those bits.
   def _CheckFirstBlock(self, script):
-    r = RangeSet((0, 1))
-    srchash = self._HashBlocks(self.src, r);
+    r = rangelib.RangeSet((0, 1))
+    srchash = self._HashBlocks(self.src, r)
 
     script.AppendExtra(('(range_sha1("%s", "%s") == "%s") || '
                         'abort("%s has been remounted R/W; '
@@ -1130,16 +1378,22 @@
 
 
 # map recovery.fstab's fs_types to mount/format "partition types"
-PARTITION_TYPES = { "yaffs2": "MTD", "mtd": "MTD",
-                    "ext4": "EMMC", "emmc": "EMMC",
-                    "f2fs": "EMMC" }
+PARTITION_TYPES = {
+    "yaffs2": "MTD",
+    "mtd": "MTD",
+    "ext4": "EMMC",
+    "emmc": "EMMC",
+    "f2fs": "EMMC",
+    "squashfs": "EMMC"
+}
 
 def GetTypeAndDevice(mount_point, info):
   fstab = info["fstab"]
   if fstab:
-    return PARTITION_TYPES[fstab[mount_point].fs_type], fstab[mount_point].device
+    return (PARTITION_TYPES[fstab[mount_point].fs_type],
+            fstab[mount_point].device)
   else:
-    return None
+    raise KeyError
 
 
 def ParseCertificate(data):
@@ -1173,58 +1427,86 @@
   if info_dict is None:
     info_dict = OPTIONS.info_dict
 
-  diff_program = ["imgdiff"]
-  path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat")
-  if os.path.exists(path):
-    diff_program.append("-b")
-    diff_program.append(path)
-    bonus_args = "-b /system/etc/recovery-resource.dat"
+  full_recovery_image = info_dict.get("full_recovery_image", None) == "true"
+  system_root_image = info_dict.get("system_root_image", None) == "true"
+
+  if full_recovery_image:
+    output_sink("etc/recovery.img", recovery_img.data)
+
   else:
-    bonus_args = ""
+    diff_program = ["imgdiff"]
+    path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat")
+    if os.path.exists(path):
+      diff_program.append("-b")
+      diff_program.append(path)
+      bonus_args = "-b /system/etc/recovery-resource.dat"
+    else:
+      bonus_args = ""
 
-  d = Difference(recovery_img, boot_img, diff_program=diff_program)
-  _, _, patch = d.ComputePatch()
-  output_sink("recovery-from-boot.p", patch)
+    d = Difference(recovery_img, boot_img, diff_program=diff_program)
+    _, _, patch = d.ComputePatch()
+    output_sink("recovery-from-boot.p", patch)
 
-  td_pair = GetTypeAndDevice("/boot", info_dict)
-  if not td_pair:
+  try:
+    boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
+    recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict)
+  except KeyError:
     return
-  boot_type, boot_device = td_pair
-  td_pair = GetTypeAndDevice("/recovery", info_dict)
-  if not td_pair:
-    return
-  recovery_type, recovery_device = td_pair
 
-  sh = """#!/system/bin/sh
+  if full_recovery_image:
+    sh = """#!/system/bin/sh
+if ! applypatch -c %(type)s:%(device)s:%(size)d:%(sha1)s; then
+  applypatch /system/etc/recovery.img %(type)s:%(device)s %(sha1)s %(size)d && log -t recovery "Installing new recovery image: succeeded" || log -t recovery "Installing new recovery image: failed"
+else
+  log -t recovery "Recovery image already installed"
+fi
+""" % {'type': recovery_type,
+       'device': recovery_device,
+       'sha1': recovery_img.sha1,
+       'size': recovery_img.size}
+  else:
+    sh = """#!/system/bin/sh
 if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then
   applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p && log -t recovery "Installing new recovery image: succeeded" || log -t recovery "Installing new recovery image: failed"
 else
   log -t recovery "Recovery image already installed"
 fi
-""" % { 'boot_size': boot_img.size,
-        'boot_sha1': boot_img.sha1,
-        'recovery_size': recovery_img.size,
-        'recovery_sha1': recovery_img.sha1,
-        'boot_type': boot_type,
-        'boot_device': boot_device,
-        'recovery_type': recovery_type,
-        'recovery_device': recovery_device,
-        'bonus_args': bonus_args,
-        }
+""" % {'boot_size': boot_img.size,
+       'boot_sha1': boot_img.sha1,
+       'recovery_size': recovery_img.size,
+       'recovery_sha1': recovery_img.sha1,
+       'boot_type': boot_type,
+       'boot_device': boot_device,
+       'recovery_type': recovery_type,
+       'recovery_device': recovery_device,
+       'bonus_args': bonus_args}
 
   # The install script location moved from /system/etc to /system/bin
-  # in the L release.  Parse the init.rc file to find out where the
+  # in the L release.  Parse init.*.rc files to find out where the
   # target-files expects it to be, and put it there.
   sh_location = "etc/install-recovery.sh"
-  try:
-    with open(os.path.join(input_dir, "BOOT", "RAMDISK", "init.rc")) as f:
+  found = False
+  if system_root_image:
+    init_rc_dir = os.path.join(input_dir, "ROOT")
+  else:
+    init_rc_dir = os.path.join(input_dir, "BOOT", "RAMDISK")
+  init_rc_files = os.listdir(init_rc_dir)
+  for init_rc_file in init_rc_files:
+    if (not init_rc_file.startswith('init.') or
+        not init_rc_file.endswith('.rc')):
+      continue
+
+    with open(os.path.join(init_rc_dir, init_rc_file)) as f:
       for line in f:
-        m = re.match("^service flash_recovery /system/(\S+)\s*$", line)
+        m = re.match(r"^service flash_recovery /system/(\S+)\s*$", line)
         if m:
           sh_location = m.group(1)
-          print "putting script in", sh_location
+          found = True
           break
-  except (OSError, IOError), e:
-    print "failed to read init.rc: %s" % (e,)
+
+    if found:
+      break
+
+  print "putting script in", sh_location
 
   output_sink(sh_location, sh)
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index e52c264..8964720 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -12,7 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import os
 import re
 
 import common
@@ -21,11 +20,15 @@
   """Class to generate scripts in the 'edify' recovery script language
   used from donut onwards."""
 
-  def __init__(self, version, info):
+  def __init__(self, version, info, fstab=None):
     self.script = []
     self.mounts = set()
     self.version = version
     self.info = info
+    if fstab is None:
+      self.fstab = self.info.get("fstab", None)
+    else:
+      self.fstab = fstab
 
   def MakeTemporary(self):
     """Make a temporary script object whose commands can latter be
@@ -36,7 +39,7 @@
     return x
 
   @staticmethod
-  def _WordWrap(cmd, linelen=80):
+  def WordWrap(cmd, linelen=80):
     """'cmd' should be a function call with null characters after each
     parameter (eg, "somefun(foo,\0bar,\0baz)").  This function wraps cmd
     to a given line length, replacing nulls with spaces and/or newlines
@@ -74,35 +77,33 @@
       raise ValueError("must specify an OEM property")
     if not value:
       raise ValueError("must specify the OEM value")
-    cmd = ('file_getprop("/oem/oem.prop", "%s") == "%s" || '
-           'abort("This package expects the value \\"%s\\"  for '
-           '\\"%s\\" on the OEM partition; '
-           'this has value \\"" + file_getprop("/oem/oem.prop") + "\\".");'
-           ) % (name, value, name, value)
+    cmd = ('file_getprop("/oem/oem.prop", "{name}") == "{value}" || '
+           'abort("This package expects the value \\"{value}\\" for '
+           '\\"{name}\\" on the OEM partition; this has value \\"" + '
+           'file_getprop("/oem/oem.prop", "{name}") + "\\".");').format(
+               name=name, value=value)
     self.script.append(cmd)
 
   def AssertSomeFingerprint(self, *fp):
     """Assert that the current recovery build fingerprint is one of *fp."""
     if not fp:
       raise ValueError("must specify some fingerprints")
-    cmd = (
-           ' ||\n    '.join([('getprop("ro.build.fingerprint") == "%s"')
-                        % i for i in fp]) +
+    cmd = (' ||\n    '.join([('getprop("ro.build.fingerprint") == "%s"') % i
+                             for i in fp]) +
            ' ||\n    abort("Package expects build fingerprint of %s; this '
-           'device has " + getprop("ro.build.fingerprint") + ".");'
-           ) % (" or ".join(fp),)
+           'device has " + getprop("ro.build.fingerprint") + ".");') % (
+               " or ".join(fp))
     self.script.append(cmd)
 
   def AssertSomeThumbprint(self, *fp):
     """Assert that the current recovery build thumbprint is one of *fp."""
     if not fp:
       raise ValueError("must specify some thumbprints")
-    cmd = (
-           ' ||\n    '.join([('getprop("ro.build.thumbprint") == "%s"')
-                        % i for i in fp]) +
+    cmd = (' ||\n    '.join([('getprop("ro.build.thumbprint") == "%s"') % i
+                             for i in fp]) +
            ' ||\n    abort("Package expects build thumbprint of %s; this '
-           'device has " + getprop("ro.build.thumbprint") + ".");'
-           ) % (" or ".join(fp),)
+           'device has " + getprop("ro.build.thumbprint") + ".");') % (
+               " or ".join(fp))
     self.script.append(cmd)
 
   def AssertOlderBuild(self, timestamp, timestamp_text):
@@ -111,15 +112,15 @@
     self.script.append(
         ('(!less_than_int(%s, getprop("ro.build.date.utc"))) || '
          'abort("Can\'t install this package (%s) over newer '
-         'build (" + getprop("ro.build.date") + ").");'
-         ) % (timestamp, timestamp_text))
+         'build (" + getprop("ro.build.date") + ").");') % (timestamp,
+                                                            timestamp_text))
 
   def AssertDevice(self, device):
     """Assert that the device identifier is the given string."""
     cmd = ('getprop("ro.product.device") == "%s" || '
            'abort("This package is for \\"%s\\" devices; '
-           'this is a \\"" + getprop("ro.product.device") + "\\".");'
-           ) % (device, device)
+           'this is a \\"" + getprop("ro.product.device") + "\\".");') % (
+               device, device)
     self.script.append(cmd)
 
   def AssertSomeBootloader(self, *bootloaders):
@@ -128,7 +129,7 @@
            " ||\0".join(['getprop("ro.bootloader") == "%s"' % (b,)
                          for b in bootloaders]) +
            ");")
-    self.script.append(self._WordWrap(cmd))
+    self.script.append(self.WordWrap(cmd))
 
   def ShowProgress(self, frac, dur):
     """Update the progress bar, advancing it over 'frac' over the next
@@ -162,7 +163,7 @@
     """Check that there's at least 'amount' space that can be made
     available on /cache."""
     self.script.append(('apply_patch_space(%d) || abort("Not enough free space '
-                        'on /system to apply patches.");') % (amount,))
+                        'on /cache to apply patches.");') % (amount,))
 
   def Mount(self, mount_point, mount_options_by_format=""):
     """Mount the partition with the given mount_point.
@@ -171,7 +172,7 @@
       where option is optname[=optvalue]
       E.g. ext4=barrier=1,nodelalloc,errors=panic|f2fs=errors=recover
     """
-    fstab = self.info.get("fstab", None)
+    fstab = self.fstab
     if fstab:
       p = fstab[mount_point]
       mount_dict = {}
@@ -180,9 +181,12 @@
           if "=" in option:
             key, value = option.split("=", 1)
             mount_dict[key] = value
-      self.script.append('mount("%s", "%s", "%s", "%s", "%s");' %
-                         (p.fs_type, common.PARTITION_TYPES[p.fs_type],
-                          p.device, p.mount_point, mount_dict.get(p.fs_type, "")))
+      mount_flags = mount_dict.get(p.fs_type, "")
+      if p.context is not None:
+        mount_flags = p.context + ("," + mount_flags if mount_flags else "")
+      self.script.append('mount("%s", "%s", "%s", "%s", "%s");' % (
+          p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device,
+          p.mount_point, mount_flags))
       self.mounts.add(p.mount_point)
 
   def UnpackPackageDir(self, src, dst):
@@ -202,22 +206,21 @@
     self.script.append('ui_print("%s");' % (message,))
 
   def TunePartition(self, partition, *options):
-    fstab = self.info.get("fstab", None)
+    fstab = self.fstab
     if fstab:
       p = fstab[partition]
-      if (p.fs_type not in ( "ext2", "ext3", "ext4")):
+      if p.fs_type not in ("ext2", "ext3", "ext4"):
         raise ValueError("Partition %s cannot be tuned\n" % (partition,))
-    self.script.append('tune2fs(' +
-                       "".join(['"%s", ' % (i,) for i in options]) +
-                       '"%s") || abort("Failed to tune partition %s");'
-                       % ( p.device,partition));
+    self.script.append(
+        'tune2fs(' + "".join(['"%s", ' % (i,) for i in options]) +
+        '"%s") || abort("Failed to tune partition %s");' % (
+            p.device, partition))
 
   def FormatPartition(self, partition):
     """Format the given partition, specified by its mount point (eg,
     "/system")."""
 
-    reserve_size = 0
-    fstab = self.info.get("fstab", None)
+    fstab = self.fstab
     if fstab:
       p = fstab[partition]
       self.script.append('format("%s", "%s", "%s", "%s", "%s");' %
@@ -227,7 +230,7 @@
   def WipeBlockDevice(self, partition):
     if partition not in ("/system", "/vendor"):
       raise ValueError(("WipeBlockDevice doesn't work on %s\n") % (partition,))
-    fstab = self.info.get("fstab", None)
+    fstab = self.fstab
     size = self.info.get(partition.lstrip("/") + "_size", None)
     device = fstab[partition].device
 
@@ -235,9 +238,10 @@
 
   def DeleteFiles(self, file_list):
     """Delete all files in file_list."""
-    if not file_list: return
+    if not file_list:
+      return
     cmd = "delete(" + ",\0".join(['"%s"' % (i,) for i in file_list]) + ");"
-    self.script.append(self._WordWrap(cmd))
+    self.script.append(self.WordWrap(cmd))
 
   def RenameFile(self, srcfile, tgtfile):
     """Moves a file from one location to another."""
@@ -251,7 +255,7 @@
        skip the action if the file exists.  Used when a patch
        is later renamed."""
     cmd = ('sha1_check(read_file("%s"), %s) || ' % (tgtfile, tgtsha1))
-    self.script.append(self._WordWrap(cmd))
+    self.script.append(self.WordWrap(cmd))
 
   def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
     """Apply binary patches (in *patchpairs) to the given srcfile to
@@ -265,13 +269,13 @@
       cmd.append(',\0%s, package_extract_file("%s")' % patchpairs[i:i+2])
     cmd.append(');')
     cmd = "".join(cmd)
-    self.script.append(self._WordWrap(cmd))
+    self.script.append(self.WordWrap(cmd))
 
   def WriteRawImage(self, mount_point, fn, mapfn=None):
     """Write the given package file into the partition for the given
     mount point."""
 
-    fstab = self.info["fstab"]
+    fstab = self.fstab
     if fstab:
       p = fstab[mount_point]
       partition_type = common.PARTITION_TYPES[p.fs_type]
@@ -289,33 +293,37 @@
           self.script.append(
               'package_extract_file("%(fn)s", "%(device)s");' % args)
       else:
-        raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,))
+        raise ValueError(
+            "don't know how to write \"%s\" partitions" % p.fs_type)
 
   def SetPermissions(self, fn, uid, gid, mode, selabel, capabilities):
     """Set file ownership and permissions."""
     if not self.info.get("use_set_metadata", False):
       self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn))
     else:
-      if capabilities is None: capabilities = "0x0"
+      if capabilities is None:
+        capabilities = "0x0"
       cmd = 'set_metadata("%s", "uid", %d, "gid", %d, "mode", 0%o, ' \
           '"capabilities", %s' % (fn, uid, gid, mode, capabilities)
       if selabel is not None:
-        cmd += ', "selabel", "%s"' % ( selabel )
+        cmd += ', "selabel", "%s"' % selabel
       cmd += ');'
       self.script.append(cmd)
 
-  def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode, selabel, capabilities):
+  def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode, selabel,
+                              capabilities):
     """Recursively set path ownership and permissions."""
     if not self.info.get("use_set_metadata", False):
       self.script.append('set_perm_recursive(%d, %d, 0%o, 0%o, "%s");'
                          % (uid, gid, dmode, fmode, fn))
     else:
-      if capabilities is None: capabilities = "0x0"
+      if capabilities is None:
+        capabilities = "0x0"
       cmd = 'set_metadata_recursive("%s", "uid", %d, "gid", %d, ' \
           '"dmode", 0%o, "fmode", 0%o, "capabilities", %s' \
           % (fn, uid, gid, dmode, fmode, capabilities)
       if selabel is not None:
-        cmd += ', "selabel", "%s"' % ( selabel )
+        cmd += ', "selabel", "%s"' % selabel
       cmd += ');'
       self.script.append(cmd)
 
@@ -328,15 +336,15 @@
     for dest, links in sorted(by_dest.iteritems()):
       cmd = ('symlink("%s", ' % (dest,) +
              ",\0".join(['"' + i + '"' for i in sorted(links)]) + ");")
-      self.script.append(self._WordWrap(cmd))
+      self.script.append(self.WordWrap(cmd))
 
   def AppendExtra(self, extra):
     """Append text verbatim to the output script."""
     self.script.append(extra)
 
   def Unmount(self, mount_point):
-    self.script.append('unmount("%s");' % (mount_point,))
-    self.mounts.remove(mount_point);
+    self.script.append('unmount("%s");' % mount_point)
+    self.mounts.remove(mount_point)
 
   def UnmountAll(self):
     for p in sorted(self.mounts):
@@ -359,4 +367,4 @@
     else:
       data = open(input_path, "rb").read()
     common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary",
-                       data, perms=0755)
+                       data, perms=0o755)
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index 4b88e73..ce5808f 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -32,18 +32,10 @@
   print >> sys.stderr, "Python 2.7 or newer is required."
   sys.exit(1)
 
-import errno
 import os
-import re
 import shutil
-import subprocess
-import tempfile
 import zipfile
 
-# missing in Python 2.4 and before
-if not hasattr(os, "SEEK_SET"):
-  os.SEEK_SET = 0
-
 import common
 
 OPTIONS = common.OPTIONS
@@ -51,14 +43,15 @@
 
 def CopyInfo(output_zip):
   """Copy the android-info.txt file from the input to the output."""
-  output_zip.write(os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"),
-                   "android-info.txt")
+  common.ZipWrite(
+      output_zip, os.path.join(OPTIONS.input_tmp, "OTA", "android-info.txt"),
+      "android-info.txt")
 
 
 def main(argv):
   bootable_only = [False]
 
-  def option_handler(o, a):
+  def option_handler(o, _):
     if o in ("-z", "--bootable_zip"):
       bootable_only[0] = True
     else:
@@ -88,11 +81,13 @@
       # and all we have to do is copy them to the output zip.
       images = os.listdir(images_path)
       if images:
-        for i in images:
-          if bootable_only and i not in ("boot.img", "recovery.img"): continue
-          if not i.endswith(".img"): continue
-          with open(os.path.join(images_path, i), "r") as f:
-            common.ZipWriteStr(output_zip, i, f.read())
+        for image in images:
+          if bootable_only and image not in ("boot.img", "recovery.img"):
+            continue
+          if not image.endswith(".img"):
+            continue
+          common.ZipWrite(
+              output_zip, os.path.join(images_path, image), image)
         done = True
 
     if not done:
@@ -100,21 +95,13 @@
       # images, so build them.
       import add_img_to_target_files
 
-      OPTIONS.info_dict = common.LoadInfoDict(input_zip)
-
-      # If this image was originally labelled with SELinux contexts,
-      # make sure we also apply the labels in our new image. During
-      # building, the "file_contexts" is in the out/ directory tree,
-      # but for repacking from target-files.zip it's in the root
-      # directory of the ramdisk.
-      if "selinux_fc" in OPTIONS.info_dict:
-        OPTIONS.info_dict["selinux_fc"] = os.path.join(
-            OPTIONS.input_tmp, "BOOT", "RAMDISK", "file_contexts")
+      OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)
 
       boot_image = common.GetBootableImage(
           "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
       if boot_image:
-          boot_image.AddToZip(output_zip)
+        boot_image.AddToZip(output_zip)
+
       recovery_image = common.GetBootableImage(
           "recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY")
       if recovery_image:
@@ -139,7 +126,7 @@
 
   finally:
     print "cleaning up..."
-    output_zip.close()
+    common.ZipClose(output_zip)
     shutil.rmtree(OPTIONS.input_tmp)
 
   print "done."
@@ -149,7 +136,7 @@
   try:
     common.CloseInheritedPipes()
     main(sys.argv[1:])
-  except common.ExternalError, e:
+  except common.ExternalError as e:
     print
     print "   ERROR: %s" % (e,)
     print
diff --git a/tools/releasetools/make_recovery_patch b/tools/releasetools/make_recovery_patch
new file mode 120000
index 0000000..45cec08
--- /dev/null
+++ b/tools/releasetools/make_recovery_patch
@@ -0,0 +1 @@
+make_recovery_patch.py
\ No newline at end of file
diff --git a/tools/releasetools/make_recovery_patch b/tools/releasetools/make_recovery_patch.py
similarity index 100%
rename from tools/releasetools/make_recovery_patch
rename to tools/releasetools/make_recovery_patch.py
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
new file mode 120000
index 0000000..6755a90
--- /dev/null
+++ b/tools/releasetools/ota_from_target_files
@@ -0,0 +1 @@
+ota_from_target_files.py
\ No newline at end of file
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files.py
similarity index 79%
rename from tools/releasetools/ota_from_target_files
rename to tools/releasetools/ota_from_target_files.py
index 25309a4..c074f10 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files.py
@@ -37,6 +37,15 @@
       Generate an incremental OTA using the given target-files zip as
       the starting build.
 
+  --full_radio
+      When generating an incremental OTA, always include a full copy of
+      radio image. This option is only meaningful when -i is specified,
+      because a full radio is always included in a full OTA if applicable.
+
+  --full_bootloader
+      Similar to --full_radio. When generating an incremental OTA, always
+      include a full copy of bootloader image.
+
   -v  (--verify)
       Remount and verify the checksums of the files written to the
       system and vendor (if used) partitions.  Incremental builds only.
@@ -79,6 +88,9 @@
       Specifies the number of worker-threads that will be used when
       generating patches for incremental updates (defaults to 3).
 
+  --stash_threshold <float>
+      Specifies the threshold that will be used to compute the maximum
+      allowed stash size (defaults to 0.8).
 """
 
 import sys
@@ -87,22 +99,13 @@
   print >> sys.stderr, "Python 2.7 or newer is required."
   sys.exit(1)
 
-import copy
-import errno
 import multiprocessing
 import os
-import re
-import subprocess
 import tempfile
-import time
 import zipfile
 
-from hashlib import sha1 as sha1
-
 import common
 import edify_generator
-import build_image
-import blockimgdiff
 import sparse_img
 
 OPTIONS = common.OPTIONS
@@ -125,12 +128,16 @@
 OPTIONS.updater_binary = None
 OPTIONS.oem_source = None
 OPTIONS.fallback_to_full = True
+OPTIONS.full_radio = False
+OPTIONS.full_bootloader = False
+
 
 def MostPopularKey(d, default):
   """Given a dict, return the key corresponding to the largest
   value.  Returns 'default' if the dict is empty."""
   x = [(v, k) for (k, v) in d.iteritems()]
-  if not x: return default
+  if not x:
+    return default
   x.sort()
   return x[-1][1]
 
@@ -138,12 +145,12 @@
 def IsSymlink(info):
   """Return true if the zipfile.ZipInfo object passed in represents a
   symlink."""
-  return (info.external_attr >> 16) == 0120777
+  return (info.external_attr >> 16) & 0o770000 == 0o120000
 
 def IsRegular(info):
   """Return true if the zipfile.ZipInfo object passed in represents a
-  symlink."""
-  return (info.external_attr >> 28) == 010
+  regular file."""
+  return (info.external_attr >> 16) & 0o770000 == 0o100000
 
 def ClosestFileMatch(src, tgtfiles, existing):
   """Returns the closest file match between a source file and list
@@ -170,15 +177,15 @@
     return result
   return None
 
-class ItemSet:
+class ItemSet(object):
   def __init__(self, partition, fs_config):
     self.partition = partition
     self.fs_config = fs_config
     self.ITEMS = {}
 
-  def Get(self, name, dir=False):
+  def Get(self, name, is_dir=False):
     if name not in self.ITEMS:
-      self.ITEMS[name] = Item(self, name, dir=dir)
+      self.ITEMS[name] = Item(self, name, is_dir=is_dir)
     return self.ITEMS[name]
 
   def GetMetadata(self, input_zip):
@@ -187,7 +194,8 @@
     output = input_zip.read(self.fs_config)
 
     for line in output.split("\n"):
-      if not line: continue
+      if not line:
+        continue
       columns = line.split()
       name, uid, gid, mode = columns[:4]
       selabel = None
@@ -209,20 +217,23 @@
         i.mode = int(mode, 8)
         i.selabel = selabel
         i.capabilities = capabilities
-        if i.dir:
+        if i.is_dir:
           i.children.sort(key=lambda i: i.name)
 
-    # set metadata for the files generated by this script.
+    # Set metadata for the files generated by this script. For full recovery
+    # image at system/etc/recovery.img, it will be taken care by fs_config.
     i = self.ITEMS.get("system/recovery-from-boot.p", None)
-    if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0644, None, None
+    if i:
+      i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0o644, None, None
     i = self.ITEMS.get("system/etc/install-recovery.sh", None)
-    if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0544, None, None
+    if i:
+      i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0o544, None, None
 
 
-class Item:
+class Item(object):
   """Items represent the metadata (user, group, mode) of files and
   directories in the system image."""
-  def __init__(self, itemset, name, dir=False):
+  def __init__(self, itemset, name, is_dir=False):
     self.itemset = itemset
     self.name = name
     self.uid = None
@@ -230,22 +241,26 @@
     self.mode = None
     self.selabel = None
     self.capabilities = None
-    self.dir = dir
+    self.is_dir = is_dir
+    self.descendants = None
+    self.best_subtree = None
 
     if name:
-      self.parent = itemset.Get(os.path.dirname(name), dir=True)
+      self.parent = itemset.Get(os.path.dirname(name), is_dir=True)
       self.parent.children.append(self)
     else:
       self.parent = None
-    if dir:
+    if self.is_dir:
       self.children = []
 
   def Dump(self, indent=0):
     if self.uid is not None:
-      print "%s%s %d %d %o" % ("  "*indent, self.name, self.uid, self.gid, self.mode)
+      print "%s%s %d %d %o" % (
+          "  " * indent, self.name, self.uid, self.gid, self.mode)
     else:
-      print "%s%s %s %s %s" % ("  "*indent, self.name, self.uid, self.gid, self.mode)
-    if self.dir:
+      print "%s%s %s %s %s" % (
+          "  " * indent, self.name, self.uid, self.gid, self.mode)
+    if self.is_dir:
       print "%s%s" % ("  "*indent, self.descendants)
       print "%s%s" % ("  "*indent, self.best_subtree)
       for i in self.children:
@@ -253,21 +268,24 @@
 
   def CountChildMetadata(self):
     """Count up the (uid, gid, mode, selabel, capabilities) tuples for
-    all children and determine the best strategy for using set_perm_recursive and
-    set_perm to correctly chown/chmod all the files to their desired
+    all children and determine the best strategy for using set_perm_recursive
+    and set_perm to correctly chown/chmod all the files to their desired
     values.  Recursively calls itself for all descendants.
 
-    Returns a dict of {(uid, gid, dmode, fmode, selabel, capabilities): count} counting up
-    all descendants of this node.  (dmode or fmode may be None.)  Also
-    sets the best_subtree of each directory Item to the (uid, gid,
-    dmode, fmode, selabel, capabilities) tuple that will match the most
-    descendants of that Item.
+    Returns a dict of {(uid, gid, dmode, fmode, selabel, capabilities): count}
+    counting up all descendants of this node.  (dmode or fmode may be None.)
+    Also sets the best_subtree of each directory Item to the (uid, gid, dmode,
+    fmode, selabel, capabilities) tuple that will match the most descendants of
+    that Item.
     """
 
-    assert self.dir
-    d = self.descendants = {(self.uid, self.gid, self.mode, None, self.selabel, self.capabilities): 1}
+    assert self.is_dir
+    key = (self.uid, self.gid, self.mode, None, self.selabel,
+           self.capabilities)
+    self.descendants = {key: 1}
+    d = self.descendants
     for i in self.children:
-      if i.dir:
+      if i.is_dir:
         for k, v in i.CountChildMetadata().iteritems():
           d[k] = d.get(k, 0) + v
       else:
@@ -286,17 +304,23 @@
 
     # Now find the dmode, fmode, selabel, and capabilities that match
     # the most descendants with that (uid, gid), and choose those.
-    best_dmode = (0, 0755)
-    best_fmode = (0, 0644)
+    best_dmode = (0, 0o755)
+    best_fmode = (0, 0o644)
     best_selabel = (0, None)
     best_capabilities = (0, None)
     for k, count in d.iteritems():
-      if k[:2] != ug: continue
-      if k[2] is not None and count >= best_dmode[0]: best_dmode = (count, k[2])
-      if k[3] is not None and count >= best_fmode[0]: best_fmode = (count, k[3])
-      if k[4] is not None and count >= best_selabel[0]: best_selabel = (count, k[4])
-      if k[5] is not None and count >= best_capabilities[0]: best_capabilities = (count, k[5])
-    self.best_subtree = ug + (best_dmode[1], best_fmode[1], best_selabel[1], best_capabilities[1])
+      if k[:2] != ug:
+        continue
+      if k[2] is not None and count >= best_dmode[0]:
+        best_dmode = (count, k[2])
+      if k[3] is not None and count >= best_fmode[0]:
+        best_fmode = (count, k[3])
+      if k[4] is not None and count >= best_selabel[0]:
+        best_selabel = (count, k[4])
+      if k[5] is not None and count >= best_capabilities[0]:
+        best_capabilities = (count, k[5])
+    self.best_subtree = ug + (
+        best_dmode[1], best_fmode[1], best_selabel[1], best_capabilities[1])
 
     return d
 
@@ -308,11 +332,11 @@
     self.CountChildMetadata()
 
     def recurse(item, current):
-      # current is the (uid, gid, dmode, fmode, selabel, capabilities) tuple that the current
-      # item (and all its children) have already been set to.  We only
-      # need to issue set_perm/set_perm_recursive commands if we're
+      # current is the (uid, gid, dmode, fmode, selabel, capabilities) tuple
+      # that the current item (and all its children) have already been set to.
+      # We only need to issue set_perm/set_perm_recursive commands if we're
       # supposed to be something different.
-      if item.dir:
+      if item.is_dir:
         if current != item.best_subtree:
           script.SetPermissionsRecursive("/"+item.name, *item.best_subtree)
           current = item.best_subtree
@@ -349,12 +373,14 @@
   partition = itemset.partition
 
   for info in input_zip.infolist():
-    if info.filename.startswith(partition.upper() + "/"):
-      basefilename = info.filename[7:]
+    prefix = partition.upper() + "/"
+    if info.filename.startswith(prefix):
+      basefilename = info.filename[len(prefix):]
       if IsSymlink(info):
         symlinks.append((input_zip.read(info.filename),
                          "/" + partition + "/" + basefilename))
       else:
+        import copy
         info2 = copy.copy(info)
         fn = info2.filename = partition + "/" + basefilename
         if substitute and fn in substitute and substitute[fn] is None:
@@ -364,11 +390,11 @@
             data = substitute[fn]
           else:
             data = input_zip.read(info.filename)
-          output_zip.writestr(info2, data)
+          common.ZipWriteStr(output_zip, info2, data)
         if fn.endswith("/"):
-          itemset.Get(fn[:-1], dir=True)
+          itemset.Get(fn[:-1], is_dir=True)
         else:
-          itemset.Get(fn, dir=False)
+          itemset.Get(fn)
 
   symlinks.sort()
   return symlinks
@@ -382,26 +408,26 @@
                   whole_file=True)
 
 
-def AppendAssertions(script, info_dict, oem_dict = None):
+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:
     device = GetBuildProp("ro.product.device", info_dict)
     script.AssertDevice(device)
   else:
     if oem_dict is None:
-      raise common.ExternalError("No OEM file provided to answer expected assertions")
+      raise common.ExternalError(
+          "No OEM file provided to answer expected assertions")
     for prop in oem_props.split():
       if oem_dict.get(prop) is None:
-        raise common.ExternalError("The OEM file is missing the property %s" % prop)
+        raise common.ExternalError(
+            "The OEM file is missing the property %s" % prop)
       script.AssertOemProperty(prop, oem_dict.get(prop))
 
 
 def HasRecoveryPatch(target_files_zip):
-  try:
-    target_files_zip.getinfo("SYSTEM/recovery-from-boot.p")
-    return True
-  except KeyError:
-    return False
+  namelist = [name for name in target_files_zip.namelist()]
+  return ("SYSTEM/recovery-from-boot.p" in namelist or
+          "SYSTEM/etc/recovery.img" in namelist)
 
 def HasVendorPartition(target_files_zip):
   try:
@@ -420,10 +446,10 @@
   if oem_props is None:
     return GetBuildProp("ro.build.fingerprint", info_dict)
   return "%s/%s/%s:%s" % (
-    GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict),
-    GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict),
-    GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict),
-    GetBuildProp("ro.build.thumbprint", info_dict))
+      GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict),
+      GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict),
+      GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict),
+      GetBuildProp("ro.build.thumbprint", info_dict))
 
 
 def GetImage(which, tmpdir, info_dict):
@@ -457,13 +483,20 @@
       path = add_img_to_target_files.BuildVendor(
           tmpdir, info_dict, block_list=mappath)
 
-  return sparse_img.SparseImage(path, mappath)
+  # Bug: http://b/20939131
+  # In ext4 filesystems, block 0 might be changed even being mounted
+  # R/O. We add it to clobbered_blocks so that it will be written to the
+  # target unconditionally. Note that they are still part of care_map.
+  clobbered_blocks = "0"
+
+  return sparse_img.SparseImage(path, mappath, clobbered_blocks)
 
 
 def WriteFullOTAPackage(input_zip, output_zip):
   # TODO: how to determine this?  We don't know what version it will
-  # be installed on top of.  For now, we expect the API just won't
-  # change very often.
+  # be installed on top of. For now, we expect the API just won't
+  # change very often. Similarly for fstab, it might have changed
+  # in the target build.
   script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict)
 
   oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
@@ -473,15 +506,16 @@
     if OPTIONS.oem_source is None:
       raise common.ExternalError("OEM source required for this build")
     script.Mount("/oem", recovery_mount_options)
-    oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines())
+    oem_dict = common.LoadDictionaryFromLines(
+        open(OPTIONS.oem_source).readlines())
 
-  metadata = {"post-build": CalculateFingerprint(
-                               oem_props, oem_dict, OPTIONS.info_dict),
-              "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
+  metadata = {
+      "post-build": CalculateFingerprint(oem_props, oem_dict,
                                          OPTIONS.info_dict),
-              "post-timestamp": GetBuildProp("ro.build.date.utc",
-                                             OPTIONS.info_dict),
-              }
+      "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
+                                   OPTIONS.info_dict),
+      "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict),
+  }
 
   device_specific = common.DeviceSpecificParams(
       input_zip=input_zip,
@@ -520,7 +554,8 @@
   #    do normal full package installation:
   #       wipe and install system, boot image, etc.
   #       set up system to update recovery partition on first boot
-  #    complete script normally (allow recovery to mark itself finished and reboot)
+  #    complete script normally
+  #    (allow recovery to mark itself finished and reboot)
 
   recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
                                          OPTIONS.input_tmp, "RECOVERY")
@@ -542,6 +577,10 @@
 else if get_stage("%(bcb_dev)s") == "3/3" then
 """ % bcb_dev)
 
+  # Dump fingerprints
+  script.Print("Target: %s" % CalculateFingerprint(
+      oem_props, oem_dict, OPTIONS.info_dict))
+
   device_specific.FullOTA_InstallBegin()
 
   system_progress = 0.75
@@ -551,6 +590,8 @@
   if HasVendorPartition(input_zip):
     system_progress -= 0.1
 
+  # Place a copy of file_contexts.bin into the OTA package which will be used
+  # by the recovery program.
   if "selinux_fc" in OPTIONS.info_dict:
     WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip)
 
@@ -578,13 +619,13 @@
     symlinks = CopyPartitionFiles(system_items, input_zip, output_zip)
     script.MakeSymlinks(symlinks)
 
-  boot_img = common.GetBootableImage("boot.img", "boot.img",
-                                     OPTIONS.input_tmp, "BOOT")
+  boot_img = common.GetBootableImage(
+      "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
 
   if not block_based:
     def output_sink(fn, data):
       common.ZipWriteStr(output_zip, "recovery/" + fn, data)
-      system_items.Get("system/" + fn, dir=False)
+      system_items.Get("system/" + fn)
 
     common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink,
                              recovery_img, boot_img)
@@ -646,10 +687,8 @@
   WriteMetadata(metadata, output_zip)
 
 
-def WritePolicyConfig(file_context, output_zip):
-  f = open(file_context, 'r');
-  basename = os.path.basename(file_context)
-  common.ZipWriteStr(output_zip, basename, f.read())
+def WritePolicyConfig(file_name, output_zip):
+  common.ZipWrite(output_zip, file_name, os.path.basename(file_name))
 
 
 def WriteMetadata(metadata, output_zip):
@@ -665,7 +704,7 @@
   prefix = partition.upper() + "/"
   for info in z.infolist():
     if info.filename.startswith(prefix) and not IsSymlink(info):
-      basefilename = info.filename[7:]
+      basefilename = info.filename[len(prefix):]
       fn = partition + "/" + basefilename
       data = z.read(info.filename)
       out[fn] = common.File(fn, data)
@@ -687,26 +726,41 @@
   while len(dirs) > 0:
     path = "/".join(dirs)
     if path in known_paths:
-      break;
+      break
     known_paths.add(path)
     dirs.pop()
 
 
 def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):
+  # TODO(tbao): We should factor out the common parts between
+  # WriteBlockIncrementalOTAPackage() and WriteIncrementalOTAPackage().
   source_version = OPTIONS.source_info_dict["recovery_api_version"]
   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.")
-  script = edify_generator.EdifyGenerator(source_version,
-                                          OPTIONS.target_info_dict)
+  script = edify_generator.EdifyGenerator(
+      source_version, OPTIONS.target_info_dict,
+      fstab=OPTIONS.source_info_dict["fstab"])
 
-  metadata = {"pre-device": GetBuildProp("ro.product.device",
-                                         OPTIONS.source_info_dict),
-              "post-timestamp": GetBuildProp("ro.build.date.utc",
-                                             OPTIONS.target_info_dict),
-              }
+  oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
+  recovery_mount_options = OPTIONS.source_info_dict.get(
+      "recovery_mount_options")
+  oem_dict = None
+  if oem_props is not None and len(oem_props) > 0:
+    if OPTIONS.oem_source is None:
+      raise common.ExternalError("OEM source required for this build")
+    script.Mount("/oem", recovery_mount_options)
+    oem_dict = common.LoadDictionaryFromLines(
+        open(OPTIONS.oem_source).readlines())
+
+  metadata = {
+      "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
+                                   OPTIONS.source_info_dict),
+      "post-timestamp": GetBuildProp("ro.build.date.utc",
+                                     OPTIONS.target_info_dict),
+  }
 
   device_specific = common.DeviceSpecificParams(
       source_zip=source_zip,
@@ -718,8 +772,10 @@
       metadata=metadata,
       info_dict=OPTIONS.info_dict)
 
-  source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict)
-  target_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.target_info_dict)
+  source_fp = CalculateFingerprint(oem_props, oem_dict,
+                                   OPTIONS.source_info_dict)
+  target_fp = CalculateFingerprint(oem_props, oem_dict,
+                                   OPTIONS.target_info_dict)
   metadata["pre-build"] = source_fp
   metadata["post-build"] = target_fp
 
@@ -731,12 +787,8 @@
   updating_boot = (not OPTIONS.two_step and
                    (source_boot.data != target_boot.data))
 
-  source_recovery = common.GetBootableImage(
-      "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY",
-      OPTIONS.source_info_dict)
   target_recovery = common.GetBootableImage(
       "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY")
-  updating_recovery = (source_recovery.data != target_recovery.data)
 
   system_src = GetImage("system", OPTIONS.source_tmp, OPTIONS.source_info_dict)
   system_tgt = GetImage("system", OPTIONS.target_tmp, OPTIONS.target_info_dict)
@@ -748,29 +800,20 @@
         OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
 
   system_diff = common.BlockDifference("system", system_tgt, system_src,
-                                       check_first_block=True,
                                        version=blockimgdiff_version)
 
   if HasVendorPartition(target_zip):
     if not HasVendorPartition(source_zip):
       raise RuntimeError("can't generate incremental that adds /vendor")
-    vendor_src = GetImage("vendor", OPTIONS.source_tmp, OPTIONS.source_info_dict)
-    vendor_tgt = GetImage("vendor", OPTIONS.target_tmp, OPTIONS.target_info_dict)
+    vendor_src = GetImage("vendor", OPTIONS.source_tmp,
+                          OPTIONS.source_info_dict)
+    vendor_tgt = GetImage("vendor", OPTIONS.target_tmp,
+                          OPTIONS.target_info_dict)
     vendor_diff = common.BlockDifference("vendor", vendor_tgt, vendor_src,
-                                         check_first_block=True,
                                          version=blockimgdiff_version)
   else:
     vendor_diff = None
 
-  oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties")
-  recovery_mount_options = OPTIONS.target_info_dict.get("recovery_mount_options")
-  oem_dict = None
-  if oem_props is not None and len(oem_props) > 0:
-    if OPTIONS.oem_source is None:
-      raise common.ExternalError("OEM source required for this build")
-    script.Mount("/oem", recovery_mount_options)
-    oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines())
-
   AppendAssertions(script, OPTIONS.target_info_dict, oem_dict)
   device_specific.IncrementalOTA_Assertions()
 
@@ -793,12 +836,13 @@
   #       patch system files, etc.
   #       force full install of new boot image
   #       set up system to update recovery partition on first boot
-  #    complete script normally (allow recovery to mark itself finished and reboot)
+  #    complete script normally
+  #    (allow recovery to mark itself finished and reboot)
 
   if OPTIONS.two_step:
-    if not OPTIONS.info_dict.get("multistage_support", None):
+    if not OPTIONS.source_info_dict.get("multistage_support", None):
       assert False, "two-step packages not supported by this build"
-    fs = OPTIONS.info_dict["fstab"]["/misc"]
+    fs = OPTIONS.source_info_dict["fstab"]["/misc"]
     assert fs.fs_type.upper() == "EMMC", \
         "two-step packages only supported on devices with EMMC /misc partitions"
     bcb_dev = {"bcb_dev": fs.device}
@@ -806,7 +850,7 @@
     script.AppendExtra("""
 if get_stage("%(bcb_dev)s") == "2/3" then
 """ % bcb_dev)
-    script.AppendExtra("sleep(20);\n");
+    script.AppendExtra("sleep(20);\n")
     script.WriteRawImage("/recovery", "recovery.img")
     script.AppendExtra("""
 set_stage("%(bcb_dev)s", "3/3");
@@ -814,6 +858,12 @@
 else if get_stage("%(bcb_dev)s") != "3/3" then
 """ % 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("Verifying current system...")
 
   device_specific.IncrementalOTA_VerifyBegin()
@@ -837,7 +887,8 @@
           GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
 
   if updating_boot:
-    boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict)
+    boot_type, boot_device = common.GetTypeAndDevice(
+        "/boot", OPTIONS.source_info_dict)
     d = common.Difference(target_boot, source_boot)
     _, _, d = d.ComputePatch()
     if d is None:
@@ -877,6 +928,7 @@
 
   system_diff.WriteScript(script, output_zip,
                           progress=0.8 if vendor_diff else 0.9)
+
   if vendor_diff:
     vendor_diff.WriteScript(script, output_zip, progress=0.1)
 
@@ -930,8 +982,9 @@
   WriteMetadata(metadata, output_zip)
 
 
-class FileDifference:
+class FileDifference(object):
   def __init__(self, partition, source_zip, target_zip, output_zip):
+    self.deferred_patch_list = None
     print "Loading target..."
     self.target_data = target_data = LoadPartitionFiles(target_zip, partition)
     print "Loading source..."
@@ -1004,7 +1057,7 @@
 
   def EmitVerification(self, script):
     so_far = 0
-    for tf, sf, size, patch_sha in self.patch_list:
+    for tf, sf, _, _ in self.patch_list:
       if tf.name != sf.name:
         script.SkipNextActionIfTargetExists(tf.name, tf.sha1)
       script.PatchCheck("/"+sf.name, tf.sha1, sf.sha1)
@@ -1012,18 +1065,18 @@
     return so_far
 
   def EmitExplicitTargetVerification(self, script):
-    for fn, size, sha1 in self.verbatim_targets:
-      if (fn[-1] != "/"):
+    for fn, _, sha1 in self.verbatim_targets:
+      if fn[-1] != "/":
         script.FileCheck("/"+fn, sha1)
     for tf, _, _, _ in self.patch_list:
       script.FileCheck(tf.name, tf.sha1)
 
   def RemoveUnneededFiles(self, script, extras=()):
-    script.DeleteFiles(["/"+i[0] for i in self.verbatim_targets] +
-                       ["/"+i for i in sorted(self.source_data)
-                              if i not in self.target_data and
-                              i not in self.renames] +
-                       list(extras))
+    script.DeleteFiles(
+        ["/" + i[0] for i in self.verbatim_targets] +
+        ["/" + i for i in sorted(self.source_data)
+         if i not in self.target_data and i not in self.renames] +
+        list(extras))
 
   def TotalPatchSize(self):
     return sum(i[1].size for i in self.patch_list)
@@ -1031,22 +1084,24 @@
   def EmitPatches(self, script, total_patch_size, so_far):
     self.deferred_patch_list = deferred_patch_list = []
     for item in self.patch_list:
-      tf, sf, size, _ = item
+      tf, sf, _, _ = item
       if tf.name == "system/build.prop":
         deferred_patch_list.append(item)
         continue
-      if (sf.name != tf.name):
+      if sf.name != tf.name:
         script.SkipNextActionIfTargetExists(tf.name, tf.sha1)
-      script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p")
+      script.ApplyPatch("/" + sf.name, "-", tf.size, tf.sha1, sf.sha1,
+                        "patch/" + sf.name + ".p")
       so_far += tf.size
       script.SetProgress(so_far / total_patch_size)
     return so_far
 
   def EmitDeferredPatches(self, script):
     for item in self.deferred_patch_list:
-      tf, sf, size, _ = item
-      script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p")
-    script.SetPermissions("/system/build.prop", 0, 0, 0644, None, None)
+      tf, sf, _, _ = item
+      script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1,
+                        "patch/" + sf.name + ".p")
+    script.SetPermissions("/system/build.prop", 0, 0, 0o644, None, None)
 
   def EmitRenames(self, script):
     if len(self.renames) > 0:
@@ -1056,8 +1111,6 @@
         script.RenameFile(src, tgt.name)
 
 
-
-
 def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
   target_has_recovery_patch = HasRecoveryPatch(target_zip)
   source_has_recovery_patch = HasRecoveryPatch(source_zip)
@@ -1073,23 +1126,27 @@
   if source_version == 0:
     print ("WARNING: generating edify script for a source that "
            "can't install it.")
-  script = edify_generator.EdifyGenerator(source_version,
-                                          OPTIONS.target_info_dict)
+  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.info_dict.get("recovery_mount_options")
+  recovery_mount_options = OPTIONS.source_info_dict.get(
+      "recovery_mount_options")
   oem_dict = None
   if oem_props is not None and len(oem_props) > 0:
     if OPTIONS.oem_source is None:
       raise common.ExternalError("OEM source required for this build")
     script.Mount("/oem", recovery_mount_options)
-    oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines())
+    oem_dict = common.LoadDictionaryFromLines(
+        open(OPTIONS.oem_source).readlines())
 
-  metadata = {"pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
-                                         OPTIONS.source_info_dict),
-              "post-timestamp": GetBuildProp("ro.build.date.utc",
-                                             OPTIONS.target_info_dict),
-              }
+  metadata = {
+      "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
+                                   OPTIONS.source_info_dict),
+      "post-timestamp": GetBuildProp("ro.build.date.utc",
+                                     OPTIONS.target_info_dict),
+  }
 
   device_specific = common.DeviceSpecificParams(
       source_zip=source_zip,
@@ -1109,8 +1166,10 @@
   else:
     vendor_diff = None
 
-  target_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.target_info_dict)
-  source_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.source_info_dict)
+  target_fp = CalculateFingerprint(oem_props, oem_dict,
+                                   OPTIONS.target_info_dict)
+  source_fp = CalculateFingerprint(oem_props, oem_dict,
+                                   OPTIONS.source_info_dict)
 
   if oem_props is None:
     script.AssertSomeFingerprint(source_fp, target_fp)
@@ -1165,12 +1224,13 @@
   #       patch system files, etc.
   #       force full install of new boot image
   #       set up system to update recovery partition on first boot
-  #    complete script normally (allow recovery to mark itself finished and reboot)
+  #    complete script normally
+  #    (allow recovery to mark itself finished and reboot)
 
   if OPTIONS.two_step:
-    if not OPTIONS.info_dict.get("multistage_support", None):
+    if not OPTIONS.source_info_dict.get("multistage_support", None):
       assert False, "two-step packages not supported by this build"
-    fs = OPTIONS.info_dict["fstab"]["/misc"]
+    fs = OPTIONS.source_info_dict["fstab"]["/misc"]
     assert fs.fs_type.upper() == "EMMC", \
         "two-step packages only supported on devices with EMMC /misc partitions"
     bcb_dev = {"bcb_dev": fs.device}
@@ -1178,7 +1238,7 @@
     script.AppendExtra("""
 if get_stage("%(bcb_dev)s") == "2/3" then
 """ % bcb_dev)
-    script.AppendExtra("sleep(20);\n");
+    script.AppendExtra("sleep(20);\n")
     script.WriteRawImage("/recovery", "recovery.img")
     script.AppendExtra("""
 set_stage("%(bcb_dev)s", "3/3");
@@ -1186,6 +1246,10 @@
 else if get_stage("%(bcb_dev)s") != "3/3" then
 """ % bcb_dev)
 
+  # Dump fingerprints
+  script.Print("Source: %s" % (source_fp,))
+  script.Print("Target: %s" % (target_fp,))
+
   script.Print("Verifying current system...")
 
   device_specific.IncrementalOTA_VerifyBegin()
@@ -1203,7 +1267,8 @@
 
     common.ZipWriteStr(output_zip, "patch/boot.img.p", d)
 
-    boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict)
+    boot_type, boot_device = common.GetTypeAndDevice(
+        "/boot", OPTIONS.source_info_dict)
 
     script.PatchCheck("%s:%s:%d:%s:%d:%s" %
                       (boot_type, boot_device,
@@ -1212,9 +1277,11 @@
     so_far += source_boot.size
 
   size = []
-  if system_diff.patch_list: size.append(system_diff.largest_source_size)
+  if system_diff.patch_list:
+    size.append(system_diff.largest_source_size)
   if vendor_diff:
-    if vendor_diff.patch_list: size.append(vendor_diff.largest_source_size)
+    if vendor_diff.patch_list:
+      size.append(vendor_diff.largest_source_size)
   if size or updating_recovery or updating_boot:
     script.CacheFreeSpaceCheck(max(size))
 
@@ -1291,11 +1358,12 @@
     if not target_has_recovery_patch:
       def output_sink(fn, data):
         common.ZipWriteStr(output_zip, "recovery/" + fn, data)
-        system_items.Get("system/" + fn, dir=False)
+        system_items.Get("system/" + fn)
 
       common.MakeRecoveryPatch(OPTIONS.target_tmp, output_sink,
                                target_recovery, target_boot)
       script.DeleteFiles(["/system/recovery-from-boot.p",
+                          "/system/etc/recovery.img",
                           "/system/etc/install-recovery.sh"])
     print "recovery image changed; including as patch from boot."
   else:
@@ -1414,6 +1482,10 @@
       OPTIONS.package_key = a
     elif o in ("-i", "--incremental_from"):
       OPTIONS.incremental_source = a
+    elif o == "--full_radio":
+      OPTIONS.full_radio = True
+    elif o == "--full_bootloader":
+      OPTIONS.full_bootloader = True
     elif o in ("-w", "--wipe_user_data"):
       OPTIONS.wipe_user_data = True
     elif o in ("-n", "--no_prereq"):
@@ -1437,7 +1509,7 @@
       OPTIONS.two_step = True
     elif o == "--no_signing":
       OPTIONS.no_signing = True
-    elif o in ("--verify"):
+    elif o == "--verify":
       OPTIONS.verify = True
     elif o == "--block":
       OPTIONS.block_based = True
@@ -1445,29 +1517,38 @@
       OPTIONS.updater_binary = a
     elif o in ("--no_fallback_to_full",):
       OPTIONS.fallback_to_full = False
+    elif o == "--stash_threshold":
+      try:
+        OPTIONS.stash_threshold = float(a)
+      except ValueError:
+        raise ValueError("Cannot parse value %r for option %r - expecting "
+                         "a float" % (a, o))
     else:
       return False
     return True
 
   args = common.ParseOptions(argv, __doc__,
                              extra_opts="b:k:i:d:wne:t:a:2o:",
-                             extra_long_opts=["board_config=",
-                                              "package_key=",
-                                              "incremental_from=",
-                                              "wipe_user_data",
-                                              "no_prereq",
-                                              "extra_script=",
-                                              "worker_threads=",
-                                              "aslr_mode=",
-                                              "two_step",
-                                              "no_signing",
-                                              "block",
-                                              "binary=",
-                                              "oem_settings=",
-                                              "verify",
-                                              "no_fallback_to_full",
-                                              ],
-                             extra_option_handler=option_handler)
+                             extra_long_opts=[
+                                 "board_config=",
+                                 "package_key=",
+                                 "incremental_from=",
+                                 "full_radio",
+                                 "full_bootloader",
+                                 "wipe_user_data",
+                                 "no_prereq",
+                                 "extra_script=",
+                                 "worker_threads=",
+                                 "aslr_mode=",
+                                 "two_step",
+                                 "no_signing",
+                                 "block",
+                                 "binary=",
+                                 "oem_settings=",
+                                 "verify",
+                                 "no_fallback_to_full",
+                                 "stash_threshold=",
+                             ], extra_option_handler=option_handler)
 
   if len(args) != 2:
     common.Usage(__doc__)
@@ -1480,15 +1561,7 @@
   OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0])
 
   OPTIONS.target_tmp = OPTIONS.input_tmp
-  OPTIONS.info_dict = common.LoadInfoDict(input_zip)
-
-  # If this image was originally labelled with SELinux contexts, make sure we
-  # also apply the labels in our new image. During building, the "file_contexts"
-  # is in the out/ directory tree, but for repacking from target-files.zip it's
-  # in the root directory of the ramdisk.
-  if "selinux_fc" in OPTIONS.info_dict:
-    OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp, "BOOT", "RAMDISK",
-        "file_contexts")
+  OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.target_tmp)
 
   if OPTIONS.verbose:
     print "--- target info ---"
@@ -1515,29 +1588,36 @@
   while True:
 
     if OPTIONS.no_signing:
-      if os.path.exists(args[1]): os.unlink(args[1])
-      output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
+      if os.path.exists(args[1]):
+        os.unlink(args[1])
+      output_zip = zipfile.ZipFile(args[1], "w",
+                                   compression=zipfile.ZIP_DEFLATED)
     else:
       temp_zip_file = tempfile.NamedTemporaryFile()
       output_zip = zipfile.ZipFile(temp_zip_file, "w",
                                    compression=zipfile.ZIP_DEFLATED)
 
+    cache_size = OPTIONS.info_dict.get("cache_size", None)
+    if cache_size is None:
+      print "--- can't determine the cache partition size ---"
+    OPTIONS.cache_size = cache_size
+
     if OPTIONS.incremental_source is None:
       WriteFullOTAPackage(input_zip, output_zip)
       if OPTIONS.package_key is None:
         OPTIONS.package_key = OPTIONS.info_dict.get(
             "default_system_dev_certificate",
             "build/target/product/security/testkey")
+      common.ZipClose(output_zip)
       break
 
     else:
       print "unzipping source target-files..."
-      OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source)
+      OPTIONS.source_tmp, source_zip = common.UnzipTemp(
+          OPTIONS.incremental_source)
       OPTIONS.target_info_dict = OPTIONS.info_dict
-      OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
-      if "selinux_fc" in OPTIONS.source_info_dict:
-        OPTIONS.source_info_dict["selinux_fc"] = os.path.join(OPTIONS.source_tmp, "BOOT", "RAMDISK",
-                                                              "file_contexts")
+      OPTIONS.source_info_dict = common.LoadInfoDict(source_zip,
+                                                     OPTIONS.source_tmp)
       if OPTIONS.package_key is None:
         OPTIONS.package_key = OPTIONS.source_info_dict.get(
             "default_system_dev_certificate",
@@ -1547,14 +1627,14 @@
         common.DumpInfoDict(OPTIONS.source_info_dict)
       try:
         WriteIncrementalOTAPackage(input_zip, source_zip, output_zip)
+        common.ZipClose(output_zip)
         break
       except ValueError:
-        if not OPTIONS.fallback_to_full: raise
+        if not OPTIONS.fallback_to_full:
+          raise
         print "--- failed to build incremental; falling back to full ---"
         OPTIONS.incremental_source = None
-        output_zip.close()
-
-  output_zip.close()
+        common.ZipClose(output_zip)
 
   if not OPTIONS.no_signing:
     SignOutput(temp_zip_file.name, args[1])
@@ -1567,7 +1647,7 @@
   try:
     common.CloseInheritedPipes()
     main(sys.argv[1:])
-  except common.ExternalError, e:
+  except common.ExternalError as e:
     print
     print "   ERROR: %s" % (e,)
     print
diff --git a/tools/releasetools/pylintrc b/tools/releasetools/pylintrc
new file mode 100644
index 0000000..90de1af
--- /dev/null
+++ b/tools/releasetools/pylintrc
@@ -0,0 +1,382 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Use multiple processes to speed up Pylint.
+jobs=1
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code
+extension-pkg-whitelist=
+
+# Allow optimization of some AST trees. This will activate a peephole AST
+# optimizer, which will apply various small optimizations. For instance, it can
+# be used to obtain the result of joining multiple strings with the addition
+# operator. Joining a lot of strings can lead to a maximum recursion error in
+# Pylint and this flag can prevent that. It has one side effect, the resulting
+# AST will be different than the one from reality.
+optimize-ast=no
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
+confidence=
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time. See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=invalid-name,missing-docstring,too-many-branches,too-many-locals,too-many-arguments,too-many-statements,duplicate-code,too-few-public-methods,too-many-instance-attributes,too-many-lines,too-many-public-methods,locally-disabled,fixme
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis
+ignored-modules=
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,input
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Include a hint for the correct naming format with invalid-name
+include-naming-hint=no
+
+# Regular expression matching correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for function names
+function-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for variable names
+variable-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct constant names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Naming hint for constant names
+const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression matching correct attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for attribute names
+attr-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for argument names
+argument-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct class attribute names
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Naming hint for class attribute names
+class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression matching correct inline iteration names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Naming hint for inline iteration names
+inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+
+# Regular expression matching correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Naming hint for class names
+class-name-hint=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression matching correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Naming hint for module names
+module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression matching correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for method names
+method-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=__.*__
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+
+[SPELLING]
+
+# Spelling dictionary name. Available dictionaries: none. To make it working
+# install python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to indicated private dictionary in
+# --spelling-private-dict-file option instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+# List of optional constructs for which whitespace checking is disabled
+no-space-check=trailing-comma,dict-separator
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='  '
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=LF
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the name of dummy variables (i.e. expectedly
+# not used).
+dummy-variables-rgx=_$|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,_cb
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/tools/releasetools/rangelib.py b/tools/releasetools/rangelib.py
index 7279c60..1506658 100644
--- a/tools/releasetools/rangelib.py
+++ b/tools/releasetools/rangelib.py
@@ -24,6 +24,7 @@
   lots of runs."""
 
   def __init__(self, data=None):
+    self.monotonic = False
     if isinstance(data, str):
       self._parse_internal(data)
     elif data:
@@ -185,7 +186,7 @@
     # This is like intersect, but we can stop as soon as we discover the
     # output is going to be nonempty.
     z = 0
-    for p, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))),
+    for _, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))),
                             zip(other.data, itertools.cycle((+1, -1)))):
       if (z == 1 and d == 1) or (z == 2 and d == -1):
         return True
@@ -237,6 +238,28 @@
         out.append(offset + p - start)
     return RangeSet(data=out)
 
+  def extend(self, n):
+    """Extend the RangeSet by 'n' blocks.
+
+    The lower bound is guaranteed to be non-negative.
+
+    >>> RangeSet("0-9").extend(1)
+    <RangeSet("0-10")>
+    >>> RangeSet("10-19").extend(15)
+    <RangeSet("0-34")>
+    >>> RangeSet("10-19 30-39").extend(4)
+    <RangeSet("6-23 26-43")>
+    >>> RangeSet("10-19 30-39").extend(10)
+    <RangeSet("0-49")>
+    """
+    out = self
+    for i in range(0, len(self.data), 2):
+      s, e = self.data[i:i+2]
+      s1 = max(0, s - n)
+      e1 = e + n
+      out = out.union(RangeSet(str(s1) + "-" + str(e1-1)))
+    return out
+
 
 if __name__ == "__main__":
   import doctest
diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks
new file mode 120000
index 0000000..b5ec59a
--- /dev/null
+++ b/tools/releasetools/sign_target_files_apks
@@ -0,0 +1 @@
+sign_target_files_apks.py
\ No newline at end of file
diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks.py
similarity index 89%
rename from tools/releasetools/sign_target_files_apks
rename to tools/releasetools/sign_target_files_apks.py
index 9e61051..e98eb8f 100755
--- a/tools/releasetools/sign_target_files_apks
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -169,48 +169,57 @@
           f.write(data)
 
   for info in input_tf_zip.infolist():
-    if info.filename.startswith("IMAGES/"): continue
+    if info.filename.startswith("IMAGES/"):
+      continue
 
     data = input_tf_zip.read(info.filename)
     out_info = copy.copy(info)
 
+    # Replace keys if requested.
     if (info.filename == "META/misc_info.txt" and
         OPTIONS.replace_verity_private_key):
-      ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info, OPTIONS.replace_verity_private_key[1])
-    elif (info.filename == "BOOT/RAMDISK/verity_key" and
-        OPTIONS.replace_verity_public_key):
-      new_data = ReplaceVerityPublicKey(output_tf_zip, OPTIONS.replace_verity_public_key[1])
+      ReplaceVerityPrivateKey(input_tf_zip, output_tf_zip, misc_info,
+                              OPTIONS.replace_verity_private_key[1])
+    elif (info.filename in ("BOOT/RAMDISK/verity_key",
+                            "BOOT/verity_key") and
+          OPTIONS.replace_verity_public_key):
+      new_data = ReplaceVerityPublicKey(output_tf_zip, info.filename,
+                                        OPTIONS.replace_verity_public_key[1])
       write_to_temp(info.filename, info.external_attr, new_data)
+    # Copy BOOT/, RECOVERY/, META/, ROOT/ to rebuild recovery patch.
     elif (info.filename.startswith("BOOT/") or
-        info.filename.startswith("RECOVERY/") or
-        info.filename.startswith("META/") or
-        info.filename == "SYSTEM/etc/recovery-resource.dat"):
+          info.filename.startswith("RECOVERY/") or
+          info.filename.startswith("META/") or
+          info.filename.startswith("ROOT/") or
+          info.filename == "SYSTEM/etc/recovery-resource.dat"):
       write_to_temp(info.filename, info.external_attr, data)
 
+    # Sign APKs.
     if info.filename.endswith(".apk"):
       name = os.path.basename(info.filename)
       key = apk_key_map[name]
       if key not in common.SPECIAL_CERT_STRINGS:
         print "    signing: %-*s (%s)" % (maxsize, name, key)
         signed_data = SignApk(data, key, key_passwords[key])
-        output_tf_zip.writestr(out_info, signed_data)
+        common.ZipWriteStr(output_tf_zip, out_info, signed_data)
       else:
         # an APK we're not supposed to sign.
         print "NOT signing: %s" % (name,)
-        output_tf_zip.writestr(out_info, data)
+        common.ZipWriteStr(output_tf_zip, out_info, data)
     elif info.filename in ("SYSTEM/build.prop",
                            "VENDOR/build.prop",
                            "RECOVERY/RAMDISK/default.prop"):
       print "rewriting %s:" % (info.filename,)
       new_data = RewriteProps(data, misc_info)
-      output_tf_zip.writestr(out_info, new_data)
+      common.ZipWriteStr(output_tf_zip, out_info, new_data)
       if info.filename == "RECOVERY/RAMDISK/default.prop":
         write_to_temp(info.filename, info.external_attr, new_data)
     elif info.filename.endswith("mac_permissions.xml"):
       print "rewriting %s with new keys." % (info.filename,)
       new_data = ReplaceCerts(data)
-      output_tf_zip.writestr(out_info, new_data)
+      common.ZipWriteStr(output_tf_zip, out_info, new_data)
     elif info.filename in ("SYSTEM/recovery-from-boot.p",
+                           "SYSTEM/etc/recovery.img",
                            "SYSTEM/bin/install-recovery.sh"):
       rebuild_recovery = True
     elif (OPTIONS.replace_ota_keys and
@@ -222,16 +231,17 @@
           info.filename == "META/misc_info.txt"):
       pass
     elif (OPTIONS.replace_verity_public_key and
-          info.filename == "BOOT/RAMDISK/verity_key"):
+          info.filename in ("BOOT/RAMDISK/verity_key",
+                            "BOOT/verity_key")):
       pass
     else:
       # a non-APK file; copy it verbatim
-      output_tf_zip.writestr(out_info, data)
+      common.ZipWriteStr(output_tf_zip, out_info, data)
 
   if OPTIONS.replace_ota_keys:
     new_recovery_keys = ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info)
     if new_recovery_keys:
-      write_to_temp("RECOVERY/RAMDISK/res/keys", 0755 << 16, new_recovery_keys)
+      write_to_temp("RECOVERY/RAMDISK/res/keys", 0o755 << 16, new_recovery_keys)
 
   if rebuild_recovery:
     recovery_img = common.GetBootableImage(
@@ -240,7 +250,7 @@
         "boot.img", "boot.img", tmpdir, "BOOT", info_dict=misc_info)
 
     def output_sink(fn, data):
-      output_tf_zip.writestr("SYSTEM/"+fn, data)
+      common.ZipWriteStr(output_tf_zip, "SYSTEM/" + fn, data)
 
     common.MakeRecoveryPatch(tmpdir, output_sink, recovery_img, boot_img,
                              info_dict=misc_info)
@@ -268,8 +278,8 @@
       if OPTIONS.verbose:
         print "    Replaced %d occurence(s) of %s.x509.pem with " \
             "%s.x509.pem" % (num, old, new)
-    except IOError, e:
-      if (e.errno == errno.ENOENT and not OPTIONS.verbose):
+    except IOError as e:
+      if e.errno == errno.ENOENT and not OPTIONS.verbose:
         continue
 
       print "    Error accessing %s. %s. Skip replacing %s.x509.pem " \
@@ -303,7 +313,7 @@
         pieces[-1] = EditTags(pieces[-1])
         value = "/".join(pieces)
       elif (key in ("ro.build.thumbprint", "ro.vendor.build.thumbprint")
-          and misc_info.get("oem_fingerprint_properties") is not None):
+            and misc_info.get("oem_fingerprint_properties") is not None):
         pieces = value.split("/")
         pieces[-1] = EditTags(pieces[-1])
         value = "/".join(pieces)
@@ -380,24 +390,25 @@
   # put into a zipfile system/etc/security/otacerts.zip.
   # We DO NOT include the extra_recovery_keys (if any) here.
 
-  tempfile = cStringIO.StringIO()
-  certs_zip = zipfile.ZipFile(tempfile, "w")
+  temp_file = cStringIO.StringIO()
+  certs_zip = zipfile.ZipFile(temp_file, "w")
   for k in mapped_keys:
     certs_zip.write(k)
   certs_zip.close()
   common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip",
-                     tempfile.getvalue())
+                     temp_file.getvalue())
 
   return new_recovery_keys
 
-def ReplaceVerityPublicKey(targetfile_zip, key_path):
+def ReplaceVerityPublicKey(targetfile_zip, filename, key_path):
   print "Replacing verity public key with %s" % key_path
   with open(key_path) as f:
     data = f.read()
-  common.ZipWriteStr(targetfile_zip, "BOOT/RAMDISK/verity_key", data)
+  common.ZipWriteStr(targetfile_zip, filename, data)
   return data
 
-def ReplaceVerityPrivateKey(targetfile_input_zip, targetfile_output_zip, misc_info, key_path):
+def ReplaceVerityPrivateKey(targetfile_input_zip, targetfile_output_zip,
+                            misc_info, key_path):
   print "Replacing verity private key with %s" % key_path
   current_key = misc_info["verity_key"]
   original_misc_info = targetfile_input_zip.read("META/misc_info.txt")
@@ -484,8 +495,8 @@
   ProcessTargetFiles(input_zip, output_zip, misc_info,
                      apk_key_map, key_passwords)
 
-  input_zip.close()
-  output_zip.close()
+  common.ZipClose(input_zip)
+  common.ZipClose(output_zip)
 
   add_img_to_target_files.AddImagesToTargetFiles(args[1])
 
diff --git a/tools/releasetools/sparse_img.py b/tools/releasetools/sparse_img.py
index 7574747..07f3c1c 100644
--- a/tools/releasetools/sparse_img.py
+++ b/tools/releasetools/sparse_img.py
@@ -14,18 +14,24 @@
 
 import bisect
 import os
-import sys
 import struct
-import pprint
 from hashlib import sha1
 
-from rangelib import *
+import rangelib
+
 
 class SparseImage(object):
-  """Wraps a sparse image file (and optional file map) into an image
-  object suitable for passing to BlockImageDiff."""
+  """Wraps a sparse image file into an image object.
 
-  def __init__(self, simg_fn, file_map_fn=None):
+  Wraps a sparse image file (and optional file map and clobbered_blocks) into
+  an image object suitable for passing to BlockImageDiff. file_map contains
+  the mapping between files and their blocks. clobbered_blocks contains the set
+  of blocks that should be always written to the target regardless of the old
+  contents (i.e. copying instead of patching). clobbered_blocks should be in
+  the form of a string like "0" or "0 1-5 8".
+  """
+
+  def __init__(self, simg_fn, file_map_fn=None, clobbered_blocks=None):
     self.simg_f = f = open(simg_fn, "rb")
 
     header_bin = f.read(28)
@@ -39,7 +45,6 @@
     self.blocksize = blk_sz = header[5]
     self.total_blocks = total_blks = header[6]
     total_chunks = header[7]
-    image_checksum = header[8]
 
     if magic != 0xED26FF3A:
       raise ValueError("Magic should be 0xED26FF3A but is 0x%08X" % (magic,))
@@ -59,12 +64,12 @@
     pos = 0   # in blocks
     care_data = []
     self.offset_map = offset_map = []
+    self.clobbered_blocks = rangelib.RangeSet(data=clobbered_blocks)
 
     for i in range(total_chunks):
       header_bin = f.read(12)
       header = struct.unpack("<2H2I", header_bin)
       chunk_type = header[0]
-      reserved1 = header[1]
       chunk_sz = header[2]
       total_sz = header[3]
       data_sz = total_sz - 12
@@ -102,21 +107,38 @@
         raise ValueError("Unknown chunk type 0x%04X not supported" %
                          (chunk_type,))
 
-    self.care_map = RangeSet(care_data)
+    self.care_map = rangelib.RangeSet(care_data)
     self.offset_index = [i[0] for i in offset_map]
 
+    # Bug: 20881595
+    # Introduce extended blocks as a workaround for the bug. dm-verity may
+    # touch blocks that are not in the care_map due to block device
+    # read-ahead. It will fail if such blocks contain non-zeroes. We zero out
+    # the extended blocks explicitly to avoid dm-verity failures. 512 blocks
+    # are the maximum read-ahead we configure for dm-verity block devices.
+    extended = self.care_map.extend(512)
+    all_blocks = rangelib.RangeSet(data=(0, self.total_blocks))
+    extended = extended.intersect(all_blocks).subtract(self.care_map)
+    self.extended = extended
+
     if file_map_fn:
-      self.LoadFileBlockMap(file_map_fn)
+      self.LoadFileBlockMap(file_map_fn, self.clobbered_blocks)
     else:
       self.file_map = {"__DATA": self.care_map}
 
   def ReadRangeSet(self, ranges):
     return [d for d in self._GetRangeData(ranges)]
 
-  def TotalSha1(self):
-    """Return the SHA-1 hash of all data in the 'care' regions of this image."""
+  def TotalSha1(self, include_clobbered_blocks=False):
+    """Return the SHA-1 hash of all data in the 'care' regions.
+
+    If include_clobbered_blocks is True, it returns the hash including the
+    clobbered_blocks."""
+    ranges = self.care_map
+    if not include_clobbered_blocks:
+      ranges = ranges.subtract(self.clobbered_blocks)
     h = sha1()
-    for d in self._GetRangeData(self.care_map):
+    for d in self._GetRangeData(ranges):
       h.update(d)
     return h.hexdigest()
 
@@ -159,24 +181,30 @@
           yield fill_data * (this_read * (self.blocksize >> 2))
         to_read -= this_read
 
-  def LoadFileBlockMap(self, fn):
+  def LoadFileBlockMap(self, fn, clobbered_blocks):
     remaining = self.care_map
     self.file_map = out = {}
 
     with open(fn) as f:
       for line in f:
         fn, ranges = line.split(None, 1)
-        ranges = RangeSet.parse(ranges)
+        ranges = rangelib.RangeSet.parse(ranges)
         out[fn] = ranges
         assert ranges.size() == ranges.intersect(remaining).size()
+
+        # Currently we assume that blocks in clobbered_blocks are not part of
+        # any file.
+        assert not clobbered_blocks.overlaps(ranges)
         remaining = remaining.subtract(ranges)
 
+    remaining = remaining.subtract(clobbered_blocks)
+
     # For all the remaining blocks in the care_map (ie, those that
-    # aren't part of the data for any file), divide them into blocks
-    # that are all zero and blocks that aren't.  (Zero blocks are
-    # handled specially because (1) there are usually a lot of them
-    # and (2) bsdiff handles files with long sequences of repeated
-    # bytes especially poorly.)
+    # aren't part of the data for any file nor part of the clobbered_blocks),
+    # divide them into blocks that are all zero and blocks that aren't.
+    # (Zero blocks are handled specially because (1) there are usually
+    # a lot of them and (2) bsdiff handles files with long sequences of
+    # repeated bytes especially poorly.)
 
     zero_blocks = []
     nonzero_blocks = []
@@ -186,7 +214,7 @@
     for s, e in remaining:
       for b in range(s, e):
         idx = bisect.bisect_right(self.offset_index, b) - 1
-        chunk_start, chunk_len, filepos, fill_data = self.offset_map[idx]
+        chunk_start, _, filepos, fill_data = self.offset_map[idx]
         if filepos is not None:
           filepos += (b-chunk_start) * self.blocksize
           f.seek(filepos, os.SEEK_SET)
@@ -204,8 +232,14 @@
           nonzero_blocks.append(b)
           nonzero_blocks.append(b+1)
 
-    out["__ZERO"] = RangeSet(data=zero_blocks)
-    out["__NONZERO"] = RangeSet(data=nonzero_blocks)
+    assert zero_blocks or nonzero_blocks or clobbered_blocks
+
+    if zero_blocks:
+      out["__ZERO"] = rangelib.RangeSet(data=zero_blocks)
+    if nonzero_blocks:
+      out["__NONZERO"] = rangelib.RangeSet(data=nonzero_blocks)
+    if clobbered_blocks:
+      out["__COPY"] = clobbered_blocks
 
   def ResetFileMap(self):
     """Throw away the file map and treat the entire image as
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
new file mode 100644
index 0000000..a861346
--- /dev/null
+++ b/tools/releasetools/test_common.py
@@ -0,0 +1,297 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import os
+import tempfile
+import time
+import unittest
+import zipfile
+
+import common
+
+
+def random_string_with_holes(size, block_size, step_size):
+  data = ["\0"] * size
+  for begin in range(0, size, step_size):
+    end = begin + block_size
+    data[begin:end] = os.urandom(block_size)
+  return "".join(data)
+
+def get_2gb_string():
+  kilobytes = 1024
+  megabytes = 1024 * kilobytes
+  gigabytes = 1024 * megabytes
+
+  size = int(2 * gigabytes + 1)
+  block_size = 4 * kilobytes
+  step_size = 4 * megabytes
+  two_gb_string = random_string_with_holes(
+        size, block_size, step_size)
+  return two_gb_string
+
+
+class CommonZipTest(unittest.TestCase):
+  def _verify(self, zip_file, zip_file_name, arcname, contents,
+              test_file_name=None, expected_stat=None, expected_mode=0o644,
+              expected_compress_type=zipfile.ZIP_STORED):
+    # Verify the stat if present.
+    if test_file_name is not None:
+      new_stat = os.stat(test_file_name)
+      self.assertEqual(int(expected_stat.st_mode), int(new_stat.st_mode))
+      self.assertEqual(int(expected_stat.st_mtime), int(new_stat.st_mtime))
+
+    # Reopen the zip file to verify.
+    zip_file = zipfile.ZipFile(zip_file_name, "r")
+
+    # Verify the timestamp.
+    info = zip_file.getinfo(arcname)
+    self.assertEqual(info.date_time, (2009, 1, 1, 0, 0, 0))
+
+    # Verify the file mode.
+    mode = (info.external_attr >> 16) & 0o777
+    self.assertEqual(mode, expected_mode)
+
+    # Verify the compress type.
+    self.assertEqual(info.compress_type, expected_compress_type)
+
+    # Verify the zip contents.
+    self.assertEqual(zip_file.read(arcname), contents)
+    self.assertIsNone(zip_file.testzip())
+
+  def _test_ZipWrite(self, contents, extra_zipwrite_args=None):
+    extra_zipwrite_args = dict(extra_zipwrite_args or {})
+
+    test_file = tempfile.NamedTemporaryFile(delete=False)
+    test_file_name = test_file.name
+
+    zip_file = tempfile.NamedTemporaryFile(delete=False)
+    zip_file_name = zip_file.name
+
+    # File names within an archive strip the leading slash.
+    arcname = extra_zipwrite_args.get("arcname", test_file_name)
+    if arcname[0] == "/":
+      arcname = arcname[1:]
+
+    zip_file.close()
+    zip_file = zipfile.ZipFile(zip_file_name, "w")
+
+    try:
+      test_file.write(contents)
+      test_file.close()
+
+      expected_stat = os.stat(test_file_name)
+      expected_mode = extra_zipwrite_args.get("perms", 0o644)
+      expected_compress_type = extra_zipwrite_args.get("compress_type",
+                                                       zipfile.ZIP_STORED)
+      time.sleep(5)  # Make sure the atime/mtime will change measurably.
+
+      common.ZipWrite(zip_file, test_file_name, **extra_zipwrite_args)
+      common.ZipClose(zip_file)
+
+      self._verify(zip_file, zip_file_name, arcname, contents, test_file_name,
+                   expected_stat, expected_mode, expected_compress_type)
+    finally:
+      os.remove(test_file_name)
+      os.remove(zip_file_name)
+
+  def _test_ZipWriteStr(self, zinfo_or_arcname, contents, extra_args=None):
+    extra_args = dict(extra_args or {})
+
+    zip_file = tempfile.NamedTemporaryFile(delete=False)
+    zip_file_name = zip_file.name
+    zip_file.close()
+
+    zip_file = zipfile.ZipFile(zip_file_name, "w")
+
+    try:
+      expected_compress_type = extra_args.get("compress_type",
+                                              zipfile.ZIP_STORED)
+      time.sleep(5)  # Make sure the atime/mtime will change measurably.
+
+      if not isinstance(zinfo_or_arcname, zipfile.ZipInfo):
+        arcname = zinfo_or_arcname
+        expected_mode = extra_args.get("perms", 0o644)
+      else:
+        arcname = zinfo_or_arcname.filename
+        expected_mode = extra_args.get("perms",
+                                       zinfo_or_arcname.external_attr >> 16)
+
+      common.ZipWriteStr(zip_file, zinfo_or_arcname, contents, **extra_args)
+      common.ZipClose(zip_file)
+
+      self._verify(zip_file, zip_file_name, arcname, contents,
+                   expected_mode=expected_mode,
+                   expected_compress_type=expected_compress_type)
+    finally:
+      os.remove(zip_file_name)
+
+  def _test_ZipWriteStr_large_file(self, large, small, extra_args=None):
+    extra_args = dict(extra_args or {})
+
+    zip_file = tempfile.NamedTemporaryFile(delete=False)
+    zip_file_name = zip_file.name
+
+    test_file = tempfile.NamedTemporaryFile(delete=False)
+    test_file_name = test_file.name
+
+    arcname_large = test_file_name
+    arcname_small = "bar"
+
+    # File names within an archive strip the leading slash.
+    if arcname_large[0] == "/":
+      arcname_large = arcname_large[1:]
+
+    zip_file.close()
+    zip_file = zipfile.ZipFile(zip_file_name, "w")
+
+    try:
+      test_file.write(large)
+      test_file.close()
+
+      expected_stat = os.stat(test_file_name)
+      expected_mode = 0o644
+      expected_compress_type = extra_args.get("compress_type",
+                                              zipfile.ZIP_STORED)
+      time.sleep(5)  # Make sure the atime/mtime will change measurably.
+
+      common.ZipWrite(zip_file, test_file_name, **extra_args)
+      common.ZipWriteStr(zip_file, arcname_small, small, **extra_args)
+      common.ZipClose(zip_file)
+
+      # Verify the contents written by ZipWrite().
+      self._verify(zip_file, zip_file_name, arcname_large, large,
+                   test_file_name, expected_stat, expected_mode,
+                   expected_compress_type)
+
+      # Verify the contents written by ZipWriteStr().
+      self._verify(zip_file, zip_file_name, arcname_small, small,
+                   expected_compress_type=expected_compress_type)
+    finally:
+      os.remove(zip_file_name)
+      os.remove(test_file_name)
+
+  def _test_reset_ZIP64_LIMIT(self, func, *args):
+    default_limit = (1 << 31) - 1
+    self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)
+    func(*args)
+    self.assertEqual(default_limit, zipfile.ZIP64_LIMIT)
+
+  def test_ZipWrite(self):
+    file_contents = os.urandom(1024)
+    self._test_ZipWrite(file_contents)
+
+  def test_ZipWrite_with_opts(self):
+    file_contents = os.urandom(1024)
+    self._test_ZipWrite(file_contents, {
+        "arcname": "foobar",
+        "perms": 0o777,
+        "compress_type": zipfile.ZIP_DEFLATED,
+    })
+    self._test_ZipWrite(file_contents, {
+        "arcname": "foobar",
+        "perms": 0o700,
+        "compress_type": zipfile.ZIP_STORED,
+    })
+
+  def test_ZipWrite_large_file(self):
+    file_contents = get_2gb_string()
+    self._test_ZipWrite(file_contents, {
+        "compress_type": zipfile.ZIP_DEFLATED,
+    })
+
+  def test_ZipWrite_resets_ZIP64_LIMIT(self):
+    self._test_reset_ZIP64_LIMIT(self._test_ZipWrite, "")
+
+  def test_ZipWriteStr(self):
+    random_string = os.urandom(1024)
+    # Passing arcname
+    self._test_ZipWriteStr("foo", random_string)
+
+    # Passing zinfo
+    zinfo = zipfile.ZipInfo(filename="foo")
+    self._test_ZipWriteStr(zinfo, random_string)
+
+    # Timestamp in the zinfo should be overwritten.
+    zinfo.date_time = (2015, 3, 1, 15, 30, 0)
+    self._test_ZipWriteStr(zinfo, random_string)
+
+  def test_ZipWriteStr_with_opts(self):
+    random_string = os.urandom(1024)
+    # Passing arcname
+    self._test_ZipWriteStr("foo", random_string, {
+        "perms": 0o700,
+        "compress_type": zipfile.ZIP_DEFLATED,
+    })
+    self._test_ZipWriteStr("bar", random_string, {
+        "compress_type": zipfile.ZIP_STORED,
+    })
+
+    # Passing zinfo
+    zinfo = zipfile.ZipInfo(filename="foo")
+    self._test_ZipWriteStr(zinfo, random_string, {
+        "compress_type": zipfile.ZIP_DEFLATED,
+    })
+    self._test_ZipWriteStr(zinfo, random_string, {
+        "perms": 0o600,
+        "compress_type": zipfile.ZIP_STORED,
+    })
+
+  def test_ZipWriteStr_large_file(self):
+    # zipfile.writestr() doesn't work when the str size is over 2GiB even with
+    # the workaround. We will only test the case of writing a string into a
+    # large archive.
+    long_string = get_2gb_string()
+    short_string = os.urandom(1024)
+    self._test_ZipWriteStr_large_file(long_string, short_string, {
+        "compress_type": zipfile.ZIP_DEFLATED,
+    })
+
+  def test_ZipWriteStr_resets_ZIP64_LIMIT(self):
+    self._test_reset_ZIP64_LIMIT(self._test_ZipWriteStr, "foo", "")
+    zinfo = zipfile.ZipInfo(filename="foo")
+    self._test_reset_ZIP64_LIMIT(self._test_ZipWriteStr, zinfo, "")
+
+  def test_bug21309935(self):
+    zip_file = tempfile.NamedTemporaryFile(delete=False)
+    zip_file_name = zip_file.name
+    zip_file.close()
+
+    try:
+      random_string = os.urandom(1024)
+      zip_file = zipfile.ZipFile(zip_file_name, "w")
+      # Default perms should be 0o644 when passing the filename.
+      common.ZipWriteStr(zip_file, "foo", random_string)
+      # Honor the specified perms.
+      common.ZipWriteStr(zip_file, "bar", random_string, perms=0o755)
+      # The perms in zinfo should be untouched.
+      zinfo = zipfile.ZipInfo(filename="baz")
+      zinfo.external_attr = 0o740 << 16
+      common.ZipWriteStr(zip_file, zinfo, random_string)
+      # Explicitly specified perms has the priority.
+      zinfo = zipfile.ZipInfo(filename="qux")
+      zinfo.external_attr = 0o700 << 16
+      common.ZipWriteStr(zip_file, zinfo, random_string, perms=0o400)
+      common.ZipClose(zip_file)
+
+      self._verify(zip_file, zip_file_name, "foo", random_string,
+                   expected_mode=0o644)
+      self._verify(zip_file, zip_file_name, "bar", random_string,
+                   expected_mode=0o755)
+      self._verify(zip_file, zip_file_name, "baz", random_string,
+                   expected_mode=0o740)
+      self._verify(zip_file, zip_file_name, "qux", random_string,
+                   expected_mode=0o400)
+    finally:
+      os.remove(zip_file_name)