resolved conflicts for merge of 9b7ebf5d to master

Change-Id: I0dfbc70b4b52a69ba43f14def4203ece8d9c9090
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b84e1b6..af90039 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -44,6 +44,10 @@
 #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
 #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
 
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/buildspec.mk.default b/buildspec.mk.default
index c568a82..46aee69 100644
--- a/buildspec.mk.default
+++ b/buildspec.mk.default
@@ -106,9 +106,9 @@
 #WEBCORE_INSTRUMENTATION:=true
 endif
 
-# To enable SVG in webcore define ENABLE_SVG:=true
+# To disable SVG in webcore define ENABLE_SVG:=false
 ifndef ENABLE_SVG
-#ENABLE_SVG:=true
+#ENABLE_SVG:=false
 endif
 
 # when the build system changes such that this file must be updated, this
diff --git a/core/Makefile b/core/Makefile
index b0a7ec4..afb2a48 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -95,6 +95,14 @@
   BUILD_DISPLAY_ID := $(build_desc)
 endif
 
+# Whether there is default locale set in PRODUCT_PROPERTY_OVERRIDES
+product_property_override_locale_language := $(strip \
+    $(patsubst ro.product.locale.language=%,%,\
+    $(filter ro.product.locale.language=%,$(PRODUCT_PROPERTY_OVERRIDES))))
+product_property_overrides_locale_region := $(strip \
+    $(patsubst ro.product.locale.region=%,%,\
+    $(filter ro.product.locale.region=%,$(PRODUCT_PROPERTY_OVERRIDES))))
+
 # Selects the first locale in the list given as the argument,
 # and splits it into language and region, which each may be
 # empty.
@@ -103,12 +111,13 @@
 endef
 
 # Selects the first locale in the list given as the argument
-# and returns the language (or the region)
+# and returns the language (or the region), if it's not set in PRODUCT_PROPERTY_OVERRIDES;
+# Return empty string if it's already set in PRODUCT_PROPERTY_OVERRIDES.
 define default-locale-language
-$(word 2, 2, $(call default-locale, $(1)))
+$(if $(product_property_override_locale_language),,$(word 1, $(call default-locale, $(1))))
 endef
 define default-locale-region
-$(word 3, 3, $(call default-locale, $(1)))
+$(if $(product_property_overrides_locale_region),,$(word 2, $(call default-locale, $(1))))
 endef
 
 BUILDINFO_SH := build/tools/buildinfo.sh
@@ -545,11 +554,38 @@
 # Targets for user images
 # #################################################################
 
+INTERNAL_USERIMAGES_EXT_VARIANT :=
 ifeq ($(TARGET_USERIMAGES_USE_EXT2),true)
-include external/genext2fs/Config.mk
-INTERNAL_MKUSERFS := $(MKEXT2IMG)
+INTERNAL_USERIMAGES_USE_EXT := true
+INTERNAL_USERIMAGES_EXT_VARIANT := ext2
 else
-INTERNAL_MKUSERFS := $(MKYAFFS2)
+ifeq ($(TARGET_USERIMAGES_USE_EXT3),true)
+INTERNAL_USERIMAGES_USE_EXT := true
+INTERNAL_USERIMAGES_EXT_VARIANT := ext3
+else
+ifeq ($(TARGET_USERIMAGES_USE_EXT4),true)
+INTERNAL_USERIMAGES_USE_EXT := true
+INTERNAL_USERIMAGES_EXT_VARIANT := ext4
+endif
+endif
+endif
+
+ifeq ($(INTERNAL_USERIMAGES_USE_EXT),true)
+INTERNAL_USERIMAGES_DEPS := $(MKEXT2USERIMG) $(MAKE_EXT4FS)
+INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS)))
+
+# $(1): src directory
+# $(2): output file
+# $(3): label
+# $(4): ext variant (ext2, ext3, ext4)
+# $(5): size of the partition
+define build-userimage-ext-target
+  @mkdir -p $(dir $(2))
+  $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$(PATH) \
+	  $(MKEXT2USERIMG) $(1) $(2) $(4) $(3) $(5)
+endef
+else
+INTERNAL_USERIMAGES_DEPS := $(MKYAFFS2)
 endif
 
 # -----------------------------------------------------------------
@@ -620,6 +656,7 @@
 	mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/tmp
 	echo Copying baseline ramdisk...
 	cp -R $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT)
+	rm $(TARGET_RECOVERY_ROOT_OUT)/init*.rc
 	echo Modifying ramdisk contents...
 	cp -f $(recovery_initrc) $(TARGET_RECOVERY_ROOT_OUT)/
 	cp -f $(recovery_binary) $(TARGET_RECOVERY_ROOT_OUT)/sbin/
@@ -664,15 +701,15 @@
 	$(ALL_GENERATED_SOURCES) \
 	$(ALL_DEFAULT_INSTALLED_MODULES))
 
-ifeq ($(TARGET_USERIMAGES_USE_EXT2),true)
-## generate an ext2 image
+ifeq ($(INTERNAL_USERIMAGES_USE_EXT),true)
+## generate an ext image
 # $(1): output file
 define build-systemimage-target
     @echo "Target system fs image: $(1)"
-    $(call build-userimage-ext2-target,$(TARGET_OUT),$(1),system,)
+    $(call build-userimage-ext-target,$(TARGET_OUT),$(1),system,$(INTERNAL_USERIMAGES_EXT_VARIANT),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
 endef
 
-else # TARGET_USERIMAGES_USE_EXT2 != true
+else # INTERNAL_USERIMAGES_USE_EXT != true
 
 ## generate a yaffs2 image
 # $(1): output file
@@ -681,9 +718,10 @@
     @mkdir -p $(dir $(1))
     $(hide) $(MKYAFFS2) -f $(mkyaffs2_extra_flags) $(TARGET_OUT) $(1)
 endef
-endif # TARGET_USERIMAGES_USE_EXT2
+endif # INTERNAL_USERIMAGES_USE_EXT
 
-$(BUILT_SYSTEMIMAGE_UNOPT): $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_MKUSERFS)
+$(BUILT_SYSTEMIMAGE_UNOPT): $(INTERNAL_SYSTEMIMAGE_FILES) \
+                            $(INTERNAL_USERIMAGES_DEPS)
 	$(call build-systemimage-target,$@)
 
 # The installed image, which may be optimized or unoptimized.
@@ -730,7 +768,7 @@
 
 .PHONY: systemimage-nodeps snod
 systemimage-nodeps snod: $(filter-out systemimage-nodeps snod,$(MAKECMDGOALS)) \
-	            | $(INTERNAL_MKUSERFS)
+	            | $(INTERNAL_USERIMAGES_DEPS)
 	@echo "make $@: ignoring dependencies"
 	$(call build-systemimage-target,$(INSTALLED_SYSTEMIMAGE))
 	$(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMIMAGE),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE),yaffs)
@@ -796,16 +834,16 @@
 INTERNAL_USERDATAIMAGE_FILES := \
 	$(filter $(TARGET_OUT_DATA)/%,$(ALL_DEFAULT_INSTALLED_MODULES))
 
-ifeq ($(TARGET_USERIMAGES_USE_EXT2),true)
+ifeq ($(INTERNAL_USERIMAGES_USE_EXT),true)
 ## Generate an ext2 image
 define build-userdataimage-target
     $(call pretty,"Target userdata fs image: $(INSTALLED_USERDATAIMAGE_TARGET)")
     @mkdir -p $(TARGET_OUT_DATA)
-    $(call build-userimage-ext2-target,$(TARGET_OUT_DATA),$(INSTALLED_USERDATAIMAGE_TARGET),userdata,)
+    $(call build-userimage-ext-target,$(TARGET_OUT_DATA),$(INSTALLED_USERDATAIMAGE_TARGET),userdata,$(INTERNAL_USERIMAGES_EXT_VARIANT),$(BOARD_USERDATAIMAGE_PARTITION_SIZE))
     $(hide) $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE),yaffs)
 endef
 
-else # TARGET_USERIMAGES_USE_EXT2 != true
+else # INTERNAL_USERIMAGES_USE_EXT != true
 
 ## Generate a yaffs2 image
 define build-userdataimage-target
@@ -814,18 +852,18 @@
     $(hide) $(MKYAFFS2) -f $(mkyaffs2_extra_flags) $(TARGET_OUT_DATA) $(INSTALLED_USERDATAIMAGE_TARGET)
     $(hide) $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE),yaffs)
 endef
-endif # TARGET_USERIMAGES_USE_EXT2
+endif # INTERNAL_USERIMAGES_USE_EXT
 
 BUILT_USERDATAIMAGE_TARGET := $(PRODUCT_OUT)/userdata.img
 
 # We just build this directly to the install location.
 INSTALLED_USERDATAIMAGE_TARGET := $(BUILT_USERDATAIMAGE_TARGET)
-$(INSTALLED_USERDATAIMAGE_TARGET): $(INTERNAL_MKUSERFS) \
+$(INSTALLED_USERDATAIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) \
                                    $(INTERNAL_USERDATAIMAGE_FILES)
 	$(build-userdataimage-target)
 
 .PHONY: userdataimage-nodeps
-userdataimage-nodeps: $(INTERNAL_MKUSERFS)
+userdataimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
 	$(build-userdataimage-target)
 
 #######
@@ -868,7 +906,12 @@
 	  $(HOST_OUT_EXECUTABLES)/bsdiff \
 	  $(HOST_OUT_EXECUTABLES)/imgdiff \
 	  $(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar \
-	  $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar
+	  $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
+	  $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \
+	  $(HOST_OUT_EXECUTABLES)/genext2fs \
+	  $(HOST_OUT_EXECUTABLES)/tune2fs \
+	  $(HOST_OUT_EXECUTABLES)/e2fsck
+
 
 .PHONY: otatools
 otatools: $(OTATOOLS)
@@ -985,11 +1028,30 @@
 	$(hide) $(ACP) $(APKCERTS_FILE) $(zip_root)/META/apkcerts.txt
 	$(hide)	echo "$(PRODUCT_OTA_PUBLIC_KEYS)" > $(zip_root)/META/otakeys.txt
 	$(hide) echo "$(PRIVATE_RECOVERY_API_VERSION)" > $(zip_root)/META/recovery-api-version.txt
-	$(hide) echo "blocksize $(BOARD_FLASH_BLOCK_SIZE)" > $(zip_root)/META/imagesizes.txt
-	$(hide) echo "boot $(call image-size-from-data-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
-	$(hide) echo "recovery $(call image-size-from-data-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
-	$(hide) echo "system $(call image-size-from-data-size,$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
-	$(hide) echo "userdata $(call image-size-from-data-size,$(BOARD_USERDATAIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/imagesizes.txt
+ifdef BOARD_FLASH_BLOCK_SIZE
+	$(hide) echo "blocksize=$(BOARD_FLASH_BLOCK_SIZE)" > $(zip_root)/META/misc_info.txt
+endif
+ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
+	$(hide) echo "boot_size=$(call image-size-from-data-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/misc_info.txt
+endif
+ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
+	$(hide) echo "recovery_size=$(call image-size-from-data-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/misc_info.txt
+endif
+ifdef BOARD_SYSTEMIMAGE_PARTITION_SIZE
+	$(hide) echo "system_size=$(call image-size-from-data-size,$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/misc_info.txt
+endif
+ifdef BOARD_USERDATAIMAGE_PARTITION_SIZE
+	$(hide) echo "userdata_size=$(call image-size-from-data-size,$(BOARD_USERDATAIMAGE_PARTITION_SIZE))" >> $(zip_root)/META/misc_info.txt
+endif
+ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
+	$(hide) echo "fs_type=ext4" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "partition_type=EMMC" >> $(zip_root)/META/misc_info.txt
+	@# TODO: where is the right place to get this path from?  BoardConfig.mk?
+	$(hide) echo "partition_path=/dev/block/platform/sdhci-tegra.3/by-name/" >> $(zip_root)/META/misc_info.txt
+else
+	$(hide) echo "fs_type=yaffs2" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "partition_type=MTD" >> $(zip_root)/META/misc_info.txt
+endif
 	$(hide) echo "$(tool_extensions)" > $(zip_root)/META/tool-extensions.txt
 	@# Zip everything up, preserving symlinks
 	$(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .)
@@ -1017,17 +1079,9 @@
 
 $(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
 
-ifeq ($(TARGET_OTA_SCRIPT_MODE),)
-# default to "auto"
-$(INTERNAL_OTA_PACKAGE_TARGET): scriptmode := auto
-else
-$(INTERNAL_OTA_PACKAGE_TARGET): scriptmode := $(TARGET_OTA_SCRIPT_MODE)
-endif
-
 $(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(OTATOOLS)
 	@echo "Package OTA: $@"
 	$(hide) ./build/tools/releasetools/ota_from_target_files \
-	   -m $(scriptmode) \
 	   -p $(HOST_OUT) \
            -k $(KEY_CERT_PAIR) \
            $(BUILT_TARGET_FILES_PACKAGE) $@
@@ -1052,8 +1106,12 @@
 
 .PHONY: installed-file-list
 installed-file-list: $(INSTALLED_FILES_FILE)
+ifneq ($(filter sdk,$(MAKECMDGOALS)),)
 $(call dist-for-goals, sdk, $(INSTALLED_FILES_FILE))
+endif
+ifneq ($(filter sdk_addon,$(MAKECMDGOALS)),)
 $(call dist-for-goals, sdk_addon, $(INSTALLED_FILES_FILE))
+endif
 
 # -----------------------------------------------------------------
 # A zip of the tests that are built when running "make tests".
@@ -1174,6 +1232,7 @@
 	$(hide) ./build/tools/releasetools/img_from_target_files \
 	   -s $(extensions) \
 	   -p $(HOST_OUT) \
+	   $(addprefix --fs_type ,$(INTERNAL_USERIMAGES_EXT_VARIANT)) \
 	   $(BUILT_TARGET_FILES_PACKAGE) $@
 
 .PHONY: updatepackage
diff --git a/core/base_rules.mk b/core/base_rules.mk
index f1a2f73..c515313 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -384,8 +384,10 @@
   full_java_lib_deps += $(link_instr_intermediates_dir.COMMON)/classes-full-names.jar
 endif
 
+jar_manifest_file :=
 ifneq ($(strip $(LOCAL_JAR_MANIFEST)),)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAR_MANIFEST := $(LOCAL_PATH)/$(LOCAL_JAR_MANIFEST)
+jar_manifest_file := $(LOCAL_PATH)/$(LOCAL_JAR_MANIFEST)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAR_MANIFEST := $(jar_manifest_file)
 else
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAR_MANIFEST :=
 endif
diff --git a/core/build_id.mk b/core/build_id.mk
index e954794..40bb35d 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -23,7 +23,7 @@
 # (like "TC1-RC5").  It must be a single word, and is
 # capitalized by convention.
 #
-BUILD_ID := OPENMASTER
+BUILD_ID := MASTER
 
 # DISPLAY_BUILD_NUMBER should only be set for development branches,
 # If set, the BUILD_NUMBER (cl) is appended to the BUILD_ID for
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 96ca2e9..69ed4f5 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -79,6 +79,7 @@
 LOCAL_STRIP_MODULE:=
 LOCAL_POST_PROCESS_COMMAND:=true
 LOCAL_JNI_SHARED_LIBRARIES:=
+LOCAL_JNI_SHARED_LIBRARIES_ABI:=
 LOCAL_JAR_MANIFEST:=
 LOCAL_INSTRUMENTATION_FOR:=
 LOCAL_INSTRUMENTATION_FOR_PACKAGE_NAME:=
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 6139b67..fbaad1c 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -44,7 +44,7 @@
 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
 ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
 TARGET_TOOLS_PREFIX := \
-	prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.4.3/bin/arm-eabi-
+	prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-linux-androideabi-4.4.x/bin/arm-linux-androideabi-
 endif
 
 TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
@@ -97,6 +97,7 @@
 TARGET_GLOBAL_CFLAGS += \
 			-msoft-float -fpic \
 			-ffunction-sections \
+			-fdata-sections \
 			-funwind-tables \
 			-fstack-protector \
 			-Wa,--noexecstack \
@@ -118,6 +119,7 @@
 
 TARGET_GLOBAL_LDFLAGS += \
 			-Wl,-z,noexecstack \
+			-Wl,--icf=safe \
 			$(arch_variant_ldflags)
 
 # We only need thumb interworking in cases where thumb support
@@ -206,7 +208,7 @@
 	$(libstdc++_root)/include \
 	$(KERNEL_HEADERS) \
 	$(libm_root)/include \
-	$(libm_root)/include/arch/arm \
+	$(libm_root)/include/arm \
 	$(libthread_db_root)/include
 
 TARGET_CRTBEGIN_STATIC_O := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_static.o
@@ -276,8 +278,12 @@
 	$(TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_ALL_OBJECTS) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+	$(call normalize-target-libraries,$(filter-out %libc_nomalloc.a,$(filter-out %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES)))) \
+	-Wl,--start-group \
+	$(call normalize-target-libraries,$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \
+	$(call normalize-target-libraries,$(filter %libc_nomalloc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \
 	$(TARGET_FDO_LIB) \
 	$(TARGET_LIBGCC) \
+	-Wl,--end-group \
 	$(TARGET_CRTEND_O)
 endef
diff --git a/core/combo/TARGET_linux-sh.mk b/core/combo/TARGET_linux-sh.mk
index cf945fe..2600b9e 100644
--- a/core/combo/TARGET_linux-sh.mk
+++ b/core/combo/TARGET_linux-sh.mk
@@ -99,7 +99,7 @@
 	$(libstdc++_root)/include \
 	$(KERNEL_HEADERS) \
 	$(libm_root)/include \
-	$(libm_root)/include/arch/sh \
+	$(libm_root)/include/sh \
 	$(libthread_db_root)/include
 
 TARGET_CRTBEGIN_STATIC_O := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_static.o
diff --git a/core/combo/javac.mk b/core/combo/javac.mk
index d4c04e7..f8c99fb 100644
--- a/core/combo/javac.mk
+++ b/core/combo/javac.mk
@@ -8,7 +8,7 @@
 #   COMMON_JAVAC -- Java compiler command with common arguments
 
 # Whatever compiler is on this system.
-ifeq ($(HOST_OS), windows)
+ifeq ($(BUILD_OS), windows)
     COMMON_JAVAC := development/host/windows/prebuilt/javawrap.exe -J-Xmx256m \
         -target 1.5 -Xmaxerrs 9999999
 else
diff --git a/core/config.mk b/core/config.mk
index 1194f4b..a866435 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -70,6 +70,8 @@
 BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
 BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
 BUILD_KEY_CHAR_MAP := $(BUILD_SYSTEM)/key_char_map.mk
+BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
+BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
 
 # ###############################################################
 # Parse out any modifier targets.
@@ -208,13 +210,16 @@
 APICHECK := $(HOST_OUT_EXECUTABLES)/apicheck$(HOST_EXECUTABLE_SUFFIX)
 FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
 MKEXT2IMG := $(HOST_OUT_EXECUTABLES)/genext2fs$(HOST_EXECUTABLE_SUFFIX)
+MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/make_ext4fs$(HOST_EXECUTABLE_SUFFIX)
+MKEXT2USERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg.sh
 MKEXT2BOOTIMG := external/genext2fs/mkbootimg_ext2.sh
 MKTARBALL := build/tools/mktarball.sh
-TUNE2FS := tune2fs
-E2FSCK := e2fsck
+TUNE2FS := $(HOST_OUT_EXECUTABLES)/tune2fs$(HOST_EXECUTABLE_SUFFIX)
+E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)
 JARJAR := $(HOST_OUT_JAVA_LIBRARIES)/jarjar.jar
 PROGUARD := external/proguard/bin/proguard.sh
 JAVATAGS := build/tools/java-event-log-tags.py
+SLANG := $(HOST_OUT_EXECUTABLES)/slang$(HOST_EXECUTABLE_SUFFIX)
 
 # ACP is always for the build OS, not for the host OS
 ACP := $(BUILD_OUT_EXECUTABLES)/acp$(BUILD_EXECUTABLE_SUFFIX)
@@ -262,6 +267,10 @@
 HOST_JDK_TOOLS_JAR :=
 else
 HOST_JDK_TOOLS_JAR:= $(shell $(BUILD_SYSTEM)/find-jdk-tools-jar.sh)
+ifeq ($(wildcard $(HOST_JDK_TOOLS_JAR)),)
+$(error Error: could not find jdk tools.jar, please install JDK-5.0, \
+    update 12 or higher, which you can download from java.sun.com)
+endif
 endif
 
 # It's called md5 on Mac OS and md5sum on Linux
diff --git a/core/definitions.mk b/core/definitions.mk
index cc638c5..26ab512 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -236,6 +236,19 @@
 endef
 
 ###########################################################
+## Find all of the RenderScript files under the named directories.
+##  Meant to be used like:
+##    SRC_FILES := $(call all-renderscript-files-under,src)
+###########################################################
+
+define all-renderscript-files-under
+$(patsubst ./%,%, \
+  $(shell cd $(LOCAL_PATH) ; \
+          find $(1) -name "*.rs" -and -not -name ".*") \
+  )
+endef
+
+###########################################################
 ## Find all of the html files under the named directories.
 ## Meant to be used like:
 ##    SRC_FILES := $(call all-html-files-under,src tests)
@@ -732,6 +745,24 @@
 rm -f $(@:$1=$(YACC_HEADER_SUFFIX))
 endef
 
+###########################################################
+## Commands to compile RenderScript
+###########################################################
+
+define transform-renderscripts-to-java-and-bc
+@echo "RenderScript: $(PRIVATE_MODULE) <= $(PRIVATE_RS_SOURCE_FILES)"
+$(hide) rm -rf $(PRIVATE_RS_OUTPUT_DIR)
+$(hide) mkdir -p $(PRIVATE_RS_OUTPUT_DIR)/res/raw
+$(hide) mkdir -p $(PRIVATE_RS_OUTPUT_DIR)/src
+$(hide) $(SLANG) \
+  --allow-rs-prefix \
+  -o $(PRIVATE_RS_OUTPUT_DIR)/res/raw \
+  -p $(PRIVATE_RS_OUTPUT_DIR)/src \
+  $(PRIVATE_RS_SOURCE_FILES)
+$(hide) mkdir -p $(dir $@)
+$(hide) touch $@
+endef
+
 
 ###########################################################
 ## Commands for running aidl
@@ -947,6 +978,24 @@
 ## Commands for running ar
 ###########################################################
 
+define _concat-if-arg2-not-empty
+$(if $(2),$(hide) $(1) $(2))
+endef
+
+# Split long argument list into smaller groups and call the command repeatedly
+#
+# $(1): the command without arguments
+# $(2): the arguments
+define split-long-arguments
+$(call _concat-if-arg2-not-empty,$(1),$(wordlist 1,500,$(2)))
+$(call _concat-if-arg2-not-empty,$(1),$(wordlist 501,1000,$(2)))
+$(call _concat-if-arg2-not-empty,$(1),$(wordlist 1001,1500,$(2)))
+$(call _concat-if-arg2-not-empty,$(1),$(wordlist 1501,2000,$(2)))
+$(call _concat-if-arg2-not-empty,$(1),$(wordlist 2001,2500,$(2)))
+$(call _concat-if-arg2-not-empty,$(1),$(wordlist 2501,3000,$(2)))
+$(call _concat-if-arg2-not-empty,$(1),$(wordlist 3001,99999,$(2)))
+endef
+
 define extract-and-include-target-whole-static-libs
 $(foreach lib,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES), \
 	$(hide) echo "preparing StaticLib: $(PRIVATE_MODULE) [including $(lib)]"; \
@@ -969,8 +1018,7 @@
 @rm -f $@
 $(extract-and-include-target-whole-static-libs)
 @echo "target StaticLib: $(PRIVATE_MODULE) ($@)"
-$(hide) echo $(filter %.o, $^) | \
-    xargs $(TARGET_AR) $(TARGET_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@
+$(call split-long-arguments,$(TARGET_AR) $(TARGET_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@,$(filter %.o, $^))
 endef
 
 ###########################################################
@@ -979,7 +1027,7 @@
 
 define extract-and-include-host-whole-static-libs
 $(foreach lib,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES), \
-	@echo "preparing StaticLib: $(PRIVATE_MODULE) [including $(lib)]"; \
+	$(hide) echo "preparing StaticLib: $(PRIVATE_MODULE) [including $(lib)]"; \
 	ldir=$(PRIVATE_INTERMEDIATES_DIR)/WHOLE/$(basename $(notdir $(lib)))_objs;\
 	rm -rf $$ldir; \
 	mkdir -p $$ldir; \
@@ -999,8 +1047,7 @@
 @rm -f $@
 $(extract-and-include-host-whole-static-libs)
 @echo "host StaticLib: $(PRIVATE_MODULE) ($@)"
-echo $(filter %.o, $^) | \
-	xargs $(HOST_AR) $(HOST_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@
+$(call split-long-arguments,$(HOST_AR) $(HOST_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@,$(filter %.o, $^))
 endef
 
 
@@ -1231,7 +1278,7 @@
     $(addprefix --min-sdk-version , $(DEFAULT_APP_TARGET_SDK)) \
     $(addprefix --target-sdk-version , $(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))) \
+    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-name , $(PLATFORM_VERSION)-$(BUILD_NUMBER))) \
     $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
     $(addprefix --rename-instrumentation-target-package , $(PRIVATE_INSTRUMENTATION_FOR_PACKAGE_NAME))
 endef
@@ -1270,7 +1317,12 @@
         @$(call emit-line,$(wordlist 3401,3600,$(1)),$(2))
         @$(call emit-line,$(wordlist 3601,3800,$(1)),$(2))
         @$(call emit-line,$(wordlist 3801,4000,$(1)),$(2))
-        @$(if $(wordlist 4001,4002,$(1)),$(error Too many words ($(words $(1)))))
+        @$(call emit-line,$(wordlist 4001,4200,$(1)),$(2))
+        @$(call emit-line,$(wordlist 4201,4400,$(1)),$(2))
+        @$(call emit-line,$(wordlist 4401,4600,$(1)),$(2))
+        @$(call emit-line,$(wordlist 4601,4800,$(1)),$(2))
+        @$(call emit-line,$(wordlist 4801,5000,$(1)),$(2))
+        @$(if $(wordlist 5001,5002,$(1)),$(error Too many words ($(words $(1)))))
 endef
 
 # For a list of jar files, unzip them to a specified directory,
@@ -1377,7 +1429,7 @@
     $(addprefix --min-sdk-version , $(DEFAULT_APP_TARGET_SDK)) \
     $(addprefix --target-sdk-version , $(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))) \
+    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-name , $(PLATFORM_VERSION)-$(BUILD_NUMBER))) \
     $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
     $(addprefix --rename-instrumentation-target-package , $(PRIVATE_INSTRUMENTATION_FOR_PACKAGE_NAME)) \
     -F $@
@@ -1385,8 +1437,8 @@
 
 define add-jni-shared-libs-to-package
 $(hide) rm -rf $(dir $@)lib
-$(hide) mkdir -p $(dir $@)lib/$(TARGET_CPU_ABI)
-$(hide) cp $(PRIVATE_JNI_SHARED_LIBRARIES) $(dir $@)lib/$(TARGET_CPU_ABI)
+$(hide) mkdir -p $(dir $@)lib/$(PRIVATE_JNI_SHARED_LIBRARIES_ABI)
+$(hide) cp $(PRIVATE_JNI_SHARED_LIBRARIES) $(dir $@)lib/$(PRIVATE_JNI_SHARED_LIBRARIES_ABI)
 $(hide) (cd $(dir $@) && zip -r $(notdir $@) lib)
 $(hide) rm -rf $(dir $@)lib
 endef
@@ -1591,7 +1643,7 @@
 endef
 else
 define transform-host-ranlib-copy-hack
-true
+@true
 endef
 endif
 
@@ -1601,7 +1653,7 @@
 endef
 else
 define transform-ranlib-copy-hack
-true
+@true
 endef
 endif
 
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index ba4857b..8495e6e 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -163,7 +163,7 @@
 		LD_LIBRARY_PATH=$(HOST_OUT_SHARED_LIBRARIES) \
 		javadoc \
                 \@$(PRIVATE_SRC_LIST_FILE) \
-                -J-Xmx768m \
+                -J-Xmx1024m \
                 -J-Djava.library.path=$(HOST_OUT_SHARED_LIBRARIES) \
                 $(PRIVATE_PROFILING_OPTIONS) \
                 -quiet \
@@ -204,7 +204,7 @@
 		javadoc \
                 $(PRIVATE_DROIDDOC_OPTIONS) \
                 \@$(PRIVATE_SRC_LIST_FILE) \
-                -J-Xmx768m \
+                -J-Xmx1024m \
                 $(PRIVATE_PROFILING_OPTIONS) \
                 $(addprefix -classpath ,$(PRIVATE_CLASSPATH)) \
                 -sourcepath $(PRIVATE_SOURCE_PATH)$(addprefix :,$(PRIVATE_CLASSPATH)) \
diff --git a/core/dumpvar.mk b/core/dumpvar.mk
index f469f35..4bc9541 100644
--- a/core/dumpvar.mk
+++ b/core/dumpvar.mk
@@ -9,7 +9,7 @@
 	ABP:=$(ABP):$(TARGET_OUT_EXECUTABLES)
 else
 	# this should be copied to HOST_OUT_EXECUTABLES instead
-	ABP:=$(ABP):$(PWD)/prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.4.3/bin
+	ABP:=$(ABP):$(PWD)/prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-linux-androideabi-4.4.x/bin
 endif
 ANDROID_BUILD_PATHS := $(ABP)
 ANDROID_PREBUILTS := prebuilt/$(HOST_PREBUILT_TAG)
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 87ac2f6..da9dd28 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -237,6 +237,7 @@
 TARGET_OUT_DATA_KEYCHARS := $(TARGET_OUT_KEYCHARS)
 TARGET_OUT_DATA_ETC := $(TARGET_OUT_ETC)
 TARGET_OUT_DATA_STATIC_LIBRARIES:= $(TARGET_OUT_STATIC_LIBRARIES)
+TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest
 
 TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols
 TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin
diff --git a/core/find-jdk-tools-jar.sh b/core/find-jdk-tools-jar.sh
index 4c40627..f21c48b 100755
--- a/core/find-jdk-tools-jar.sh
+++ b/core/find-jdk-tools-jar.sh
@@ -3,7 +3,6 @@
 else
     JAVAC=$(which javac)
     if [ -z "$JAVAC" ] ; then
-	echo "Please-install-JDK-5.0,-update-12-or-higher,-which-you-can-download-from-java.sun.com"
 	exit 1
     fi
     while [ -L $JAVAC ] ; do
diff --git a/core/host_java_library.mk b/core/host_java_library.mk
index 1977115..3307bf3 100644
--- a/core/host_java_library.mk
+++ b/core/host_java_library.mk
@@ -26,5 +26,5 @@
 include $(BUILD_SYSTEM)/base_rules.mk
 
 $(LOCAL_BUILT_MODULE): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS)
-$(LOCAL_BUILT_MODULE): $(java_sources) $(java_resource_sources) $(full_java_lib_deps)
+$(LOCAL_BUILT_MODULE): $(java_sources) $(java_resource_sources) $(full_java_lib_deps) $(jar_manifest_file)
 	$(transform-host-java-to-package)
diff --git a/core/host_native_test.mk b/core/host_native_test.mk
new file mode 100644
index 0000000..2a77f1e
--- /dev/null
+++ b/core/host_native_test.mk
@@ -0,0 +1,14 @@
+################################################
+## A thin wrapper around BUILD_HOST_EXECUTABLE
+## Common flags for host native tests are added.
+################################################
+
+LOCAL_CFLAGS += -DGTEST_OS_LINUX -DGTEST_HAS_STD_STRING -O0 -g
+LOCAL_C_INCLUDES +=  \
+                    bionic/libstdc++/include \
+                    external/gtest/include \
+                    external/astl/include
+LOCAL_STATIC_LIBRARIES += libgtest_host libgtest_main_host libastl_host
+LOCAL_SHARED_LIBRARIES +=
+
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/core/java.mk b/core/java.mk
index 4c34479..da53a5c 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -94,6 +94,30 @@
 
 LOCAL_INTERMEDIATE_SOURCE_DIR := $(intermediates.COMMON)/src
 
+###############################################################
+## .rs files: RenderScript sources to .java files and .bc files
+###############################################################
+renderscript_sources := $(filter %.rs,$(LOCAL_SRC_FILES))
+# Because names of the java files from RenderScript are unknown until the
+# .rs file(s) are compiled, we have to depend on a timestamp file.
+RenderScript_file_stamp :=
+ifneq ($(renderscript_sources),)
+renderscript_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(renderscript_sources))
+RenderScript_file_stamp := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/RenderScript.stamp
+
+$(RenderScript_file_stamp): PRIVATE_RS_SOURCE_FILES := $(renderscript_sources_fullpath)
+# By putting the generated java files into $(LOCAL_INTERMEDIATE_SOURCE_DIR), they will be
+# automatically found by the java compiling function transform-java-to-classes.jar.
+$(RenderScript_file_stamp): PRIVATE_RS_OUTPUT_DIR := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/renderscript
+# TODO: slang support to generate implicit dependency derived from "include" directives.
+$(RenderScript_file_stamp): $(renderscript_sources_fullpath) $(SLANG)
+	$(transform-renderscripts-to-java-and-bc)
+
+LOCAL_INTERMEDIATE_TARGETS += $(RenderScript_file_stamp)
+# Make sure the generated resource will be added to the apk.
+LOCAL_RESOURCE_DIR := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/renderscript/res $(LOCAL_RESOURCE_DIR)
+endif
+
 # TODO: It looks like the only thing we need from base_rules is
 # all_java_sources.  See if we can get that by adding a
 # common_java.mk, and moving the include of base_rules.mk to
@@ -148,9 +172,14 @@
 # Deps for generated source files must be handled separately,
 # via deps on the target that generates the sources.
 $(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS)
-$(full_classes_compiled_jar): $(java_sources) $(full_java_lib_deps)
+$(full_classes_compiled_jar): $(java_sources) $(full_java_lib_deps) $(jar_manifest_file)
 	$(transform-java-to-classes.jar)
 
+# source files generated from RenderScript must be generated before java compiling
+ifneq ($(RenderScript_file_stamp),)
+$(full_classes_compiled_jar): $(RenderScript_file_stamp)
+endif
+
 # All of the rules after full_classes_compiled_jar are very unlikely
 # to fail except for bugs in their respective tools.  If you would
 # like to run these rules, add the "all" modifier goal to the make
diff --git a/core/main.mk b/core/main.mk
index 89d1a50..da66c36 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -694,12 +694,15 @@
 	$(INSTALLED_USERDATAIMAGE_TARGET) \
 	$(INSTALLED_FILES_FILE)
 
+# dist_libraries only for putting your library into the dist directory with a full build.
+.PHONY: dist_libraries
+
 ifeq ($(EMMA_INSTRUMENT),true)
   $(call dist-for-goals, droid, $(EMMA_META_ZIP))
 endif
 
-# dist_libraries only for putting your library into the dist directory with a full build.
-.PHONY: dist_libraries
+# Dist for droid if droid is among the cmd goals, or no cmd goal is given.
+ifneq ($(filter droid,$(MAKECMDGOALS))$(filter ||,|$(filter-out $(INTERNAL_MODIFIER_TARGETS),$(MAKECMDGOALS))|),)
 
 ifneq ($(TARGET_BUILD_APPS),)
   # If this build is just for apps, only build apps and not the full system by default.
@@ -751,7 +754,8 @@
 # Building a full system-- the default is to build droidcore
 droid: droidcore dist_libraries
 
-endif
+endif # TARGET_BUILD_APPS
+endif # droid in $(MAKECMDGOALS)
 
 
 .PHONY: droid tests
@@ -767,10 +771,26 @@
 .PHONY: sdk
 ALL_SDK_TARGETS := $(INTERNAL_SDK_TARGET)
 sdk: $(ALL_SDK_TARGETS)
+ifneq ($(filter sdk,$(MAKECMDGOALS)),)
 $(call dist-for-goals,sdk, \
 	$(ALL_SDK_TARGETS) \
 	$(SYMBOLS_ZIP) \
  )
+endif
+
+.PHONY: samplecode
+sample_MODULES := $(sort $(call get-tagged-modules,samples))
+sample_APKS_DEST_PATH := $(TARGET_COMMON_OUT_ROOT)/samples
+sample_APKS_COLLECTION := \
+        $(foreach module,$(sample_MODULES),$(sample_APKS_DEST_PATH)/$(notdir $(module)))
+$(foreach module,$(sample_MODULES),$(eval $(call \
+        copy-one-file,$(module),$(sample_APKS_DEST_PATH)/$(notdir $(module)))))
+sample_ADDITIONAL_INSTALLED := \
+        $(filter-out $(modules_to_install) $(modules_to_check) $(ALL_PREBUILT),$(sample_MODULES))
+samplecode: $(sample_APKS_COLLECTION)
+	@echo "Collect sample code apks: $^"
+	# remove apks that are not intended to be installed.
+	rm -f $(sample_ADDITIONAL_INSTALLED)
 
 .PHONY: findbugs
 findbugs: $(INTERNAL_FINDBUGS_HTML_TARGET) $(INTERNAL_FINDBUGS_XML_TARGET)
diff --git a/core/native_test.mk b/core/native_test.mk
new file mode 100644
index 0000000..3253a5e
--- /dev/null
+++ b/core/native_test.mk
@@ -0,0 +1,18 @@
+###########################################
+## A thin wrapper around BUILD_EXECUTABLE
+## Common flags for native tests are added.
+###########################################
+
+LOCAL_CFLAGS += -DGTEST_OS_LINUX -DGTEST_HAS_STD_STRING
+LOCAL_C_INCLUDES += bionic \
+                    bionic/libstdc++/include \
+                    external/gtest/include \
+                    external/stlport/stlport
+LOCAL_STATIC_LIBRARIES += libgtest libgtest_main
+LOCAL_SHARED_LIBRARIES += libstlport
+
+ifndef LOCAL_MODULE_PATH
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/core/package.mk b/core/package.mk
index 8254bae..b634824 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -187,7 +187,7 @@
 $(R_file_stamp): PRIVATE_RESOURCE_PUBLICS_OUTPUT := \
 			$(intermediates.COMMON)/public_resources.xml
 $(R_file_stamp): PRIVATE_PROGUARD_OPTIONS_FILE := $(proguard_options_file)
-$(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(AAPT) | $(ACP)
+$(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(RenderScript_file_stamp) $(AAPT) | $(ACP)
 	@echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
 	@rm -f $@
 	$(create-resource-java-files)
@@ -282,6 +282,16 @@
       $(addsuffix $(so_suffix), \
         $(LOCAL_JNI_SHARED_LIBRARIES)))
 
+# Set the abi directory used by the local JNI shared libraries.
+# (Doesn't change how the local shared libraries are compiled, just
+# sets where they are stored in the apk.)
+
+ifeq ($(LOCAL_JNI_SHARED_LIBRARIES_ABI),)
+    jni_shared_libraries_abi := $(TARGET_CPU_ABI)
+else
+    jni_shared_libraries_abi := $(LOCAL_JNI_SHARED_LIBRARIES_ABI)
+endif
+
 # Pick a key to sign the package with.  If this package hasn't specified
 # an explicit certificate, use the default.
 # Secure release builds will have their packages signed after the fact,
@@ -315,6 +325,7 @@
 # Define the rule to build the actual package.
 $(LOCAL_BUILT_MODULE): $(AAPT) | $(ZIPALIGN)
 $(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries)
+$(LOCAL_BUILT_MODULE): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abi)
 ifneq ($(TARGET_BUILD_APPS),)
     # Include all resources for unbundled apps.
     $(LOCAL_BUILT_MODULE): PRODUCT_AAPT_CONFIG :=
diff --git a/core/pathmap.mk b/core/pathmap.mk
index 6cd3b8f..eae48af 100644
--- a/core/pathmap.mk
+++ b/core/pathmap.mk
@@ -88,6 +88,7 @@
 	    wifi \
 	    vpn \
 	    keystore \
+	    icu4j \
 	    voip \
 	 )
 
diff --git a/core/prelink-linux-arm.map b/core/prelink-linux-arm.map
index 7daaf98..b178242 100644
--- a/core/prelink-linux-arm.map
+++ b/core/prelink-linux-arm.map
@@ -19,7 +19,7 @@
 #
 # note: look at the LOAD sections in the library header:
 #
-#   arm-eabi-objdump -x <lib>
+#   arm-linux-androideabi-objdump -x <lib>
 #
 
 # core system libraries
@@ -211,3 +211,5 @@
 libzxing.so             0x9D000000 # [<64K] for goggles
 libinterstitial.so      0x9CF00000 # [<64K] for goggles
 liblept.so              0x9CA00000 # [~5M] for external/leptonica
+libbcc.so               0x9C600000 # [~4M] for external/llvm
+libchromium_net.so      0x9C400000 # [~2M] for exteral/webkit
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index f697347..9834404 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -41,7 +41,7 @@
 -include cts/CtsTestCaseList.mk
 CTS_CASE_LIST := $(CTS_CORE_CASE_LIST) $(CTS_TEST_CASE_LIST)
 
-DEFAULT_TEST_PLAN := $(PRIVATE_DIR)/resource/plans
+DEFAULT_TEST_PLAN := $(cts_dir)/$(cts_name)/resource/plans
 
 $(cts_dir)/all_cts_files_stamp: PRIVATE_JUNIT_HOST_JAR := $(junit_host_jar)
 
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index a30b7d9..af00479 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -41,7 +41,7 @@
   # which is the version that we reveal to the end user.
   # Update this value when the platform version changes (rather
   # than overriding it somewhere else).  Can be an arbitrary string.
-  PLATFORM_VERSION := AOSP
+  PLATFORM_VERSION := Froyo
 endif
 
 ifeq "" "$(PLATFORM_SDK_VERSION)"
@@ -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 := AOSP
+  PLATFORM_VERSION_CODENAME := Froyo
 endif
 
 ifeq "" "$(DEFAULT_APP_TARGET_SDK)"
diff --git a/envsetup.sh b/envsetup.sh
index 0873474..96684d9 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -29,8 +29,8 @@
         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
         return
     fi
-    CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
-      make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-abs-$1
+    (cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
+      make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-abs-$1)
 }
 
 # Get the exact value of a build variable.
@@ -106,10 +106,11 @@
     # and in with the new
     CODE_REVIEWS=
     prebuiltdir=$(getprebuilt)
-    export ANDROID_EABI_TOOLCHAIN=$prebuiltdir/toolchain/arm-eabi-4.4.3/bin
+    export ANDROID_EABI_TOOLCHAIN=$prebuiltdir/toolchain/arm-linux-androideabi-4.4.x/bin
+    export ARM_EABI_TOOLCHAIN=$prebuiltdir/toolchain/arm-eabi-4.4.3/bin
     export ANDROID_TOOLCHAIN=$ANDROID_EABI_TOOLCHAIN
     export ANDROID_QTOOLS=$T/development/emulator/qtools
-    export ANDROID_BUILD_PATHS=:$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_QTOOLS:$ANDROID_TOOLCHAIN:$ANDROID_EABI_TOOLCHAIN$CODE_REVIEWS
+    export ANDROID_BUILD_PATHS=:$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_QTOOLS:$ANDROID_TOOLCHAIN:$ARM_EABI_TOOLCHAIN$CODE_REVIEWS
     export PATH=$PATH$ANDROID_BUILD_PATHS
 
     unset ANDROID_JAVA_TOOLCHAIN
@@ -546,6 +547,19 @@
     printconfig
 }
 
+# Tab completion for lunch.
+function _lunch()
+{
+    local cur prev opts
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    prev="${COMP_WORDS[COMP_CWORD-1]}"
+
+    COMPREPLY=( $(compgen -W "${LUNCH_MENU_CHOICES[*]}" -- ${cur}) )
+    return 0
+}
+complete -F _lunch lunch
+
 # Configures the build to build unbundled apps.
 # Run tapas with one ore more app names (from LOCAL_PACKAGE_NAME)
 function tapas()
@@ -787,7 +801,7 @@
        echo >>"$OUT_ROOT/gdbclient.cmds" "target remote $PORT"
        echo >>"$OUT_ROOT/gdbclient.cmds" ""
 
-       arm-eabi-gdb -x "$OUT_ROOT/gdbclient.cmds" "$OUT_EXE_SYMBOLS/$EXE"
+       arm-linux-androideabi-gdb -x "$OUT_ROOT/gdbclient.cmds" "$OUT_EXE_SYMBOLS/$EXE"
   else
        echo "Unable to determine build system output dir."
    fi
@@ -909,10 +923,10 @@
 {
     # process standard adb options
     local adbTarget=""
-    if [ $1 = "-d" -o $1 = "-e" ]; then
+    if [ "$1" = "-d" -o "$1" = "-e" ]; then
         adbTarget=$1
         shift 1
-    elif [ $1 = "-s" ]; then
+    elif [ "$1" = "-s" ]; then
         adbTarget="$1 $2"
         shift 2
     fi
@@ -921,10 +935,9 @@
 
     # runhat options
     local targetPid=$1
-    local outputFile=$2
 
     if [ "$targetPid" = "" ]; then
-        echo "Usage: runhat [ -d | -e | -s serial ] target-pid [output-file]"
+        echo "Usage: runhat [ -d | -e | -s serial ] target-pid"
         return
     fi
 
@@ -934,18 +947,14 @@
         return
     fi
 
-    adb ${adbOptions} shell >/dev/null mkdir /data/misc
-    adb ${adbOptions} shell chmod 777 /data/misc
-
-    # send a SIGUSR1 to cause the hprof dump
+    # issue "am" command to cause the hprof dump
+    local devFile=/sdcard/hprof-$targetPid
     echo "Poking $targetPid and waiting for data..."
-    adb ${adbOptions} shell kill -10 $targetPid
+    adb ${adbOptions} shell am dumpheap $targetPid $devFile
     echo "Press enter when logcat shows \"hprof: heap dump completed\""
     echo -n "> "
     read
 
-    local availFiles=( $(adb ${adbOptions} shell ls /data/misc | grep '^heap-dump' | sed -e 's/.*heap-dump-/heap-dump-/' | sort -r | tr '[:space:][:cntrl:]' ' ') )
-    local devFile=/data/misc/${availFiles[0]}
     local localFile=/tmp/$$-hprof
 
     echo "Retrieving file $devFile..."
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 89b37e0..a4b3502 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -38,5 +38,6 @@
     $(LOCAL_DIR)/full.mk \
     $(LOCAL_DIR)/full_x86.mk \
     $(LOCAL_DIR)/sdk.mk \
-    $(LOCAL_DIR)/sim.mk
+    $(LOCAL_DIR)/sim.mk \
+    $(LOCAL_DIR)/large_emu_hw.mk
 endif
diff --git a/target/product/core.mk b/target/product/core.mk
index f87ee46..becbe50 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -29,7 +29,6 @@
     Contacts \
     Home \
     HTMLViewer \
-    Phone \
     ApplicationsProvider \
     ContactsProvider \
     DownloadProvider \
diff --git a/target/product/generic.mk b/target/product/generic.mk
index 1f26a75..51e17f3 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -14,9 +14,11 @@
 # limitations under the License.
 #
 
-# This is a generic product that isn't specialized for a specific device.
+# This is a generic phone product that isn't specialized for a specific device.
 # It includes the base Android platform.
 
+PRODUCT_POLICY := android.policy_phone
+
 PRODUCT_PACKAGES := \
     AccountAndSyncSettings \
     CarHome \
@@ -35,6 +37,7 @@
     Mms \
     Music \
     Provision \
+    Phone \
     Protips \
     QuickSearchBox \
     Settings \
diff --git a/target/product/large_emu_hw.mk b/target/product/large_emu_hw.mk
new file mode 100644
index 0000000..6aadc23
--- /dev/null
+++ b/target/product/large_emu_hw.mk
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This is a generic product for devices with large display but not specialized
+# for a specific device. It includes the base Android platform.
+
+PRODUCT_POLICY := android.policy_mid
+
+PRODUCT_PACKAGES := \
+    AccountAndSyncSettings \
+    CarHome \
+    DeskClock \
+    AlarmProvider \
+    Bluetooth \
+    Calculator \
+    Calendar \
+    Camera \
+    CertInstaller \
+    DrmProvider \
+    Email \
+    Gallery3D \
+    LatinIME \
+    Launcher2 \
+    Mms \
+    Music \
+    Provision \
+    QuickSearchBox \
+    Settings \
+    Sync \
+    Updater \
+    CalendarProvider \
+    SyncProvider
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
+
+# Overrides
+PRODUCT_BRAND := generic
+PRODUCT_DEVICE := generic
+PRODUCT_NAME := large_emu_hw
diff --git a/target/product/locales_full.mk b/target/product/locales_full.mk
new file mode 100644
index 0000000..f46caeb
--- /dev/null
+++ b/target/product/locales_full.mk
@@ -0,0 +1,5 @@
+# The locales from the ICU "-large.dat" data set.
+# See external/icu4c/stubdata.
+# This is distinct from "languages_full.mk", which contains those locales for
+# which we have translations. If you like, this file is i18n rather than l18n.
+PRODUCT_LOCALES := cs_CZ da_DA de_AT de_CH de_DE de_LI el_GR en_AU en_CA en_GB en_NZ en_SG en_US es_ES fr_CA fr_CH fr_BE fr_FR it_CH it_IT ja_JP ko_KR nb_NO nl_BE nl_NL pl_PL pt_PT ru_RU sv_SV tr_TR zh_CN zh_HK zh_TW
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index b6700b6..aa5170a 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -14,9 +14,11 @@
 # limitations under the License.
 #
 
+PRODUCT_POLICY := android.policy_phone
 PRODUCT_PROPERTY_OVERRIDES :=
 
 PRODUCT_PACKAGES := \
+	SystemUI \
 	AccountAndSyncSettings \
 	Camera \
 	Calculator \
@@ -39,6 +41,7 @@
 	sqlite3 \
 	LatinIME \
 	PinyinIME \
+	Phone \
 	OpenWnn \
 	libWnnEngDic \
 	libWnnJpnDic \
@@ -61,40 +64,13 @@
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
 
+$(call inherit-product, $(SRC_TARGET_DIR)/product/locales_full.mk)
+
 # Overrides
 PRODUCT_BRAND := generic
 PRODUCT_NAME := sdk
 PRODUCT_DEVICE := generic
-PRODUCT_LOCALES := \
-	ldpi \
-	hdpi \
-	mdpi \
-	en_US \
-	en_GB \
-	en_CA \
-	en_AU \
-	en_NZ \
-	en_SG \
-	ja_JP \
-	fr_FR \
-	fr_BE \
-	fr_CA \
-	fr_CH \
-	it_IT \
-	it_CH \
-	es_ES \
-	de_DE \
-	de_AT \
-	de_CH \
-	de_LI \
-	nl_NL \
-	nl_BE \
-	cs_CZ \
-	pl_PL \
-	zh_CN \
-	zh_TW \
-	ru_RU \
-	ko_KR
+PRODUCT_LOCALES += ldpi hdpi mdpi
 
 # include available languages for TTS in the system image
 include external/svox/pico/lang/PicoLangDeDeInSystem.mk
diff --git a/target/product/sim.mk b/target/product/sim.mk
index 51b3676..09722d6 100644
--- a/target/product/sim.mk
+++ b/target/product/sim.mk
@@ -1,6 +1,6 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/locales_full.mk)
 
 # Overrides
 PRODUCT_NAME := sim
 PRODUCT_DEVICE := sim
-PRODUCT_LOCALES := en_US
diff --git a/tools/adbs b/tools/adbs
index 8277790..4fb94d5 100755
--- a/tools/adbs
+++ b/tools/adbs
@@ -144,23 +144,23 @@
       uname = "darwin-ppc"
   elif uname == "Linux":
     uname = "linux-x86"
-  prefix = "./prebuilt/" + uname + "/toolchain/arm-eabi-4.4.3/bin/"
-  addr2line_cmd = prefix + "arm-eabi-addr2line"
+  prefix = "./prebuilt/" + uname + "/toolchain/arm-linux-androideabi-4.4.x/bin/"
+  addr2line_cmd = prefix + "arm-linux-androideabi-addr2line"
 
   if (not os.path.exists(addr2line_cmd)):
     try:
       prefix = os.environ['ANDROID_BUILD_TOP'] + "/prebuilt/" + uname + \
-               "/toolchain/arm-eabi-4.4.3/bin/"
+               "/toolchain/arm-linux-androideabi-4.4.x/bin/"
     except:
       prefix = "";
 
-    addr2line_cmd = prefix + "arm-eabi-addr2line"
+    addr2line_cmd = prefix + "arm-linux-androideabi-addr2line"
     if (not os.path.exists(addr2line_cmd)):
       print addr2line_cmd + " not found!"
       sys.exit(1)
 
-  objdump_cmd = prefix + "arm-eabi-objdump"
-  cppfilt_cmd = prefix + "arm-eabi-c++filt"
+  objdump_cmd = prefix + "arm-linux-androideabi-objdump"
+  cppfilt_cmd = prefix + "arm-linux-androideabi-c++filt"
 
 ###############################################################################
 # look up the function and file/line number for a raw stack trace line
diff --git a/tools/apicheck/src/com/android/apicheck/ApiCheck.java b/tools/apicheck/src/com/android/apicheck/ApiCheck.java
index c8272dd..b2f2265 100644
--- a/tools/apicheck/src/com/android/apicheck/ApiCheck.java
+++ b/tools/apicheck/src/com/android/apicheck/ApiCheck.java
@@ -107,6 +107,7 @@
             xmlreader.parse(new InputSource(fileReader));
             ApiInfo apiInfo = handler.getApi();
             apiInfo.resolveSuperclasses();
+            apiInfo.resolveInterfaces();
             return apiInfo;
         } catch (SAXParseException e) {
             Errors.error(Errors.PARSE_ERROR,
diff --git a/tools/apicheck/src/com/android/apicheck/ApiInfo.java b/tools/apicheck/src/com/android/apicheck/ApiInfo.java
index c237814..47b9a15 100644
--- a/tools/apicheck/src/com/android/apicheck/ApiInfo.java
+++ b/tools/apicheck/src/com/android/apicheck/ApiInfo.java
@@ -31,14 +31,13 @@
         return mAllClasses.get(name);
     }
 
-    private void resolveInterfaces() {
+    public void resolveInterfaces() {
         for (ClassInfo c : mAllClasses.values()) {
             c.resolveInterfaces(this);
         }
     }
     
     public boolean isConsistent(ApiInfo otherApi) {
-        resolveInterfaces();
         boolean consistent = true;
         for (PackageInfo pInfo : mPackages.values()) {
             if (otherApi.getPackages().containsKey(pInfo.name())) {
diff --git a/tools/apicheck/src/com/android/apicheck/ClassInfo.java b/tools/apicheck/src/com/android/apicheck/ClassInfo.java
index e62a3d0..962a316 100644
--- a/tools/apicheck/src/com/android/apicheck/ClassInfo.java
+++ b/tools/apicheck/src/com/android/apicheck/ClassInfo.java
@@ -86,41 +86,35 @@
         return mIsFinal;
     }
     
-    // Find a superclass implementation of the given method.  Looking at our superclass
-    // instead of at 'this' is unusual, but it fits the point-of-call demands well.
-    public MethodInfo overriddenMethod(MethodInfo candidate) {
-        if (mSuperClass == null) {
+    // Find a superclass implementation of the given method.
+    public static MethodInfo overriddenMethod(MethodInfo candidate, ClassInfo newClassObj) {
+        if (newClassObj == null) {
             return null;
         }
-        
-        // does our immediate superclass have it?
-        ClassInfo sup = mSuperClass;
-        for (MethodInfo mi : sup.mMethods.values()) {
+        for (MethodInfo mi : newClassObj.mMethods.values()) {
             if (mi.matches(candidate)) {
                 // found it
                 return mi;
             }
         }
 
-        // no, so recurse
-        if (sup.mSuperClass != null) {
-            return mSuperClass.overriddenMethod(candidate);
-        }
-        
-        // no parent, so we just don't have it
-        return null;
+        // not found here. recursively search ancestors
+        return ClassInfo.overriddenMethod(candidate, newClassObj.mSuperClass);
     }
     
     // Find a superinterface declaration of the given method.
-    public MethodInfo interfaceMethod(MethodInfo candidate) {
-        for (ClassInfo interfaceInfo : mInterfaces) {
+    public static MethodInfo interfaceMethod(MethodInfo candidate, ClassInfo newClassObj) {
+        if (newClassObj == null) {
+            return null;
+        }
+        for (ClassInfo interfaceInfo : newClassObj.mInterfaces) {
             for (MethodInfo mi : interfaceInfo.mMethods.values()) {
                 if (mi.matches(candidate)) {
                     return mi;
                 }
             }
         }
-        return (mSuperClass != null) ? mSuperClass.interfaceMethod(candidate) : null;
+        return ClassInfo.interfaceMethod(candidate, newClassObj.mSuperClass);
     }
 
     public boolean isConsistent(ClassInfo cl) {
@@ -135,11 +129,7 @@
             consistent = false;
         }
         for (String iface : mInterfaceNames) {
-            boolean found = false;
-            for (ClassInfo c = cl; c != null && !found; c = c.mSuperClass) {
-                found = c.mInterfaceNames.contains(iface);
-            }
-            if (!found) {
+            if (!implementsInterface(cl, iface)) {
                 Errors.error(Errors.REMOVED_INTERFACE, cl.position(),
                         "Class " + qualifiedName() + " no longer implements " + iface);
             }
@@ -163,9 +153,9 @@
                  * Check our ancestry to see if there's an inherited version that still
                  * fulfills the API requirement.
                  */
-                MethodInfo mi = mInfo.containingClass().overriddenMethod(mInfo);
+                MethodInfo mi = ClassInfo.overriddenMethod(mInfo, cl);
                 if (mi == null) {
-                    mi = mInfo.containingClass().interfaceMethod(mInfo);
+                    mi = ClassInfo.interfaceMethod(mInfo, cl);
                 }
                 if (mi == null) {
                     Errors.error(Errors.REMOVED_METHOD, mInfo.position(),
@@ -179,7 +169,7 @@
                 /* Similarly to the above, do not fail if this "new" method is
                  * really an override of an existing superclass method.
                  */
-                MethodInfo mi = mInfo.containingClass().overriddenMethod(mInfo);
+                MethodInfo mi = ClassInfo.overriddenMethod(mInfo, cl);
                 if (mi == null) {
                     Errors.error(Errors.ADDED_METHOD, mInfo.position(),
                             "Added public method " + mInfo.qualifiedName());
@@ -274,6 +264,26 @@
         return consistent;
     }
 
+    /**
+     * Returns true if {@code cl} implements the interface {@code iface} either
+     * by either being that interface, implementing that interface or extending
+     * a type that implements the interface.
+     */
+    private boolean implementsInterface(ClassInfo cl, String iface) {
+        if (cl.qualifiedName().equals(iface)) {
+            return true;
+        }
+        for (ClassInfo clImplements : cl.mInterfaces) {
+            if (implementsInterface(clImplements, iface)) {
+                return true;
+            }
+        }
+        if (cl.mSuperClass != null && implementsInterface(cl.mSuperClass, iface)) {
+            return true;
+        }
+        return false;
+    }
+
     public void resolveInterfaces(ApiInfo apiInfo) {
         for (String interfaceName : mInterfaceNames) {
             mInterfaces.add(apiInfo.findClass(interfaceName));
diff --git a/tools/apriori/apriori.c b/tools/apriori/apriori.c
index d1807b3..b25ac2b 100644
--- a/tools/apriori/apriori.c
+++ b/tools/apriori/apriori.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <stdlib.h>
 #include <common.h>
 #include <debug.h>
 #include <libelf.h>
@@ -54,6 +55,154 @@
 
 static source_t *sources = NULL;
 
+/* Retouch data is a very concise representation of the resolved relocations.
+   This data is used to randomize the location of prelinked libraries at
+   update time, on the device.
+ */
+
+// We will store retouch entries into this buffer, then dump them at the
+// end of the .so file before setup_prelink_info().
+#define RETOUCH_MAX_SIZE 500000
+static char *retouch_buf;
+static unsigned int retouch_byte_cnt;
+// Compression state.
+static int32_t offs_prev;
+static uint32_t cont_prev;
+
+#define false 0
+#define true 1
+
+void retouch_init(void) {
+    offs_prev = 0;
+    cont_prev = 0;
+    retouch_byte_cnt = 0;
+    retouch_buf = malloc(RETOUCH_MAX_SIZE+12);
+    FAILIF(retouch_buf == NULL,
+           "Could not allocate %d bytes.\n", RETOUCH_MAX_SIZE+12);
+}
+
+//
+// We use three encoding schemes; this takes care of much of the redundancy
+// inherent in lists of relocations:
+//
+//   * two bytes, leading 1, 2b for d_offset ("s"), 13b for d_contents ("c")
+//
+//     76543210 76543210
+//     1ssccccc cccccccc
+//
+//   * three bytes, leading 01, 2b for delta offset, 20b for delta contents
+//
+//     76543210 76543210 76543210
+//     01sscccc cccccccc cccccccc
+//
+//   * eigth bytes, leading 00, 30b for offset, 32b for contents
+//
+//     76543210 76543210 76543210 76543210
+//     00ssssss ssssssss ssssssss ssssssss + 4 bytes contents
+//
+// NOTE 1: All deltas are w.r.t. the previous line in the list.
+// NOTE 2: Two-bit ("ss") offsets mean: "00"=4, "01"=8, "10"=12, and "11"=16.
+// NOTE 3: Delta contents are signed. To map back to a int32 we refill with 1s.
+// NOTE 4: Special encoding for -1 offset. Extended back to 32b when decoded.
+//
+
+void retouch_encode(int32_t offset, uint32_t contents) {
+    int64_t d_offs = offset-offs_prev;
+    int64_t d_cont = (int64_t)contents-(int64_t)cont_prev;
+
+    uint8_t output[8];
+    uint32_t output_size;
+
+    if ((d_offs > 3) &&
+        (d_offs % 4) == 0 &&
+        (d_offs / 4) < 5 &&
+        (d_cont < 4000) &&
+        (d_cont > -4000)) {
+        // we can fit in 2 bytes
+        output[0] =
+          0x80 |
+          (((d_offs/4)-1) << 5) |
+          (((uint64_t)d_cont & 0x1f00) >> 8);
+        output[1] =
+          ((uint64_t)d_cont & 0xff);
+        output_size = 2;
+    } else if ((d_offs > 3) &&
+               (d_offs % 4) == 0 &&
+               (d_offs / 4) < 5 &&
+               (d_cont < 510000) &&
+               (d_cont > -510000)) {
+        // fit in 3 bytes
+        output[0] =
+          0x40 |
+          (((d_offs/4)-1) << 4) |
+          (((uint64_t)d_cont & 0xf0000) >> 16);
+        output[1] =
+          ((uint64_t)d_cont & 0xff00) >> 8;
+        output[2] =
+          ((uint64_t)d_cont & 0xff);
+        output_size = 3;
+    } else {
+        // fit in 8 bytes; we can't support files bigger than (1GB-1)
+        // with this encoding: no library is that big anyway..
+        FAILIF(offset < -1 || offset > 0x3ffffffe, "Offset out of range.\n");
+        output[0] = (offset & 0x3f000000) >> 24;
+        output[1] = (offset & 0xff0000) >> 16;
+        output[2] = (offset & 0xff00) >> 8;
+        output[3] = (offset & 0xff);
+        output[4] = (contents & 0xff000000) >> 24;
+        output[5] = (contents & 0xff0000) >> 16;
+        output[6] = (contents & 0xff00) >> 8;
+        output[7] = (contents & 0xff);
+        output_size = 8;
+    }
+
+    // If this happens, the retouch buffer size can be bumped up.
+    // Currently, the largest case is libwebcore, at about 250K.
+    FAILIF((retouch_byte_cnt+output_size) > RETOUCH_MAX_SIZE,
+           "About to overflow retouch buffer.\n");
+
+    memcpy(retouch_buf+retouch_byte_cnt, output, output_size);
+    retouch_byte_cnt += output_size;
+
+    offs_prev = offset;
+    cont_prev = contents;
+}
+
+void retouch_dump(const char *fname, int elf_little,
+                  unsigned int retouch_byte_cnt, char *retouch_buf) {
+    int fd = open(fname, O_WRONLY);
+    FAILIF(fd < 0,
+           "open(%s, O_WRONLY): %s (%d)\n" ,
+           fname, strerror(errno), errno);
+    off_t sz = lseek(fd, 0, SEEK_END);
+    FAILIF(sz == (off_t)-1,
+           "lseek(%d, 0, SEEK_END): %s (%d)!\n",
+           fd, strerror(errno), errno);
+
+    // The retouch blob ends with "RETOUCH XXXX", where XXXX is the 4-byte
+    // size of the retouch blob, in target endianness.
+    strncpy(retouch_buf+retouch_byte_cnt, "RETOUCH ", 8);
+    if (elf_little ^ is_host_little()) {
+        *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
+          switch_endianness(retouch_byte_cnt);
+    } else {
+        *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
+          retouch_byte_cnt;
+    }
+
+    int num_written = write(fd, retouch_buf, retouch_byte_cnt+12);
+    FAILIF(num_written < 0,
+           "write(%d, &info, sizeof(info)): %s (%d)\n",
+           fd, strerror(errno), errno);
+    FAILIF((retouch_byte_cnt+12) != num_written,
+           "Could not write %d bytes as expected (wrote %d bytes instead)!\n",
+           retouch_byte_cnt, num_written);
+    FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
+}
+
+/* End of retouch code.
+ */
+
 #if defined(DEBUG) && 0
 
 static void print_shdr(source_t *source, Elf_Scn *scn)
@@ -325,6 +474,9 @@
                    basename(source->name));
         }
 
+        /* Save some of the info; needed for retouching (ASLR). */
+        retouch_init();
+
         source->newelf_fd = open(source->output,
                                  O_RDWR | O_CREAT,
                                  0666);
@@ -615,15 +767,15 @@
            strerror(errno),
            errno);
 
-	FAILIF(fstat(source->elf_fd, &source->elf_file_info) < 0,
-		   "fstat(%s(fd %d)): %s (%d)\n",
-		   source->name,
-		   source->elf_fd,
-		   strerror(errno),
-		   errno);
-	INFO("File [%s]'s size is %lld bytes!\n",
-		 source->name,
-		 source->elf_file_info.st_size);
+    FAILIF(fstat(source->elf_fd, &source->elf_file_info) < 0,
+           "fstat(%s(fd %d)): %s (%d)\n",
+           source->name,
+           source->elf_fd,
+           strerror(errno),
+           errno);
+    INFO("File [%s]'s size is %lld bytes!\n",
+         source->name,
+         source->elf_file_info.st_size);
 
     INFO("Calling elf_begin(%s)...\n", full_path);
 
@@ -775,6 +927,11 @@
                function setup_prelink_info() below. */
             INFO("%s: setting up prelink tag at end of file.\n",
                  source->output ? source->output : source->name);
+            retouch_encode(-1, source->base);
+            retouch_dump(source->output ? source->output : source->name,
+                         source->elf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
+                         retouch_byte_cnt,
+                         retouch_buf);
             setup_prelink_info(source->output ? source->output : source->name,
                                source->elf_hdr.e_ident[EI_DATA] == ELFDATA2LSB,
                                source->base);
@@ -785,6 +942,7 @@
 #endif/*SUPPORT_ANDROID_PRELINK_TAGS*/
 
     do_destroy_source(source);
+    if (retouch_buf != NULL) { free(retouch_buf); retouch_buf = NULL; }
 
     if (source->shstrtab_data != NULL)
         FREEIF(source->shstrtab_data->d_buf); /* adjust_elf */
@@ -1226,8 +1384,11 @@
                        rel->r_offset,
                        found_sym->st_value,
                        sym_source->base);
-                  if (!dry_run)
+                  if (!dry_run) {
+                    PRINT("WARNING: Relocation type not supported "
+                          "for retouching!");
                     *dest = found_sym->st_value + sym_source->base;
+                  }
                 }
               num_relocations++;
               break;
@@ -1240,8 +1401,15 @@
                    sname,
                    symname ?: "(symbol has no name)",
                    rel->r_offset, *dest, source->base);
-              if (!dry_run)
+              if (!dry_run) {
                 *dest += source->base;
+
+                /* Output an entry for the ASLR touch-up process. */
+                retouch_encode(rel->r_offset
+                               -shdr_mem.sh_addr
+                               +shdr_mem.sh_offset,
+                               *dest);
+              }
               num_relocations++;
               break;
             case R_ARM_COPY:
@@ -1352,15 +1520,21 @@
                             ASSERT(data->d_buf != NULL);
                             ASSERT(data->d_size >= rel->r_offset -
                                    shdr_mem.sh_addr);
-                            if (!dry_run)
-                              memcpy(dest, src, found_sym->st_size);
+                            if (!dry_run) {
+                                PRINT("WARNING: Relocation type not supported "
+                                      "for retouching!");
+                                memcpy(dest, src, found_sym->st_size);
+                            }
                           }
                         else {
                           ASSERT(src == NULL);
                           ASSERT(elf_ndxscn(src_scn) ==
                                  elf_ndxscn(sym_source->bss.scn));
-                          if (!dry_run)
-                            memset(dest, 0, found_sym->st_size);
+                          if (!dry_run) {
+                              PRINT("WARNING: Relocation type not supported "
+                                    "for retouching!");
+                              memset(dest, 0, found_sym->st_size);
+                          }
                         }
                       }
                     }
diff --git a/tools/apriori/source.h b/tools/apriori/source.h
index a5d96bd..5381a29 100644
--- a/tools/apriori/source.h
+++ b/tools/apriori/source.h
@@ -62,7 +62,8 @@
     Elf_Data *shstrtab_data;
     int elf_fd;
     int newelf_fd; /* fd of output file, -1 if output == NULL */
-	struct stat elf_file_info;
+    int newelf_relo_fd; /* fd of relocaion output file */
+    struct stat elf_file_info;
     GElf_Ehdr elf_hdr, oldelf_hdr;
     size_t shstrndx;
     int shnum; /* number of sections */
diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh
index 6c85149..ce3ee81 100755
--- a/tools/buildinfo.sh
+++ b/tools/buildinfo.sh
@@ -25,8 +25,12 @@
   echo "ro.product.cpu.abi2=$TARGET_CPU_ABI2"
 fi
 echo "ro.product.manufacturer=$PRODUCT_MANUFACTURER"
-echo "ro.product.locale.language=$PRODUCT_DEFAULT_LANGUAGE"
-echo "ro.product.locale.region=$PRODUCT_DEFAULT_REGION"
+if [ -n "$PRODUCT_DEFAULT_LANGUAGE" ] ; then
+  echo "ro.product.locale.language=$PRODUCT_DEFAULT_LANGUAGE"
+fi
+if [ -n "$PRODUCT_DEFAULT_REGION" ] ; then
+  echo "ro.product.locale.region=$PRODUCT_DEFAULT_REGION"
+fi
 echo "ro.wifi.channels=$PRODUCT_DEFAULT_WIFI_CHANNELS"
 echo "ro.board.platform=$TARGET_BOARD_PLATFORM"
 
diff --git a/tools/droiddoc/templates-pdk/customization.cs b/tools/droiddoc/templates-pdk/customization.cs
index 3e9be06..d075bda 100644
--- a/tools/droiddoc/templates-pdk/customization.cs
+++ b/tools/droiddoc/templates-pdk/customization.cs
@@ -11,7 +11,6 @@
                       elif:doc.type == "source" ?>source<?cs
                       elif:doc.type == "porting" ?>porting<?cs
                       elif:doc.type == "compatibility" ?>compatibility<?cs
-                      elif:doc.type == "downloads" ?>downloads<?cs
                       elif:doc.type == "community" ?>community<?cs
                       elif:doc.type == "about" ?>about<?cs /if ?>">
               <li id="home-link"><a href="<?cs var:toroot ?>index.html"><span>Home</span></a></li>
@@ -23,8 +22,6 @@
                                   onClick="return loadLast('compatibility')"><span>Compatibility</span></a></li>
               <li id="community-link"><a href="<?cs var:toroot ?>community/index.html"
                                   onClick="return loadLast('community')"><span>Community</span></a></li>
-              <li id="downloads-link"><a href="<?cs var:toroot ?>downloads/index.html"
-                                  onClick="return loadLast('downloads')"><span>Downloads</span></a></li>
               <li id="about-link"><a href="<?cs var:toroot ?>about/index.html"
                                   onClick="return loadLast('about')"><span>About</span></a></li>
           </ul> 
@@ -102,21 +99,6 @@
   </div>
 <?cs /def ?>
 
-<?cs def:downloads_nav() ?>
-  <div class="g-section g-tpl-240" id="body-content">
-    <div class="g-unit g-first side-nav-resizable" id="side-nav">
-      <div id="devdoc-nav"><?cs
-        include:"../../../../development/pdk/docs/downloads/downloads_toc.cs" ?>
-      </div>
-    </div> <!-- end side-nav -->
-    <script>
-      addLoadEvent(function() {
-        scrollIntoView("devdoc-nav");
-        });
-    </script>
-  </div>
-<?cs /def ?>
-
 <?cs def:compatibility_nav() ?>
   <div class="g-section g-tpl-240" id="body-content">
     <div class="g-unit g-first side-nav-resizable" id="side-nav">
@@ -140,8 +122,6 @@
       <?cs call:porting_nav() ?>
     <?cs elif:doc.type == "compatibility" ?>
       <?cs call:compatibility_nav() ?>
-    <?cs elif:doc.type == "downloads" ?>
-      <?cs call:downloads_nav() ?>
     <?cs elif:doc.type == "community" ?>
       <?cs call:community_nav() ?>
     <?cs elif:doc.type == "about" ?>
@@ -150,33 +130,20 @@
   <?cs /if ?>
 <?cs /def ?>
 
-<?cs # appears at the bottom of every page ?><?cs 
-def:custom_cc_copyright() ?>
-  Except as noted, this content is 
-  licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
-  Creative Commons Attribution 2.5</a>. For details and 
-  restrictions, see the <a href="http://developer.android.com/license.html">Content 
-  License</a>.<?cs 
-/def ?>
+<?cs def:custom_cc_copyright() ?>
+<?cs /def ?>
 
-<?cs 
-def:custom_copyright() ?>
-  Except as noted, this content is licensed under <a
-  href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0</a>. 
-  For details and restrictions, see the <a href="http://developer.android.com/license.html">
-  Content License</a>.<?cs 
-/def ?>
+<?cs def:custom_copyright() ?>
+<?cs /def ?>
 
 <?cs 
 def:custom_footerlinks() ?>
   <p>
     <a href="http://www.android.com/terms.html">Site Terms of Service</a> -
-    <a href="http://www.android.com/privacy.html">Privacy Policy</a> -
-    <a href="http://www.android.com/branding.html">Brand Guidelines</a>
+    <a href="http://www.android.com/privacy.html">Privacy Policy</a>
   </p><?cs 
 /def ?>
 
-<?cs # appears on the right side of the blue bar at the bottom off every page ?><?cs 
-def:custom_buildinfo() ?>
-  Android <?cs var:sdk.platform.version ?>&nbsp;r<?cs var:sdk.rel.id ?> - <?cs var:page.now ?>
+<?cs # appears on the right side of the blue bar at the bottom off every page ?>
+<?cs def:custom_buildinfo() ?>
 <?cs /def ?>
diff --git a/tools/droiddoc/templates-pdk/head_tag.cs b/tools/droiddoc/templates-pdk/head_tag.cs
index 915dc0e..cccbb14 100644
--- a/tools/droiddoc/templates-pdk/head_tag.cs
+++ b/tools/droiddoc/templates-pdk/head_tag.cs
@@ -1,6 +1,6 @@
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<link rel="shortcut icon" type="image/x-icon" href="<?cs var:toroot ?>assets-pdk/favicon.ico" />
+<link rel="shortcut icon" type="image/x-icon" href="<?cs var:toroot ?>assets/favicon.ico" />
 <title><?cs 
   if:page.title ?><?cs 
     var:page.title ?><?cs
@@ -9,7 +9,7 @@
     /if ?> | <?cs
   /if ?>Android Open Source</title>
 <link href="<?cs var:toroot ?>assets/android-developer-docs-devguide.css" rel="stylesheet" type="text/css" />
-<link href="<?cs var:toroot ?>assets-pdk/pdk-local.css" rel="stylesheet" type="text/css" />
+<!-- <link href="<?cs var:toroot ?>assets-pdk/pdk-local.css" rel="stylesheet" type="text/css" /> -->
 <script src="<?cs var:toroot ?>assets/search_autocomplete.js" type="text/javascript"></script>
 <script src="<?cs var:toroot ?>assets/jquery-resizable.min.js" type="text/javascript"></script>
 <script src="<?cs var:toroot ?>assets/android-developer-docs.js" type="text/javascript"></script>
@@ -28,7 +28,7 @@
 	}
 }
 </script>
-<script type="text/javascript>
+<script type="text/javascript">
   jQuery(document).ready(function() {
         jQuery("pre").addClass("prettyprint");
   });
diff --git a/tools/droiddoc/templates/assets/android-developer-docs.js b/tools/droiddoc/templates/assets/android-developer-docs.js
index 4c59dd6..d61ce72 100644
--- a/tools/droiddoc/templates/assets/android-developer-docs.js
+++ b/tools/droiddoc/templates/assets/android-developer-docs.js
@@ -27,10 +27,10 @@
 
 var agent = navigator['userAgent'].toLowerCase();
 // If a mobile phone, set flag and do mobile setup
-if ((agent.indexOf("mobile") != -1) ||      // android, iphone, ipod 
+if ((agent.indexOf("mobile") != -1) ||      // android, iphone, ipod
     (agent.indexOf("blackberry") != -1) ||
     (agent.indexOf("webos") != -1) ||
-    (agent.indexOf("mini") != -1)) {        // opera mini browsers 
+    (agent.indexOf("mini") != -1)) {        // opera mini browsers
   isMobile = true;
   addLoadEvent(mobileSetup);
 // If not a mobile browser, set the onresize event for IE6, and others
@@ -126,7 +126,7 @@
     expiration = date.toGMTString();
   }
   document.cookie = cookie_namespace + section + cookie + "=" + val + "; expires=" + expiration+"; path=/";
-} 
+}
 
 function init() {
   $("#side-nav").css({position:"absolute",left:0});
@@ -162,11 +162,84 @@
     }
   }
 
-  if (devdocNav.length) { // only dev guide and sdk 
-    highlightNav(location.href); 
+  if (devdocNav.length) { // only dev guide, resources, and sdk
+    tryPopulateResourcesNav();
+    highlightNav(location.href);
   }
 }
 
+function tryPopulateResourcesNav() {
+  var sampleList = $('#devdoc-nav-sample-list');
+  var articleList = $('#devdoc-nav-article-list');
+  var tutorialList = $('#devdoc-nav-tutorial-list');
+  var topicList = $('#devdoc-nav-topic-list');
+
+  if (!topicList.length || !ANDROID_TAGS || !ANDROID_RESOURCES)
+    return;
+
+  var topics = [];
+  for (var topic in ANDROID_TAGS['topic']) {
+    topics.push({name:topic,title:ANDROID_TAGS['topic'][topic]});
+  }
+  topics.sort(function(x,y){ return (x.title < y.title) ? -1 : 1; });
+  for (var i = 0; i < topics.length; i++) {
+    topicList.append(
+        $('<li>').append(
+          $('<a>')
+            .attr('href', toRoot + "resources/browser.html?tag=" + topics[i].name)
+            .append($('<span>')
+              .addClass('en')
+              .html(topics[i].title)
+            )
+          )
+        );
+  }
+
+  var _renderResourceList = function(tag, listNode) {
+    var resources = [];
+    var tags;
+    var resource;
+    var i, j;
+    for (i = 0; i < ANDROID_RESOURCES.length; i++) {
+      resource = ANDROID_RESOURCES[i];
+      tags = resource.tags || [];
+      var hasTag = false;
+      for (j = 0; j < tags.length; j++)
+        if (tags[j] == tag) {
+          hasTag = true;
+          break;
+        }
+      if (!hasTag)
+        continue;
+      resources.push(resource);
+    }
+    //resources.sort(function(x,y){ return (x.title.en < y.title.en) ? -1 : 1; });
+    for (i = 0; i < resources.length; i++) {
+      resource = resources[i];
+      var listItemNode = $('<li>').append(
+          $('<a>')
+            .attr('href', toRoot + "resources/" + resource.path)
+            .append($('<span>')
+              .addClass('en')
+              .html(resource.title.en)
+            )
+          );
+      tags = resource.tags || [];
+      for (j = 0; j < tags.length; j++) {
+        if (tags[j] == 'new') {
+          listItemNode.get(0).innerHTML += '&nbsp;<span class="new">new!</span>';
+          break;
+        }
+      }
+      listNode.append(listItemNode);
+    }
+  };
+
+  _renderResourceList('sample', sampleList);
+  _renderResourceList('article', articleList);
+  _renderResourceList('tutorial', tutorialList);
+}
+
 function highlightNav(fullPageName) {
   var lastSlashPos = fullPageName.lastIndexOf("/");
   var firstSlashPos;
@@ -180,17 +253,23 @@
   if (lastSlashPos == (fullPageName.length - 1)) { // if the url ends in slash (add 'index.html')
     fullPageName = fullPageName + "index.html";
   }
-  var htmlPos = fullPageName.lastIndexOf(".html", fullPageName.length);
-  var pathPageName = fullPageName.slice(firstSlashPos, htmlPos + 5);
+  // First check if the exact URL, with query string and all, is in the navigation menu
+  var pathPageName = fullPageName.substr(firstSlashPos);
   var link = $("#devdoc-nav a[href$='"+ pathPageName+"']");
-  if ((link.length == 0) && ((fullPageName.indexOf("/guide/") != -1) || (fullPageName.indexOf("/resources/") != -1))) { 
-// if there's no match, then let's backstep through the directory until we find an index.html page that matches our ancestor directories (only for dev guide)
-    lastBackstep = pathPageName.lastIndexOf("/");
-    while (link.length == 0) {
-      backstepDirectory = pathPageName.lastIndexOf("/", lastBackstep);
-      link = $("#devdoc-nav a[href$='"+ pathPageName.slice(0, backstepDirectory + 1)+"index.html']");
-      lastBackstep = pathPageName.lastIndexOf("/", lastBackstep - 1);
-      if (lastBackstep == 0) break;
+  if (link.length == 0) {
+    var htmlPos = fullPageName.lastIndexOf(".html", fullPageName.length);
+    pathPageName = fullPageName.slice(firstSlashPos, htmlPos + 5); // +5 advances past ".html"
+    link = $("#devdoc-nav a[href$='"+ pathPageName+"']");
+    if ((link.length == 0) && ((fullPageName.indexOf("/guide/") != -1) || (fullPageName.indexOf("/resources/") != -1))) {
+      // if there's no match, then let's backstep through the directory until we find an index.html page
+      // that matches our ancestor directories (only for dev guide and resources)
+      lastBackstep = pathPageName.lastIndexOf("/");
+      while (link.length == 0) {
+        backstepDirectory = pathPageName.lastIndexOf("/", lastBackstep);
+        link = $("#devdoc-nav a[href$='"+ pathPageName.slice(0, backstepDirectory + 1)+"index.html']");
+        lastBackstep = pathPageName.lastIndexOf("/", lastBackstep - 1);
+        if (lastBackstep == 0) break;
+      }
     }
   }
 
@@ -436,12 +515,12 @@
 
 function changeTabLang(lang) {
   var nodes = $("#header-tabs").find("."+lang);
-  for (i=0; i < nodes.length; i++) { // for each node in this language 
+  for (i=0; i < nodes.length; i++) { // for each node in this language
     var node = $(nodes[i]);
-    node.siblings().css("display","none"); // hide all siblings 
-    if (node.not(":empty").length != 0) { //if this languages node has a translation, show it 
+    node.siblings().css("display","none"); // hide all siblings
+    if (node.not(":empty").length != 0) { //if this languages node has a translation, show it
       node.css("display","inline");
-    } else { //otherwise, show English instead 
+    } else { //otherwise, show English instead
       node.css("display","none");
       node.siblings().filter(".en").css("display","inline");
     }
@@ -450,12 +529,12 @@
 
 function changeNavLang(lang) {
   var nodes = $("#side-nav").find("."+lang);
-  for (i=0; i < nodes.length; i++) { // for each node in this language 
+  for (i=0; i < nodes.length; i++) { // for each node in this language
     var node = $(nodes[i]);
-    node.siblings().css("display","none"); // hide all siblings 
-    if (node.not(":empty").length != 0) { // if this languages node has a translation, show it 
+    node.siblings().css("display","none"); // hide all siblings
+    if (node.not(":empty").length != 0) { // if this languages node has a translation, show it
       node.css("display","inline");
-    } else { // otherwise, show English instead 
+    } else { // otherwise, show English instead
       node.css("display","none");
       node.siblings().filter(".en").css("display","inline");
     }
diff --git a/tools/droiddoc/templates/assets/android-developer-resource-browser.css b/tools/droiddoc/templates/assets/android-developer-resource-browser.css
new file mode 100644
index 0000000..a454caa
--- /dev/null
+++ b/tools/droiddoc/templates/assets/android-developer-resource-browser.css
@@ -0,0 +1,31 @@
+/* Resource Browser */
+
+#resource-browser-results .no-results {
+  font-style: italic;
+  display: none;
+}
+
+#resource-browser-results .result {
+  position: relative;
+  padding-left: 84px;
+  background: transparent none no-repeat scroll 4px 12px;
+  border-bottom: 1px solid #ddd;
+}
+
+#resource-browser-results .tagged-article {
+  background-image: url(images/resource-article.png);
+}
+
+#resource-browser-results .tagged-sample {
+  background-image: url(images/resource-sample.png);
+}
+
+#resource-browser-results .tagged-tutorial {
+  background-image: url(images/resource-tutorial.png);
+}
+
+#resource-browser-results .resource-meta {
+  margin-top: -1em;
+  font-size: 0.85em;
+  font-weight: normal;
+}
diff --git a/tools/droiddoc/templates/assets/android-developer-resource-browser.js b/tools/droiddoc/templates/assets/android-developer-resource-browser.js
new file mode 100644
index 0000000..dc65aa2
--- /dev/null
+++ b/tools/droiddoc/templates/assets/android-developer-resource-browser.js
@@ -0,0 +1,235 @@
+(function() { // anonymize
+
+var allTags = {};
+var loadedResults = [];
+
+/**
+ * Initialization code run upon the DOM being ready.
+ */
+$(document).ready(function() {
+  // Parse page query parameters.
+  var params = parseParams(document.location.search);
+  params.tag = params.tag ? makeArray(params.tag) : null;
+
+  // Load tag and resource dataset.
+  loadTags();
+  loadResources();
+
+  showResults(params);
+
+  // Watch for keypresses in the keyword filter textbox, and update
+  // search results to reflect the keyword filter.
+  $('#resource-browser-keyword-filter').keyup(function() {
+    // Filter results on screen by keyword.
+    var keywords = $(this).val().split(/\s+/g);
+    for (var i = 0; i < loadedResults.length; i++) {
+      var hide = false;
+      for (var j = 0; j < keywords.length; j++) {
+        if (!resultMatchesKeyword(loadedResults[i].result, keywords[j])) {
+          hide = true;
+          break;
+        }
+      }
+
+      loadedResults[i].node[hide ? 'hide' : 'show']();
+    }
+  });
+});
+
+/**
+ * Returns whether or not the given search result contains the given keyword.
+ */
+function resultMatchesKeyword(result, keyword) {
+  keyword = keyword.toLowerCase();
+  if (result.title &&
+      result.title.en.toLowerCase().indexOf(keyword) >= 0)
+    return true;
+  else if (result.description &&
+           result.description.en.toLowerCase().indexOf(keyword) >= 0)
+    return true;
+  else if (result.topicsHtml &&
+           result.topicsHtml.replace(/\<.*?\>/g,'').toLowerCase().indexOf(keyword) >= 0)
+    return true;
+  return false;
+}
+
+/**
+ * Populates the allTags array with tag data from the ANDROID_TAGS
+ * variable in the resource data JS file.
+ */
+function loadTags() {
+  for (var tagClass in ANDROID_TAGS) {
+    for (var tag in ANDROID_TAGS[tagClass]) {
+      allTags[tag] = {
+        displayTag: ANDROID_TAGS[tagClass][tag],
+        tagClass: tagClass
+      };
+    }
+  }
+}
+
+/**
+ * Massage the ANDROID_RESOURCES resource list in the resource data JS file.
+ */
+function loadResources() {
+  for (var i = 0; i < ANDROID_RESOURCES.length; i++) {
+    var resource = ANDROID_RESOURCES[i];
+
+    // Convert the tags array to a tags hash for easier querying.
+    resource.tagsHash = {};
+    for (var j = 0; j < resource.tags.length; j++)
+      resource.tagsHash[resource.tags[j]] = true;
+
+    // Determine the type and topics of the resource by inspecting its tags.
+    resource.topics = [];
+    for (tag in resource.tagsHash)
+      if (tag in allTags) {
+        if (allTags[tag].tagClass == 'type') {
+          resource.type = tag;
+        } else if (allTags[tag].tagClass == 'topic') {
+          resource.topics.push(tag);
+        }
+      }
+
+    // Add a humanized topics list string.
+    resource.topicsHtml = humanizeList(resource.topics, function(item) {
+      return '<strong>' + allTags[item].displayTag + '</strong>';
+    });
+  }
+}
+
+/**
+ * Loads resources for the given query parameters.
+ */
+function showResults(params) {
+  loadedResults = [];
+  $('#resource-browser-search-params').empty();
+  $('#resource-browser-results').empty();
+
+  var i, j;
+  var searchTags = [];
+  if (params.tag) {
+    for (i = 0; i < params.tag.length; i++) {
+      var tag = params.tag[i];
+      if (tag.toLowerCase() in allTags) {
+        searchTags.push(tag.toLowerCase());
+      }
+    }
+  }
+
+  if (searchTags.length) {
+    // Show query params.
+    var taggedWithHtml = ['Showing technical resources tagged with '];
+    taggedWithHtml.push(humanizeList(searchTags, function(item) {
+      return '<strong>' + allTags[item].displayTag + '</strong>';
+    }));
+    $('#resource-browser-search-params').html(taggedWithHtml.join('') + ':');
+  } else {
+    $('#resource-browser-search-params').html('Showing all technical resources:');
+  }
+
+  var results = [];
+
+  // Create the list of resources to show.
+  for (i = 0; i < ANDROID_RESOURCES.length; i++) {
+    var resource = ANDROID_RESOURCES[i];
+    var skip = false;
+
+    if (searchTags.length) {
+      for (j = 0; j < searchTags.length; j++)
+        if (!(searchTags[j] in resource.tagsHash)) {
+          skip = true;
+          break;
+        }
+
+      if (skip)
+        continue;
+
+      results.push(resource);
+      continue;
+    }
+
+    results.push(resource);
+  }
+
+  // Format and show the list of resource results.
+  if (results.length) {
+    $('#resource-browser-results .no-results').hide();
+    for (i = 0; i < results.length; i++) {
+      var result = results[i];
+      var resultJqNode = $(tmpl('tmpl_resource_browser_result', result));
+      for (tag in result.tagsHash)
+        resultJqNode.addClass('tagged-' + tag);
+      $('#resource-browser-results').append(resultJqNode);
+
+      loadedResults.push({ node: resultJqNode, result: result });
+    }
+  } else {
+    $('#resource-browser-results .no-results').show();
+  }
+}
+
+/**
+ * Formats the given array into a human readable, English string, ala
+ * 'a, b and c', with an optional item formatter/wrapper function.
+ */
+function humanizeList(arr, itemFormatter) {
+  itemFormatter = itemFormatter || function(o){ return o; };
+  arr = arr || [];
+
+  var out = [];
+  for (var i = 0; i < arr.length; i++) {
+    out.push(itemFormatter(arr[i]) +
+        ((i < arr.length - 2) ? ', ' : '') +
+        ((i == arr.length - 2) ? ' and ' : ''));
+  }
+
+  return out.join('');
+}
+
+/**
+ * Parses a parameter string, i.e. foo=1&bar=2 into
+ * a dictionary object.
+ */
+function parseParams(paramStr) {
+  var params = {};
+  paramStr = paramStr.replace(/^[?#]/, '');
+
+  var pairs = paramStr.split('&');
+  for (var i = 0; i < pairs.length; i++) {
+    var p = pairs[i].split('=');
+    var key = p[0] ? decodeURIComponent(p[0]) : p[0];
+    var val = p[1] ? decodeURIComponent(p[1]) : p[1];
+    if (val === '0')
+      val = 0;
+    if (val === '1')
+      val = 1;
+
+    if (key in params) {
+      // Handle array values.
+      params[key] = makeArray(params[key]);
+      params[key].push(val);
+    } else {
+      params[key] = val;
+    }
+  }
+
+  return params;
+}
+
+/**
+ * Returns the argument as a single-element array, or the argument itself
+ * if it's already an array.
+ */
+function makeArray(o) {
+  if (!o)
+    return [];
+
+  if (typeof o === 'object' && 'splice' in o) {
+    return o;
+  } else {
+    return [o];
+  }
+}
+
+})();
diff --git a/tools/droiddoc/templates/assets/images/resource-article.png b/tools/droiddoc/templates/assets/images/resource-article.png
new file mode 100644
index 0000000..416493f
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-article.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/images/resource-big-article.png b/tools/droiddoc/templates/assets/images/resource-big-article.png
new file mode 100644
index 0000000..7273275
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-big-article.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/images/resource-big-sample.png b/tools/droiddoc/templates/assets/images/resource-big-sample.png
new file mode 100644
index 0000000..59b6b68
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-big-sample.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/images/resource-big-tutorial.png b/tools/droiddoc/templates/assets/images/resource-big-tutorial.png
new file mode 100644
index 0000000..c32e89a
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-big-tutorial.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/images/resource-big-video.png b/tools/droiddoc/templates/assets/images/resource-big-video.png
new file mode 100644
index 0000000..59d46a0
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-big-video.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/images/resource-sample.png b/tools/droiddoc/templates/assets/images/resource-sample.png
new file mode 100644
index 0000000..f7a411c
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-sample.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/images/resource-tutorial.png b/tools/droiddoc/templates/assets/images/resource-tutorial.png
new file mode 100644
index 0000000..10a14fe
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-tutorial.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/images/resource-video.png b/tools/droiddoc/templates/assets/images/resource-video.png
new file mode 100644
index 0000000..8fd5cae
--- /dev/null
+++ b/tools/droiddoc/templates/assets/images/resource-video.png
Binary files differ
diff --git a/tools/droiddoc/templates/assets/microtemplate.js b/tools/droiddoc/templates/assets/microtemplate.js
new file mode 100644
index 0000000..ada1235
--- /dev/null
+++ b/tools/droiddoc/templates/assets/microtemplate.js
@@ -0,0 +1,35 @@
+// Simple JavaScript Templating
+// John Resig - http://ejohn.org/ - MIT Licensed
+(function(){
+  var cache = {};
+
+  this.tmpl = function tmpl(str, data){
+    // Figure out if we're getting a template, or if we need to
+    // load the template - and be sure to cache the result.
+    var fn = !/\W/.test(str) ?
+      cache[str] = cache[str] ||
+        tmpl(document.getElementById(str).innerHTML) :
+
+      // Generate a reusable function that will serve as a template
+      // generator (and which will be cached).
+      new Function("obj",
+        "var p=[],print=function(){p.push.apply(p,arguments);};" +
+
+        // Introduce the data as local variables using with(){}
+        "with(obj){p.push('" +
+
+        // Convert the template into pure JavaScript
+        str
+          .replace(/[\r\t\n]/g, " ")
+          .split("<%").join("\t")
+          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
+          .replace(/\t=(.*?)%>/g, "',$1,'")
+          .split("\t").join("');")
+          .split("%>").join("p.push('")
+          .split("\r").join("\\'")
+      + "');}return p.join('');");
+
+    // Provide some basic currying to the user
+    return data ? fn( data ) : fn;
+  };
+})();
\ No newline at end of file
diff --git a/tools/droiddoc/templates/head_tag.cs b/tools/droiddoc/templates/head_tag.cs
index 5a7fd40..b418e1e 100644
--- a/tools/droiddoc/templates/head_tag.cs
+++ b/tools/droiddoc/templates/head_tag.cs
@@ -20,6 +20,9 @@
 if:reference ?>
 <script src="<?cs var:toroot ?>assets/android-developer-reference.js" type="text/javascript"></script>
 <script src="<?cs var:toroot ?>navtree_data.js" type="text/javascript"></script><?cs 
+/if ?><?cs 
+if:resources ?>
+<script src="<?cs var:toroot ?>resources/resources-data.js" type="text/javascript"></script><?cs 
 /if ?>
 <noscript>
   <style type="text/css">
diff --git a/tools/releasetools/amend_generator.py b/tools/releasetools/amend_generator.py
deleted file mode 100644
index b543bf7..0000000
--- a/tools/releasetools/amend_generator.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-
-import common
-
-class AmendGenerator(object):
-  """Class to generate scripts in the 'amend' recovery script language
-  used up through cupcake."""
-
-  def __init__(self):
-    self.script = ['assert compatible_with("0.2") == "true"']
-    self.included_files = set()
-
-  def MakeTemporary(self):
-    """Make a temporary script object whose commands can latter be
-    appended to the parent script with AppendScript().  Used when the
-    caller wants to generate script commands out-of-order."""
-    x = AmendGenerator()
-    x.script = []
-    x.included_files = self.included_files
-    return x
-
-  @staticmethod
-  def _FileRoot(fn):
-    """Convert a file path to the 'root' notation used by amend."""
-    if fn.startswith("/system/"):
-      return "SYSTEM:" + fn[8:]
-    elif fn == "/system":
-      return "SYSTEM:"
-    elif fn.startswith("/tmp/"):
-      return "CACHE:.." + fn
-    else:
-      raise ValueError("don't know root for \"%s\"" % (fn,))
-
-  @staticmethod
-  def _PartitionRoot(partition):
-    """Convert a partition name to the 'root' notation used by amend."""
-    if partition == "userdata":
-      return "DATA:"
-    else:
-      return partition.upper() + ":"
-
-  def AppendScript(self, other):
-    """Append the contents of another script (which should be created
-    with temporary=True) to this one."""
-    self.script.extend(other.script)
-    self.included_files.update(other.included_files)
-
-  def AssertSomeFingerprint(self, *fp):
-    """Assert that the current fingerprint is one of *fp."""
-    x = [('file_contains("SYSTEM:build.prop", '
-          '"ro.build.fingerprint=%s") == "true"') % i for i in fp]
-    self.script.append("assert %s" % (" || ".join(x),))
-
-  def AssertOlderBuild(self, timestamp):
-    """Assert that the build on the device is older (or the same as)
-    the given timestamp."""
-    self.script.append("run_program PACKAGE:check_prereq %s" % (timestamp,))
-    self.included_files.add("check_prereq")
-
-  def AssertDevice(self, device):
-    """Assert that the device identifier is the given string."""
-    self.script.append('assert getprop("ro.product.device") == "%s" || '
-                       'getprop("ro.build.product") == "%s"' % (device, device))
-
-  def AssertSomeBootloader(self, *bootloaders):
-    """Asert that the bootloader version is one of *bootloaders."""
-    self.script.append("assert " +
-                  " || ".join(['getprop("ro.bootloader") == "%s"' % (b,)
-                               for b in bootloaders]))
-
-  def ShowProgress(self, frac, dur):
-    """Update the progress bar, advancing it over 'frac' over the next
-    'dur' seconds."""
-    self.script.append("show_progress %f %d" % (frac, int(dur)))
-
-  def SetProgress(self, frac):
-    """Not implemented in amend."""
-    pass
-
-  def PatchCheck(self, filename, *sha1):
-    """Check that the given file (or MTD reference) has one of the
-    given *sha1 hashes."""
-    out = ["run_program PACKAGE:applypatch -c %s" % (filename,)]
-    for i in sha1:
-      out.append(" " + i)
-    self.script.append("".join(out))
-    self.included_files.add(("applypatch_static", "applypatch"))
-
-  # Not quite right since we don't need to check /cache/saved.file on
-  # failure, but shouldn't hurt.
-  FileCheck = PatchCheck
-
-  def CacheFreeSpaceCheck(self, amount):
-    """Check that there's at least 'amount' space that can be made
-    available on /cache."""
-    self.script.append("run_program PACKAGE:applypatch -s %d" % (amount,))
-    self.included_files.add(("applypatch_static", "applypatch"))
-
-  def Mount(self, kind, what, path):
-    # no-op; amend uses it's 'roots' system to automatically mount
-    # things when they're referred to
-    pass
-
-  def UnpackPackageDir(self, src, dst):
-    """Unpack a given directory from the OTA package into the given
-    destination directory."""
-    dst = self._FileRoot(dst)
-    self.script.append("copy_dir PACKAGE:%s %s" % (src, dst))
-
-  def Comment(self, comment):
-    """Write a comment into the update script."""
-    self.script.append("")
-    for i in comment.split("\n"):
-      self.script.append("# " + i)
-    self.script.append("")
-
-  def Print(self, message):
-    """Log a message to the screen (if the logs are visible)."""
-    # no way to do this from amend; substitute a script comment instead
-    self.Comment(message)
-
-  def FormatPartition(self, partition):
-    """Format the given MTD partition."""
-    self.script.append("format %s" % (self._PartitionRoot(partition),))
-
-  def DeleteFiles(self, file_list):
-    """Delete all files in file_list."""
-    line = []
-    t = 0
-    for i in file_list:
-      i = self._FileRoot(i)
-      line.append(i)
-      t += len(i) + 1
-      if t > 80:
-        self.script.append("delete " + " ".join(line))
-        line = []
-        t = 0
-    if line:
-      self.script.append("delete " + " ".join(line))
-
-  def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
-    """Apply binary patches (in *patchpairs) to the given srcfile to
-    produce tgtfile (which may be "-" to indicate overwriting the
-    source file."""
-    if len(patchpairs) % 2 != 0:
-      raise ValueError("bad patches given to ApplyPatch")
-    self.script.append(
-        ("run_program PACKAGE:applypatch %s %s %s %d " %
-         (srcfile, tgtfile, tgtsha1, tgtsize)) +
-        " ".join(["%s:%s" % patchpairs[i:i+2]
-                  for i in range(0, len(patchpairs), 2)]))
-    self.included_files.add(("applypatch_static", "applypatch"))
-
-  def WriteFirmwareImage(self, kind, fn):
-    """Arrange to update the given firmware image (kind must be
-    "hboot" or "radio") when recovery finishes."""
-    self.script.append("write_%s_image PACKAGE:%s" % (kind, fn))
-
-  def WriteRawImage(self, partition, fn):
-    """Write the given file into the given MTD partition."""
-    self.script.append("write_raw_image PACKAGE:%s %s" %
-                       (fn, self._PartitionRoot(partition)))
-
-  def SetPermissions(self, fn, uid, gid, mode):
-    """Set file ownership and permissions."""
-    fn = self._FileRoot(fn)
-    self.script.append("set_perm %d %d 0%o %s" % (uid, gid, mode, fn))
-
-  def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode):
-    """Recursively set path ownership and permissions."""
-    fn = self._FileRoot(fn)
-    self.script.append("set_perm_recursive %d %d 0%o 0%o %s" %
-                       (uid, gid, dmode, fmode, fn))
-
-  def MakeSymlinks(self, symlink_list):
-    """Create symlinks, given a list of (dest, link) pairs."""
-    self.DeleteFiles([i[1] for i in symlink_list])
-    self.script.extend(["symlink %s %s" % (i[0], self._FileRoot(i[1]))
-                        for i in sorted(symlink_list)])
-
-  def AppendExtra(self, extra):
-    """Append text verbatim to the output script."""
-    self.script.append(extra)
-
-  def UnmountAll(self):
-    pass
-
-  def AddToZip(self, input_zip, output_zip, input_path=None):
-    """Write the accumulated script to the output_zip file.  input_zip
-    is used as the source for any ancillary binaries needed by the
-    script.  If input_path is not None, it will be used as a local
-    path for binaries instead of input_zip."""
-    common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-script",
-                       "\n".join(self.script) + "\n")
-    for i in self.included_files:
-      if isinstance(i, tuple):
-        sourcefn, targetfn = i
-      else:
-        sourcefn = i
-        targetfn = i
-      try:
-        if input_path is None:
-          data = input_zip.read(os.path.join("OTA/bin", sourcefn))
-        else:
-          data = open(os.path.join(input_path, sourcefn)).read()
-        common.ZipWriteStr(output_zip, targetfn, data, perms=0755)
-      except (IOError, KeyError), e:
-        raise ExternalError("unable to include binary %s: %s" % (i, e))
diff --git a/tools/releasetools/both_generator.py b/tools/releasetools/both_generator.py
deleted file mode 100644
index 4ae8d50..0000000
--- a/tools/releasetools/both_generator.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import edify_generator
-import amend_generator
-
-class BothGenerator(object):
-  def __init__(self, version):
-    self.version = version
-    self.edify = edify_generator.EdifyGenerator(version)
-    self.amend = amend_generator.AmendGenerator()
-
-  def MakeTemporary(self):
-    x = BothGenerator(self.version)
-    x.edify = self.edify.MakeTemporary()
-    x.amend = self.amend.MakeTemporary()
-    return x
-
-  def AppendScript(self, other):
-    self.edify.AppendScript(other.edify)
-    self.amend.AppendScript(other.amend)
-
-  def _DoBoth(self, name, *args):
-    getattr(self.edify, name)(*args)
-    getattr(self.amend, name)(*args)
-
-  def AssertSomeFingerprint(self, *a): self._DoBoth("AssertSomeFingerprint", *a)
-  def AssertOlderBuild(self, *a): self._DoBoth("AssertOlderBuild", *a)
-  def AssertDevice(self, *a): self._DoBoth("AssertDevice", *a)
-  def AssertSomeBootloader(self, *a): self._DoBoth("AssertSomeBootloader", *a)
-  def ShowProgress(self, *a): self._DoBoth("ShowProgress", *a)
-  def PatchCheck(self, *a): self._DoBoth("PatchCheck", *a)
-  def FileCheck(self, filename, *sha1): self._DoBoth("FileCheck", *a)
-  def CacheFreeSpaceCheck(self, *a): self._DoBoth("CacheFreeSpaceCheck", *a)
-  def Mount(self, *a): self._DoBoth("Mount", *a)
-  def UnpackPackageDir(self, *a): self._DoBoth("UnpackPackageDir", *a)
-  def Comment(self, *a): self._DoBoth("Comment", *a)
-  def Print(self, *a): self._DoBoth("Print", *a)
-  def FormatPartition(self, *a): self._DoBoth("FormatPartition", *a)
-  def DeleteFiles(self, *a): self._DoBoth("DeleteFiles", *a)
-  def ApplyPatch(self, *a): self._DoBoth("ApplyPatch", *a)
-  def WriteFirmwareImage(self, *a): self._DoBoth("WriteFirmwareImage", *a)
-  def WriteRawImage(self, *a): self._DoBoth("WriteRawImage", *a)
-  def SetPermissions(self, *a): self._DoBoth("SetPermissions", *a)
-  def SetPermissionsRecursive(self, *a): self._DoBoth("SetPermissionsRecursive", *a)
-  def MakeSymlinks(self, *a): self._DoBoth("MakeSymlinks", *a)
-  def AppendExtra(self, *a): self._DoBoth("AppendExtra", *a)
-  def UnmountAll(self, *a): self._DoBoth("UnmountAll", *a)
-
-  def AddToZip(self, input_zip, output_zip, input_path=None):
-    self._DoBoth("AddToZip", input_zip, output_zip, input_path)
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index ab6678a..18ba842 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -53,9 +53,35 @@
   return subprocess.Popen(args, **kwargs)
 
 
-def LoadMaxSizes():
+def LoadInfoDict():
+  """Read and parse the META/misc_info.txt key/value pairs from the
+  input target files and return a dict."""
+
+  d = {}
+  try:
+    for line in open(os.path.join(OPTIONS.input_tmp, "META", "misc_info.txt")):
+      line = line.strip()
+      if not line or line.startswith("#"): continue
+      k, v = line.split("=", 1)
+      d[k] = v
+  except IOError, e:
+    if e.errno == errno.ENOENT:
+      # ok if misc_info.txt file doesn't exist
+      pass
+    else:
+      raise
+
+  if "fs_type" not in d: info["fs_type"] = "yaffs2"
+  if "partition_type" not in d: info["partition_type"] = "MTD"
+
+  return d
+
+
+def LoadMaxSizes(info):
   """Load the maximum allowable images sizes from the input
-  target_files size."""
+  target_files.  Uses the imagesizes.txt file if it's available
+  (pre-honeycomb target_files), or the more general info dict (which
+  must be passed in) if not."""
   OPTIONS.max_image_size = {}
   try:
     for line in open(os.path.join(OPTIONS.input_tmp, "META", "imagesizes.txt")):
@@ -66,7 +92,15 @@
       OPTIONS.max_image_size[image + ".img"] = size
   except IOError, e:
     if e.errno == errno.ENOENT:
-      pass
+      def copy(x, y):
+        if x+y in info: OPTIONS.max_image_size[x+".img"] = int(info[x+y])
+      copy("blocksize", "")
+      copy("boot", "_size")
+      copy("recovery", "_size")
+      copy("system", "_size")
+      copy("userdata", "_size")
+    else:
+      raise
 
 
 def BuildAndAddBootableImage(sourcedir, targetname, output_zip):
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 68b0850..328700f 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -21,16 +21,17 @@
   """Class to generate scripts in the 'edify' recovery script language
   used from donut onwards."""
 
-  def __init__(self, version):
+  def __init__(self, version, info):
     self.script = []
     self.mounts = set()
     self.version = version
+    self.info = info
 
   def MakeTemporary(self):
     """Make a temporary script object whose commands can latter be
     appended to the parent script with AppendScript().  Used when the
     caller wants to generate script commands out-of-order."""
-    x = EdifyGenerator(self.version)
+    x = EdifyGenerator(self.version, self.info)
     x.mounts = self.mounts
     return x
 
@@ -130,12 +131,15 @@
     available on /cache."""
     self.script.append("assert(apply_patch_space(%d));" % (amount,))
 
-  def Mount(self, kind, what, path):
+  def Mount(self, what, mount_point):
     """Mount the given 'what' at the given path.  'what' should be a
-    partition name if kind is "MTD", or a block device if kind is
-    "vfat".  No other values of 'kind' are supported."""
-    self.script.append('mount("%s", "%s", "%s");' % (kind, what, path))
-    self.mounts.add(path)
+    partition name for an MTD partition, or a block device for
+    anything else."""
+    what = self.info.get("partition_path", "") + what
+    self.script.append('mount("%s", "%s", "%s", "%s");' %
+                       (self.info["fs_type"], self.info["partition_type"],
+                        what, mount_point))
+    self.mounts.add(mount_point)
 
   def UnpackPackageDir(self, src, dst):
     """Unpack a given directory from the OTA package into the given
@@ -154,8 +158,11 @@
     self.script.append('ui_print("%s");' % (message,))
 
   def FormatPartition(self, partition):
-    """Format the given MTD partition."""
-    self.script.append('format("MTD", "%s");' % (partition,))
+    """Format the given partition."""
+    partition = self.info.get("partition_path", "") + partition
+    self.script.append('format("%s", "%s", "%s");' %
+                       (self.info["fs_type"], self.info["partition_type"],
+                        partition))
 
   def DeleteFiles(self, file_list):
     """Delete all files in file_list."""
@@ -190,12 +197,23 @@
           'write_firmware_image("PACKAGE:%s", "%s");' % (fn, kind))
 
   def WriteRawImage(self, partition, fn):
-    """Write the given package file into the given MTD partition."""
-    self.script.append(
-        ('assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n'
-         '       write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n'
-         '       delete("/tmp/%(partition)s.img"));')
-        % {'partition': partition, 'fn': fn})
+    """Write the given package file into the given partition."""
+
+    if self.info["partition_type"] == "MTD":
+      self.script.append(
+          ('assert(package_extract_file("%(fn)s", "/tmp/%(partition)s.img"),\n'
+           '       write_raw_image("/tmp/%(partition)s.img", "%(partition)s"),\n'
+           '       delete("/tmp/%(partition)s.img"));')
+          % {'partition': partition, 'fn': fn})
+    elif self.info["partition_type"] == "EMMC":
+      self.script.append(
+          ('package_extract_file("%(fn)s", "%(dir)s%(partition)s");')
+          % {'partition': partition, 'fn': fn,
+             'dir': self.info.get("partition_path", ""),
+             })
+    else:
+      raise ValueError("don't know how to write \"%s\" partitions" %
+                       (self.info["partition_type"],))
 
   def SetPermissions(self, fn, uid, gid, mode):
     """Set file ownership and permissions."""
@@ -217,6 +235,20 @@
              ",\0".join(['"' + i + '"' for i in sorted(links)]) + ");")
       self.script.append(self._WordWrap(cmd))
 
+  def RetouchBinaries(self, file_list):
+    """Execute the retouch instructions in files listed."""
+    cmd = ('retouch_binaries(' +
+           ', '.join(['"' + i[0] + '", "' + i[1] + '"' for i in file_list]) +
+           ');')
+    self.script.append(self._WordWrap(cmd))
+
+  def UndoRetouchBinaries(self, file_list):
+    """Undo the retouching (retouch to zero offset)."""
+    cmd = ('undo_retouch_binaries(' +
+           ', '.join(['"' + i[0] + '", "' + i[1] + '"' for i in file_list]) +
+           ');')
+    self.script.append(self._WordWrap(cmd))
+
   def AppendExtra(self, extra):
     """Append text verbatim to the output script."""
     self.script.append(extra)
diff --git a/tools/releasetools/img_from_target_files b/tools/releasetools/img_from_target_files
index d157dca..d180998 100755
--- a/tools/releasetools/img_from_target_files
+++ b/tools/releasetools/img_from_target_files
@@ -23,6 +23,11 @@
   -b  (--board_config)  <file>
       Deprecated.
 
+  -f  (--fs_type) <value>
+      The file system type of the user image files to be created.
+      It can be ext fs variants, such as ext2, ext3, ext4, etc.
+      Default is yaffs.
+
 """
 
 import sys
@@ -47,6 +52,10 @@
 
 OPTIONS = common.OPTIONS
 
+class UserImageOptions(object): pass
+USERIMAGE_OPTIONS = UserImageOptions()
+USERIMAGE_OPTIONS.fs_type = None
+
 
 def AddUserdata(output_zip):
   """Create an empty userdata image and store it in output_zip."""
@@ -61,11 +70,22 @@
   os.mkdir(user_dir)
   img = tempfile.NamedTemporaryFile()
 
-  p = common.Run(["mkyaffs2image", "-f", user_dir, img.name])
-  p.communicate()
-  assert p.returncode == 0, "mkyaffs2image of userdata.img image failed"
+  build_command = []
+  if USERIMAGE_OPTIONS.fs_type is not None and USERIMAGE_OPTIONS.fs_type.startswith("ext"):
+    build_command = ["mkuserimg.sh",
+                     user_dir, img.name, USERIMAGE_OPTIONS.fs_type, "userdata"]
+    if "userdata.img" in OPTIONS.max_image_size:
+      build_command.append(str(OPTIONS.max_image_size["userdata.img"]))
+  else:
+    build_command = ["mkyaffs2image", "-f",
+                     user_dir, img.name]
 
-  common.CheckSize(img.name, "userdata.img")
+  p = common.Run(build_command);
+  p.communicate()
+  assert p.returncode == 0, "build userdata.img image failed"
+
+  if USERIMAGE_OPTIONS.fs_type is None or not USERIMAGE_OPTIONS.fs_type.startswith("ext"):
+    common.CheckSize(img.name, "userdata.img")
   output_zip.write(img.name, "userdata.img")
   img.close()
   os.rmdir(user_dir)
@@ -94,16 +114,27 @@
     if (e.errno == errno.EEXIST):
       pass
 
-  p = common.Run(["mkyaffs2image", "-f",
-                  os.path.join(OPTIONS.input_tmp, "system"), img.name])
+  build_command = []
+  if USERIMAGE_OPTIONS.fs_type is not None and USERIMAGE_OPTIONS.fs_type.startswith("ext"):
+    build_command = ["mkuserimg.sh",
+                     os.path.join(OPTIONS.input_tmp, "system"), img.name,
+                     USERIMAGE_OPTIONS.fs_type, "system"]
+    if "system.img" in OPTIONS.max_image_size:
+      build_command.append(str(OPTIONS.max_image_size["system.img"]))
+  else:
+    build_command = ["mkyaffs2image", "-f",
+                     os.path.join(OPTIONS.input_tmp, "system"), img.name]
+
+  p = common.Run(build_command)
   p.communicate()
-  assert p.returncode == 0, "mkyaffs2image of system.img image failed"
+  assert p.returncode == 0, "build system.img image failed"
 
   img.seek(os.SEEK_SET, 0)
   data = img.read()
   img.close()
 
-  common.CheckSize(data, "system.img")
+  if USERIMAGE_OPTIONS.fs_type is None or not USERIMAGE_OPTIONS.fs_type.startswith("ext"):
+    common.CheckSize(data, "system.img")
   common.ZipWriteStr(output_zip, "system.img", data)
 
 
@@ -118,13 +149,15 @@
   def option_handler(o, a):
     if o in ("-b", "--board_config"):
       pass       # deprecated
+    elif o in ("-f", "--fs_type"):
+      USERIMAGE_OPTIONS.fs_type = a
     else:
       return False
     return True
 
   args = common.ParseOptions(argv, __doc__,
-                             extra_opts="b:",
-                             extra_long_opts=["board_config="],
+                             extra_opts="b:f:",
+                             extra_long_opts=["board_config=", "fs_type="],
                              extra_option_handler=option_handler)
 
   if len(args) != 2:
@@ -133,7 +166,8 @@
 
   OPTIONS.input_tmp = common.UnzipTemp(args[0])
 
-  common.LoadMaxSizes()
+  info = common.LoadInfoDict()
+  common.LoadMaxSizes(info)
   if not OPTIONS.max_image_size:
     print
     print "  WARNING:  Failed to load max image sizes; will not enforce"
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
index 932d5b0..d249214 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -44,10 +44,8 @@
   -e  (--extra_script)  <file>
       Insert the contents of file at the end of the update script.
 
-  -m  (--script_mode)  <mode>
-      Specify 'amend' or 'edify' scripts, or 'auto' to pick
-      automatically (this is the default).
-
+  -a  (--use_aslr)
+      Specify whether to build the package with ASLR enabled (off by default).
 """
 
 import sys
@@ -68,9 +66,7 @@
 import zipfile
 
 import common
-import amend_generator
 import edify_generator
-import both_generator
 
 OPTIONS = common.OPTIONS
 OPTIONS.package_key = "build/target/product/security/testkey"
@@ -81,7 +77,7 @@
 OPTIONS.wipe_user_data = False
 OPTIONS.omit_prereq = False
 OPTIONS.extra_script = None
-OPTIONS.script_mode = 'auto'
+OPTIONS.aslr_mode = False
 OPTIONS.worker_threads = 3
 
 def MostPopularKey(d, default):
@@ -98,6 +94,10 @@
   symlink."""
   return (info.external_attr >> 16) == 0120777
 
+def IsRegular(info):
+  """Return true if the zipfile.ZipInfo object passed in represents a
+  symlink."""
+  return (info.external_attr >> 28) == 010
 
 
 class Item:
@@ -253,13 +253,15 @@
                     substitute=None):
   """Copies files underneath system/ in the input zip to the output
   zip.  Populates the Item class with their metadata, and returns a
-  list of symlinks.  output_zip may be None, in which case the copy is
-  skipped (but the other side effects still happen).  substitute is an
-  optional dict of {output filename: contents} to be output instead of
-  certain input files.
+  list of symlinks as well as a list of files that will be retouched.
+  output_zip may be None, in which case the copy is skipped (but the
+  other side effects still happen).  substitute is an optional dict
+  of {output filename: contents} to be output instead of certain input
+  files.
   """
 
   symlinks = []
+  retouch_files = []
 
   for info in input_zip.infolist():
     if info.filename.startswith("SYSTEM/"):
@@ -277,6 +279,9 @@
             data = substitute[fn]
           else:
             data = input_zip.read(info.filename)
+          if info.filename.startswith("SYSTEM/lib/") and IsRegular(info):
+            retouch_files.append(("/system/" + basefilename,
+                                  sha.sha(data).hexdigest()))
           output_zip.writestr(info2, data)
         if fn.endswith("/"):
           Item.Get(fn[:-1], dir=True)
@@ -284,7 +289,7 @@
           Item.Get(fn, dir=False)
 
   symlinks.sort()
-  return symlinks
+  return (symlinks, retouch_files)
 
 
 def SignOutput(temp_zip_name, output_zip_name):
@@ -300,7 +305,7 @@
   script.AssertDevice(device)
 
 
-def MakeRecoveryPatch(output_zip, recovery_img, boot_img):
+def MakeRecoveryPatch(output_zip, recovery_img, boot_img, info):
   """Generate a binary patch that creates the recovery image starting
   with the boot image.  (Most of the space in these images is just the
   kernel, which is identical for the two, so the resulting patch
@@ -309,7 +314,8 @@
   patching and install the new recovery image.
 
   recovery_img and boot_img should be File objects for the
-  corresponding images.
+  corresponding images.  info should be the dictionary returned by
+  common.LoadInfoDict() on the input target_files.
 
   Returns an Item for the shell script, which must be made
   executable.
@@ -326,9 +332,9 @@
   HEADER_SIZE = 2048
   header_sha1 = sha.sha(recovery_img.data[:HEADER_SIZE]).hexdigest()
   sh = """#!/system/bin/sh
-if ! applypatch -c MTD:recovery:%(header_size)d:%(header_sha1)s; then
+if ! applypatch -c %(partition_type)s:%(partition_path)srecovery:%(header_size)d:%(header_sha1)s; then
   log -t recovery "Installing new recovery image"
-  applypatch MTD:boot:%(boot_size)d:%(boot_sha1)s MTD:recovery %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p
+  applypatch %(partition_type)s:%(partition_path)sboot:%(boot_size)d:%(boot_sha1)s %(partition_type)s:%(partition_path)srecovery %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p
 else
   log -t recovery "Recovery image already installed"
 fi
@@ -337,21 +343,19 @@
         'header_size': HEADER_SIZE,
         'header_sha1': header_sha1,
         'recovery_size': recovery_img.size,
-        'recovery_sha1': recovery_img.sha1 }
+        'recovery_sha1': recovery_img.sha1,
+        'partition_type': info["partition_type"],
+        'partition_path': info.get("partition_path", ""),
+        }
   common.ZipWriteStr(output_zip, "recovery/etc/install-recovery.sh", sh)
   return Item.Get("system/etc/install-recovery.sh", dir=False)
 
 
-def WriteFullOTAPackage(input_zip, output_zip):
-  if OPTIONS.script_mode == "auto":
-    script = both_generator.BothGenerator(2)
-  elif OPTIONS.script_mode == "amend":
-    script = amend_generator.AmendGenerator()
-  else:
-    # TODO: how to determine this?  We don't know what version it will
-    # be installed on top of.  For now, we expect the API just won't
-    # change very often.
-    script = edify_generator.EdifyGenerator(2)
+def WriteFullOTAPackage(input_zip, output_zip, info):
+  # TODO: how to determine this?  We don't know what version it will
+  # be installed on top of.  For now, we expect the API just won't
+  # change very often.
+  script = edify_generator.EdifyGenerator(3, info)
 
   metadata = {"post-build": GetBuildProp("ro.build.fingerprint", input_zip),
               "pre-device": GetBuildProp("ro.product.device", input_zip),
@@ -379,18 +383,22 @@
     script.FormatPartition("userdata")
 
   script.FormatPartition("system")
-  script.Mount("MTD", "system", "/system")
+  script.Mount("system", "/system")
   script.UnpackPackageDir("recovery", "/system")
   script.UnpackPackageDir("system", "/system")
 
-  symlinks = CopySystemFiles(input_zip, output_zip)
+  (symlinks, retouch_files) = CopySystemFiles(input_zip, output_zip)
   script.MakeSymlinks(symlinks)
+  if OPTIONS.aslr_mode:
+    script.RetouchBinaries(retouch_files)
+  else:
+    script.UndoRetouchBinaries(retouch_files)
 
   boot_img = File("boot.img", common.BuildBootableImage(
       os.path.join(OPTIONS.input_tmp, "BOOT")))
   recovery_img = File("recovery.img", common.BuildBootableImage(
       os.path.join(OPTIONS.input_tmp, "RECOVERY")))
-  MakeRecoveryPatch(output_zip, recovery_img, boot_img)
+  MakeRecoveryPatch(output_zip, recovery_img, boot_img, info)
 
   Item.GetMetadata(input_zip)
   Item.Get("system").SetPermissions(script)
@@ -440,12 +448,17 @@
   """Load all the files from SYSTEM/... in a given target-files
   ZipFile, and return a dict of {filename: File object}."""
   out = {}
+  retouch_files = []
   for info in z.infolist():
     if info.filename.startswith("SYSTEM/") and not IsSymlink(info):
-      fn = "system/" + info.filename[7:]
+      basefilename = info.filename[7:]
+      fn = "system/" + basefilename
       data = z.read(info.filename)
       out[fn] = File(fn, data)
-  return out
+      if info.filename.startswith("SYSTEM/lib/") and IsRegular(info):
+        retouch_files.append(("/system/" + basefilename,
+                              out[fn].sha1))
+  return (out, retouch_files)
 
 
 DIFF_PROGRAM_BY_EXT = {
@@ -583,24 +596,16 @@
       return 0
 
 
-def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
+def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip, info):
   source_version = GetRecoveryAPIVersion(source_zip)
   target_version = GetRecoveryAPIVersion(target_zip)
+  partition_type = info["partition_type"]
+  partition_path = info.get("partition_path", "")
 
-  if OPTIONS.script_mode == 'amend':
-    script = amend_generator.AmendGenerator()
-  elif OPTIONS.script_mode == 'edify':
-    if source_version == 0:
-      print ("WARNING: generating edify script for a source that "
-             "can't install it.")
-    script = edify_generator.EdifyGenerator(source_version)
-  elif OPTIONS.script_mode == 'auto':
-    if source_version > 0:
-      script = edify_generator.EdifyGenerator(source_version)
-    else:
-      script = amend_generator.AmendGenerator()
-  else:
-    raise ValueError('unknown script mode "%s"' % (OPTIONS.script_mode,))
+  if source_version == 0:
+    print ("WARNING: generating edify script for a source that "
+           "can't install it.")
+  script = edify_generator.EdifyGenerator(source_version, info)
 
   metadata = {"pre-device": GetBuildProp("ro.product.device", source_zip),
               "post-timestamp": GetBuildProp("ro.build.date.utc", target_zip),
@@ -616,9 +621,9 @@
       metadata=metadata)
 
   print "Loading target..."
-  target_data = LoadSystemFiles(target_zip)
+  (target_data, target_retouch_files) = LoadSystemFiles(target_zip)
   print "Loading source..."
-  source_data = LoadSystemFiles(source_zip)
+  (source_data, source_retouch_files) = LoadSystemFiles(source_zip)
 
   verbatim_targets = []
   patch_list = []
@@ -661,7 +666,7 @@
   metadata["pre-build"] = source_fp
   metadata["post-build"] = target_fp
 
-  script.Mount("MTD", "system", "/system")
+  script.Mount("system", "/system")
   script.AssertSomeFingerprint(source_fp, target_fp)
 
   source_boot = File("/tmp/boot.img",
@@ -710,8 +715,9 @@
 
     common.ZipWriteStr(output_zip, "patch/boot.img.p", d)
 
-    script.PatchCheck("MTD:boot:%d:%s:%d:%s" %
-                      (source_boot.size, source_boot.sha1,
+    script.PatchCheck("%s:%sboot:%d:%s:%d:%s" %
+                      (partition_type, partition_path,
+                       source_boot.size, source_boot.sha1,
                        target_boot.size, target_boot.sha1))
     so_far += source_boot.size
     script.SetProgress(so_far / total_verify_size)
@@ -750,8 +756,9 @@
     # contents of the boot partition, and write it back to the
     # partition.
     script.Print("Patching boot image...")
-    script.ApplyPatch("MTD:boot:%d:%s:%d:%s"
-                      % (source_boot.size, source_boot.sha1,
+    script.ApplyPatch("%s:%sboot:%d:%s:%d:%s"
+                      % (partition_type, partition_path,
+                         source_boot.size, source_boot.sha1,
                          target_boot.size, target_boot.sha1),
                       "-",
                       target_boot.size, target_boot.sha1,
@@ -774,7 +781,7 @@
     # partition, include the binaries and image files from recovery in
     # the boot image (though not in the ramdisk) so they can be used
     # as fodder for constructing the recovery image.
-    MakeRecoveryPatch(output_zip, target_recovery, target_boot)
+    MakeRecoveryPatch(output_zip, target_recovery, target_boot, info)
     script.DeleteFiles(["/system/recovery-from-boot.p",
                         "/system/etc/install-recovery.sh"])
     print "recovery image changed; including as patch from boot."
@@ -783,7 +790,7 @@
 
   script.ShowProgress(0.1, 10)
 
-  target_symlinks = CopySystemFiles(target_zip, None)
+  (target_symlinks, target_retouch_dummies) = CopySystemFiles(target_zip, None)
 
   target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks])
   temp_script = script.MakeTemporary()
@@ -792,7 +799,7 @@
 
   # Note that this call will mess up the tree of Items, so make sure
   # we're done with it.
-  source_symlinks = CopySystemFiles(source_zip, None)
+  (source_symlinks, source_retouch_dummies) = CopySystemFiles(source_zip, None)
   source_symlinks_d = dict([(i[1], i[0]) for i in source_symlinks])
 
   # Delete all the symlinks in source that aren't in target.  This
@@ -826,6 +833,10 @@
       to_create.append((dest, link))
   script.DeleteFiles([i[1] for i in to_create])
   script.MakeSymlinks(to_create)
+  if OPTIONS.aslr_mode:
+    script.RetouchBinaries(target_retouch_files)
+  else:
+    script.UndoRetouchBinaries(target_retouch_files)
 
   # Now that the symlinks are created, we can set all the
   # permissions.
@@ -835,7 +846,7 @@
   device_specific.IncrementalOTA_InstallEnd()
 
   if OPTIONS.extra_script is not None:
-    scirpt.AppendExtra(OPTIONS.extra_script)
+    script.AppendExtra(OPTIONS.extra_script)
 
   script.AddToZip(target_zip, output_zip)
   WriteMetadata(metadata, output_zip)
@@ -856,8 +867,8 @@
       OPTIONS.omit_prereq = True
     elif o in ("-e", "--extra_script"):
       OPTIONS.extra_script = a
-    elif o in ("-m", "--script_mode"):
-      OPTIONS.script_mode = a
+    elif o in ("-a", "--use_aslr"):
+      OPTIONS.aslr_mode = True
     elif o in ("--worker_threads"):
       OPTIONS.worker_threads = int(a)
     else:
@@ -865,24 +876,21 @@
     return True
 
   args = common.ParseOptions(argv, __doc__,
-                             extra_opts="b:k:i:d:wne:m:",
+                             extra_opts="b:k:i:d:wne:a",
                              extra_long_opts=["board_config=",
                                               "package_key=",
                                               "incremental_from=",
                                               "wipe_user_data",
                                               "no_prereq",
                                               "extra_script=",
-                                              "script_mode=",
-                                              "worker_threads="],
+                                              "worker_threads=",
+                                              "use_aslr"],
                              extra_option_handler=option_handler)
 
   if len(args) != 2:
     common.Usage(__doc__)
     sys.exit(1)
 
-  if OPTIONS.script_mode not in ("amend", "edify", "auto"):
-    raise ValueError('unknown script mode "%s"' % (OPTIONS.script_mode,))
-
   if OPTIONS.extra_script is not None:
     OPTIONS.extra_script = open(OPTIONS.extra_script).read()
 
@@ -906,7 +914,8 @@
       else:
         raise
 
-  common.LoadMaxSizes()
+  info = common.LoadInfoDict()
+  common.LoadMaxSizes(info)
   if not OPTIONS.max_image_size:
     print
     print "  WARNING:  Failed to load max image sizes; will not enforce"
@@ -924,12 +933,12 @@
                                  compression=zipfile.ZIP_DEFLATED)
 
   if OPTIONS.incremental_source is None:
-    WriteFullOTAPackage(input_zip, output_zip)
+    WriteFullOTAPackage(input_zip, output_zip, info)
   else:
     print "unzipping source target-files..."
     OPTIONS.source_tmp = common.UnzipTemp(OPTIONS.incremental_source)
     source_zip = zipfile.ZipFile(OPTIONS.incremental_source, "r")
-    WriteIncrementalOTAPackage(input_zip, source_zip, output_zip)
+    WriteIncrementalOTAPackage(input_zip, source_zip, output_zip, info)
 
   output_zip.close()
   if OPTIONS.package_key:
diff --git a/tools/soslim/main.c b/tools/soslim/main.c
index dd8a60b..e23fbce 100644
--- a/tools/soslim/main.c
+++ b/tools/soslim/main.c
@@ -188,9 +188,13 @@
             else INFO("Not building symbol filter, filter file is empty.\n");
         }
 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
-        int prelinked = 0;
+        int prelinked = 0, retouched = 0;
         int elf_little; /* valid if prelinked != 0 */
         long prelink_addr; /* valid if prelinked != 0 */
+#define RETOUCH_MAX_SIZE 500000
+        /* _cnt valid if retouched != 0 */
+        unsigned int retouch_byte_cnt = RETOUCH_MAX_SIZE;
+        char retouch_buf[RETOUCH_MAX_SIZE]; /* valid if retouched != 0 */
 #endif
         clone_elf(elf, newelf,
                   infile, outfile,
@@ -200,7 +204,10 @@
 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
                   , &prelinked,
                   &elf_little,
-                  &prelink_addr
+                  &prelink_addr,
+                  &retouched,
+                  &retouch_byte_cnt,
+                  retouch_buf
 #endif
                   ,
                   true, /* rebuild the section-header-strings table */
@@ -223,6 +230,13 @@
                infile, strerror(errno), errno);
 
 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
+        if (retouched) {
+            INFO("File has retouch data, putting it back in place.\n");
+            retouch_dump(outfile != NULL ? outfile : infile,
+                         elf_little,
+                         retouch_byte_cnt,
+                         retouch_buf);
+        }
         if (prelinked) {
             INFO("File is prelinked, putting prelink TAG back in place.\n");
             setup_prelink_info(outfile != NULL ? outfile : infile,
diff --git a/tools/soslim/prelink_info.c b/tools/soslim/prelink_info.c
index 81d5de3..2600ac7 100644
--- a/tools/soslim/prelink_info.c
+++ b/tools/soslim/prelink_info.c
@@ -11,6 +11,7 @@
 #include <debug.h>
 #include <common.h>
 
+#define RETOUCH_SUFFIX_SIZE 12
 typedef struct {
 	uint32_t mmap_addr;
 	char tag[4]; /* 'P', 'R', 'E', ' ' */
@@ -28,7 +29,7 @@
 		}
 		else {
 			/* Different endianness */
-			*prelink_addr = switch_endianness(info->mmap_addr);
+                        *prelink_addr = switch_endianness(info->mmap_addr);
 		}
 	}
 }
@@ -67,10 +68,104 @@
 		set_prelink(prelink_addr, elf_little, &info);
 		prelinked = 1;
 	}
-	FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
+	FAILIF(close(fd) < 0,
+               "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
 	return prelinked;
 }
 
+int check_retouched(const char *fname, int elf_little,
+                    unsigned int *retouch_byte_cnt, char *retouch_buf) {
+    FAILIF(sizeof(prelink_info_t) != 8,
+           "Unexpected sizeof(prelink_info_t) == %d!\n",
+           sizeof(prelink_info_t));
+    int fd = open(fname, O_RDONLY);
+    FAILIF(fd < 0, "open(%s, O_RDONLY): %s (%d)!\n",
+           fname, strerror(errno), errno);
+    off_t end = lseek(fd, 0, SEEK_END);
+    int nr = sizeof(prelink_info_t);
+    off_t sz = lseek(fd, -nr-RETOUCH_SUFFIX_SIZE, SEEK_CUR);
+    ASSERT((long)(end - sz) == (long)(nr+RETOUCH_SUFFIX_SIZE));
+    FAILIF(sz == (off_t)-1,
+           "lseek(%d, 0, SEEK_END): %s (%d)!\n",
+           fd, strerror(errno), errno);
+
+    char retouch_meta[RETOUCH_SUFFIX_SIZE];
+    int num_read = read(fd, &retouch_meta, RETOUCH_SUFFIX_SIZE);
+    FAILIF(num_read < 0,
+           "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
+           fd, strerror(errno), errno);
+    FAILIF(num_read != RETOUCH_SUFFIX_SIZE,
+           "read(%d, &info, sizeof(prelink_info_t)): did not read %d bytes as "
+           "expected (read %d)!\n",
+           fd, RETOUCH_SUFFIX_SIZE, num_read);
+
+    int retouched = 0;
+    if (!strncmp(retouch_meta, "RETOUCH ", 8)) {
+        unsigned int retouch_byte_cnt_meta;
+        if (!(elf_little ^ is_host_little()))
+            retouch_byte_cnt_meta = *(unsigned int *)(retouch_meta+8);
+        else
+            retouch_byte_cnt_meta =
+              switch_endianness(*(unsigned int *)(retouch_meta+8));
+        FAILIF(*retouch_byte_cnt < retouch_byte_cnt_meta,
+               "Retouch buffer too small at %d bytes (%d needed).",
+               *retouch_byte_cnt, retouch_byte_cnt_meta);
+        *retouch_byte_cnt = retouch_byte_cnt_meta;
+        off_t sz = lseek(fd,
+                         -((long)*retouch_byte_cnt)-RETOUCH_SUFFIX_SIZE-nr,
+                         SEEK_END);
+        ASSERT((long)(end - sz) ==
+               (long)(*retouch_byte_cnt+RETOUCH_SUFFIX_SIZE+nr));
+        FAILIF(sz == (off_t)-1,
+               "lseek(%d, 0, SEEK_END): %s (%d)!\n",
+               fd, strerror(errno), errno);
+        num_read = read(fd, retouch_buf, *retouch_byte_cnt);
+        FAILIF(num_read < 0,
+               "read(%d, &info, sizeof(prelink_info_t)): %s (%d)!\n",
+               fd, strerror(errno), errno);
+        FAILIF(num_read != *retouch_byte_cnt,
+               "read(%d, retouch_buf, %u): did not read %d bytes as "
+               "expected (read %d)!\n",
+               fd, *retouch_byte_cnt, *retouch_byte_cnt, num_read);
+
+        retouched = 1;
+    }
+    FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
+    return retouched;
+}
+
+void retouch_dump(const char *fname, int elf_little,
+                  unsigned int retouch_byte_cnt, char *retouch_buf) {
+    int fd = open(fname, O_WRONLY);
+    FAILIF(fd < 0,
+           "open(%s, O_WRONLY): %s (%d)\n",
+           fname, strerror(errno), errno);
+    off_t sz = lseek(fd, 0, SEEK_END);
+    FAILIF(sz == (off_t)-1,
+           "lseek(%d, 0, SEEK_END): %s (%d)!\n",
+           fd, strerror(errno), errno);
+
+    // The retouch blob ends with "RETOUCH XXXX", where XXXX is the 4-byte
+    // size of the retouch blob, in target endianness.
+    strncpy(retouch_buf+retouch_byte_cnt, "RETOUCH ", 8);
+    if (elf_little ^ is_host_little()) {
+        *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
+          switch_endianness(retouch_byte_cnt);
+    } else {
+        *(unsigned int *)(retouch_buf+retouch_byte_cnt+8) =
+          retouch_byte_cnt;
+    }
+
+    int num_written = write(fd, retouch_buf, retouch_byte_cnt+12);
+    FAILIF(num_written < 0,
+           "write(%d, &info, sizeof(info)): %s (%d)\n",
+           fd, strerror(errno), errno);
+    FAILIF((retouch_byte_cnt+12) != num_written,
+           "Could not write %d bytes as expected (wrote %d bytes instead)!\n",
+           retouch_byte_cnt, num_written);
+    FAILIF(close(fd) < 0, "close(%d): %s (%d)!\n", fd, strerror(errno), errno);
+}
+
 void setup_prelink_info(const char *fname, int elf_little, long base)
 {
     FAILIF(sizeof(prelink_info_t) != 8, "Unexpected sizeof(prelink_info_t) == %zd!\n", sizeof(prelink_info_t));
@@ -92,7 +187,7 @@
     else {
         /* Different endianness */
         INFO("Host and ELF file [%s] have different endianness.\n", fname);
-		info.mmap_addr = switch_endianness(base);
+        info.mmap_addr = switch_endianness(base);
     }
     strncpy(info.tag, "PRE ", 4);
 
diff --git a/tools/soslim/prelink_info.h b/tools/soslim/prelink_info.h
index e2787cb..efa84fd 100644
--- a/tools/soslim/prelink_info.h
+++ b/tools/soslim/prelink_info.h
@@ -3,6 +3,10 @@
 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
 
 int check_prelinked(const char *fname, int elf_little, long *prelink_addr);
+int check_retouched(const char *fname, int elf_little,
+                    unsigned int *retouch_byte_cnt, char *retouch_buf);
+void retouch_dump(const char *fname, int elf_little,
+                  unsigned int retouch_byte_cnt, char *retouch_buf);
 void setup_prelink_info(const char *fname, int elf_little, long base);
 
 #endif
diff --git a/tools/soslim/soslim.c b/tools/soslim/soslim.c
index 125e29e..33b1ee7 100644
--- a/tools/soslim/soslim.c
+++ b/tools/soslim/soslim.c
@@ -27,7 +27,10 @@
 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
                , int *prelinked,
                int *elf_little,
-               long *prelink_addr
+               long *prelink_addr,
+               int *retouched,
+               unsigned int *retouch_byte_cnt,
+               char *retouch_buf
 #endif
                , bool rebuild_shstrtab,
                bool strip_debug,
@@ -70,6 +73,11 @@
     ASSERT(elf_little);
     *elf_little = (ehdr->e_ident[EI_DATA] == ELFDATA2LSB);
     *prelinked = check_prelinked(elf_name, *elf_little, prelink_addr);
+    ASSERT(retouched);
+    ASSERT(retouch_byte_cnt);
+    ASSERT(retouch_buf);
+    *retouched = check_retouched(elf_name, *elf_little,
+                                 retouch_byte_cnt, retouch_buf);
 #endif
 
     INFO("\n\nCALCULATING MODIFICATIONS\n\n");
diff --git a/tools/soslim/soslim.h b/tools/soslim/soslim.h
index dfcb085..952c960 100644
--- a/tools/soslim/soslim.h
+++ b/tools/soslim/soslim.h
@@ -23,7 +23,10 @@
 #ifdef SUPPORT_ANDROID_PRELINK_TAGS
 			   , int *prelinked,
 			   int *elf_little,
-			   long *prelink_addr
+			   long *prelink_addr,
+                           int *retouched,
+                           unsigned int *retouch_byte_cnt,
+                           char *retouch_buf
 #endif
                , bool rebuild_shstrtab,
                bool strip_debug,