am 33c11ac3: am e1f37ba0: am 55edb20e: Merge "Dist apkcerts.txt for unbundled builds" into froyo

Merge commit '33c11ac3f150a388ebf2df80a42b577c136282de'

* commit '33c11ac3f150a388ebf2df80a42b577c136282de':
  Dist apkcerts.txt for unbundled builds
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b84e1b65..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..897cc40 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,37 @@
 # 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) $(MKEXT2IMG) $(TUNE2FS) $(E2FSCK)
+INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS)))
+
+# $(1): src directory
+# $(2): output file
+# $(3): label (if any)
+# $(4): ext variant (ext2, ext3, ext4)
+define build-userimage-ext-target
+  @mkdir -p $(dir $(2))
+  $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$(PATH) \
+	  $(MKEXT2USERIMG) $(1) $(2) $(4) $(3)
+endef
+else
+INTERNAL_USERIMAGES_DEPS := $(MKYAFFS2)
 endif
 
 # -----------------------------------------------------------------
@@ -620,6 +655,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 +700,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))
 endef
 
-else # TARGET_USERIMAGES_USE_EXT2 != true
+else # INTERNAL_USERIMAGES_USE_EXT != true
 
 ## generate a yaffs2 image
 # $(1): output file
@@ -681,9 +717,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 +767,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 +833,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))
     $(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 +851,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 +905,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 +1027,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 +1078,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 +1105,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 +1231,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..98bb00d 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -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
@@ -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/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..a2173dd 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,15 @@
 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)
+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 +266,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..1feb5ec 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,29 @@
 rm -f $(@:$1=$(YACC_HEADER_SUFFIX))
 endef
 
+###########################################################
+## Commands to compile RenderScript
+###########################################################
+# $(1) the .rs file
+define _compile-one-rs-file
+$(hide) $(SLANG) \
+  --allow-rs-prefix \
+  -o $(PRIVATE_RS_OUTPUT_DIR)/res/raw/$(patsubst %.rs,%.bc,$(notdir $(1))) \
+  -p $(PRIVATE_RS_OUTPUT_DIR)/src \
+  $(1)
+
+endef
+
+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
+$(foreach rs,$(PRIVATE_RS_SOURCE_FILES),$(call _compile-one-rs-file,$(rs)))
+$(hide) mkdir -p $(dir $@)
+$(hide) touch $@
+endef
+
 
 ###########################################################
 ## Commands for running aidl
@@ -947,6 +983,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 +1023,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 +1032,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 +1052,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 +1283,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 +1322,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 +1434,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 +1442,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 +1648,7 @@
 endef
 else
 define transform-host-ranlib-copy-hack
-true
+@true
 endef
 endif
 
@@ -1601,7 +1658,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/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 9f7715b..da53a5c 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -29,7 +29,7 @@
   endif
 else
   ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-    LOCAL_JAVA_LIBRARIES := core ext framework $(LOCAL_JAVA_LIBRARIES)
+    LOCAL_JAVA_LIBRARIES := core core-junit ext framework $(LOCAL_JAVA_LIBRARIES)
   endif
 endif
 LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES))
@@ -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 70441b7..b97e622 100644
--- a/core/pathmap.mk
+++ b/core/pathmap.mk
@@ -88,6 +88,7 @@
 	    wifi \
 	    vpn \
 	    keystore \
+	    icu4j \
 	 )
 
 #
diff --git a/core/prelink-linux-arm.map b/core/prelink-linux-arm.map
index 7daaf98..0090441 100644
--- a/core/prelink-linux-arm.map
+++ b/core/prelink-linux-arm.map
@@ -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 c6aecb4..9834404 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -29,32 +29,19 @@
 junit_host_jar := $(HOST_OUT_JAVA_LIBRARIES)/junit.jar
 HOSTTESTLIB_JAR := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar
 
-CTS_CORE_CASE_LIST := android.core.tests.annotation \
-	android.core.tests.archive \
-	android.core.tests.concurrent \
-	android.core.tests.crypto \
+CTS_CORE_CASE_LIST := \
 	android.core.tests.dom \
-	android.core.tests.logging \
 	android.core.tests.luni.io \
 	android.core.tests.luni.lang \
 	android.core.tests.luni.net \
 	android.core.tests.luni.util \
-	android.core.tests.math \
-	android.core.tests.nio \
-	android.core.tests.nio_char \
-	android.core.tests.prefs \
-	android.core.tests.regex \
-	android.core.tests.security \
-	android.core.tests.sql \
-	android.core.tests.text \
 	android.core.tests.xml \
-	android.core.tests.xnet \
 	android.core.tests.runner
 
 -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)
 
@@ -98,8 +85,13 @@
 endef
 
 CORE_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core,,COMMON)
+JUNIT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-junit,,COMMON)
+RUNNER_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-junitrunner,,COMMON)
+SUPPORT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests-support,,COMMON)
+DOM_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests-dom,,COMMON)
+XML_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests-xml,,COMMON)
 TESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)
-GEN_CLASSPATH := $(CORE_INTERMEDIATES)/classes.jar:$(TESTS_INTERMEDIATES)/classes.jar:$(CORE_INTERMEDIATES)/javalib.jar:$(TESTS_INTERMEDIATES)/javalib.jar:$(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_JDK_TOOLS_JAR)
+GEN_CLASSPATH := $(CORE_INTERMEDIATES)/classes.jar:$(JUNIT_INTERMEDIATES)/classes.jar:$(RUNNER_INTERMEDIATES)/classes.jar:$(SUPPORT_INTERMEDIATES)/classes.jar:$(DOM_INTERMEDIATES)/classes.jar:$(XML_INTERMEDIATES)/classes.jar:$(TESTS_INTERMEDIATES)/classes.jar:$(CORE_INTERMEDIATES)/javalib.jar:$(JUNIT_INTERMEDIATES)/javalib.jar:$(RUNNER_INTERMEDIATES)/javalib.jar:$(SUPPORT_INTERMEDIATES)/javalib.jar:$(DOM_INTERMEDIATES)/javalib.jar:$(XML_INTERMEDIATES)/javalib.jar:$(TESTS_INTERMEDIATES)/javalib.jar:$(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_JDK_TOOLS_JAR)
 
 $(cts_dir)/all_cts_core_files_stamp: PRIVATE_CLASSPATH:=$(GEN_CLASSPATH)
 $(cts_dir)/all_cts_core_files_stamp: PRIVATE_JAVAOPTS:=-Xmx256M
@@ -110,25 +102,10 @@
 # build system requires that dependencies use javalib.jar.  If
 # javalib.jar is up-to-date, then classes.jar is as well.  Depending
 # on classes.jar will build the files incorrectly.
-$(cts_dir)/all_cts_core_files_stamp: $(CTS_CORE_CASE_LIST) $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(CORE_INTERMEDIATES)/javalib.jar $(TESTS_INTERMEDIATES)/javalib.jar $(cts_dir)/all_cts_files_stamp | $(ACP)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.annotation,\
-		cts/tests/core/annotation/AndroidManifest.xml,\
-		tests.annotation.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.archive,\
-		cts/tests/core/archive/AndroidManifest.xml,\
-		tests.archive.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.concurrent,\
-		cts/tests/core/concurrent/AndroidManifest.xml,\
-		tests.concurrent.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.crypto,\
-		cts/tests/core/crypto/AndroidManifest.xml,\
-		tests.crypto.AllTests)
+$(cts_dir)/all_cts_core_files_stamp: $(CTS_CORE_CASE_LIST) $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(CORE_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(RUNNER_INTERMEDIATES)/javalib.jar $(SUPPORT_INTERMEDIATES)/javalib.jar $(DOM_INTERMEDIATES)/javalib.jar $(XML_INTERMEDIATES)/javalib.jar $(TESTS_INTERMEDIATES)/javalib.jar $(cts_dir)/all_cts_files_stamp | $(ACP)
 	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.dom,\
 		cts/tests/core/dom/AndroidManifest.xml,\
 		tests.dom.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.logging,\
-		cts/tests/core/logging/AndroidManifest.xml,\
-		tests.logging.AllTests)
 	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.luni.io,\
 		cts/tests/core/luni-io/AndroidManifest.xml,\
 		tests.luni.AllTestsIo)
@@ -141,36 +118,9 @@
 	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.luni.util,\
 		cts/tests/core/luni-util/AndroidManifest.xml,\
 		tests.luni.AllTestsUtil)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.math,\
-		cts/tests/core/math/AndroidManifest.xml,\
-		tests.math.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.nio,\
-		cts/tests/core/nio/AndroidManifest.xml,\
-		tests.nio.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.nio_char,\
-		cts/tests/core/nio_char/AndroidManifest.xml,\
-		tests.nio_char.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.prefs,\
-		cts/tests/core/prefs/AndroidManifest.xml,\
-		tests.prefs.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.regex,\
-		cts/tests/core/regex/AndroidManifest.xml,\
-		tests.regex.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.security,\
-		cts/tests/core/security/AndroidManifest.xml,\
-		tests.security.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.sql,\
-		cts/tests/core/sql/AndroidManifest.xml,\
-		tests.sql.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.text,\
-		cts/tests/core/text/AndroidManifest.xml,\
-		tests.text.AllTests)
 	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.xml,\
 		cts/tests/core/xml/AndroidManifest.xml,\
 		tests.xml.AllTests)
-	$(call generate-core-test-description,$(cts_dir)/$(cts_name)/repository/testcases/android.core.tests.xnet,\
-		cts/tests/core/xnet/AndroidManifest.xml,\
-		tests.xnet.AllTests)
 	$(hide) touch $@
 
 
@@ -180,17 +130,19 @@
 
 VMTESTS_INTERMEDIATES :=$(call intermediates-dir-for,EXECUTABLES,vm-tests,1,)
 # core tests only needed to get hold of junit-framework-classes
-TESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)
 CORE_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core,,COMMON)
+JUNIT_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-junit,,COMMON)
+RUNNER_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-junitrunner,,COMMON)
+TESTS_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)
 
-GEN_CLASSPATH := $(CORE_INTERMEDIATES)/classes.jar:$(TESTS_INTERMEDIATES)/classes.jar:$(VMTESTS_INTERMEDIATES)/android.core.vm-tests.jar:$(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_JDK_TOOLS_JAR)
+GEN_CLASSPATH := $(CORE_INTERMEDIATES)/classes.jar:$(JUNIT_INTERMEDIATES)/classes.jar:$(RUNNER_INTERMEDIATES)/classes.jar:$(TESTS_INTERMEDIATES)/classes.jar:$(VMTESTS_INTERMEDIATES)/android.core.vm-tests.jar:$(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_JDK_TOOLS_JAR)
 
 $(CORE_VM_TEST_DESC): PRIVATE_CLASSPATH:=$(GEN_CLASSPATH)
 $(CORE_VM_TEST_DESC): PRIVATE_PARAMS:=-Dcts.useSuppliedTestResult=true
 $(CORE_VM_TEST_DESC): PRIVATE_PARAMS+=-Dcts.useEnhancedJunit=true
 $(CORE_VM_TEST_DESC): PRIVATE_JAVAOPTS:=-Xmx256M
 # Please see big comment above on why this line depends on javalib.jar instead of classes.jar
-$(CORE_VM_TEST_DESC): vm-tests $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(CORE_INTERMEDIATES)/javalib.jar $(VMTESTS_INTERMEDIATES)/android.core.vm-tests.jar $(TESTS_INTERMEDIATES)/javalib.jar $(cts_dir)/all_cts_files_stamp | $(ACP)
+$(CORE_VM_TEST_DESC): vm-tests $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(CORE_INTERMEDIATES)/javalib.jar $(JUNIT_INTERMEDIATES)/javalib.jar $(RUNNER_INTERMEDIATES)/javalib.jar $(VMTESTS_INTERMEDIATES)/android.core.vm-tests.jar $(TESTS_INTERMEDIATES)/javalib.jar $(cts_dir)/all_cts_files_stamp | $(ACP)
 	$(call generate-core-test-description,$(CORE_VM_TEST_DESC),\
 		cts/tests/vm-tests/AndroidManifest.xml,\
 		dot.junit.AllJunitHostTests, cts/tools/vm-tests/Android.mk)
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..df7bfc1 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.
@@ -909,10 +909,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 +921,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 +933,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/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/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/src/Stubs.java b/tools/droiddoc/src/Stubs.java
index e1ec76a..b988ef5 100644
--- a/tools/droiddoc/src/Stubs.java
+++ b/tools/droiddoc/src/Stubs.java
@@ -315,6 +315,12 @@
             return;
         }
 
+        // Work around the bogus "Array" class we invent for
+        // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
+        if (cl.containingPackage() != null && cl.containingPackage().name().equals("")) {
+            return;
+        }
+
         String filename = stubsDir + '/' + javaFileName(cl);
         File file = new File(filename);
         ClearPage.ensureDirectory(file);
@@ -788,6 +794,11 @@
                                 HashSet notStrippable) {
         ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
         Arrays.sort(classes, ClassInfo.comparator);
+        // Work around the bogus "Array" class we invent for
+        // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
+        if (pack.name().equals("")) {
+            return;
+        }
         xmlWriter.println("<package name=\"" + pack.name() + "\"\n"
                 //+ " source=\"" + pack.position() + "\"\n"
                 + ">");
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..fc8a2be 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 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..390bd4b 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."""
diff --git a/tools/releasetools/img_from_target_files b/tools/releasetools/img_from_target_files
index d157dca..15a43cd 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,9 +70,17 @@
   os.mkdir(user_dir)
   img = tempfile.NamedTemporaryFile()
 
-  p = common.Run(["mkyaffs2image", "-f", user_dir, img.name])
+  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"]
+  else:
+    build_command = ["mkyaffs2image", "-f",
+                     user_dir, img.name]
+
+  p = common.Run(build_command);
   p.communicate()
-  assert p.returncode == 0, "mkyaffs2image of userdata.img image failed"
+  assert p.returncode == 0, "build userdata.img image failed"
 
   common.CheckSize(img.name, "userdata.img")
   output_zip.write(img.name, "userdata.img")
@@ -94,10 +111,18 @@
     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"]
+  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()
@@ -118,13 +143,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 +160,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..8cd1941 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -44,10 +44,6 @@
   -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).
-
 """
 
 import sys
@@ -68,9 +64,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 +75,6 @@
 OPTIONS.wipe_user_data = False
 OPTIONS.omit_prereq = False
 OPTIONS.extra_script = None
-OPTIONS.script_mode = 'auto'
 OPTIONS.worker_threads = 3
 
 def MostPopularKey(d, default):
@@ -300,7 +293,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 +302,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 +320,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 +331,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,7 +371,7 @@
     script.FormatPartition("userdata")
 
   script.FormatPartition("system")
-  script.Mount("MTD", "system", "/system")
+  script.Mount("system", "/system")
   script.UnpackPackageDir("recovery", "/system")
   script.UnpackPackageDir("system", "/system")
 
@@ -390,7 +382,7 @@
       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)
@@ -583,24 +575,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),
@@ -661,7 +645,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 +694,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 +735,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 +760,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."
@@ -835,7 +821,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 +842,6 @@
       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 ("--worker_threads"):
       OPTIONS.worker_threads = int(a)
     else:
@@ -865,14 +849,13 @@
     return True
 
   args = common.ParseOptions(argv, __doc__,
-                             extra_opts="b:k:i:d:wne:m:",
+                             extra_opts="b:k:i:d:wne:",
                              extra_long_opts=["board_config=",
                                               "package_key=",
                                               "incremental_from=",
                                               "wipe_user_data",
                                               "no_prereq",
                                               "extra_script=",
-                                              "script_mode=",
                                               "worker_threads="],
                              extra_option_handler=option_handler)
 
@@ -880,9 +863,6 @@
     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 +886,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 +905,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: