Merge "Add compressor options for squashfs system images"
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/core/Makefile b/core/Makefile
index 255a6fb..e0aa9c3 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.
@@ -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,14 @@
 			PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
 			BUILD_ID="$(BUILD_ID)" \
 			BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \
-			BUILD_NUMBER="$(BUILD_NUMBER)" \
+			BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
 			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)" \
@@ -244,7 +247,7 @@
 	$(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.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
 endif
 
 # ----------------------------------------------------------------
@@ -260,7 +263,7 @@
 	$(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.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
 
 # -----------------------------------------------------------------
 # sdk-build.prop
@@ -783,8 +786,15 @@
 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),)
   $(info No private recovery resources for TARGET_DEVICE $(TARGET_DEVICE))
@@ -876,16 +886,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
@@ -993,6 +1005,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) \
@@ -1002,6 +1015,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
 
 
@@ -1456,6 +1472,7 @@
 	$(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) $(ACP) $(SELINUX_FC) $(zip_root)/META/file_contexts
 	$(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
@@ -1494,6 +1511,9 @@
 	# 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 MKBOOTIMG=$(MKBOOTIMG) \
 	    ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
@@ -1507,7 +1527,7 @@
 	$(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 MKBOOTIMG=$(MKBOOTIMG) \
-	    ./build/tools/releasetools/add_img_to_target_files -p $(HOST_OUT) $@
+	    ./build/tools/releasetools/add_img_to_target_files -v -p $(HOST_OUT) $@
 
 .PHONY: target-files-package
 target-files-package: $(BUILT_TARGET_FILES_PACKAGE)
diff --git a/core/binary.mk b/core/binary.mk
index 116e261..e18f8c8 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -46,7 +46,9 @@
 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)
@@ -201,6 +203,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)
@@ -227,6 +231,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
 
 ###########################################################
@@ -337,6 +344,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)"
@@ -353,6 +361,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)"
@@ -361,6 +370,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)
 
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/TARGET_arm.mk b/core/clang/TARGET_arm.mk
index cd25604..5ac5477 100644
--- a/core/clang/TARGET_arm.mk
+++ b/core/clang/TARGET_arm.mk
@@ -70,3 +70,4 @@
 # 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 0861568..5120a6d 100644
--- a/core/clang/TARGET_arm64.mk
+++ b/core/clang/TARGET_arm64.mk
@@ -68,3 +68,4 @@
 # 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/cleanbuild.mk b/core/cleanbuild.mk
index b76e7a5..c2386a4 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -105,11 +105,10 @@
   _crs_new_cmd :=
   steps :=
 endif
-CURRENT_CLEAN_BUILD_VERSION :=
-CURRENT_CLEAN_STEPS :=
 
 # Write the new state to the file.
 #
+ifneq ($(CURRENT_CLEAN_BUILD_VERSION)-$(CURRENT_CLEAN_STEPS),$(INTERNAL_CLEAN_BUILD_VERSION)-$(INTERNAL_CLEAN_STEPS))
 $(shell \
   mkdir -p $(dir $(clean_steps_file)) && \
   echo "CURRENT_CLEAN_BUILD_VERSION := $(INTERNAL_CLEAN_BUILD_VERSION)" > \
@@ -117,7 +116,10 @@
   echo "CURRENT_CLEAN_STEPS := $(INTERNAL_CLEAN_STEPS)" >> \
       $(clean_steps_file) \
  )
+endif
 
+CURRENT_CLEAN_BUILD_VERSION :=
+CURRENT_CLEAN_STEPS :=
 clean_steps_file :=
 INTERNAL_CLEAN_STEPS :=
 INTERNAL_CLEAN_BUILD_VERSION :=
@@ -164,7 +166,6 @@
     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)"
@@ -172,10 +173,10 @@
     force_objclean := true
   endif
 endif  # else, this is the first build, so no need to clean.
-PREVIOUS_SANITIZE_TARGET :=
 
 # 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)" > \
@@ -183,6 +184,9 @@
   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 :=
 
@@ -286,6 +290,50 @@
 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
@@ -303,4 +351,3 @@
 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 9d6f91b..e5d299c 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -154,7 +154,6 @@
 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:=
@@ -163,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:=
diff --git a/core/combo/include/arch/darwin-x86/AndroidConfig.h b/core/combo/include/arch/darwin-x86/AndroidConfig.h
index ee62edc..1a5a4f4 100644
--- a/core/combo/include/arch/darwin-x86/AndroidConfig.h
+++ b/core/combo/include/arch/darwin-x86/AndroidConfig.h
@@ -33,11 +33,6 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-/* #define HAVE_MALLOC_H 1 */
-
-/*
  * The default path separator for the platform
  */
 #define OS_PATH_SEPARATOR '/'
diff --git a/core/combo/include/arch/linux-arm/AndroidConfig.h b/core/combo/include/arch/linux-arm/AndroidConfig.h
index fdd5b37..d7d90f7 100644
--- a/core/combo/include/arch/linux-arm/AndroidConfig.h
+++ b/core/combo/include/arch/linux-arm/AndroidConfig.h
@@ -33,11 +33,6 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H 1
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
diff --git a/core/combo/include/arch/linux-arm64/AndroidConfig.h b/core/combo/include/arch/linux-arm64/AndroidConfig.h
index f7ab30f..f4e99e9 100644
--- a/core/combo/include/arch/linux-arm64/AndroidConfig.h
+++ b/core/combo/include/arch/linux-arm64/AndroidConfig.h
@@ -33,11 +33,6 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H 1
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
diff --git a/core/combo/include/arch/linux-mips/AndroidConfig.h b/core/combo/include/arch/linux-mips/AndroidConfig.h
index 0d7eaf0..5a08dde 100644
--- a/core/combo/include/arch/linux-mips/AndroidConfig.h
+++ b/core/combo/include/arch/linux-mips/AndroidConfig.h
@@ -33,11 +33,6 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H 1
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
diff --git a/core/combo/include/arch/linux-mips64/AndroidConfig.h b/core/combo/include/arch/linux-mips64/AndroidConfig.h
index 947691f..debd486 100644
--- a/core/combo/include/arch/linux-mips64/AndroidConfig.h
+++ b/core/combo/include/arch/linux-mips64/AndroidConfig.h
@@ -33,11 +33,6 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H 1
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
diff --git a/core/combo/include/arch/linux-x86/AndroidConfig.h b/core/combo/include/arch/linux-x86/AndroidConfig.h
index 4409e76..966144a 100644
--- a/core/combo/include/arch/linux-x86/AndroidConfig.h
+++ b/core/combo/include/arch/linux-x86/AndroidConfig.h
@@ -41,11 +41,6 @@
 #define _LARGEFILE_SOURCE 1
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H 1
-
-/*
  * The default path separator for the platform
  */
 #define OS_PATH_SEPARATOR '/'
diff --git a/core/combo/include/arch/target_linux-x86/AndroidConfig.h b/core/combo/include/arch/target_linux-x86/AndroidConfig.h
index e73ceaa..e22dedc 100644
--- a/core/combo/include/arch/target_linux-x86/AndroidConfig.h
+++ b/core/combo/include/arch/target_linux-x86/AndroidConfig.h
@@ -19,11 +19,6 @@
  */
 
 /*
- * Define if we have <malloc.h> header
- */
-#define HAVE_MALLOC_H 1
-
-/*
  * Define if we're running on *our* linux on device or emulator.
  */
 #define HAVE_ANDROID_OS 1
diff --git a/core/combo/include/arch/windows/AndroidConfig.h b/core/combo/include/arch/windows/AndroidConfig.h
index e7eb837..4abec42 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
 
@@ -55,9 +47,6 @@
 #  endif
 #endif
 
-/* TODO: replace references to this. */
-#define HAVE_WIN32_IPC
-
 #ifdef __CYGWIN__
 #error "CYGWIN is unsupported for platform builds"
 #endif
@@ -87,8 +76,6 @@
 #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
  */
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 88a1bcb..7a90a0e 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -257,6 +257,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
@@ -465,7 +467,6 @@
 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
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index b43b1cc..f71996d 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -45,6 +45,10 @@
         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
 
@@ -85,12 +89,14 @@
     my_ldlibs += -lm -lpthread
     my_ldflags += -Wl,--no-as-needed
   else
+    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)
   endif
 endif
 
diff --git a/core/cxx_stl_setup.mk b/core/cxx_stl_setup.mk
index c59cd34..f150714 100644
--- a/core/cxx_stl_setup.mk
+++ b/core/cxx_stl_setup.mk
@@ -24,6 +24,18 @@
     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.
@@ -70,6 +82,7 @@
     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)
diff --git a/core/definitions.mk b/core/definitions.mk
index 442501e..80c6b4a 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -810,42 +810,6 @@
 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);
-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
@@ -866,8 +830,8 @@
 ###########################################################
 
 define transform-l-to-cpp
-@mkdir -p $(dir $@)
 @echo "Lex: $(PRIVATE_MODULE) <= $<"
+@mkdir -p $(dir $@)
 $(hide) $(LEX) -o$@ $<
 endef
 
@@ -880,8 +844,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)
@@ -997,8 +961,8 @@
 ## Commands for running protoc to compile .proto into .pb.cc 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) \
@@ -1011,8 +975,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)) \
@@ -1118,8 +1082,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)) \
@@ -1327,10 +1291,10 @@
 # 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) $@,$(PRIVATE_ALL_OBJECTS))
@@ -1376,10 +1340,10 @@
 # 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) $@,$(PRIVATE_ALL_OBJECTS))
@@ -1420,14 +1384,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
 
@@ -1463,8 +1427,8 @@
 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
 
@@ -1479,15 +1443,15 @@
 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) $< $@
@@ -1498,8 +1462,8 @@
 ###########################################################
 
 define pack-elf-relocations
-$(copy-file-to-target)
 @echo "target Pack Relocations: $(PRIVATE_MODULE) ($@)"
+$(copy-file-to-target)
 $(hide) $(RELOCATION_PACKER) $@
 endef
 
@@ -1510,7 +1474,7 @@
 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) \
@@ -1536,8 +1500,8 @@
 endef
 
 define transform-o-to-executable
-@mkdir -p $(dir $@)
 @echo "target Executable: $(PRIVATE_MODULE) ($@)"
+@mkdir -p $(dir $@)
 $(transform-o-to-executable-inner)
 endef
 
@@ -1580,8 +1544,8 @@
 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
 
@@ -1626,8 +1590,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
 
@@ -1664,8 +1628,8 @@
     $(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
@@ -1788,7 +1752,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) ., \
@@ -1990,7 +1954,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) ., \
@@ -2093,8 +2057,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 $@
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 1de72b7..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
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 41f135c..0de1837 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -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 "+%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/java.mk b/core/java.mk
index 4885d74..f295973 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -251,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)
diff --git a/core/main.mk b/core/main.mk
index 7f561ab..38fe994 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -93,6 +93,16 @@
 # 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)
+BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
+
 # CTS-specific config.
 -include cts/build/config.mk
 
@@ -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))))
@@ -1016,8 +1027,6 @@
 endif
 endif
 
-.PHONY: lintall
-
 ifneq (,$(filter samplecode, $(MAKECMDGOALS)))
 .PHONY: samplecode
 sample_MODULES := $(sort $(call get-tagged-modules,samples))
@@ -1061,3 +1070,4 @@
 .PHONY: nothing
 nothing:
 	@echo Successfully read the makefiles.
+endif # !USE_NINJA
diff --git a/core/ninja.mk b/core/ninja.mk
new file mode 100644
index 0000000..05498d8
--- /dev/null
+++ b/core/ninja.mk
@@ -0,0 +1,50 @@
+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),$(MAKECMDGOALS))
+
+ifeq (,$(NINJA_STATUS))
+NINJA_STATUS := [%p %s/%t]$(space)
+endif
+
+ifneq (,$(filter showcommands,$(MAKECMDGOALS)))
+NINJA_ARGS += "-v"
+PHONY: showcommands
+showcommands: droid
+endif
+
+ifeq (,$(filter generateonly,$(MAKECMDGOALS)))
+fastincremental droid $(ANDROID_TARGETS): ninja.intermediate
+	@#empty
+
+.INTERMEDIATE: ninja.intermediate
+ninja.intermediate: $(KATI_OUTPUTS)
+	@echo Starting build with ninja
+	@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,$(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
+	@$(KATI) --ninja --ninja_dir=$(PRODUCT_OUT) --ignore_optional_include=out/%.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)
+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/package_internal.mk b/core/package_internal.mk
index fee484f..4f3c339 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -510,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/envsetup.sh b/envsetup.sh
index 65a536e..62802df 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.
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/sepolicy/file_contexts b/target/board/generic/sepolicy/file_contexts
index d057dc3..e626d9d 100644
--- a/target/board/generic/sepolicy/file_contexts
+++ b/target/board/generic/sepolicy/file_contexts
@@ -1,11 +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/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
-/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_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index 4b6136d..0c4d59c 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -76,7 +76,7 @@
 USE_OPENGL_RENDERER := true
 
 TARGET_USERIMAGES_USE_EXT4 := true
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1073741824
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1258291200
 BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
 BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
 BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index dee5a69..bc2667d 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -130,21 +130,11 @@
   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 fc_config:
-    image_props["selinux_fc"] = fc_config
   if block_list:
     image_props["block_list"] = block_list
-  if image_props.get("system_root_image") == "true":
-    image_props["ramdisk_dir"] = os.path.join(input_dir, "BOOT/RAMDISK")
-    image_props["ramdisk_fs_config"] = os.path.join(
-        input_dir, "META/boot_filesystem_config.txt")
 
   succ = build_image.BuildImage(os.path.join(input_dir, what),
                                 image_props, img)
@@ -167,8 +157,7 @@
     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
@@ -214,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
@@ -258,10 +246,7 @@
   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)
 
   common.ZipClose(input_zip)
   output_zip = zipfile.ZipFile(filename, "a",
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 3402572..a007f81 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -16,6 +16,7 @@
 
 from collections import deque, OrderedDict
 from hashlib import sha1
+import common
 import heapq
 import itertools
 import multiprocessing
@@ -83,6 +84,7 @@
   blocksize = 4096
   care_map = RangeSet()
   clobbered_blocks = RangeSet()
+  extended = RangeSet()
   total_blocks = 0
   file_map = {}
   def ReadRangeSet(self, ranges):
@@ -119,6 +121,7 @@
     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 = []
@@ -411,7 +414,7 @@
           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();
+              temp_stash_usage = stashed_blocks + xf.src_ranges.size()
               if temp_stash_usage > max_stashed_blocks:
                 max_stashed_blocks = temp_stash_usage
 
@@ -435,7 +438,7 @@
         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();
+            temp_stash_usage = stashed_blocks + xf.src_ranges.size()
             if temp_stash_usage > max_stashed_blocks:
               max_stashed_blocks = temp_stash_usage
 
@@ -458,22 +461,32 @@
       if free_string:
         out.append("".join(free_string))
 
-      # 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)
+      if self.version >= 2:
+        # 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)
 
+    # 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")
@@ -488,8 +501,11 @@
         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
+      max_allowed = common.OPTIONS.cache_size * common.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))
 
   def ComputePatches(self, prefix):
     print("Reticulating splines...")
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 32c0ee4..bf5d9dd 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -417,6 +417,7 @@
     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")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index ae449c3..5fcdbe4 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -94,7 +94,7 @@
       pass
 
 
-def LoadInfoDict(input_file):
+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."""
 
@@ -145,6 +145,34 @@
   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 under META/. If not available, search
+    # BOOT/RAMDISK/. Note that sometimes we may need a different file_contexts
+    # 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")
+    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")
+      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"):
@@ -891,7 +919,7 @@
     zinfo = zipfile.ZipInfo(filename=zinfo_or_arcname)
     zinfo.compress_type = zip_file.compression
     if perms is None:
-      perms = 0o644
+      perms = 0o100644
   else:
     zinfo = zinfo_or_arcname
 
@@ -901,6 +929,9 @@
 
   # 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.
@@ -1240,7 +1271,23 @@
     script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
                        self.device, ranges_str,
                        self.tgt.TotalSha1(include_clobbered_blocks=True)))
-    script.Print('Verified the updated %s image.' % (partition,))
+
+    # 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,))
+
     script.AppendExtra(
         'else\n'
         '  abort("%s partition has unexpected contents after OTA update");\n'
@@ -1273,6 +1320,15 @@
 
     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.
@@ -1339,18 +1395,24 @@
   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"
-  else:
-    bonus_args = ""
+  full_recovery_image = info_dict.get("full_recovery_image", None) == "true"
 
-  d = Difference(recovery_img, boot_img, diff_program=diff_program)
-  _, _, patch = d.ComputePatch()
-  output_sink("recovery-from-boot.p", patch)
+  if full_recovery_image:
+    output_sink("etc/recovery.img", recovery_img.data)
+
+  else:
+    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)
 
   try:
     boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
@@ -1358,7 +1420,19 @@
   except KeyError:
     return
 
-  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
@@ -1375,18 +1449,28 @@
        '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
+  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(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) as 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/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index c486992..608aad1 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -95,16 +95,7 @@
       # 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")
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index a87363b..69987ab 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -84,6 +84,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
@@ -122,6 +125,10 @@
 OPTIONS.oem_source = None
 OPTIONS.fallback_to_full = True
 OPTIONS.full_radio = False
+# Stash size cannot exceed cache_size * threshold.
+OPTIONS.cache_size = None
+OPTIONS.stash_threshold = 0.8
+
 
 def MostPopularKey(d, default):
   """Given a dict, return the key corresponding to the largest
@@ -211,7 +218,8 @@
         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, 0o644, None, None
@@ -415,11 +423,9 @@
 
 
 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:
@@ -582,6 +588,8 @@
   if HasVendorPartition(input_zip):
     system_progress -= 0.1
 
+  # Place a copy of file_contexts 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)
 
@@ -830,9 +838,9 @@
   #    (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}
@@ -877,7 +885,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:
@@ -1217,9 +1226,9 @@
   #    (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}
@@ -1256,7 +1265,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,
@@ -1351,6 +1361,7 @@
       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:
@@ -1502,6 +1513,12 @@
       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
@@ -1525,6 +1542,7 @@
                                  "oem_settings=",
                                  "verify",
                                  "no_fallback_to_full",
+                                 "stash_threshold=",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
@@ -1538,15 +1556,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 ---"
@@ -1582,6 +1592,11 @@
       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:
+      raise RuntimeError("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:
@@ -1596,10 +1611,8 @@
       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",
diff --git a/tools/releasetools/rangelib.py b/tools/releasetools/rangelib.py
index 8b327fe..1506658 100644
--- a/tools/releasetools/rangelib.py
+++ b/tools/releasetools/rangelib.py
@@ -238,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.py b/tools/releasetools/sign_target_files_apks.py
index ec49112..962d3dd 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -175,6 +175,7 @@
     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,
@@ -184,12 +185,14 @@
       new_data = ReplaceVerityPublicKey(output_tf_zip,
                                         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"):
       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]
@@ -214,6 +217,7 @@
       new_data = ReplaceCerts(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
diff --git a/tools/releasetools/sparse_img.py b/tools/releasetools/sparse_img.py
index 7019f00..07f3c1c 100644
--- a/tools/releasetools/sparse_img.py
+++ b/tools/releasetools/sparse_img.py
@@ -110,6 +110,17 @@
     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.clobbered_blocks)
     else: