Merge "Use analyzer at new location: prebuilts/misc/{linux-x86,darwin-x86}/analyzer"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 4eec704..f8d0e6f 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -234,6 +234,11 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*)
 
+# L development
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/64_bit_blacklist.mk b/core/64_bit_blacklist.mk
index ea72967..9f16536 100644
--- a/core/64_bit_blacklist.mk
+++ b/core/64_bit_blacklist.mk
@@ -2,31 +2,22 @@
 
 # JNI - needs 64-bit VM
 _64_bit_directory_blacklist += \
-	external/conscrypt \
-	external/neven \
-	external/svox \
-	packages \
+        external/svox/ \
+        packages/
+
 
 # Chromium/V8: needs 64-bit support
 _64_bit_directory_blacklist += \
 	external/chromium \
 	external/chromium-libpac \
 	external/chromium_org \
-	external/skia \
+	external/v8 \
 	frameworks/webview \
 
 # misc build errors
 _64_bit_directory_blacklist += \
-	external/bluetooth/bluedroid \
-	external/oprofile/daemon \
-	external/oprofile/opcontrol \
 	frameworks/av \
 	frameworks/base \
-	frameworks/ex \
-	frameworks/ml \
-	frameworks/opt \
-	frameworks/wilhelm \
-	frameworks/native/cmds/idmap \
 	device/generic/goldfish/opengl \
 	device/generic/goldfish/camera \
 
@@ -35,6 +26,9 @@
 	external/srec \
 	hardware/libhardware_legacy/audio \
 	hardware/libhardware/modules/audio_remote_submix \
+	frameworks/wilhelm \
+	frameworks/opt \
+	frameworks/ex \
 
 _64_bit_directory_blacklist_pattern := $(addsuffix %,$(_64_bit_directory_blacklist))
 
diff --git a/core/Makefile b/core/Makefile
index e7eafe8..bae7d59 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1135,7 +1135,9 @@
 	  $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \
 	  $(HOST_OUT_EXECUTABLES)/make_ext4fs \
 	  $(HOST_OUT_EXECUTABLES)/simg2img \
-	  $(HOST_OUT_EXECUTABLES)/e2fsck
+	  $(HOST_OUT_EXECUTABLES)/e2fsck \
+	  $(HOST_OUT_EXECUTABLES)/xdelta3 \
+	  $(HOST_OUT_EXECUTABLES)/syspatch_host
 
 OTATOOLS := $(DISTTOOLS) \
 	  $(HOST_OUT_EXECUTABLES)/aapt
diff --git a/core/binary.mk b/core/binary.mk
index 55662fc..931e422 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -143,7 +143,7 @@
   my_static_libraries += $(ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES)
 endif
 
-ifeq ($(strip $($(LOCAL_2ND_ARCH_VAR_PREFIX)WITHOUT_CLANG)),true)
+ifeq ($(strip $($(LOCAL_2ND_ARCH_VAR_PREFIX)WITHOUT_$(my_prefix)CLANG)),true)
   LOCAL_CLANG :=
 endif
 
@@ -454,22 +454,38 @@
 
 
 ###########################################################
-## YACC: Compile .y files to .cpp and the to .o.
+## YACC: Compile .y and .yy files to .cpp and the to .o.
 ###########################################################
 
-yacc_sources := $(filter %.y,$(my_src_files))
-yacc_cpps := $(addprefix \
-    $(intermediates)/,$(yacc_sources:.y=$(LOCAL_CPP_EXTENSION)))
+y_yacc_sources := $(filter %.y,$(my_src_files))
+y_yacc_cpps := $(addprefix \
+    $(intermediates)/,$(y_yacc_sources:.y=$(LOCAL_CPP_EXTENSION)))
+
+yy_yacc_sources := $(filter %.yy,$(my_src_files))
+yy_yacc_cpps := $(addprefix \
+    $(intermediates)/,$(yy_yacc_sources:.yy=$(LOCAL_CPP_EXTENSION)))
+
+yacc_cpps := $(y_yacc_cpps) $(yy_yacc_cpps)
 yacc_headers := $(yacc_cpps:$(LOCAL_CPP_EXTENSION)=.h)
 yacc_objects := $(yacc_cpps:$(LOCAL_CPP_EXTENSION)=.o)
 
-ifneq ($(strip $(yacc_cpps)),)
-$(yacc_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
+ifneq ($(strip $(y_yacc_cpps)),)
+$(y_yacc_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
     $(TOPDIR)$(LOCAL_PATH)/%.y \
     $(lex_cpps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	$(call transform-y-to-cpp,$(PRIVATE_CPP_EXTENSION))
 $(yacc_headers): $(intermediates)/%.h: $(intermediates)/%$(LOCAL_CPP_EXTENSION)
+endif
 
+ifneq ($(strip $(yy_yacc_cpps)),)
+$(yy_yacc_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
+    $(TOPDIR)$(LOCAL_PATH)/%.yy \
+    $(lex_cpps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(call transform-y-to-cpp,$(PRIVATE_CPP_EXTENSION))
+$(yacc_headers): $(intermediates)/%.h: $(intermediates)/%$(LOCAL_CPP_EXTENSION)
+endif
+
+ifneq ($(strip $(yacc_cpps)),)
 $(yacc_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(yacc_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 $(yacc_objects): $(intermediates)/%.o: $(intermediates)/%$(LOCAL_CPP_EXTENSION)
@@ -477,19 +493,33 @@
 endif
 
 ###########################################################
-## LEX: Compile .l files to .cpp and then to .o.
+## LEX: Compile .l and .ll files to .cpp and then to .o.
 ###########################################################
 
-lex_sources := $(filter %.l,$(my_src_files))
-lex_cpps := $(addprefix \
-    $(intermediates)/,$(lex_sources:.l=$(LOCAL_CPP_EXTENSION)))
+l_lex_sources := $(filter %.l,$(my_src_files))
+l_lex_cpps := $(addprefix \
+    $(intermediates)/,$(l_lex_sources:.l=$(LOCAL_CPP_EXTENSION)))
+
+ll_lex_sources := $(filter %.ll,$(my_src_files))
+ll_lex_cpps := $(addprefix \
+    $(intermediates)/,$(ll_lex_sources:.ll=$(LOCAL_CPP_EXTENSION)))
+
+lex_cpps := $(l_lex_cpps) $(ll_lex_cpps)
 lex_objects := $(lex_cpps:$(LOCAL_CPP_EXTENSION)=.o)
 
-ifneq ($(strip $(lex_cpps)),)
-$(lex_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
+ifneq ($(strip $(l_lex_cpps)),)
+$(l_lex_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
     $(TOPDIR)$(LOCAL_PATH)/%.l
 	$(transform-l-to-cpp)
+endif
 
+ifneq ($(strip $(ll_lex_cpps)),)
+$(ll_lex_cpps): $(intermediates)/%$(LOCAL_CPP_EXTENSION): \
+    $(TOPDIR)$(LOCAL_PATH)/%.ll
+	$(transform-l-to-cpp)
+endif
+
+ifneq ($(strip $(lex_cpps)),)
 $(lex_objects): PRIVATE_ARM_MODE := $(normal_objects_mode)
 $(lex_objects): PRIVATE_ARM_CFLAGS := $(normal_objects_cflags)
 $(lex_objects): $(intermediates)/%.o: \
diff --git a/core/clang/config.mk b/core/clang/config.mk
index 1fd69d7..96f860d 100644
--- a/core/clang/config.mk
+++ b/core/clang/config.mk
@@ -1,3 +1,11 @@
+## Clang configurations.
+
+# WITHOUT_CLANG covers both HOST and TARGET
+ifeq ($(WITHOUT_CLANG),true)
+WITHOUT_TARGET_CLANG := true
+WITHOUT_HOST_CLANG := true
+endif
+
 ifeq (true,$(FORCE_BUILD_LLVM_COMPONENTS))
 LLVM_PREBUILTS_PATH := $(BUILD_OUT_EXECUTABLES)
 LLVM_PREBUILTS_HEADER_PATH := external/clang/lib/include
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index fa67332..dfdf43d 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -196,7 +196,8 @@
 	$(PRODUCT_OUT)/obj/EXECUTABLES/adbd_intermediates \
 	$(PRODUCT_OUT)/obj/EXECUTABLES/init_intermediates \
 	$(PRODUCT_OUT)/obj/ETC/mac_permissions.xml_intermediates \
-	$(PRODUCT_OUT)/obj/ETC/sepolicy_intermediates
+	$(PRODUCT_OUT)/obj/ETC/sepolicy_intermediates \
+	$(PRODUCT_OUT)/obj/ETC/init.environ.rc_intermediates
 
 # The files/dirs to delete during a dataclean, which removes any files
 # in the staging and emulator data partitions.
diff --git a/core/combo/HOST_darwin-x86.mk b/core/combo/HOST_darwin-x86.mk
index a0aaafa..037dee6 100644
--- a/core/combo/HOST_darwin-x86.mk
+++ b/core/combo/HOST_darwin-x86.mk
@@ -36,7 +36,7 @@
 
 # Workaround differences in inttypes.h between host and target.
 # See bug 12708004.
-HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS
+HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
 
 build_mac_version := $(shell sw_vers -productVersion)
 
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index 3d03ed6..944a31d 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -60,6 +60,6 @@
 
 # Workaround differences in inttypes.h between host and target.
 # See bug 12708004.
-HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS
+HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
 
 HOST_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
diff --git a/core/combo/HOST_windows-x86.mk b/core/combo/HOST_windows-x86.mk
index 2f27aa7..1709711 100644
--- a/core/combo/HOST_windows-x86.mk
+++ b/core/combo/HOST_windows-x86.mk
@@ -42,7 +42,7 @@
 
 # Workaround differences in inttypes.h between host and target.
 # See bug 12708004.
-HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS
+HOST_GLOBAL_CFLAGS += -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS
 
 HOST_CC := $(TOOLS_PREFIX)gcc$(TOOLS_EXE_SUFFIX)
 HOST_CXX := $(TOOLS_PREFIX)g++$(TOOLS_EXE_SUFFIX)
diff --git a/core/combo/TARGET_linux-arm64.mk b/core/combo/TARGET_linux-arm64.mk
index 7a7a0c9..290cebe 100644
--- a/core/combo/TARGET_linux-arm64.mk
+++ b/core/combo/TARGET_linux-arm64.mk
@@ -48,7 +48,7 @@
 endif
 
 # TODO: Enable Clang when aarch64 prebuilt is added
-WITHOUT_CLANG := true
+WITHOUT_TARGET_CLANG := true
 
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 
diff --git a/core/combo/TARGET_linux-mips64.mk b/core/combo/TARGET_linux-mips64.mk
index c1c6439..099edfa 100644
--- a/core/combo/TARGET_linux-mips64.mk
+++ b/core/combo/TARGET_linux-mips64.mk
@@ -48,7 +48,7 @@
 endif
 
 # TODO: Enable Clang when its mips64 prebuilt is added
-WITHOUT_CLANG := true
+WITHOUT_TARGET_CLANG := true
 
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 
diff --git a/core/config.mk b/core/config.mk
index 6217f2b..5cfa857 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -375,7 +375,7 @@
 
 ifneq ($(HOST_JDK_TOOLS_JAR),)
 ifeq ($(wildcard $(HOST_JDK_TOOLS_JAR)),)
-$(error Error: could not find jdk tools.jar, please install JDK6)
+$(error Error: could not find jdk tools.jar, please check if your JDK was installed correctly)
 endif
 endif
 
diff --git a/core/definitions.mk b/core/definitions.mk
index 94e7432..ba6b9dd 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -850,7 +850,6 @@
 echo '#define '$(@F:$1=_h) >> $(@:$1=.h)
 cat $(@:$1=$(YACC_HEADER_SUFFIX)) >> $(@:$1=.h)
 echo '#endif' >> $(@:$1=.h)
-rm -f $(@:$1=$(YACC_HEADER_SUFFIX))
 endef
 
 ###########################################################
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index fa2b7e3..70ffee9 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -74,7 +74,7 @@
 		--oat-location=$(patsubst %.art,%.oat,$(LIBART_BOOT_IMAGE)) \
 		--image=$@ --base=$(LIBART_IMG_TARGET_BASE_ADDRESS) \
 		--instruction-set=$(TARGET_ARCH) --instruction-set-features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
-		--host-prefix=$(DEXPREOPT_PRODUCT_DIR_FULL_PATH) --android-root=$(PRODUCT_OUT)/system
+		--android-root=$(PRODUCT_OUT)/system
 
 
 ########################################################################
@@ -93,7 +93,6 @@
 	--dex-file=$(2) \
 	--dex-location=$(3) \
 	--oat-file=$(4) \
-	--host-prefix=$(DEXPREOPT_PRODUCT_DIR_FULL_PATH) \
 	--android-root=$(PRODUCT_OUT)/system \
 	--instruction-set=$(TARGET_ARCH) \
 	--instruction-set-features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES)
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index eedbfd2..e16383b 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -59,7 +59,7 @@
 ifeq "" "$(PLATFORM_VERSION_CODENAME)"
   # This is the current development code-name, if the build is not a final
   # release build.  If this is a final release build, it is simply "REL".
-  PLATFORM_VERSION_CODENAME := KKWT
+  PLATFORM_VERSION_CODENAME := L
 endif
 
 ifeq "" "$(DEFAULT_APP_TARGET_SDK)"
diff --git a/envsetup.sh b/envsetup.sh
index dfd1617..ba4f683 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -7,6 +7,7 @@
 - m:       Makes from the top of the tree.
 - mm:      Builds all of the modules in the current directory, but not their dependencies.
 - mmm:     Builds all of the modules in the supplied directories, but not their dependencies.
+           To limit the modules being built use the syntax: mmm dir/:target1,target2.
 - mma:     Builds all of the modules in the current directory, and their dependencies.
 - mmma:    Builds all of the modules in the supplied directories, and their dependencies.
 - cgrep:   Greps on all local C/C++ files.
@@ -190,10 +191,6 @@
     unset ANDROID_HOST_OUT
     export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT)
 
-    # needed for processing samples collected by perf counters
-    unset OPROFILE_EVENTS_DIR
-    export OPROFILE_EVENTS_DIR=$T/external/oprofile/events
-
     # needed for building linux on MacOS
     # TODO: fix the path
     #export HOST_EXTRACFLAGS="-I "$T/system/kernel_headers/host_include
diff --git a/target/product/base.mk b/target/product/base.mk
index 657d88c..36f1f97 100644
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -97,7 +97,6 @@
     racoon \
     run-as \
     schedtest \
-    screenshot \
     sdcard \
     services \
     settings \
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index 33a1dde..5905b8a 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -59,6 +59,9 @@
     ro.carrier=unknown
 
 $(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk)
+$(call inherit-product-if-exists, external/google-fonts/dancing-script/fonts.mk)
+$(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts.mk)
+$(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk)
 $(call inherit-product-if-exists, external/noto-fonts/fonts.mk)
 $(call inherit-product-if-exists, external/naver-fonts/fonts.mk)
 $(call inherit-product-if-exists, external/sil-fonts/fonts.mk)
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index 15fa1f7..b1ed4a1 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -75,6 +75,9 @@
 
 $(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
 $(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk)
+$(call inherit-product-if-exists, external/google-fonts/dancing-script/fonts.mk)
+$(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts.mk)
+$(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk)
 $(call inherit-product-if-exists, external/noto-fonts/fonts.mk)
 $(call inherit-product-if-exists, external/naver-fonts/fonts.mk)
 $(call inherit-product-if-exists, external/sil-fonts/fonts.mk)
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index ffda6cf..927d89a 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -27,6 +27,8 @@
 import commands
 import shutil
 
+import simg_map
+
 def RunCommand(cmd):
   """ Echo and run the given command
 
@@ -146,6 +148,13 @@
     return False, None
   return True, unsparse_image_path
 
+def MappedUnsparseImage(sparse_image_path, unsparse_image_path,
+                        map_path, mapped_unsparse_image_path):
+  if simg_map.ComputeMap(sparse_image_path, unsparse_image_path,
+                         map_path, mapped_unsparse_image_path):
+    return False
+  return True
+
 def MakeVerityEnabledImage(out_file, prop_dict):
   """Creates an image that is verifiable using dm-verity.
 
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index b7e18fa..ca73ee4 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1015,7 +1015,7 @@
     with open(output_file.name + ".xz") as patch_file:
       patch_data = patch_file.read()
       os.unlink(patch_file.name)
-      return File("system.img.p", patch_data)
+      return File("system.muimg.p", patch_data)
 
 def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
                       info_dict=None):
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index a5340a0..af545db 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -190,6 +190,16 @@
                          (p.fs_type, common.PARTITION_TYPES[p.fs_type],
                           p.device, p.length, p.mount_point))
 
+  def WipeBlockDevice(self, partition):
+    if partition != "/system":
+      raise ValueError(("WipeBlockDevice currently only works "
+                        "on /system, not %s\n") % (partition,))
+    fstab = self.info.get("fstab", None)
+    size = self.info.get("system_size", None)
+    device = fstab[partition].device
+
+    self.script.append('wipe_block_device("%s", %s);' % (device, size))
+
   def DeleteFiles(self, file_list):
     """Delete all files in file_list."""
     if not file_list: return
@@ -224,7 +234,7 @@
     cmd = "".join(cmd)
     self.script.append(self._WordWrap(cmd))
 
-  def WriteRawImage(self, mount_point, fn):
+  def WriteRawImage(self, mount_point, fn, mapfn=None):
     """Write the given package file into the partition for the given
     mount point."""
 
@@ -238,8 +248,13 @@
             'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");'
             % args)
       elif partition_type == "EMMC":
-        self.script.append(
-            'package_extract_file("%(fn)s", "%(device)s");' % args)
+        if mapfn:
+          args["map"] = mapfn
+          self.script.append(
+              'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args)
+        else:
+          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,))
 
@@ -305,11 +320,13 @@
     if input_path is None:
       data = input_zip.read("OTA/bin/updater")
     else:
-      data = open(os.path.join(input_path, "updater")).read()
+      data = open(input_path, "rb").read()
     common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary",
                        data, perms=0755)
 
-  def Syspatch(self, filename, size, target_sha, source_sha, patchfile):
+  def Syspatch(self, filename, target_mapfile, target_sha,
+               source_mapfile, source_sha, patchfile):
     """Applies a compressed binary patch to a block device."""
-    call = 'syspatch("%s", "%s", "%s", "%s", "%s");'
-    self.script.append(call % (filename, size, target_sha, source_sha, patchfile))
+    call = 'syspatch("%s", "%s", "%s", "%s", "%s", "%s");'
+    self.script.append(call % (filename, target_mapfile, target_sha,
+                               source_mapfile, source_sha, patchfile))
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index bd11a45..596a47e 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -60,7 +60,7 @@
   common.ZipWriteStr(output_zip, "system.img", data)
 
 
-def BuildSystem(input_dir, info_dict, sparse=True):
+def BuildSystem(input_dir, info_dict, sparse=True, map_file=None):
   print "creating system.img..."
 
   img = tempfile.NamedTemporaryFile()
@@ -87,6 +87,8 @@
                                 image_props, img.name)
   assert succ, "build system.img image failed"
 
+  mapdata = None
+
   if sparse:
     img.seek(os.SEEK_SET, 0)
     data = img.read()
@@ -95,13 +97,30 @@
     success, name = build_image.UnsparseImage(img.name, replace=False)
     if not success:
       assert False, "unsparsing system.img failed"
+
+    if map_file:
+      mmap = tempfile.NamedTemporaryFile()
+      mimg = tempfile.NamedTemporaryFile(delete=False)
+      success = build_image.MappedUnsparseImage(
+          img.name, name, mmap.name, mimg.name)
+      if not success:
+        assert False, "creating sparse map failed"
+      os.unlink(name)
+      name = mimg.name
+
+      with open(mmap.name) as f:
+        mapdata = f.read()
+
     try:
       with open(name) as f:
         data = f.read()
     finally:
       os.unlink(name)
 
-  return data
+  if mapdata is None:
+    return data
+  else:
+    return mapdata, data
 
 
 def AddVendor(output_zip):
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
index 1afc640..255f0ea 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -21,7 +21,7 @@
 
 Usage:  ota_from_target_files [flags] input_target_files output_ota_package
 
-  -b  (--board_config)  <file>
+  --board_config  <file>
       Deprecated.
 
   -k (--package_key) <key> Key to use to sign the package (default is
@@ -62,6 +62,11 @@
       file-based OTA if the target_files is older and doesn't support
       block-based OTAs.
 
+  -b  (--binary)  <file>
+      Use the given binary as the update-binary in the output package,
+      instead of the binary in the build's target_files.  Use for
+      development only.
+
 """
 
 import sys
@@ -103,6 +108,7 @@
 OPTIONS.two_step = False
 OPTIONS.no_signing = False
 OPTIONS.block_based = False
+OPTIONS.updater_binary = None
 
 def MostPopularKey(d, default):
   """Given a dict, return the key corresponding to the largest
@@ -447,16 +453,20 @@
 
   if OPTIONS.wipe_user_data:
     system_progress -= 0.1
-    script.ShowProgress(0.1, 10)
-    script.FormatPartition("/data")
 
   if "selinux_fc" in OPTIONS.info_dict:
     WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip)
 
   script.ShowProgress(system_progress, 30)
   if block_based:
-    img_from_target_files.AddSystem(output_zip, sparse=False)
-    script.WriteRawImage("/system", "system.img")
+    mapdata, data = img_from_target_files.BuildSystem(
+        OPTIONS.input_tmp, OPTIONS.info_dict,
+        sparse=False, map_file=True)
+
+    common.ZipWriteStr(output_zip, "system.map", mapdata)
+    common.ZipWriteStr(output_zip, "system.muimg", data)
+    script.WipeBlockDevice("/system")
+    script.WriteRawImage("/system", "system.muimg", mapfn="system.map")
   else:
     script.FormatPartition("/system")
     script.Mount("/system")
@@ -495,6 +505,10 @@
 
   script.UnmountAll()
 
+  if OPTIONS.wipe_user_data:
+    script.ShowProgress(0.1, 10)
+    script.FormatPartition("/data")
+    
   if OPTIONS.two_step:
     script.AppendExtra("""
 set_stage("%(bcb_dev)s", "");
@@ -507,7 +521,7 @@
 endif;
 endif;
 """ % bcb_dev)
-  script.AddToZip(input_zip, output_zip)
+  script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary)
   WriteMetadata(metadata, output_zip)
 
 def WritePolicyConfig(file_context, output_zip):
@@ -602,26 +616,36 @@
     with tempfile.NamedTemporaryFile() as tgt_file:
       print "building source system image..."
       src_file = tempfile.NamedTemporaryFile()
-      src_data = img_from_target_files.BuildSystem(
-          OPTIONS.source_tmp, OPTIONS.source_info_dict, sparse=False)
+      src_mapdata, src_data = img_from_target_files.BuildSystem(
+          OPTIONS.source_tmp, OPTIONS.source_info_dict,
+          sparse=False, map_file=True)
+
       src_sys_sha1 = sha1(src_data).hexdigest()
       print "source system sha1:", src_sys_sha1
       src_file.write(src_data)
-      src_data = None
 
       print "building target system image..."
       tgt_file = tempfile.NamedTemporaryFile()
-      tgt_data = img_from_target_files.BuildSystem(
-          OPTIONS.target_tmp, OPTIONS.target_info_dict, sparse=False)
+      tgt_mapdata, tgt_data = img_from_target_files.BuildSystem(
+          OPTIONS.target_tmp, OPTIONS.target_info_dict,
+          sparse=False, map_file=True)
       tgt_sys_sha1 = sha1(tgt_data).hexdigest()
       print "target system sha1:", tgt_sys_sha1
       tgt_sys_len = len(tgt_data)
       tgt_file.write(tgt_data)
-      tgt_data = None
 
       system_type, system_device = common.GetTypeAndDevice("/system", OPTIONS.info_dict)
       system_patch = common.MakeSystemPatch(src_file, tgt_file)
+
+      TestBlockPatch(src_data, src_mapdata, system_patch.data, tgt_mapdata, tgt_sys_sha1)
+      src_data = None
+      tgt_data = None
+
       system_patch.AddToZip(output_zip, compression=zipfile.ZIP_STORED)
+      src_mapfilename = system_patch.name + ".src.map"
+      common.ZipWriteStr(output_zip, src_mapfilename, src_mapdata)
+      tgt_mapfilename = system_patch.name + ".tgt.map"
+      common.ZipWriteStr(output_zip, tgt_mapfilename, tgt_mapdata)
 
   AppendAssertions(script, OPTIONS.target_info_dict)
   device_specific.IncrementalOTA_Assertions()
@@ -701,15 +725,10 @@
 
   device_specific.IncrementalOTA_InstallBegin()
 
-  if OPTIONS.wipe_user_data:
-    script.Print("Erasing user data...")
-    script.FormatPartition("/data")
-
   script.Print("Patching system image...")
   script.Syspatch(system_device,
-                  OPTIONS.info_dict["system_size"],
-                  tgt_sys_sha1,
-                  src_sys_sha1,
+                  tgt_mapfilename, tgt_sys_sha1,
+                  src_mapfilename, src_sys_sha1,
                   system_patch.name)
 
   if OPTIONS.two_step:
@@ -740,6 +759,10 @@
   if OPTIONS.extra_script is not None:
     script.AppendExtra(OPTIONS.extra_script)
 
+  if OPTIONS.wipe_user_data:
+    script.Print("Erasing user data...")
+    script.FormatPartition("/data")
+
   if OPTIONS.two_step:
     script.AppendExtra("""
 set_stage("%(bcb_dev)s", "");
@@ -748,9 +771,69 @@
 """ % bcb_dev)
 
   script.SetProgress(1)
-  script.AddToZip(target_zip, output_zip)
+  script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary)
   WriteMetadata(metadata, output_zip)
 
+def ParseMap(map_str):
+  x = map_str.split()
+  assert int(x[0]) == 4096
+  assert int(x[1]) == len(x)-2
+  return int(x[0]), [int(i) for i in x[2:]]
+
+def TestBlockPatch(src_muimg, src_map, patch_data, tgt_map, tgt_sha1):
+  src_blksize, src_regions = ParseMap(src_map)
+  tgt_blksize, tgt_regions = ParseMap(tgt_map)
+
+  with tempfile.NamedTemporaryFile() as src_file,\
+       tempfile.NamedTemporaryFile() as patch_file,\
+       tempfile.NamedTemporaryFile() as tgt_file,\
+       tempfile.NamedTemporaryFile() as src_map_file,\
+       tempfile.NamedTemporaryFile() as tgt_map_file:
+
+    src_total = sum(src_regions) * src_blksize
+    src_file.truncate(src_total)
+    p = 0
+    for i in range(0, len(src_regions), 2):
+      c, dc = src_regions[i:i+2]
+      src_file.write(src_muimg[p:(p+c*src_blksize)])
+      p += c*src_blksize
+      src_file.seek(dc*src_blksize, 1)
+    assert src_file.tell() == src_total
+
+    patch_file.write(patch_data)
+
+    tgt_total = sum(tgt_regions) * tgt_blksize
+    tgt_file.truncate(tgt_total)
+
+    src_map_file.write(src_map)
+    tgt_map_file.write(tgt_map)
+
+    src_file.flush()
+    src_map_file.flush()
+    patch_file.flush()
+    tgt_file.flush()
+    tgt_map_file.flush()
+
+    p = common.Run(["syspatch_host", src_file.name, src_map_file.name,
+                    patch_file.name, tgt_file.name, tgt_map_file.name],
+                   stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    stdoutdata, _ = p.communicate()
+    if p.returncode != 0:
+      print stdoutdata
+      raise ValueError("failed to reconstruct target system image from patch")
+
+    h = sha1()
+    for i in range(0, len(tgt_regions), 2):
+      c, dc = tgt_regions[i:i+2]
+      h.update(tgt_file.read(c*tgt_blksize))
+      tgt_file.seek(dc*tgt_blksize, 1)
+
+    if h.hexdigest() != tgt_sha1:
+      raise ValueError("patch reconstructed incorrect target system image")
+
+  print "test of system image patch succeeded"
+
+
 def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
   target_has_recovery_patch = HasRecoveryPatch(target_zip)
   source_has_recovery_patch = HasRecoveryPatch(source_zip)
@@ -841,7 +924,7 @@
     if d is None or len(d) > tf.size * OPTIONS.patch_threshold or \
         path not in known_paths:
       # patch is almost as big as the file; don't bother patching
-      # or a patch + rename cannot take place due to the target 
+      # or a patch + rename cannot take place due to the target
       # directory not existing
       tf.AddToZip(output_zip)
       verbatim_targets.append((tf.name, tf.size))
@@ -976,10 +1059,6 @@
     script.WriteRawImage("/boot", "boot.img")
     print "writing full boot image (forced by two-step mode)"
 
-  if OPTIONS.wipe_user_data:
-    script.Print("Erasing user data...")
-    script.FormatPartition("/data")
-
   script.Print("Removing unneeded files...")
   script.DeleteFiles(["/"+i[0] for i in verbatim_targets] +
                      ["/"+i for i in sorted(source_data)
@@ -1120,6 +1199,10 @@
     script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p")
   script.SetPermissions("/system/build.prop", 0, 0, 0644, None, None)
 
+  if OPTIONS.wipe_user_data:
+    script.Print("Erasing user data...")
+    script.FormatPartition("/data")
+
   if OPTIONS.two_step:
     script.AppendExtra("""
 set_stage("%(bcb_dev)s", "");
@@ -1127,14 +1210,14 @@
 endif;
 """ % bcb_dev)
 
-  script.AddToZip(target_zip, output_zip)
+  script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary)
   WriteMetadata(metadata, output_zip)
 
 
 def main(argv):
 
   def option_handler(o, a):
-    if o in ("-b", "--board_config"):
+    if o == "--board_config":
       pass   # deprecated
     elif o in ("-k", "--package_key"):
       OPTIONS.package_key = a
@@ -1159,6 +1242,8 @@
       OPTIONS.no_signing = True
     elif o == "--block":
       OPTIONS.block_based = True
+    elif o in ("-b", "--binary"):
+      OPTIONS.updater_binary = a
     else:
       return False
     return True
@@ -1176,6 +1261,7 @@
                                               "two_step",
                                               "no_signing",
                                               "block",
+                                              "binary=",
                                               ],
                              extra_option_handler=option_handler)
 
@@ -1240,6 +1326,9 @@
     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")
     if OPTIONS.package_key is None:
       OPTIONS.package_key = OPTIONS.source_info_dict.get(
           "default_system_dev_certificate",
diff --git a/tools/releasetools/simg_map.py b/tools/releasetools/simg_map.py
new file mode 100644
index 0000000..22dc863
--- /dev/null
+++ b/tools/releasetools/simg_map.py
@@ -0,0 +1,148 @@
+#! /usr/bin/env python
+
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+import getopt, posixpath, signal, struct, sys
+
+def main():
+  if len(sys.argv) == 4:
+    print("No sparse_image_file specified")
+    usage(me)
+
+  sparse_fn = sys.argv[1]
+  unsparse_fn = sys.argv[2]
+  map_file = sys.argv[3]
+  mapped_unsparse_fn = sys.argv[4]
+
+  return ComputeMap(sparse_fn, unsparse_fn, map_file, mapped_unsparse_fn)
+
+
+def ComputeMap(sparse_fn, unsparse_fn, map_file, mapped_unsparse_fn):
+  care_map = []
+
+  with open(sparse_fn, "rb") as FH:
+    header_bin = FH.read(28)
+    header = struct.unpack("<I4H4I", header_bin)
+
+    magic = header[0]
+    major_version = header[1]
+    minor_version = header[2]
+    file_hdr_sz = header[3]
+    chunk_hdr_sz = header[4]
+    blk_sz = header[5]
+    total_blks = header[6]
+    total_chunks = header[7]
+    image_checksum = header[8]
+
+    if magic != 0xED26FF3A:
+      print("%s: %s: Magic should be 0xED26FF3A but is 0x%08X"
+            % (me, path, magic))
+      return 1
+    if major_version != 1 or minor_version != 0:
+      print("%s: %s: I only know about version 1.0, but this is version %u.%u"
+            % (me, path, major_version, minor_version))
+      return 1
+    if file_hdr_sz != 28:
+      print("%s: %s: The file header size was expected to be 28, but is %u."
+            % (me, path, file_hdr_sz))
+      return 1
+    if chunk_hdr_sz != 12:
+      print("%s: %s: The chunk header size was expected to be 12, but is %u."
+            % (me, path, chunk_hdr_sz))
+      return 1
+
+    print("%s: Total of %u %u-byte output blocks in %u input chunks."
+          % (sparse_fn, total_blks, blk_sz, total_chunks))
+
+    offset = 0
+    for i in range(total_chunks):
+      header_bin = FH.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
+
+      if chunk_type == 0xCAC1:
+        if data_sz != (chunk_sz * blk_sz):
+          print("Raw chunk input size (%u) does not match output size (%u)"
+                % (data_sz, chunk_sz * blk_sz))
+          return 1
+        else:
+          care_map.append((1, chunk_sz))
+          FH.seek(data_sz, 1)
+
+      elif chunk_type == 0xCAC2:
+        print("Fill chunks are not supported")
+        return 1
+
+      elif chunk_type == 0xCAC3:
+        if data_sz != 0:
+          print("Don't care chunk input size is non-zero (%u)" % (data_sz))
+          return 1
+        else:
+          care_map.append((0, chunk_sz))
+
+      elif chunk_type == 0xCAC4:
+        print("CRC32 chunks are not supported")
+
+      else:
+        print("Unknown chunk type 0x%04X not supported" % (chunk_type,))
+        return 1
+
+      offset += chunk_sz
+
+    if total_blks != offset:
+      print("The header said we should have %u output blocks, but we saw %u"
+            % (total_blks, offset))
+
+    junk_len = len(FH.read())
+    if junk_len:
+      print("There were %u bytes of extra data at the end of the file."
+            % (junk_len))
+      return 1
+
+  last_kind = None
+  new_care_map = []
+  for kind, size in care_map:
+    if kind != last_kind:
+      new_care_map.append((kind, size))
+      last_kind = kind
+    else:
+      new_care_map[-1] = (kind, new_care_map[-1][1] + size)
+
+  if new_care_map[0][0] == 0:
+    new_care_map.insert(0, (1, 0))
+  if len(new_care_map) % 2:
+    new_care_map.append((0, 0))
+
+  with open(map_file, "w") as fmap:
+    fmap.write("%d\n%d\n" % (blk_sz, len(new_care_map)))
+    for _, sz in new_care_map:
+      fmap.write("%d\n" % sz)
+
+  with open(unsparse_fn, "rb") as fin:
+    with open(mapped_unsparse_fn, "wb") as fout:
+      for k, sz in care_map:
+        data = fin.read(sz * blk_sz)
+        if k:
+          fout.write(data)
+        else:
+          assert data == "\x00" * len(data)
+
+if __name__ == "__main__":
+  sys.exit(main())