merge from open-source master

Change-Id: I9fedeb014c946b53bfdd424b00c0cb5fc08f8333
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/cleanspec.mk b/cleanspec.mk
deleted file mode 100644
index 4b88868..0000000
--- a/cleanspec.mk
+++ /dev/null
@@ -1,113 +0,0 @@
-# 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.
-#
-
-# Just bump this if you want to force a clean build.
-# **********************************************************************
-# WHEN DOING SO, DELETE ANY "add-clean-step" ENTRIES THAT HAVE PILED UP.
-# **********************************************************************
-#
-INTERNAL_CLEAN_BUILD_VERSION := 3
-#
-# ***********************************************************************
-# Do not touch INTERNAL_CLEAN_BUILD_VERSION if you've added a clean step!
-# ***********************************************************************
-
-# If you don't need to do a full clean build but would like to touch
-# a file or delete some intermediate files, add a clean step to the end
-# of the list.  These steps will only be run once, if they haven't been
-# run before.
-#
-# E.g.:
-#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
-#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
-#
-# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
-# files that are missing or have been moved.
-#
-# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
-# Use $(OUT_DIR) to refer to the "out" directory.
-#
-# If you need to re-do something that's already mentioned, just copy
-# the command and add it to the bottom of the list.  E.g., if a change
-# that you made last week required touching a file and a change you
-# made today requires touching the same file, just copy the old
-# touch step and add it to the end of the list.
-#
-# ************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
-# ************************************************
-
-# For example:
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
-#$(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 $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/com.google.android.datamessaging_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/pvasflocal.cfg)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ringtones/Silence.ogg)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ringtones/notifications/Silence.ogg)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/passion/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/com.google.android.datamessaging_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libcrypto_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libssl_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/openssl_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes/system/build.prop)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/bugreport)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/obj/target/common/obj/APPS/VoiceSearch_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/VoiceSearch_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libgps-rpc_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/pdsm_atl_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgps_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/*/system/app/Launcher.apk)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/bluetooth/)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes/system/build.prop)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/com.amazon.mp3_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/com.amazon.mp3.apk)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
-$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
-
-# ************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
-# ************************************************
diff --git a/core/Makefile b/core/Makefile
index 46f5311..a59159d 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -14,12 +14,15 @@
 # PRODUCT_COPY_FILES contains words like <source file>:<dest file>.
 # <dest file> is relative to $(PRODUCT_OUT), so it should look like,
 # e.g., "system/etc/file.xml".
+# The filter part means "only eval the copy-one-file rule if this
+# src:dest pair is the first one to match %:dest"
 $(foreach cf,$(PRODUCT_COPY_FILES), \
   $(eval _src := $(call word-colon,1,$(cf))) \
-  $(eval _dest := $(call \
-          append-path,$(PRODUCT_OUT),$(call word-colon,2,$(cf)))) \
-  $(eval $(call copy-one-file,$(_src),$(_dest))) \
-  $(eval ALL_DEFAULT_INSTALLED_MODULES += $(_dest)) \
+  $(eval _dest := $(call word-colon,2,$(cf))) \
+  $(eval _fulldest := $(call append-path,$(PRODUCT_OUT),$(_dest))) \
+  $(if $(filter $(_src):$(_dest),$(firstword $(filter %:$(_dest),$(PRODUCT_COPY_FILES)))), \
+    $(eval $(call copy-one-file,$(_src),$(_fulldest))),) \
+  $(eval ALL_DEFAULT_INSTALLED_MODULES += $(_fulldest)) \
  )
 
 # -----------------------------------------------------------------
@@ -208,8 +211,11 @@
 	@mkdir -p $(dir $@)
 	@rm -f $@
 	$(hide) $(foreach p,$(PACKAGES),\
-	  echo 'name="$(p).apk" certificate="$(PACKAGES.$(p).CERTIFICATE)" \
-	       private_key="$(PACKAGES.$(p).PRIVATE_KEY)"' >> $@;)
+          $(if $(PACKAGES.$(p).EXTERNAL_KEY),\
+	    echo 'name="$(p).apk" certificate="EXTERNAL" \
+	         private_key=""' >> $@;,\
+	    echo 'name="$(p).apk" certificate="$(PACKAGES.$(p).CERTIFICATE)" \
+	         private_key="$(PACKAGES.$(p).PRIVATE_KEY)"' >> $@;))
 
 .PHONY: apkcerts-list
 apkcerts-list: $(APKCERTS_FILE)
@@ -242,6 +248,29 @@
 .PHONY: systemimage
 systemimage:
 
+# -----------------------------------------------------------------
+
+.PHONY: event-log-tags
+
+event_log_tags_file := $(TARGET_OUT)/etc/event-log-tags
+ALL_PREBUILT += $(event_log_tag_file)
+
+# Include tags from all packages included in this product.
+event_log_tags_src := \
+    $(sort $(foreach m,\
+      $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES) \
+      $(call module-names-for-tag-list,user), \
+      $(ALL_MODULES.$(m).EVENT_LOG_TAGS)))
+
+$(event_log_tags_file): PRIVATE_SRC_FILES := $(event_log_tags_src)
+$(event_log_tags_file): $(event_log_tags_src)
+	$(hide) mkdir -p $(dir $@)
+	$(hide) build/tools/merge-event-log-tags.py -o $@ $(PRIVATE_SRC_FILES)
+
+event-log-tags: $(event_log_tags_file)
+
+ALL_DEFAULT_INSTALLED_MODULES += $(event_log_tags_file)
+
 ifneq ($(TARGET_SIMULATOR),true)
 
 # #################################################################
@@ -588,6 +617,13 @@
 .PHONY: recoveryimage
 recoveryimage: $(INSTALLED_RECOVERYIMAGE_TARGET)
 
+ifneq ($(BOARD_NAND_PAGE_SIZE),)
+mkyaffs2_extra_flags := -c $(BOARD_NAND_PAGE_SIZE)
+else
+mkyaffs2_extra_flags :=
+endif
+
+
 # -----------------------------------------------------------------
 # system yaffs image
 #
@@ -619,7 +655,7 @@
 define build-systemimage-target
     @echo "Target system fs image: $(1)"
     @mkdir -p $(dir $(1))
-    $(hide) $(MKYAFFS2) -f $(TARGET_OUT) $(1)
+    $(hide) $(MKYAFFS2) -f $(mkyaffs2_extra_flags) $(TARGET_OUT) $(1)
 endef
 endif # TARGET_USERIMAGES_USE_EXT2
 
@@ -719,7 +755,7 @@
 define build-userdataimage-target
     $(call pretty,"Target userdata fs image: $(INSTALLED_USERDATAIMAGE_TARGET)")
     @mkdir -p $(TARGET_OUT_DATA)
-    $(hide) $(MKYAFFS2) -f $(TARGET_OUT_DATA) $(INSTALLED_USERDATAIMAGE_TARGET)
+    $(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
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 64b74e7..c4e19b4 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -62,6 +62,13 @@
 #$(warning default tags: $(lastword $(filter-out config/% out/%,$(MAKEFILE_LIST))))
 endif
 
+# Only the tags mentioned in this test are expected to be set by module
+# makefiles. Anything else is either a typo or a source of unexpected
+# behaviors.
+ifneq ($(filter-out user debug eng tests optional samples,$(LOCAL_MODULE_TAGS)),)
+$(warning unusual tags $(LOCAL_MODULE_TAGS) on $(LOCAL_MODULE) at $(LOCAL_PATH))
+endif
+
 # Add implicit tags.
 #
 # If the local directory or one of its parents contains a MODULE_LICENSE_GPL
@@ -94,9 +101,13 @@
   $(error $(LOCAL_PATH): LOCAL_MODULE_CLASS must contain exactly one word, not "$(LOCAL_MODULE_CLASS)")
 endif
 
-# Add a tag like "_class@APPS" to this module so that we can filter
-# based on the class.
-LOCAL_MODULE_TAGS += _class@$(LOCAL_MODULE_CLASS)
+# Those used to be implicitly ignored, but aren't any more.
+# As of 20100110 there are no apps with the user tag.
+ifeq ($(LOCAL_MODULE_CLASS),APPS)
+  ifneq ($(filter $(LOCAL_MODULE_TAGS),user),)
+    $(warning user tag on app $(LOCAL_MODULE) at $(LOCAL_PATH) - add your app to core.mk instead)
+  endif
+endif
 
 LOCAL_MODULE_PATH := $(strip $(LOCAL_MODULE_PATH))
 ifeq ($(LOCAL_MODULE_PATH),)
@@ -175,7 +186,14 @@
 aidl_java_sources := $(patsubst %.aidl,%.java,$(addprefix $(intermediates.COMMON)/src/, $(aidl_sources)))
 aidl_sources := $(addprefix $(TOP_DIR)$(LOCAL_PATH)/, $(aidl_sources))
 
-$(aidl_java_sources): PRIVATE_AIDL_FLAGS := -b -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
+aidl_preprocess_import :=
+LOCAL_SDK_VERSION:=$(strip $(LOCAL_SDK_VERSION))
+ifdef LOCAL_SDK_VERSION
+ifneq ($(LOCAL_SDK_VERSION),current)
+aidl_preprocess_import := -p$(TOPDIR)prebuilt/sdk/$(LOCAL_SDK_VERSION)/framework.aidl
+endif # !current
+endif # LOCAL_SDK_VERSION
+$(aidl_java_sources): PRIVATE_AIDL_FLAGS := -b $(aidl_preprocess_import) -I$(LOCAL_PATH) -I$(LOCAL_PATH)/src $(addprefix -I,$(LOCAL_AIDL_INCLUDES))
 
 $(aidl_java_sources): $(intermediates.COMMON)/src/%.java: $(TOPDIR)$(LOCAL_PATH)/%.aidl $(PRIVATE_ADDITIONAL_DEPENDENCIES) $(AIDL)
 	$(transform-aidl-to-java)
@@ -186,11 +204,38 @@
 endif
 
 ###########################################################
+## logtags: Add .logtags files to global list, emit java source
+###########################################################
+
+logtags_sources := $(filter %.logtags,$(LOCAL_SRC_FILES))
+
+ifneq ($(strip $(logtags_sources)),)
+
+event_log_tags := $(addprefix $(LOCAL_PATH)/,$(logtags_sources))
+
+# Emit a java source file with constants for the tags, if
+# LOCAL_MODULE_CLASS is "APPS" or "JAVA_LIBRARIES".
+ifneq ($(strip $(filter $(LOCAL_MODULE_CLASS),APPS JAVA_LIBRARIES)),)
+
+logtags_java_sources := $(patsubst %.logtags,%.java,$(addprefix $(intermediates.COMMON)/src/, $(logtags_sources)))
+logtags_sources := $(addprefix $(TOP_DIR)$(LOCAL_PATH)/, $(logtags_sources))
+
+$(logtags_java_sources): $(intermediates.COMMON)/src/%.java: $(TOPDIR)$(LOCAL_PATH)/%.logtags $(TARGET_OUT)/etc/event-log-tags
+	$(transform-logtags-to-java)
+
+endif
+
+else
+logtags_java_sources :=
+event_log_tags :=
+endif
+
+###########################################################
 ## Java: Compile .java files to .class
 ###########################################################
 #TODO: pull this into java.make once host and target are combined
 
-java_sources := $(addprefix $(TOP_DIR)$(LOCAL_PATH)/, $(filter %.java,$(LOCAL_SRC_FILES))) $(aidl_java_sources)
+java_sources := $(addprefix $(TOP_DIR)$(LOCAL_PATH)/, $(filter %.java,$(LOCAL_SRC_FILES))) $(aidl_java_sources) $(logtags_java_sources)
 all_java_sources := $(java_sources) $(addprefix $($(my_prefix)OUT_COMMON_INTERMEDIATES)/, $(filter %.java,$(LOCAL_INTERMEDIATE_SOURCES)))
 
 ## Java resources #########################################
@@ -292,9 +337,21 @@
 full_java_libs := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,$(addsuffix $(COMMON_JAVA_PACKAGE_SUFFIX),$(LOCAL_JAVA_LIBRARIES)))
 full_java_lib_deps := $(full_java_libs)
 else
+ifdef LOCAL_SDK_VERSION
+ifneq ($(LOCAL_SDK_VERSION),current)
+full_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+# For prebuilt sdk versions, we can't depend on the javalib.jar but classes.jar.
+full_java_lib_deps := $(call java-lib-deps,$(filter-out sdk_v$(LOCAL_SDK_VERSION),$(LOCAL_JAVA_LIBRARIES)),$(LOCAL_IS_HOST_MODULE))
+full_java_lib_deps += $(call java-lib-files,sdk_v$(LOCAL_SDK_VERSION),$(LOCAL_IS_HOST_MODULE))
+else
 full_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
 full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
-endif
+endif # !current
+else
+full_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+endif # LOCAL_SDK_VERSION
+endif # !LOCAL_IS_HOST_MODULE
 full_java_libs += $(full_static_java_libs) $(LOCAL_CLASSPATH)
 full_java_lib_deps += $(full_static_java_libs) $(LOCAL_CLASSPATH)
 
@@ -313,7 +370,8 @@
   link_instr_intermediates_dir.COMMON := $(call intermediates-dir-for, \
       APPS,$(LOCAL_INSTRUMENTATION_FOR),,COMMON)
 
-  full_java_libs += $(link_instr_intermediates_dir.COMMON)/classes.jar
+  # link against the jar with full original names (before proguard processing).
+  full_java_libs += $(link_instr_intermediates_dir.COMMON)/classes-full-names.jar
 
   # We can't depend on the .jar file, so we depend on something that
   # depends on the jar file; the final built package file.
@@ -352,6 +410,7 @@
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_POST_PROCESS_COMMAND:= $(LOCAL_POST_PROCESS_COMMAND)
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_AAPT_FLAGS:= $(LOCAL_AAPT_FLAGS)
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_JAVA_LIBRARIES:= $(LOCAL_JAVA_LIBRARIES)
+$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_MANIFEST_PACKAGE_NAME:= $(LOCAL_MANIFEST_PACKAGE_NAME)
 
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_ALL_JAVA_LIBRARIES:= $(full_java_libs)
 $(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_IS_HOST_MODULE := $(LOCAL_IS_HOST_MODULE)
@@ -402,7 +461,9 @@
 # checked modules, use LOCAL_BUILT_MODULE.  This was old
 # behavior, so it should be a safe default.
 ifndef LOCAL_CHECKED_MODULE
-  LOCAL_CHECKED_MODULE := $(LOCAL_BUILT_MODULE)
+  ifndef LOCAL_SDK_VERSION
+    LOCAL_CHECKED_MODULE := $(LOCAL_BUILT_MODULE)
+  endif
 endif
 
 # If they request that this module not be checked, then don't.
@@ -432,6 +493,8 @@
     $(ALL_MODULES.$(LOCAL_MODULE).INSTALLED) $(LOCAL_INSTALLED_MODULE)
 ALL_MODULES.$(LOCAL_MODULE).REQUIRED := \
     $(ALL_MODULES.$(LOCAL_MODULE).REQUIRED) $(LOCAL_REQUIRED_MODULES)
+ALL_MODULES.$(LOCAL_MODULE).EVENT_LOG_TAGS := \
+    $(ALL_MODULES.$(LOCAL_MODULE).EVENT_LOG_TAGS) $(event_log_tags)
 
 ###########################################################
 ## Take care of LOCAL_MODULE_TAGS
diff --git a/core/binary.mk b/core/binary.mk
index 4413d47..d5528b1 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -9,6 +9,15 @@
 include $(BUILD_SYSTEM)/base_rules.mk
 #######################################
 
+####################################################
+## Add FDO flags if FDO is turned on and supported
+####################################################
+ifeq ($(strip $(LOCAL_NO_FDO_SUPPORT)),)
+  LOCAL_CFLAGS += $(TARGET_FDO_CFLAGS)
+  LOCAL_CPPFLAGS += $(TARGET_FDO_CFLAGS)
+  LOCAL_LDFLAGS += $(TARGET_FDO_CFLAGS)
+endif
+
 ###########################################################
 ## Define PRIVATE_ variables used by multiple module types
 ###########################################################
diff --git a/core/build-system.html b/core/build-system.html
index 43bae03..ce5e869 100644
--- a/core/build-system.html
+++ b/core/build-system.html
@@ -704,6 +704,11 @@
 See the <a href="#custom-tools">Custom Tools</a> template makefile for an
 example.</p>
 
+<h4>LOCAL_JAVACFLAGS</h4>
+<p>If you have additional flags to pass into the javac compiler, add
+them here.  For example:</p>
+<p><code>LOCAL_JAVACFLAGS += -Xlint:deprecation</code></p>
+
 <h4>LOCAL_JAVA_LIBRARIES</h4>
 <p>When linking Java apps and libraries, <code>LOCAL_JAVA_LIBRARIES</code>
 specifies which sets of java classes to include.  Currently there are
diff --git a/core/build_id.mk b/core/build_id.mk
index 4661aea..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 := ECLAIR
+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/cleanbuild.mk b/core/cleanbuild.mk
index a753554..7e68d6f 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -16,28 +16,40 @@
 INTERNAL_CLEAN_STEPS :=
 
 # Builds up a list of clean steps.  Creates a unique
-# id for each step by taking INTERNAL_CLEAN_BUILD_VERSION
+# id for each step by taking makefile path, INTERNAL_CLEAN_BUILD_VERSION
 # and appending an increasing number of '@' characters.
 #
 # $(1): shell command to run
+# $(2): indicate to not use makefile path as part of step id if not empty.
+#       $(2) should only be used in build/core/cleanspec.mk: just for compatibility.
 define _add-clean-step
   $(if $(strip $(INTERNAL_CLEAN_BUILD_VERSION)),, \
       $(error INTERNAL_CLEAN_BUILD_VERSION not set))
-  $(eval _acs_id := $(strip $(lastword $(INTERNAL_CLEAN_STEPS))))
-  $(if $(_acs_id),,$(eval _acs_id := $(INTERNAL_CLEAN_BUILD_VERSION)))
-  $(eval _acs_id := $(_acs_id)@)
+  $(eval _acs_makefile_prefix := $(lastword $(MAKEFILE_LIST)))
+  $(eval _acs_makefile_prefix := $(subst /,_,$(_acs_makefile_prefix)))
+  $(eval _acs_makefile_prefix := $(subst .,-,$(_acs_makefile_prefix)))
+  $(eval _acs_makefile_prefix := $(_acs_makefile_prefix)_acs)
+  $(if $($(_acs_makefile_prefix)),,\
+      $(eval $(_acs_makefile_prefix) := $(INTERNAL_CLEAN_BUILD_VERSION)))
+  $(eval $(_acs_makefile_prefix) := $($(_acs_makefile_prefix))@)
+  $(if $(strip $(2)),$(eval _acs_id := $($(_acs_makefile_prefix))),\
+      $(eval _acs_id := $(_acs_makefile_prefix)$($(_acs_makefile_prefix))))
   $(eval INTERNAL_CLEAN_STEPS += $(_acs_id))
   $(eval INTERNAL_CLEAN_STEP.$(_acs_id) := $(1))
   $(eval _acs_id :=)
+  $(eval _acs_makefile_prefix :=)
 endef
 define add-clean-step
-$(if $(call _add-clean-step,$(1)),)
+$(eval # for build/core/cleanspec.mk, dont use makefile path as part of step id) \
+$(if $(filter %/cleanspec.mk,$(lastword $(MAKEFILE_LIST))),\
+    $(eval $(call _add-clean-step,$(1),true)),\
+    $(eval $(call _add-clean-step,$(1))))
 endef
 
 # Defines INTERNAL_CLEAN_BUILD_VERSION and the individual clean steps.
 # cleanspec.mk is outside of the core directory so that more people
 # can have permission to touch it.
-include build/cleanspec.mk
+include $(BUILD_SYSTEM)/cleanspec.mk
 INTERNAL_CLEAN_BUILD_VERSION := $(strip $(INTERNAL_CLEAN_BUILD_VERSION))
 
 # If the clean_steps.mk file is missing (usually after a clean build)
diff --git a/core/cleanspec.mk b/core/cleanspec.mk
new file mode 100644
index 0000000..675c7da
--- /dev/null
+++ b/core/cleanspec.mk
@@ -0,0 +1,189 @@
+# 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.
+#
+
+# Just bump this if you want to force a clean build.
+# **********************************************************************
+# WHEN DOING SO
+# 1. DELETE ANY "add-clean-step" ENTRIES THAT HAVE PILED UP IN THIS FILE.
+# 2. REMOVE ALL FILES NAMED CleanSpec.mk.
+# 3. BUMP THE VERSION.
+# IDEALLY, THOSE STEPS SHOULD BE DONE ATOMICALLY.
+# **********************************************************************
+#
+INTERNAL_CLEAN_BUILD_VERSION := 3
+#
+# ***********************************************************************
+# Do not touch INTERNAL_CLEAN_BUILD_VERSION if you've added a clean step!
+# ***********************************************************************
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(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 $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/com.google.android.datamessaging_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/pvasflocal.cfg)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ringtones/Silence.ogg)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ringtones/notifications/Silence.ogg)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/passion/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/com.google.android.datamessaging_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libcrypto_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libssl_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/openssl_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/bugreport)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvm_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libandroid_runtime_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/obj/target/common/obj/APPS/VoiceSearch_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/VoiceSearch_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libgps-rpc_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/pdsm_atl_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgps_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/*/system/app/Launcher.apk)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/bluetooth/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/product/sholes/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/com.amazon.mp3_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/com.amazon.mp3.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/openssl_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libv8_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libjs_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libv8_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/os/IDropBoxService.java)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/GoogleSubscribedFeedsProvider.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhardware_legacy_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libmediaplayerservice_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libstagefright_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/GoogleServicesFramework_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/VoiceSearchWithKeyboard.apk)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Email_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Email_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/vendor/google_voiceime)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/QuickSearchBox.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvm_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/speech)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Email_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/EnhancedGoogleSearchProvider.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/GoogleCheckin.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libdvm*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libgtest_main_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libgtest_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/Music*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Music*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/Music*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Music*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/AlarmClock.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Calendar.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/DeskClock.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Email.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Facebook.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Gallery3D.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Maps.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/MyFaves.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/googlevoice.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/kickback.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/soundback.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/talkback.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/Launcher*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher*.apk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/Music*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Music*)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/jsr305_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/guava_intermediates)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+subdir_cleanspecs := \
+    $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git . CleanSpec.mk)
+include $(subdir_cleanspecs)
+subdir_cleanspecs :=
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index a7eba3f..0fe3c8b 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -19,6 +19,7 @@
 LOCAL_PACKAGE_NAME:=
 LOCAL_OVERRIDES_PACKAGES:=
 LOCAL_EXPORT_PACKAGE_RESOURCES:=
+LOCAL_MANIFEST_PACKAGE_NAME:=
 LOCAL_REQUIRED_MODULES:=
 LOCAL_ACP_UNAVAILABLE:=
 LOCAL_MODULE_TAGS:=
@@ -33,6 +34,7 @@
 LOCAL_CXX:=
 LOCAL_CPP_EXTENSION:=
 LOCAL_NO_DEFAULT_COMPILER_FLAGS:=
+LOCAL_NO_FDO_SUPPORT :=
 LOCAL_ARM_MODE:=
 LOCAL_YACCFLAGS:=
 LOCAL_ASFLAGS:=
@@ -49,6 +51,7 @@
 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
 LOCAL_PREBUILT_STRIP_COMMENTS:=
 LOCAL_INTERMEDIATE_SOURCES:=
+LOCAL_JAVACFLAGS:=
 LOCAL_JAVA_LIBRARIES:=
 LOCAL_NO_STANDARD_LIBRARIES:=
 LOCAL_CLASSPATH:=
diff --git a/core/combo/HOST_darwin-x86.mk b/core/combo/HOST_darwin-x86.mk
new file mode 100644
index 0000000..bbd78ba
--- /dev/null
+++ b/core/combo/HOST_darwin-x86.mk
@@ -0,0 +1,68 @@
+#
+# Copyright (C) 2006 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.
+#
+
+# Configuration for Darwin (Mac OS X) on x86.
+# Included by combo/select.mk
+
+HOST_GLOBAL_CFLAGS += -fPIC
+HOST_NO_UNDEFINED_LDFLAGS := -Wl,-undefined,error
+
+HOST_CC := $(CC)
+HOST_CXX := $(CXX)
+HOST_AR := $(AR)
+
+HOST_SHLIB_SUFFIX := .dylib
+HOST_JNILIB_SUFFIX := .jnilib
+
+HOST_GLOBAL_CFLAGS += \
+	-include $(call select-android-config-h,darwin-x86)
+HOST_RUN_RANLIB_AFTER_COPYING := true
+HOST_GLOBAL_ARFLAGS := cqs
+
+HOST_CUSTOM_LD_COMMAND := true
+
+define transform-host-o-to-shared-lib-inner
+    $(HOST_CXX) \
+        -dynamiclib -single_module -read_only_relocs suppress \
+        $(HOST_GLOBAL_LD_DIRS) \
+        $(PRIVATE_ALL_OBJECTS) \
+        $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+        $(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+        $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+        $(PRIVATE_LDLIBS) \
+        -o $@ \
+        $(PRIVATE_LDFLAGS) \
+        $(HOST_LIBGCC)
+endef
+
+define transform-host-o-to-executable-inner
+$(HOST_CXX) \
+        -o $@ \
+        -Wl,-dynamic -headerpad_max_install_names \
+        $(HOST_GLOBAL_LD_DIRS) \
+        $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+        $(PRIVATE_ALL_OBJECTS) \
+        $(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+        $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+        $(PRIVATE_LDFLAGS) \
+        $(PRIVATE_LDLIBS) \
+        $(HOST_LIBGCC)
+endef
+
+# $(1): The file to check
+define get-file-size
+stat -f "%z" $(1)
+endef
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
new file mode 100644
index 0000000..26052d6
--- /dev/null
+++ b/core/combo/HOST_linux-x86.mk
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2006 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.
+#
+
+# Configuration for builds hosted on linux-x86.
+# Included by combo/select.mk
+
+# $(1): The file to check
+define get-file-size
+stat --format "%s" "$(1)" | tr -d '\n'
+endef
+
+# We build everything in 32-bit, because some host tools are
+# 32-bit-only anyway (emulator, acc), and because it gives us
+# more consistency between the host tools and the target.
+# The exception is the host side of the simulator, which
+# requires to use the default size, as wxWidgets code otherwise
+# fails to build.
+ifneq ($(TARGET_SIMULATOR),true)
+HOST_GLOBAL_CFLAGS += -m32
+HOST_GLOBAL_LDFLAGS += -m32
+endif
+
+HOST_GLOBAL_CFLAGS += -fPIC
+HOST_GLOBAL_CFLAGS += \
+	-include $(call select-android-config-h,linux-x86)
+
+HOST_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
diff --git a/core/combo/HOST_windows-x86.mk b/core/combo/HOST_windows-x86.mk
new file mode 100644
index 0000000..9870998
--- /dev/null
+++ b/core/combo/HOST_windows-x86.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2006 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.
+#
+
+# Configuration for Linux on x86.
+# Included by combo/select.make
+
+# right now we get these from the environment, but we should
+# pick them from the tree somewhere
+TOOLS_PREFIX := #prebuilt/windows/host/bin/
+TOOLS_EXE_SUFFIX := .exe
+
+# Settings to use MinGW has a cross-compiler under Linux
+ifneq ($(findstring Linux,$(UNAME)),)
+ifneq ($(strip $(USE_MINGW)),)
+HOST_ACP_UNAVAILABLE := true
+TOOLS_PREFIX := /usr/bin/i586-mingw32msvc-
+TOOLS_EXE_SUFFIX :=
+HOST_GLOBAL_CFLAGS += -DUSE_MINGW
+HOST_C_INCLUDES += /usr/lib/gcc/i586-mingw32msvc/3.4.4/include
+HOST_GLOBAL_LD_DIRS += -L/usr/i586-mingw32msvc/lib
+endif
+endif
+
+HOST_CC := $(TOOLS_PREFIX)gcc$(TOOLS_EXE_SUFFIX)
+HOST_CXX := $(TOOLS_PREFIX)g++$(TOOLS_EXE_SUFFIX)
+HOST_AR := $(TOOLS_PREFIX)ar$(TOOLS_EXE_SUFFIX)
+
+HOST_GLOBAL_CFLAGS += -include $(call select-android-config-h,windows)
+HOST_GLOBAL_LDFLAGS += --enable-stdcall-fixup
+
+# when building under Cygwin, ensure that we use Mingw compilation by default.
+# you can disable this (i.e. to generate Cygwin executables) by defining the
+# USE_CYGWIN variable in your environment, e.g.:
+#
+#   export USE_CYGWIN=1
+#
+# note that the -mno-cygwin flags are not needed when cross-compiling the
+# Windows host tools on Linux
+#
+ifneq ($(findstring CYGWIN,$(UNAME)),)
+ifeq ($(strip $(USE_CYGWIN)),)
+HOST_GLOBAL_CFLAGS += -mno-cygwin
+HOST_GLOBAL_LDFLAGS += -mno-cygwin -mconsole
+endif
+endif
+
+HOST_SHLIB_SUFFIX := .dll
+HOST_EXECUTABLE_SUFFIX := .exe
+
+# $(1): The file to check
+# TODO: find out what format cygwin's stat(1) uses
+define get-file-size
+999999999
+endef
diff --git a/core/combo/linux-arm.mk b/core/combo/TARGET_linux-arm.mk
similarity index 67%
rename from core/combo/linux-arm.mk
rename to core/combo/TARGET_linux-arm.mk
index 6011351..972b10c 100644
--- a/core/combo/linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -1,5 +1,21 @@
+#
+# Copyright (C) 2006 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.
+#
+
 # Configuration for Linux on ARM.
-# Included by combo/select.make
+# Included by combo/select.mk
 
 # You can set TARGET_ARCH_VARIANT to use an arch version other
 # than ARMv5TE. Each value should correspond to a file named
@@ -18,16 +34,6 @@
 TARGET_ARCH_VARIANT := armv5te
 endif
 
-# TARGET_ARCH_VARIANT used to be called TARGET_ARCH_VERSION
-# to avoid any weirdness, issue an error message if the latter
-# is defined.
-#
-ifneq ($(strip $(TARGET_ARCH_VERSION)),)
-$(info Definition for TARGET_ARCH_VERSION encountered !)
-$(info This variable has been renamed TARGET_ARCH_VARIANT, please update your build files !!)
-$(error Aborting the build.)
-endif
-
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
 $(error Unknown ARM architecture version: $(TARGET_ARCH_VARIANT))
@@ -36,18 +42,18 @@
 include $(TARGET_ARCH_SPECIFIC_MAKEFILE)
 
 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $($(combo_target)TOOLS_PREFIX)),)
-$(combo_target)TOOLS_PREFIX := \
+ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
+TARGET_TOOLS_PREFIX := \
 	prebuilt/$(HOST_PREBUILT_TAG)/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
 endif
 
-$(combo_target)CC := $($(combo_target)TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)CXX := $($(combo_target)TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)AR := $($(combo_target)TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)OBJCOPY := $($(combo_target)TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)LD := $($(combo_target)TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
+TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
+TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
+TARGET_AR := $(TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
+TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
+TARGET_LD := $(TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
 
-$(combo_target)NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
+TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
 
 TARGET_arm_CFLAGS :=    -O2 \
                         -fomit-frame-pointer \
@@ -86,7 +92,7 @@
 android_config_h := $(call select-android-config-h,linux-arm)
 arch_include_dir := $(dir $(android_config_h))
 
-$(combo_target)GLOBAL_CFLAGS += \
+TARGET_GLOBAL_CFLAGS += \
 			-msoft-float -fpic \
 			-ffunction-sections \
 			-funwind-tables \
@@ -96,7 +102,7 @@
 			-include $(android_config_h) \
 			-I $(arch_include_dir)
 
-$(combo_target)GLOBAL_LDFLAGS += \
+TARGET_GLOBAL_LDFLAGS += \
 			$(arch_variant_ldflags)
 
 # We only need thumb interworking in cases where thumb support
@@ -104,15 +110,15 @@
 # since sometimes thumb-interwork appears to be default), we
 # specifically disable when thumb support is unavailable.
 ifeq ($(ARCH_ARM_HAVE_THUMB_SUPPORT),true)
-$(combo_target)GLOBAL_CFLAGS +=	-mthumb-interwork
+TARGET_GLOBAL_CFLAGS +=	-mthumb-interwork
 else
-$(combo_target)GLOBAL_CFLAGS +=	-mno-thumb-interwork
+TARGET_GLOBAL_CFLAGS +=	-mno-thumb-interwork
 endif
 
-$(combo_target)GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
+TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
 
-$(combo_target)RELEASE_CFLAGS := \
-			-DSK_RELEASE -DNDEBUG \
+TARGET_RELEASE_CFLAGS := \
+			-DNDEBUG \
 			-g \
 			-Wstrict-aliasing=2 \
 			-finline-functions \
@@ -128,13 +134,44 @@
 
 
 ## on some hosts, the target cross-compiler is not available so do not run this command
-ifneq ($(wildcard $($(combo_target)CC)),)
+ifneq ($(wildcard $(TARGET_CC)),)
 # We compile with the global cflags to ensure that
 # any flags which affect libgcc are correctly taken
 # into account.
-$(combo_target)LIBGCC := $(shell $($(combo_target)CC) $($(combo_target)GLOBAL_CFLAGS) -print-libgcc-file-name)
+TARGET_LIBGCC := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) -print-libgcc-file-name)
 endif
 
+# Define FDO (Feedback Directed Optimization) options.
+
+TARGET_FDO_CFLAGS:=
+TARGET_FDO_LIB:=
+
+target_libgcov := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \
+        --print-file-name=libgcov.a)
+ifneq ($(strip $(BUILD_FDO_INSTRUMENT)),)
+  # Set BUILD_FDO_INSTRUMENT=true to turn on FDO instrumentation.
+  # The profile will be generated on /data/local/tmp/profile on the device.
+  TARGET_FDO_CFLAGS := -fprofile-generate=/data/local/tmp/profile -DANDROID_FDO
+  TARGET_FDO_LIB := $(target_libgcov)
+else
+  # If BUILD_FDO_INSTRUMENT is turned off, then consider doing the FDO optimizations.
+  # Set TARGET_FDO_PROFILE_PATH to set a custom profile directory for your build.
+  ifeq ($(strip $(TARGET_FDO_PROFILE_PATH)),)
+    TARGET_FDO_PROFILE_PATH := fdo/profiles/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT)
+  else
+    ifeq ($(strip $(wildcard $(TARGET_FDO_PROFILE_PATH))),)
+      $(warning Custom TARGET_FDO_PROFILE_PATH supplied, but directory does not exist. Turn off FDO.)
+    endif
+  endif
+
+  # If the FDO profile directory can't be found, then FDO is off.
+  ifneq ($(strip $(wildcard $(TARGET_FDO_PROFILE_PATH))),)
+    TARGET_FDO_CFLAGS := -fprofile-use=$(TARGET_FDO_PROFILE_PATH) -DANDROID_FDO
+    TARGET_FDO_LIB := $(target_libgcov)
+  endif
+endif
+
+
 # unless CUSTOM_KERNEL_HEADERS is defined, we're going to use
 # symlinks located in out/ to point to the appropriate kernel
 # headers. see 'config/kernel_headers.make' for more details
@@ -148,7 +185,7 @@
 endif
 KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
 
-$(combo_target)C_INCLUDES := \
+TARGET_C_INCLUDES := \
 	$(libc_root)/arch-arm/include \
 	$(libc_root)/include \
 	$(libstdc++_root)/include \
@@ -163,9 +200,15 @@
 
 TARGET_STRIP_MODULE:=true
 
-$(combo_target)DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libm
+TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libm
 
-$(combo_target)CUSTOM_LD_COMMAND := true
+TARGET_CUSTOM_LD_COMMAND := true
+
+# Enable the Dalvik JIT compiler if not already specified.
+ifeq ($(strip $(WITH_JIT)),)
+    WITH_JIT := true
+endif
+
 define transform-o-to-shared-lib-inner
 $(TARGET_CXX) \
 	-nostdlib -Wl,-soname,$(notdir $@) -Wl,-T,$(BUILD_SYSTEM)/armelf.xsc \
@@ -181,6 +224,7 @@
 	-o $@ \
 	$(PRIVATE_LDFLAGS) \
 	$(TARGET_GLOBAL_LDFLAGS) \
+	$(TARGET_FDO_LIB) \
 	$(TARGET_LIBGCC)
 endef
 
@@ -198,6 +242,7 @@
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(PRIVATE_LDFLAGS) \
 	$(TARGET_GLOBAL_LDFLAGS) \
+	$(TARGET_FDO_LIB) \
 	$(TARGET_LIBGCC) \
 	$(TARGET_CRTEND_O)
 endef
@@ -212,6 +257,7 @@
 	$(TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_ALL_OBJECTS) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
+	$(TARGET_FDO_LIB) \
 	$(TARGET_LIBGCC) \
 	$(TARGET_CRTEND_O)
 endef
diff --git a/core/combo/linux-sh.mk b/core/combo/TARGET_linux-sh.mk
similarity index 74%
rename from core/combo/linux-sh.mk
rename to core/combo/TARGET_linux-sh.mk
index 79cf49d..361fe2e 100644
--- a/core/combo/linux-sh.mk
+++ b/core/combo/TARGET_linux-sh.mk
@@ -1,19 +1,35 @@
+#
+# Copyright (C) 2006 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.
+#
+
 # Configuration for Linux on SuperH.
 # Included by combo/select.make
 
 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $($(combo_target)TOOLS_PREFIX)),)
-$(combo_target)TOOLS_PREFIX := \
+ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
+TARGET_TOOLS_PREFIX := \
 	prebuilt/$(HOST_PREBUILT_TAG)/toolchain/sh-4.3.3/bin/sh-linux-gnu-
 endif
 
-$(combo_target)CC := $($(combo_target)TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)CXX := $($(combo_target)TOOLS_PREFIX)c++$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)AR := $($(combo_target)TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)OBJCOPY := $($(combo_target)TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)LD := $($(combo_target)TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
+TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
+TARGET_CXX := $(TARGET_TOOLS_PREFIX)c++$(HOST_EXECUTABLE_SUFFIX)
+TARGET_AR := $(TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
+TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
+TARGET_LD := $(TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
 
-$(combo_target)NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
+TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
 
 TARGET_sh_release_CFLAGS :=     -O2 \
                                 -fomit-frame-pointer \
@@ -24,18 +40,18 @@
 # When building for debug, compile everything as superh.
 TARGET_sh_debug_CFLAGS := $(TARGET_sh_release_CFLAGS) -fno-omit-frame-pointer -fno-strict-aliasing
 
-$(combo_target)GLOBAL_CFLAGS += \
+TARGET_GLOBAL_CFLAGS += \
 			-fpic \
 			-ffunction-sections \
 			-funwind-tables \
 			-fstack-protector \
 			-include $(call select-android-config-h,linux-sh)
 
-$(combo_target)GLOBAL_CPPFLAGS += \
+TARGET_GLOBAL_CPPFLAGS += \
 			-fno-use-cxa-atexit \
 			-fvisibility-inlines-hidden
 
-$(combo_target)RELEASE_CFLAGS := \
+TARGET_RELEASE_CFLAGS := \
 			-DSK_RELEASE -DNDEBUG \
 			-O2 -g \
 			-Wstrict-aliasing=2 \
@@ -53,13 +69,13 @@
 
 
 ## on some hosts, the target cross-compiler is not available so do not run this command
-ifneq ($(wildcard $($(combo_target)CC)),)
+ifneq ($(wildcard $(TARGET_CC)),)
 # We compile with the global cflags to ensure that
 # any flags which affect libgcc are correctly taken
 # into account.
-LIBGCC_FILENAME := $(shell $($(combo_target)CC) $($(combo_target)GLOBAL_CFLAGS) -print-libgcc-file-name)
+LIBGCC_FILENAME := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) -print-libgcc-file-name)
 LIBGCC_EH_FILENAME := $(subst libgcc,libgcc_eh,$(LIBGCC_FILENAME))
-$(combo_target)LIBGCC := $(LIBGCC_EH_FILENAME) $(LIBGCC_FILENAME)
+TARGET_LIBGCC := $(LIBGCC_EH_FILENAME) $(LIBGCC_FILENAME)
 endif
 
 # unless CUSTOM_KERNEL_HEADERS is defined, we're going to use
@@ -75,7 +91,7 @@
 endif
 KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
 
-$(combo_target)C_INCLUDES := \
+TARGET_C_INCLUDES := \
 	$(libc_root)/arch-sh/include \
 	$(libc_root)/include \
 	$(libstdc++_root)/include \
@@ -92,9 +108,9 @@
 
 TARGET_STRIP_MODULE:=false
 
-$(combo_target)DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libm
+TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libm
 
-$(combo_target)CUSTOM_LD_COMMAND := true
+TARGET_CUSTOM_LD_COMMAND := true
 define transform-o-to-shared-lib-inner
 $(TARGET_CXX) \
 	-nostdlib -Wl,-soname,$(notdir $@) -Wl,-T,$(BUILD_SYSTEM)/shlelf.xsc \
diff --git a/core/combo/target_linux-x86.mk b/core/combo/TARGET_linux-x86.mk
similarity index 60%
rename from core/combo/target_linux-x86.mk
rename to core/combo/TARGET_linux-x86.mk
index 2d359ff..cd7d4b3 100644
--- a/core/combo/target_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -1,25 +1,57 @@
+#
+# Copyright (C) 2006 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.
+#
+
 # Configuration for Linux on x86 as a target.
-# Included by combo/select.make
+# Included by combo/select.mk
+
+ifeq ($(TARGET_SIMULATOR),true)
+# When building for the simulator, use the HOST settings as TARGET settings
+TARGET_CC := $(HOST_CC)
+TARGET_CXX := $(HOST_CXX)
+TARGET_AR := $(HOST_AR)
+TARGET_GLOBAL_CFLAGS := $(HOST_GLOBAL_CFLAGS) -m32
+TARGET_GLOBAL_LDFLAGS := $(HOST_GLOBAL_LDFLAGS) -m32 -lpthread
+TARGET_NO_UNDEFINED_LDFLAGS := $(HOST_NO_UNDEFINED_LDFLAGS)
+TARGET_ARCH_VARIANT := x86
+else #simulator
+
+# Provide a default variant.
+ifeq ($(strip $(TARGET_ARCH_VARIANT)),)
+TARGET_ARCH_VARIANT := x86
+endif
 
 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
-ifeq ($(strip $($(combo_target)TOOLS_PREFIX)),)
-$(combo_target)TOOLS_PREFIX := \
+ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
+TARGET_TOOLS_PREFIX := \
 	prebuilt/$(HOST_PREBUILT_TAG)/toolchain/i686-unknown-linux-gnu-4.2.1/bin/i686-unknown-linux-gnu-
 endif
 
-$(combo_target)CC := $($(combo_target)TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)CXX := $($(combo_target)TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)AR := $($(combo_target)TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)OBJCOPY := $($(combo_target)TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
-$(combo_target)LD := $($(combo_target)TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
+TARGET_CC := $(TARGET_TOOLS_PREFIX)gcc$(HOST_EXECUTABLE_SUFFIX)
+TARGET_CXX := $(TARGET_TOOLS_PREFIX)g++$(HOST_EXECUTABLE_SUFFIX)
+TARGET_AR := $(TARGET_TOOLS_PREFIX)ar$(HOST_EXECUTABLE_SUFFIX)
+TARGET_OBJCOPY := $(TARGET_TOOLS_PREFIX)objcopy$(HOST_EXECUTABLE_SUFFIX)
+TARGET_LD := $(TARGET_TOOLS_PREFIX)ld$(HOST_EXECUTABLE_SUFFIX)
 
-ifneq ($(wildcard $($(combo_target)CC)),)
-$(combo_target)LIBGCC := \
-	$(shell $($(combo_target)CC) -m32 -print-file-name=libgcc.a) \
-        $(shell $($(combo_target)CC) -m32 -print-file-name=libgcc_eh.a)
+ifneq ($(wildcard $(TARGET_CC)),)
+TARGET_LIBGCC := \
+	$(shell $(TARGET_CC) -m32 -print-file-name=libgcc.a) \
+        $(shell $(TARGET_CC) -m32 -print-file-name=libgcc_eh.a)
 endif
 
-$(combo_target)NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
+TARGET_NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
 
 libc_root := bionic/libc
 libm_root := bionic/libm
@@ -39,16 +71,16 @@
 endif
 KERNEL_HEADERS := $(KERNEL_HEADERS_COMMON) $(KERNEL_HEADERS_ARCH)
 
-$(combo_target)GLOBAL_CFLAGS += \
+TARGET_GLOBAL_CFLAGS += \
 			-march=i686 \
 			-m32 \
 			-fPIC \
 			-include $(call select-android-config-h,target_linux-x86)
 
-$(combo_target)GLOBAL_CPPFLAGS += \
+TARGET_GLOBAL_CPPFLAGS += \
 			-fno-use-cxa-atexit
 
-$(combo_target)C_INCLUDES := \
+TARGET_C_INCLUDES := \
 	$(libc_root)/arch-x86/include \
 	$(libc_root)/include \
 	$(libstdc++_root)/include \
@@ -67,9 +99,9 @@
 
 # TARGET_STRIP_MODULE:=true
 
-$(combo_target)DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libm
+TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libm
 
-$(combo_target)CUSTOM_LD_COMMAND := true
+TARGET_CUSTOM_LD_COMMAND := true
 define transform-o-to-shared-lib-inner
 $(TARGET_CXX) \
 	$(TARGET_GLOBAL_LDFLAGS) \
@@ -125,5 +157,7 @@
 	$(TARGET_CRTEND_O)
 endef
 
-$(combo_target)GLOBAL_CFLAGS += -m32
-$(combo_target)GLOBAL_LDFLAGS += -m32
+TARGET_GLOBAL_CFLAGS += -m32
+TARGET_GLOBAL_LDFLAGS += -m32
+
+endif #simulator
diff --git a/core/combo/darwin-x86.mk b/core/combo/darwin-x86.mk
deleted file mode 100644
index 2150960..0000000
--- a/core/combo/darwin-x86.mk
+++ /dev/null
@@ -1,97 +0,0 @@
-# Configuration for Darwin (Mac OS X) on PPC.
-# Included by combo/select.make
-
-$(combo_target)GLOBAL_CFLAGS += -fPIC
-$(combo_target)NO_UNDEFINED_LDFLAGS := -Wl,-undefined,error
-
-$(combo_target)CC := $(CC)
-$(combo_target)CXX := $(CXX)
-$(combo_target)AR := $(AR)
-
-$(combo_target)SHLIB_SUFFIX := .dylib
-$(combo_target)JNILIB_SUFFIX := .jnilib
-
-$(combo_target)GLOBAL_CFLAGS += \
-	-include $(call select-android-config-h,darwin-x86)
-$(combo_target)RUN_RANLIB_AFTER_COPYING := true
-
-ifeq ($(combo_target),TARGET_)
-$(combo_target)CUSTOM_LD_COMMAND := true
-define transform-o-to-shared-lib-inner
-    $(TARGET_CXX) \
-        -dynamiclib -single_module -read_only_relocs suppress \
-        $(TARGET_GLOBAL_LD_DIRS) \
-        $(PRIVATE_ALL_OBJECTS) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
-        $(PRIVATE_LDLIBS) \
-        -o $@ \
-        $(PRIVATE_LDFLAGS) \
-        $(if $(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES),-all_load) \
-        $(TARGET_LIBGCC)
-endef
-
-define transform-o-to-executable-inner
-	$(TARGET_CXX) \
-        -o $@ \
-        -Wl,-dynamic -headerpad_max_install_names \
-        $(TARGET_GLOBAL_LD_DIRS) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-        $(PRIVATE_ALL_OBJECTS) \
-        $(PRIVATE_LDLIBS) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
-        $(TARGET_LIBGCC)
-endef
-
-define transform-o-to-static-executable-inner
-    $(TARGET_CXX) \
-        -static \
-        -o $@ \
-        $(TARGET_GLOBAL_LD_DIRS) \
-        $(PRIVATE_LDFLAGS) \
-        $(PRIVATE_ALL_OBJECTS) \
-        $(PRIVATE_LDLIBS) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
-        $(TARGET_LIBGCC)
-endef
-
-else
-$(combo_target)CUSTOM_LD_COMMAND := true
-
-define transform-host-o-to-shared-lib-inner
-    $(HOST_CXX) \
-        -dynamiclib -single_module -read_only_relocs suppress \
-        $(HOST_GLOBAL_LD_DIRS) \
-        $(PRIVATE_ALL_OBJECTS) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
-        $(PRIVATE_LDLIBS) \
-        -o $@ \
-        $(PRIVATE_LDFLAGS) \
-        $(HOST_LIBGCC)
-endef
-
-define transform-host-o-to-executable-inner
-$(HOST_CXX) \
-        -o $@ \
-        -Wl,-dynamic -headerpad_max_install_names \
-        $(HOST_GLOBAL_LD_DIRS) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
-        $(PRIVATE_ALL_OBJECTS) \
-        $(PRIVATE_LDLIBS) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
-        $(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
-        $(HOST_LIBGCC)
-endef
-
-# $(1): The file to check
-define get-file-size
-stat -f "%z" $(1)
-endef
-
-endif
-
diff --git a/core/combo/linux-x86.mk b/core/combo/linux-x86.mk
deleted file mode 100644
index f466147..0000000
--- a/core/combo/linux-x86.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Configuration for Linux on x86.
-# Included by combo/select.make
-
-# right now we get these from the environment, but we should
-# pick them from the tree somewhere
-$(combo_target)CC := $(CC)
-$(combo_target)CXX := $(CXX)
-$(combo_target)AR := $(AR)
-
-ifeq ($(combo_target),HOST_)
-# $(1): The file to check
-define get-file-size
-stat --format "%s" "$(1)" | tr -d '\n'
-endef
-endif
-
-# On the sim, we build the "host" tools in 64 bit iff the compiler
-# does it for us automatically.  In other words, that means on 64 bit
-# system, they're 64 bit and on 32 bit systems, they're 32 bits.  In
-# all other cases, we build 32 bit, since this is what we release.
-ifneq ($(combo_target)$(TARGET_SIMULATOR),HOST_true)
-$(combo_target)GLOBAL_CFLAGS := $($(combo_target)GLOBAL_CFLAGS) -m32
-$(combo_target)GLOBAL_LDFLAGS := $($(combo_target)GLOBAL_LDFLAGS) -m32
-endif
-
-
-$(combo_target)GLOBAL_CFLAGS += -fPIC
-$(combo_target)GLOBAL_CFLAGS += \
-	-include $(call select-android-config-h,linux-x86)
-
-$(combo_target)NO_UNDEFINED_LDFLAGS := -Wl,--no-undefined
-
-
diff --git a/core/combo/select.mk b/core/combo/select.mk
index 793b0a9..916320b 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -1,24 +1,33 @@
+#
+# Copyright (C) 2006 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.
+#
+
 # Select a combo based on the compiler being used.
 #
 # Inputs:
 #	combo_target -- prefix for final variables (HOST_ or TARGET_)
 #
-# Outputs:
-#   $(combo_target)OS -- standard name for this host (LINUX, DARWIN, etc.)
-#   $(combo_target)ARCH -- standard name for process architecture (powerpc, x86, etc.)
-#   $(combo_target)GLOBAL_CFLAGS -- C compiler flags to use for everything
-#   $(combo_target)RELEASE_CFLAGS -- additional C compiler flags for release builds
-#   $(combo_target)GLOBAL_ARFLAGS -- flags to use for static linking everything
-#   $(combo_target)SHLIB_SUFFIX -- suffix of shared libraries
 
 # Build a target string like "linux-arm" or "darwin-x86".
 combo_os_arch := $($(combo_target)OS)-$($(combo_target)ARCH)
 
-# Set the defaults.
+# Set reasonable defaults for the various variables
 
-HOST_CC ?= $(CC)
-HOST_CXX ?= $(CXX)
-HOST_AR ?= $(AR)
+$(combo_target)CC := $(CC)
+$(combo_target)CXX := $(CXX)
+$(combo_target)AR := $(AR)
 
 $(combo_target)BINDER_MINI := 0
 
@@ -36,11 +45,10 @@
 $(combo_target)HAVE_STRLCAT := 0
 $(combo_target)HAVE_KERNEL_MODULES := 0
 
-# These flags might (will) be overridden by the target makefiles
 $(combo_target)GLOBAL_CFLAGS := -fno-exceptions -Wno-multichar
 $(combo_target)RELEASE_CFLAGS := -O2 -g -fno-strict-aliasing
 $(combo_target)GLOBAL_LDFLAGS :=
-$(combo_target)GLOBAL_ARFLAGS := crs
+$(combo_target)GLOBAL_ARFLAGS := crsP
 
 $(combo_target)EXECUTABLE_SUFFIX := 
 $(combo_target)SHLIB_SUFFIX := .so
@@ -49,28 +57,8 @@
 
 $(combo_target)PRELINKER_MAP := $(BUILD_SYSTEM)/prelink-$(combo_os_arch).map
 
-# We try to find a target or host specific file for the os/arch specified, and
-# default to just looking for the os/arch one. This will allow us to define
-# things separately for targets and hosts that have the same architecture
-# but need different defines. e.g. target_linux-x86 and host_linux-x86
-
-ifneq ($(TARGET_SIMULATOR),true)
-# Convert the combo_target string to lowercase
-combo_target_lc := $(shell echo $(combo_target) | tr '[A-Z]' '[a-z]')
-
-# form combo makefile name like "<path>/target_linux-x86.make",
-# "<path>/host_darwin-x86.make", etc.
-combo_target_os_arch := $(BUILD_COMBOS)/$(combo_target_lc)$(combo_os_arch).mk
-else
-combo_target_os_arch :=
-endif
-
 # Now include the combo for this specific target.
-ifneq ($(wildcard $(combo_target_os_arch)),)
-include $(combo_target_os_arch)
-else
-include $(BUILD_COMBOS)/$(combo_os_arch).mk
-endif
+include $(BUILD_COMBOS)/$(combo_target)$(combo_os_arch).mk
 
 ifneq ($(USE_CCACHE),)
   ccache := prebuilt/$(HOST_PREBUILT_TAG)/ccache/ccache
diff --git a/core/combo/windows-x86.mk b/core/combo/windows-x86.mk
deleted file mode 100644
index e32a077..0000000
--- a/core/combo/windows-x86.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-# Configuration for Linux on x86.
-# Included by combo/select.make
-
-# right now we get these from the environment, but we should
-# pick them from the tree somewhere
-TOOLS_PREFIX := #prebuilt/windows/host/bin/
-TOOLS_EXE_SUFFIX := .exe
-
-# Settings to use MinGW has a cross-compiler under Linux
-ifneq ($(findstring Linux,$(UNAME)),)
-ifneq ($(strip $(USE_MINGW)),)
-HOST_ACP_UNAVAILABLE := true
-TOOLS_PREFIX := /usr/bin/i586-mingw32msvc-
-TOOLS_EXE_SUFFIX :=
-$(combo_target)GLOBAL_CFLAGS += -DUSE_MINGW
-$(combo_target)C_INCLUDES += /usr/lib/gcc/i586-mingw32msvc/3.4.4/include
-$(combo_target)GLOBAL_LD_DIRS += -L/usr/i586-mingw32msvc/lib
-endif
-endif
-
-$(combo_target)CC := $(TOOLS_PREFIX)gcc$(TOOLS_EXE_SUFFIX)
-$(combo_target)CXX := $(TOOLS_PREFIX)g++$(TOOLS_EXE_SUFFIX)
-$(combo_target)AR := $(TOOLS_PREFIX)ar$(TOOLS_EXE_SUFFIX)
-
-$(combo_target)GLOBAL_CFLAGS += -include $(call select-android-config-h,windows)
-$(combo_target)GLOBAL_LDFLAGS += --enable-stdcall-fixup
-
-# when building under Cygwin, ensure that we use Mingw compilation by default.
-# you can disable this (i.e. to generate Cygwin executables) by defining the
-# USE_CYGWIN variable in your environment, e.g.:
-#
-#   export USE_CYGWIN=1
-#
-# note that the -mno-cygwin flags are not needed when cross-compiling the
-# Windows host tools on Linux
-#
-ifneq ($(findstring CYGWIN,$(UNAME)),)
-ifeq ($(strip $(USE_CYGWIN)),)
-$(combo_target)GLOBAL_CFLAGS += -mno-cygwin
-$(combo_target)GLOBAL_LDFLAGS += -mno-cygwin -mconsole
-endif
-endif
-
-$(combo_target)SHLIB_SUFFIX := .dll
-$(combo_target)EXECUTABLE_SUFFIX := .exe
-
-ifeq ($(combo_target),HOST_)
-# $(1): The file to check
-# TODO: find out what format cygwin's stat(1) uses
-define get-file-size
-999999999
-endef
-endif
diff --git a/core/config.mk b/core/config.mk
index 4662a38..64a5dd0 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -8,6 +8,10 @@
 # directly.
 SHELL := /bin/bash
 
+# Tell python not to spam the source tree with .pyc files.  This
+# only has an effect on python 2.6 and above.
+export PYTHONDONTWRITEBYTECODE := 1
+
 # Standard source directories.
 SRC_DOCS:= $(TOPDIR)docs
 # TODO: Enforce some kind of layering; only add include paths
@@ -202,6 +206,7 @@
 E2FSCK := e2fsck
 JARJAR := java -jar $(HOST_OUT_JAVA_LIBRARIES)/jarjar.jar
 PROGUARD := external/proguard/bin/proguard.sh
+JAVATAGS := build/tools/java-event-log-tags.py
 
 # dx is java behind a shell script; no .exe necessary.
 DX := $(HOST_OUT_EXECUTABLES)/dx
@@ -296,7 +301,6 @@
 
 PREBUILT_IS_PRESENT := $(if $(wildcard prebuilt/Android.mk),true)
 
-
 # ###############################################################
 # Collect a list of the SDK versions that we could compile against
 # For use with the LOCAL_SDK_VERSION variable for include $(BUILD_PACKAGE)
diff --git a/core/definitions.mk b/core/definitions.mk
index 3221525..1afbb90 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -223,12 +223,38 @@
 endef
 
 ###########################################################
+## Find all of the logtags files under the named directories.
+## Meant to be used like:
+##    SRC_FILES := $(call all-logtags-files-under,src)
+###########################################################
+
+define all-logtags-files-under
+$(patsubst ./%,%, \
+  $(shell cd $(LOCAL_PATH) ; \
+          find $(1) -name "*.logtags" -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)
+###########################################################
+
+define all-html-files-under
+$(patsubst ./%,%, \
+  $(shell cd $(LOCAL_PATH) ; \
+          find $(1) -name "*.html" -and -not -name ".*") \
+ )
+endef
+
+###########################################################
 ## Find all of the html files from here.  Meant to be used like:
 ##    SRC_FILES := $(call all-subdir-html-files)
 ###########################################################
 
 define all-subdir-html-files
-$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find . -name "*.html"))
+$(call all-html-files-under,.)
 endef
 
 ###########################################################
@@ -559,6 +585,7 @@
 # $(1): list of tags to accept
 # $(2): list of tags to reject
 #TODO(dbort): do $(if $(strip $(1)),$(1),$(ALL_MODULE_TAGS))
+#TODO(jbq): as of 20100106 nobody uses the second parameter
 define get-tagged-modules
 $(filter-out \
 	$(call modules-for-tag-list,$(2)), \
@@ -644,6 +671,7 @@
 @echo PRIVATE_ARFLAGS=$(PRIVATE_ARFLAGS);
 @echo PRIVATE_AAPT_FLAGS=$(PRIVATE_AAPT_FLAGS);
 @echo PRIVATE_DX_FLAGS=$(PRIVATE_DX_FLAGS);
+@echo PRIVATE_JAVACFLAGS=$(PRIVATE_JAVACFLAGS);
 @echo PRIVATE_JAVA_LIBRARIES=$(PRIVATE_JAVA_LIBRARIES);
 @echo PRIVATE_ALL_SHARED_LIBRARIES=$(PRIVATE_ALL_SHARED_LIBRARIES);
 @echo PRIVATE_ALL_STATIC_LIBRARIES=$(PRIVATE_ALL_STATIC_LIBRARIES);
@@ -717,6 +745,16 @@
 #$(AIDL) $(PRIVATE_AIDL_FLAGS) $< - | indent -nut -br -npcs -l1000 > $@
 
 
+###########################################################
+## Commands for running java-event-log-tags.py
+###########################################################
+
+define transform-logtags-to-java
+@mkdir -p $(dir $@)
+@echo "logtags: $@ <= $<"
+$(hide) $(JAVATAGS) -o $@ $^
+endef
+
 
 ###########################################################
 ## Commands for running gcc to compile a C++ file
@@ -727,11 +765,11 @@
 @echo "target $(PRIVATE_ARM_MODE) C++: $(PRIVATE_MODULE) <= $<"
 $(hide) $(PRIVATE_CXX) \
 	$(foreach incdir, \
+	    $(PRIVATE_C_INCLUDES) \
 	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 		$(TARGET_PROJECT_INCLUDES) \
 		$(TARGET_C_INCLUDES) \
 	     ) \
-	    $(PRIVATE_C_INCLUDES) \
 	  , \
 	    -I $(incdir) \
 	 ) \
@@ -759,11 +797,11 @@
 @mkdir -p $(dir $@)
 $(hide) $(PRIVATE_CC) \
 	$(foreach incdir, \
+	    $(PRIVATE_C_INCLUDES) \
 	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 		$(TARGET_PROJECT_INCLUDES) \
 		$(TARGET_C_INCLUDES) \
 	     ) \
-	    $(PRIVATE_C_INCLUDES) \
 	  , \
 	    -I $(incdir) \
 	 ) \
@@ -823,11 +861,11 @@
 @echo "host C++: $(PRIVATE_MODULE) <= $<"
 $(hide) $(PRIVATE_CXX) \
 	$(foreach incdir, \
+	    $(PRIVATE_C_INCLUDES) \
 	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 		$(HOST_PROJECT_INCLUDES) \
 		$(HOST_C_INCLUDES) \
 	     ) \
-	    $(PRIVATE_C_INCLUDES) \
 	  , \
 	    -I $(incdir) \
 	 ) \
@@ -853,11 +891,11 @@
 @mkdir -p $(dir $@)
 $(hide) $(PRIVATE_CC) \
 	$(foreach incdir, \
+	    $(PRIVATE_C_INCLUDES) \
 	    $(if $(PRIVATE_NO_DEFAULT_COMPILER_FLAGS),, \
 		$(HOST_PROJECT_INCLUDES) \
 		$(HOST_C_INCLUDES) \
 	     ) \
-	    $(PRIVATE_C_INCLUDES) \
 	  , \
 	    -I $(incdir) \
 	 ) \
@@ -909,7 +947,7 @@
 ## Commands for running ar
 ###########################################################
 
-define extract-and-include-whole-static-libs
+define extract-and-include-target-whole-static-libs
 $(foreach lib,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES), \
 	@echo "preparing StaticLib: $(PRIVATE_MODULE) [including $(lib)]"; \
 	ldir=$(PRIVATE_INTERMEDIATES_DIR)/WHOLE/$(basename $(notdir $(lib)))_objs;\
@@ -929,22 +967,39 @@
 define transform-o-to-static-lib
 @mkdir -p $(dir $@)
 @rm -f $@
-$(extract-and-include-whole-static-libs)
+$(extract-and-include-target-whole-static-libs)
 @echo "target StaticLib: $(PRIVATE_MODULE) ($@)"
-$(hide) $(TARGET_AR) $(TARGET_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@ $^
+$(hide) echo $^ | xargs $(TARGET_AR) $(TARGET_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@
 endef
 
 ###########################################################
 ## Commands for running host ar
 ###########################################################
 
+define extract-and-include-host-whole-static-libs
+$(foreach lib,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES), \
+	@echo "preparing StaticLib: $(PRIVATE_MODULE) [including $(lib)]"; \
+	ldir=$(PRIVATE_INTERMEDIATES_DIR)/WHOLE/$(basename $(notdir $(lib)))_objs;\
+	rm -rf $$ldir; \
+	mkdir -p $$ldir; \
+	filelist=; \
+	for f in `$(HOST_AR) t $(lib) | grep '\.o$$'`; do \
+	    $(HOST_AR) p $(lib) $$f > $$ldir/$$f; \
+	    filelist="$$filelist $$ldir/$$f"; \
+	done ; \
+	$(HOST_AR) $(HOST_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@ $$filelist;\
+)
+endef
+
 # Explicitly delete the archive first so that ar doesn't
 # try to add to an existing archive.
 define transform-host-o-to-static-lib
 @mkdir -p $(dir $@)
-@echo "host StaticLib: $(PRIVATE_MODULE) ($@)"
 @rm -f $@
-$(HOST_AR) $(HOST_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@ $^
+$(extract-and-include-host-whole-static-libs)
+@echo "host StaticLib: $(PRIVATE_MODULE) ($@)"
+echo $(filter %.o, $^) | \
+	xargs $(HOST_AR) $(HOST_GLOBAL_ARFLAGS) $(PRIVATE_ARFLAGS) $@
 endef
 
 
@@ -1178,7 +1233,8 @@
     $(addprefix --min-sdk-version , $(DEFAULT_APP_TARGET_SDK)) \
     $(addprefix --target-sdk-version , $(DEFAULT_APP_TARGET_SDK)) \
     $(addprefix --version-code , $(PLATFORM_SDK_VERSION)) \
-    $(addprefix --version-name , $(PLATFORM_VERSION))
+    $(addprefix --version-name , $(PLATFORM_VERSION)) \
+    $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME))
 endef
 
 ifeq ($(HOST_OS),windows)
@@ -1254,7 +1310,7 @@
 $(hide) $(TARGET_JAVAC) -encoding ascii $(PRIVATE_BOOTCLASSPATH) \
     $(addprefix -classpath ,$(strip \
         $(call normalize-path-list,$(PRIVATE_ALL_JAVA_LIBRARIES)))) \
-    $(strip $(PRIVATE_JAVAC_DEBUG_FLAGS)) $(xlint_unchecked) \
+    $(PRIVATE_JAVACFLAGS) $(strip $(PRIVATE_JAVAC_DEBUG_FLAGS)) $(xlint_unchecked) \
     -extdirs "" -d $(PRIVATE_CLASS_INTERMEDIATES_DIR) \
     \@$(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))/java-source-list-uniq \
     || ( rm -rf $(PRIVATE_CLASS_INTERMEDIATES_DIR) ; exit 41 )
@@ -1321,6 +1377,7 @@
     $(addprefix --target-sdk-version , $(DEFAULT_APP_TARGET_SDK)) \
     $(addprefix --version-code , $(PLATFORM_SDK_VERSION)) \
     $(addprefix --version-name , $(PLATFORM_VERSION)) \
+    $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
     -F $@
 endef
 
@@ -1392,7 +1449,7 @@
 	$(PRIVATE_JAVA_SOURCES)),\
 	$(PRIVATE_INTERMEDIATES_DIR)/java-source-list-uniq)
 $(hide) $(HOST_JAVAC) -encoding ascii -g \
-	$(xlint_unchecked) \
+	$(PRIVATE_JAVACFLAGS) $(xlint_unchecked) \
 	$(addprefix -classpath ,$(strip \
 		$(call normalize-path-list,$(PRIVATE_ALL_JAVA_LIBRARIES)))) \
 	-extdirs "" -d $(PRIVATE_CLASS_INTERMEDIATES_DIR)\
@@ -1522,7 +1579,6 @@
 $(copy-file-to-target-strip-comments)
 endef
 
-
 ###########################################################
 ## On some platforms (MacOS), after copying a static
 ## library, ranlib must be run to update an internal
@@ -1551,6 +1607,37 @@
 
 
 ###########################################################
+## Commands to call Proguard
+###########################################################
+
+# Command to copy the file with acp, if proguard is disabled.
+define proguard-disabled-commands
+@echo Copying: $@
+$(hide) $(ACP) $< $@
+endef
+
+# Command to call Proguard
+# $(1): extra flags for instrumentation.
+define proguard-enabled-commands
+@echo Proguard: $@
+$(hide) $(PROGUARD) -injars $< -outjars $@ $(PRIVATE_PROGUARD_FLAGS) $(1)
+endef
+
+# Figure out the proguard dictionary file of the module that is instrumentationed for.
+define get-instrumentation-proguard-flags
+$(if $(PRIVATE_INSTRUMENTATION_FOR),$(if $(ALL_MODULES.$(PRIVATE_INSTRUMENTATION_FOR).PROGUARD_ENABLED),-applymapping $(call intermediates-dir-for,APPS,$(PRIVATE_INSTRUMENTATION_FOR),,COMMON)/proguard_dictionary))
+endef
+
+define transform-jar-to-proguard
+$(eval _instrumentation_proguard_flags:=$(call get-instrumentation-proguard-flags))
+$(eval _enable_proguard:=$(PRIVATE_PROGUARD_ENABLED)$(_instrumentation_proguard_flags))
+$(if $(_enable_proguard),$(call proguard-enabled-commands,$(_instrumentation_proguard_flags)),$(call proguard-disabled-commands))
+$(eval _instrumentation_proguard_flags:=)
+$(eval _enable_proguard:=)
+endef
+
+
+###########################################################
 ## Stuff source generated from one-off tools
 ###########################################################
 
@@ -1636,17 +1723,66 @@
 # INSTALLED_RADIOIMAGE_TARGET.
 # $(1): filename
 define add-radio-file
-  $(eval $(call add-radio-file-internal,$(1)))
+  $(eval $(call add-radio-file-internal,$(1),$(notdir $(1))))
 endef
 define add-radio-file-internal
-INSTALLED_RADIOIMAGE_TARGET += $$(PRODUCT_OUT)/$(1)
-ALL_PREBUILT += $$(PRODUCT_OUT)/$(1)
-$$(PRODUCT_OUT)/$(1) : $$(LOCAL_PATH)/$(1) | $$(ACP)
+INSTALLED_RADIOIMAGE_TARGET += $$(PRODUCT_OUT)/$(2)
+ALL_PREBUILT += $$(PRODUCT_OUT)/$(2)
+$$(PRODUCT_OUT)/$(2) : $$(LOCAL_PATH)/$(1) | $$(ACP)
 	$$(transform-prebuilt-to-target)
 endef
 
 
 ###########################################################
+# Override the package defined in $(1), setting the
+# variables listed below differently.
+#
+#  $(1): The makefile to override (relative to the source
+#        tree root)
+#  $(2): Old LOCAL_PACKAGE_NAME value.
+#  $(3): New LOCAL_PACKAGE_NAME value.
+#  $(4): New LOCALE_MANIFEST_PACKAGE_NAME value.
+#  $(5): New LOCAL_CERTIFICATE value.
+#
+# Note that LOCAL_PACKAGE_OVERRIDES is NOT cleared in
+# clear_vars.mk.
+###########################################################
+define inherit-package
+  $(eval $(call inherit-package-internal,$(1),$(2),$(3),$(4)))
+endef
+
+define inherit-package-internal
+  LOCAL_PACKAGE_OVERRIDES \
+      := $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||$(strip $(5)) $(LOCAL_PACKAGE_OVERRIDES)
+  include $(1)
+  LOCAL_PACKAGE_OVERRIDES \
+      := $(wordlist 1,$(words $(LOCAL_PACKAGE_OVERRIDES)), $(LOCAL_PACKAGE_OVERRIDES))
+endef
+
+# To be used with inherit-package above
+# Evalutes to true if the package was overridden
+define set-inherited-package-variables
+$(strip $(call set-inherited-package-variables-internal))
+endef
+
+define keep-or-override
+$(eval $(1) := $(if $(2),$(2),$($(1))))
+endef
+
+define set-inherited-package-variables-internal
+  $(eval _o := $(subst ||, ,$(lastword $(LOCAL_PACKAGE_OVERRIDES))))
+  $(eval _n := $(subst ||, ,$(firstword $(LOCAL_PACKAGE_OVERRIDES))))
+  $(if $(filter $(word 2,$(_n)),$(LOCAL_PACKAGE_NAME)), \
+    $(eval LOCAL_PACKAGE_NAME := $(word 3,$(_o))) \
+    $(eval LOCAL_MANIFEST_PACKAGE_NAME := $(word 4,$(_o))) \
+    $(call keep-or-override,LOCAL_CERTIFICATE,$(word 5,$(_o))) \
+    $(eval LOCAL_OVERRIDES_PACKAGES := $(sort $(LOCAL_OVERRIDES_PACKAGES) $(word 2,$(_o)))) \
+    true \
+  ,)
+endef
+
+
+###########################################################
 ## Other includes
 ###########################################################
 
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index f07cf2a..0818d87 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -91,6 +91,13 @@
 # around, so we have to use this version.
 prelink_output := $(LOCAL_UNSTRIPPED_PATH)/$(LOCAL_MODULE_SUBDIR)$(LOCAL_BUILT_MODULE_STEM)
 
+# Skip prelinker if it is FDO instrumentation build.
+ifneq ($(strip $(BUILD_FDO_INSTRUMENT)),)
+ifneq ($(LOCAL_NO_FDO_SUPPORT),true)
+LOCAL_PRELINK_MODULE := false
+endif
+endif
+
 ifeq ($(LOCAL_PRELINK_MODULE),true)
 $(prelink_output): $(prelink_input) $(TARGET_PRELINKER_MAP) $(APRIORI)
 	$(transform-to-prelinked)
diff --git a/core/host_java_library.mk b/core/host_java_library.mk
index 92b5ff6..1977115 100644
--- a/core/host_java_library.mk
+++ b/core/host_java_library.mk
@@ -25,5 +25,6 @@
 
 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)
 	$(transform-host-java-to-package)
diff --git a/core/host_static_library.mk b/core/host_static_library.mk
index 237981f..39c99ee 100644
--- a/core/host_static_library.mk
+++ b/core/host_static_library.mk
@@ -1,5 +1,5 @@
 ###########################################################
-## Standard rules for building a static library.
+## Standard rules for building a static library for the host.
 ##
 ## Additional inputs from base_rules.make:
 ## None.
@@ -7,8 +7,6 @@
 ## LOCAL_MODULE_SUFFIX will be set for you.
 ###########################################################
 
-LOCAL_IS_HOST_MODULE := true
-
 ifeq ($(strip $(LOCAL_MODULE_CLASS)),)
 LOCAL_MODULE_CLASS := STATIC_LIBRARIES
 endif
@@ -17,7 +15,10 @@
 endif
 LOCAL_UNINSTALLABLE_MODULE := true
 
+LOCAL_IS_HOST_MODULE := true
+
 include $(BUILD_SYSTEM)/binary.mk
 
+$(LOCAL_BUILT_MODULE): $(built_whole_libraries)
 $(LOCAL_BUILT_MODULE): $(all_objects)
 	$(transform-host-o-to-static-lib)
diff --git a/core/java.mk b/core/java.mk
index ddb8737..bc81eae 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -20,7 +20,11 @@
       $(error $(LOCAL_PATH): Invalid LOCAL_SDK_VERSION '$(LOCAL_SDK_VERSION)' \
              Choices are: $(TARGET_AVAILABLE_SDK_VERSIONS))
     else
-      LOCAL_JAVA_LIBRARIES := android_stubs_$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES) 
+      ifeq ($(LOCAL_SDK_VERSION),current)
+        LOCAL_JAVA_LIBRARIES := android_stubs_$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES)
+      else
+        LOCAL_JAVA_LIBRARIES := sdk_v$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES)
+      endif
     endif
   endif
 else
@@ -70,6 +74,7 @@
 full_classes_emma_jar := $(emma_intermediates_dir)/lib/$(full_classes_compiled_jar_leaf)
 full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar
 full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
+full_classes_full_names_jar := $(intermediates.COMMON)/classes-full-names.jar
 full_classes_proguard_jar := $(full_classes_jar)
 built_dex := $(intermediates.COMMON)/classes.dex
 
@@ -135,6 +140,7 @@
 # This intentionally depends on java_sources, not all_java_sources.
 # 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)
 	$(transform-java-to-classes.jar)
 
@@ -192,39 +198,55 @@
 	$(hide) $(ACP) $< $@
 endif
 
+# Keep a copy of the jar just before proguard processing.
+$(full_classes_full_names_jar): $(full_classes_emma_jar) | $(ACP)
+	@echo Copying: $@
+	$(hide) $(ACP) $< $@
+
 # Run proguard if necessary, otherwise just copy the file.  This is the last
 # part of this step, so the output of this command is full_classes_jar.
-ifneq ($(strip $(LOCAL_PROGUARD_ENABLED)),)
 proguard_dictionary := $(intermediates.COMMON)/proguard_dictionary
-proguard_flags := $(addprefix -libraryjars ,$(full_java_libs)) \
+# Proguard doesn't like a class in both library and the jar to be processed.
+proguard_full_java_libs := $(filter-out $(full_static_java_libs),$(full_java_libs))
+proguard_flags := $(addprefix -libraryjars ,$(proguard_full_java_libs)) \
                   -include $(BUILD_SYSTEM)/proguard.flags \
                   -forceprocessing \
                   -printmapping $(proguard_dictionary)
-ifeq ($(strip $(LOCAL_PROGUARD_ENABLED)),full)
+# If this is a test package, add proguard keep flags for tests.
+ifneq ($(strip $(LOCAL_INSTRUMENTATION_FOR)$(filter tests,$(LOCAL_MODULE_TAGS))$(filter android.test.runner,$(LOCAL_JAVA_LIBRARIES))),)
+proguard_flags := $(proguard_flags) -include $(BUILD_SYSTEM)/proguard_tests.flags
+endif # test package
+
+LOCAL_PROGUARD_ENABLED:=$(strip $(LOCAL_PROGUARD_ENABLED))
+ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
+    LOCAL_PROGUARD_ENABLED :=
+endif
+ifneq ($(LOCAL_PROGUARD_ENABLED),)
+ifeq ($(LOCAL_PROGUARD_ENABLED),full)
     # full
 else
-ifeq ($(strip $(LOCAL_PROGUARD_ENABLED)),optonly)
+ifeq ($(LOCAL_PROGUARD_ENABLED),optonly)
     # optonly
     proguard_flags += -dontobfuscate
 else
-ifeq ($(strip $(LOCAL_PROGUARD_ENABLED)),custom)
+ifeq ($(LOCAL_PROGUARD_ENABLED),custom)
     # custom
 else
     $(warning while processing: $(LOCAL_MODULE))
     $(error invalid value for LOCAL_PROGUARD_ENABLED: $(LOCAL_PROGUARD_ENABLED))
-endif
-endif
-endif
+endif # custom
+endif # optonly
+endif # full
+endif # LOCAL_PROGUARD_ENABLED
 
+$(full_classes_proguard_jar): PRIVATE_PROGUARD_ENABLED:=$(LOCAL_PROGUARD_ENABLED)
 $(full_classes_proguard_jar): PRIVATE_PROGUARD_FLAGS := $(proguard_flags) $(LOCAL_PROGUARD_FLAGS)
-$(full_classes_proguard_jar): $(full_classes_emma_jar) | $(PROGUARD)
-	@echo Proguard: $@
-	$(hide) $(PROGUARD) -injars $< -outjars $@ $(PRIVATE_PROGUARD_FLAGS)
-else
-$(full_classes_proguard_jar): $(full_classes_emma_jar) | $(ACP)
-	@echo Copying: $@
-	$(hide) $(ACP) $< $@
-endif
+$(full_classes_proguard_jar): PRIVATE_INSTRUMENTATION_FOR:=$(strip $(LOCAL_INSTRUMENTATION_FOR))
+
+$(full_classes_proguard_jar): $(full_classes_full_names_jar) | $(ACP) $(PROGUARD)
+	$(call transform-jar-to-proguard)
+
+ALL_MODULES.$(LOCAL_MODULE).PROGUARD_ENABLED:=$(LOCAL_PROGUARD_ENABLED)
 
 # Override PRIVATE_INTERMEDIATES_DIR so that install-dex-debug
 # will work even when intermediates != intermediates.COMMON.
diff --git a/core/main.mk b/core/main.mk
index 386c0c9..688ad9d 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -254,6 +254,11 @@
 else # !sdk
 endif
 
+# build the full stagefright library
+ifneq ($(strip BUILD_WITH_FULL_STAGEFRIGHT),)
+BUILD_WITH_FULL_STAGEFRIGHT := true
+endif
+
 ## precise GC ##
 
 ifneq ($(filter dalvik.gc.type-precise,$(PRODUCT_TAGS)),)
@@ -286,13 +291,11 @@
 endif
 
 ADDITIONAL_BUILD_PROPERTIES += net.bt.name=Android
-ADDITIONAL_BUILD_PROPERTIES += ro.config.sync=yes
 
 # enable vm tracing in files for now to help track
 # the cause of ANRs in the content process
 ADDITIONAL_BUILD_PROPERTIES += dalvik.vm.stack-trace-file=/data/anr/traces.txt
 
-
 # ------------------------------------------------------------
 # Define a function that, given a list of module tags, returns
 # non-empty if that module should be installed in /system.
@@ -400,7 +403,6 @@
 	development/apps \
 	development/tools/mkstubs \
 	frameworks/base/tools/layoutlib \
-	external/googleclient \
 	packages
 else
 $(warning sdk-only: javac not available.)
@@ -452,7 +454,7 @@
 # modules as a side-effect.  Do this after including ONE_SHOT_MAKEFILE
 # so that the modules will be installed in the same place they
 # would have been with a normal make.
-CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS),))
+CUSTOM_MODULES := $(sort $(call get-tagged-modules,$(ALL_MODULE_TAGS)))
 FULL_BUILD :=
 # Stub out the notice targets, which probably aren't defined
 # when using ONE_SHOT_MAKEFILE.
@@ -526,9 +528,6 @@
 
 # Of the modules defined by the component makefiles,
 # determine what we actually want to build.
-# If a module has the "restricted" tag on it, it
-# poisons the rest of the tags and shouldn't appear
-# on any list.
 Default_MODULES := $(sort $(ALL_DEFAULT_INSTALLED_MODULES) \
                           $(CUSTOM_MODULES))
 # TODO: Remove the 3 places in the tree that use
@@ -554,12 +553,12 @@
 endif
 # Use tags to get the non-APPS user modules.  Use the product
 # definition files to get the APPS user modules.
-user_MODULES := $(sort $(call get-tagged-modules,user,_class@APPS restricted))
+user_MODULES := $(sort $(call get-tagged-modules,user))
 user_MODULES := $(user_MODULES) $(user_PACKAGES)
 
-eng_MODULES := $(sort $(call get-tagged-modules,eng,restricted))
-debug_MODULES := $(sort $(call get-tagged-modules,debug,restricted))
-tests_MODULES := $(sort $(call get-tagged-modules,tests,restricted))
+eng_MODULES := $(sort $(call get-tagged-modules,eng))
+debug_MODULES := $(sort $(call get-tagged-modules,debug))
+tests_MODULES := $(sort $(call get-tagged-modules,tests))
 
 ifeq ($(strip $(tags_to_install)),)
 $(error ASSERTION FAILED: tags_to_install should not be empty)
@@ -744,4 +743,3 @@
 .PHONY: showcommands
 showcommands:
 	@echo >/dev/null
-
diff --git a/core/node_fns.mk b/core/node_fns.mk
index 5d2a669..38ecea7 100644
--- a/core/node_fns.mk
+++ b/core/node_fns.mk
@@ -162,8 +162,9 @@
           $(call uniq-word,$($(_eiv_tv)),$(INHERIT_TAG)$(i))) \
       $(eval ### "Expand the inherit tag") \
       $(eval $(_eiv_tv) := \
-          $(patsubst $(INHERIT_TAG)$(i),$($(1).$(i).$(v)), \
-              $($(_eiv_tv)))) \
+          $(strip \
+              $(patsubst $(INHERIT_TAG)$(i),$($(1).$(i).$(v)), \
+                  $($(_eiv_tv))))) \
       $(eval ### "Clear the child so DAGs don't create duplicate entries" ) \
       $(eval $(1).$(i).$(v) :=) \
       $(eval ### "If we just inherited ourselves, it's a cycle.") \
@@ -187,7 +188,10 @@
   $(eval _include_stack := $(2) $$(_include_stack))
   $(call clear-var-list, $(3))
   $(eval LOCAL_PATH := $(patsubst %/,%,$(dir $(2))))
+  $(eval MAKEFILE_LIST :=)
   $(eval include $(2))
+  $(eval _included := $(filter-out $(2),$(MAKEFILE_LIST)))
+  $(eval MAKEFILE_LIST :=)
   $(eval LOCAL_PATH :=)
   $(call copy-var-list, $(1).$(2), $(3))
   $(call clear-var-list, $(3))
@@ -203,6 +207,13 @@
 endef
 
 #
+# This will generate a warning for _included above
+#  $(if $(_included), \
+#      $(eval $(warning product spec file: $(2)))\
+#      $(foreach _inc,$(_included),$(eval $(warning $(space)$(space)$(space)includes: $(_inc)))),)
+#
+
+#
 # $(1): context prefix
 # $(2): list of makefiles representing nodes to import
 # $(3): list of node variable names
diff --git a/core/package.mk b/core/package.mk
index d92a8b8..0b9036b 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -25,6 +25,19 @@
 ## be set for you.
 ###########################################################
 
+
+# If this makefile is being read from within an inheritance,
+# use the new values.
+skip_definition:=
+ifdef LOCAL_PACKAGE_OVERRIDES
+  package_overridden := $(call set-inherited-package-variables)
+  ifeq ($(strip $(package_overridden)),)
+    skip_definition := true
+  endif
+endif
+
+ifndef skip_definition
+
 LOCAL_PACKAGE_NAME := $(strip $(LOCAL_PACKAGE_NAME))
 ifeq ($(LOCAL_PACKAGE_NAME),)
 $(error $(LOCAL_PATH): Package modules must define LOCAL_PACKAGE_NAME)
@@ -69,8 +82,10 @@
   LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 endif
 LOCAL_RESOURCE_DIR := \
-  $(wildcard $(addsuffix /$(LOCAL_RESOURCE_DIR), $(PRODUCT_PACKAGE_OVERLAYS))) \
-  $(wildcard $(addsuffix /$(LOCAL_RESOURCE_DIR), $(DEVICE_PACKAGE_OVERLAYS))) \
+  $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \
+    $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \
+  $(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \
+    $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \
   $(LOCAL_RESOURCE_DIR)
 
 # this is an app, so add the system libraries to the search path
@@ -111,10 +126,24 @@
 
 LOCAL_BUILT_MODULE_STEM := package.apk
 
-proguard_options_file := $(package_expected_intermediates_COMMON)/proguard_options
-ifneq ($(strip $(LOCAL_PROGUARD_ENABLED)),custom)
-    LOCAL_PROGUARD_FLAGS := -include $(proguard_options_file) $(LOCAL_PROGUARD_FLAGS)
+LOCAL_PROGUARD_ENABLED:=$(strip $(LOCAL_PROGUARD_ENABLED))
+ifndef LOCAL_PROGUARD_ENABLED
+ifneq ($(filter user userdebug, $(TARGET_BUILD_VARIANT)),)
+    # turn on Proguard by default for user & userdebug build
+    LOCAL_PROGUARD_ENABLED :=full
 endif
+endif
+ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
+    # the package explicitly request to disable proguard.
+    LOCAL_PROGUARD_ENABLED :=
+endif
+proguard_options_file :=
+ifneq ($(LOCAL_PROGUARD_ENABLED),custom)
+ifneq ($(all_resources),)
+    proguard_options_file := $(package_expected_intermediates_COMMON)/proguard_options
+endif # all_resources
+endif # !custom
+LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
 
 # The dex files go in the package, so we don't
 # want to install them separately for this module.
@@ -244,6 +273,15 @@
 ifeq ($(LOCAL_CERTIFICATE),)
     LOCAL_CERTIFICATE := testkey
 endif
+
+ifeq ($(LOCAL_CERTIFICATE),EXTERNAL)
+  # The special value "EXTERNAL" means that we will sign it with the
+  # default testkey, apply predexopt, but then expect the final .apk
+  # (after dexopting) to be signed by an outside tool.
+  LOCAL_CERTIFICATE := testkey
+  PACKAGES.$(LOCAL_PACKAGE_NAME).EXTERNAL_KEY := 1
+endif
+
 # If this is not an absolute certificate, assign it to a generic one.
 ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)
     LOCAL_CERTIFICATE := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE)
@@ -280,3 +318,5 @@
 PACKAGES.$(LOCAL_PACKAGE_NAME).RESOURCE_FILES := $(all_resources)
 
 PACKAGES := $(PACKAGES) $(LOCAL_PACKAGE_NAME)
+
+endif # skip_definition
diff --git a/core/pathmap.mk b/core/pathmap.mk
index 1ae663d..25de0ea 100644
--- a/core/pathmap.mk
+++ b/core/pathmap.mk
@@ -72,6 +72,11 @@
 # A list of all source roots under frameworks/base, which will be
 # built into the android.jar.
 #
+# Note - "common" is included here, even though it is also built
+# into a static library (android-common) for unbundled use.  This
+# is so common and the other framework libraries can have mutual
+# interdependencies.
+#
 FRAMEWORKS_BASE_SUBDIRS := \
 	$(addsuffix /java, \
 	    core \
diff --git a/core/prebuilt.mk b/core/prebuilt.mk
index b2bb07c..b03f2af 100644
--- a/core/prebuilt.mk
+++ b/core/prebuilt.mk
@@ -42,19 +42,40 @@
 endif
 endif
 
-ifeq ($(LOCAL_CERTIFICATE),)
-  # can't re-sign this package, so predexopt is not available.
-else
-
-# If this is not an absolute certificate, assign it to a generic one.
-ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)
-    LOCAL_CERTIFICATE := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE)
+ifeq ($(LOCAL_CERTIFICATE),EXTERNAL)
+  # The magic string "EXTERNAL" means this package will be signed with
+  # the test key throughout the build process, but we expect the final
+  # package to be signed with a different key.
+  #
+  # This can be used for packages where we don't have access to the
+  # keys, but want the package to be predexopt'ed.
+  LOCAL_CERTIFICATE := testkey
+  PACKAGES.$(LOCAL_MODULE).EXTERNAL_KEY := 1
 endif
+ifeq ($(LOCAL_CERTIFICATE),)
+  ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
+    # It is now a build error to add a prebuilt .apk without
+    # specifying a key for it.
+    $(error No LOCAL_CERTIFICATE specified for prebuilt "$(LOCAL_SRC_FILES)")
+  endif
+else ifeq ($(LOCAL_CERTIFICATE),PRESIGNED)
+  # The magic string "PRESIGNED" means this package is already checked
+  # signed with its release key.
+  #
+  # By setting .CERTIFICATE but not .PRIVATE_KEY, this package will be
+  # mentioned in apkcerts.txt (with certificate set to "PRESIGNED")
+  # but the dexpreopt process will not try to re-sign the app.
+  PACKAGES.$(LOCAL_MODULE).CERTIFICATE := PRESIGNED
+  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
+else
+  # If this is not an absolute certificate, assign it to a generic one.
+  ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./)
+      LOCAL_CERTIFICATE := $(SRC_TARGET_DIR)/product/security/$(LOCAL_CERTIFICATE)
+  endif
 
-PACKAGES.$(LOCAL_MODULE).PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
-PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
-PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
-
+  PACKAGES.$(LOCAL_MODULE).PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+  PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
+  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
 endif
 
 ifneq ($(prebuilt_module_is_a_library),)
diff --git a/core/prelink-linux-arm.map b/core/prelink-linux-arm.map
index 64149bc..5ae1a78 100644
--- a/core/prelink-linux-arm.map
+++ b/core/prelink-linux-arm.map
@@ -52,6 +52,7 @@
 libpixelflinger.so      0xACF00000
 # libcorecg is for backward-compatibility with donut
 libcorecg.so            0xACE00000
+libsurfaceflinger_client.so 0xACD80000
 libsurfaceflinger.so    0xACD00000
 libGLES_android.so      0xACC80000
 libagl.so               0xACC00000
@@ -61,10 +62,12 @@
 libOpenVG_CM.so         0xAC900000
 libOpenVGU_CM.so        0xAC800000
 libEGL.so               0xAC700000
+libETC1.so              0xAC680000
 
 libacc.so               0xAC600000
 
 libexif.so              0xAC500000
+libcamera_client.so     0xAC480000
 libui.so                0xAC400000
 # libsgl is for backward-compatibility with donut
 libsgl.so               0xAC200000
@@ -143,7 +146,6 @@
 libwbxml.so             0x9E800000
 libwbxml_jni.so         0x9E400000
 libxml2wbxml.so         0x9E000000
-libaes.so               0x9DC00000
 libdrm1.so              0x9D800000
 libdrm1_jni.so          0x9D400000
 libwapcore.so           0x9D000000
@@ -162,5 +164,4 @@
 librpc.so               0x9A400000
 libtrace_test.so        0x9A300000
 libsrec_jni.so          0x9A200000
-libcerttool_jni.so      0x9A100000
-
+libjpeg.so              0x9A000000
diff --git a/core/product.mk b/core/product.mk
index 5417242..eca98ed 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -101,6 +101,14 @@
   $(eval ALL_PRODUCTS := $(sort $(ALL_PRODUCTS) $(word 1,$(_include_stack))))
 endef
 
+
+#
+# Do inherit-product only if $(1) exists
+#
+define inherit-product-if-exists
+  $(if $(wildcard $(1)),$(call inherit-product,$(1)),)
+endef
+
 #
 # $(1): product makefile list
 #
diff --git a/core/proguard.flags b/core/proguard.flags
index afd1548..3544b90 100644
--- a/core/proguard.flags
+++ b/core/proguard.flags
@@ -1,7 +1,54 @@
 # see http://sourceforge.net/tracker/?func=detail&aid=2787465&group_id=54750&atid=474707
 -optimizations !code/simplification/arithmetic
+-optimizations !code/simplification/cast
 -allowaccessmodification
 
+# To prevent name conflict in incremental obfuscation.
+-useuniqueclassmembernames
+
+# dex does not like code run through proguard optimize and preverify steps.
+-dontoptimize
+-dontpreverify
+
+# Don't obfuscate. We only need dead code striping.
+-dontobfuscate
+
+# Add this flag in your package's own configuration if it's needed.
+#-flattenpackagehierarchy
+
 # Some classes in the libraries extend package private classes to chare common functionality
 # that isn't explicitly part of the API
--dontskipnonpubliclibraryclasses
+-dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers
+
+# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+# class$ methods are inserted by some compilers to implement .class construct,
+# see http://proguard.sourceforge.net/manual/examples.html#library
+-keepclassmembernames class * {
+    java.lang.Class class$(java.lang.String);
+    java.lang.Class class$(java.lang.String, boolean);
+}
+
+# Please specify classes to be kept explicitly in your package's configuration.
+# -keep class * extends android.app.Activity
+# -keep class * extends android.view.View
+# -keep class * extends android.app.Service
+# -keep class * extends android.content.BroadcastReceiver
+# -keep class * extends android.content.ContentProvider
+# -keep class * extends android.preference.Preference
+# -keep class * extends android.app.BackupAgent
+
+#-keep class * implements android.os.Parcelable {
+#  public static final android.os.Parcelable$Creator *;
+#}
+
+
diff --git a/core/proguard_tests.flags b/core/proguard_tests.flags
new file mode 100644
index 0000000..f4063d6
--- /dev/null
+++ b/core/proguard_tests.flags
@@ -0,0 +1,21 @@
+# Keep everything for tests
+-dontshrink -dontobfuscate
+
+#-keep class * extends junit.framework.TestCase {
+#  public void test*();
+#}
+
+#-keepclasseswithmembers class * {
+#  public static void run();
+#  public static junit.framework.Test suite();
+#}
+
+# some AllTests don't include run().
+#-keepclasseswithmembers class * {
+#  public static junit.framework.Test suite();
+#}
+
+#-keep class * extends junit.framework.TestSuite
+#-keep class * extends android.app.Instrumentation
+#-keep class * extends android.test.TestSuiteProvider
+
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 9cc49c4..244371e 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 := 2.1-update1
+  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 := REL
+  PLATFORM_VERSION_CODENAME := Froyo
 endif
 
 ifeq "" "$(DEFAULT_APP_TARGET_SDK)"
diff --git a/envsetup.sh b/envsetup.sh
index 4eede33..1c114d0 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -625,7 +625,8 @@
             if [ -f $DIR/Android.mk ]; then
                 TO_CHOP=`echo $T | wc -c | tr -d ' '`
                 TO_CHOP=`expr $TO_CHOP + 1`
-                MFILE=`echo $PWD | cut -c${TO_CHOP}-`
+                START=`PWD= /bin/pwd`
+                MFILE=`echo $START | cut -c${TO_CHOP}-`
                 if [ "$MFILE" = "" ] ; then
                     MFILE=$DIR/Android.mk
                 else
@@ -770,7 +771,7 @@
 
 function cgrep()
 {
-    find . -type f -name "*\.c*" -print0 | xargs -0 grep --color -n "$@"
+    find . -type f \( -name '*.c' -o -name '*.cc' -o -name '*.cpp' -o -name '*.h' \) -print0 | xargs -0 grep --color -n "$@"
 }
 
 function resgrep()
@@ -985,9 +986,10 @@
         echo "Usage: godir <regex>"
         return
     fi
+    T=$(gettop)
     if [[ ! -f $T/filelist ]]; then
         echo -n "Creating index..."
-        (cd $T; find . -wholename ./out -prune -o -type f > filelist)
+        (cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > filelist)
         echo " Done"
         echo ""
     fi
diff --git a/history/cupcake.txt b/history/cupcake.txt
deleted file mode 100644
index 7947f93..0000000
--- a/history/cupcake.txt
+++ /dev/null
@@ -1,1103 +0,0 @@
-Cupcake auto-import at change 127436, Jan 22 2009.
-
-(cd bionic && git checkout c2f23bb1cdea20fc5e8e5b8101d9d0bd6d14b74b)
-(cd bootable/bootloader/legacy && git checkout d08c9e9444e2fb688ca4d3c4d807ba69c680fb3c)
-(cd bootable/diskinstaller && git checkout a2bb8bf00fbd01859e2475fc36fc6fa070e6eaa9)
-(cd bootable/recovery && git checkout 6d12e0d6f8fe05ebd6b0210fed00e0ff874a3d70)
-(cd build && git checkout b33e7b0cb085a1937c1a2e5b81eb78d6059bf6bc)
-(cd dalvik && git checkout cd18d5743d1957b1c1f57c0abe7ea28187c63a9f)
-(cd development && git checkout 2f3ec0146063b7bed40ff4f41c73407cebdc71fc)
-(cd external/aes && git checkout 17e798f9d2c0a804b5dcac6ee4b2bc1eee66e3b2)
-(cd external/apache-http && git checkout 4e30c8f9f80e5bd40fd8f018760b01a80b16b8c3)
-(cd external/bison && git checkout b7f2b4d529ee03ee0e4172cc06e7cd973bd9bef5)
-(cd external/bluez && git checkout dbbd69e74e390449430a6c357a098fd345fde2ed)
-(cd external/bsdiff && git checkout 03874566c6f74e11d030fa2c534b3dd5a06721af)
-(cd external/bzip2 && git checkout d78fa13a44d08622d61d0df71e731de77021dcf1)
-(cd external/clearsilver && git checkout b651aeec8a719c9f639ef710423e29463123d4f6)
-(cd external/dbus && git checkout ed0821c6a30852d02d05ce85d4ad4a567ff8a3da)
-(cd external/dhcpcd && git checkout 4c5a5fb53bccceff331bae70f748bf9b4609fe0a)
-(cd external/dosfstools && git checkout c936fe75ee33b6cbc46e6124679d9a1d5d471663)
-(cd external/dropbear && git checkout 1abbfe5d373a44e7e0525fb7971ef0e00955f2e4)
-(cd external/e2fsprogs && git checkout 0bc54db4f9a9aab8225f5107a712c4bbbe34f79c)
-(cd external/elfcopy && git checkout 8d6d7ea32d2e40489fa8be26618167fb6e2dfb40)
-(cd external/elfutils && git checkout ee6008996aa701ad2a50d5d6b1529c9e2c2724c1)
-(cd external/embunit && git checkout 225a86217dd274aea51b1e442568e7aec43a74e9)
-(cd external/emma && git checkout 725ce5e17f431acc3b549f87464a7883f98adf66)
-(cd external/esd && git checkout 7ef614b2e0ad463c3454cd9ba1052c2964e14596)
-(cd external/expat && git checkout da44bf784a2b6acb5df7f40b32c0d4b563fba3ed)
-(cd external/fdlibm && git checkout 74aa530c6ca9c2f10a0e3635b4211f1438b972b2)
-(cd external/freetype && git checkout b36db06baca4c030538565e01b8264971c9b69f8)
-(cd external/gdata && git checkout e784ba4a104f64d1f57dad38ff76764b5718bea0)
-(cd external/genext2fs && git checkout f4a0b4d282a1718ac6e3fff10d02aa877e294324)
-(cd external/giflib && git checkout ff6a75e423d8333c6657e4a66494e0bc9ed34385)
-(cd external/googleclient && git checkout d3974b69b023cb38541d1870ad5c35e4b2ea2c35)
-(cd external/grub && git checkout 1650e5296608be8925d9831310c9ad3595fd6869)
-(cd external/icu4c && git checkout 80865003e90c51ddd5f1e5e1be5ebc1add6af188)
-(cd external/iptables && git checkout 10a1e8d1003257d408c77662fc5ce6470a19b245)
-(cd external/jdiff && git checkout 0e7cb56de28fb496d69a1dd1907388b2076224d6)
-(cd external/jhead && git checkout 9705c3e3c1b19598026449c303d54cdc485f35a9)
-(cd external/jpeg && git checkout 9175dba76b0c31e0870fe074d476650cf258071c)
-(cd external/libffi && git checkout 8c63892438fbb7ef754e55c60220dd02e7c8fd70)
-(cd external/libpcap && git checkout 23295e59cff9c04be154ede6afad16bc9fe385cf)
-(cd external/libpng && git checkout 78ac9384d6ca0067d77b843b70bbdd828bb738df)
-(cd external/libxml2 && git checkout 2c905f99793b8da7f02349aa69fc01cba533f935)
-(cd external/netcat && git checkout 6fc2e7182a81d3665e5233a6555fc6c1960b6b8a)
-(cd external/netperf && git checkout acbeb739a2260972afbd58233fc8939fe5014e3c)
-(cd external/neven && git checkout dfddd36f99a6e11ca3b0107b49f35c623203c8f2)
-(cd external/opencore && git checkout 7a7c607909568a2a1b561023be821919bdb9d578)
-(cd external/openssl && git checkout 499ee9f31d10290f510c2f3785b6abe1314993ec)
-(cd external/oprofile && git checkout b0a81c270584f10323634816b6e5e19711690233)
-(cd external/ping && git checkout 8a5b42ad26815061053bc553b2d04fcbbce5f9d0)
-(cd external/ppp && git checkout 9d869087afe63b8506a367aaeb2008459c823ecf)
-(cd external/protobuf && git checkout 2f1917b2d9754d6288e8de2739469bf719438388)
-(cd external/qemu && git checkout 7a5cb2bf2725afddd4ff9ede151063d23b849d94)
-(cd external/safe-iop && git checkout a625f2f303bd1e1eb8287d82075fa9a240296167)
-(cd external/skia && git checkout 07051704de661e1c4e0fffc4f486afb60110f7e6)
-(cd external/sonivox && git checkout 372b906dec9f897dc04ba3bbd00c908bb2304e95)
-(cd external/sqlite && git checkout 60a965a2f8a63d7704130d867458495a324801e1)
-(cd external/srec && git checkout 00743dcf9e86961f3867b81ef81022040c821f18)
-(cd external/strace && git checkout 67670f6420d064f0b0f54ab2cf2f07752dcc35c7)
-(cd external/tagsoup && git checkout 4bb395b502d0c2495f7a5d226ccf7f06f53dea38)
-(cd external/tcpdump && git checkout f3ccc4ec63431539743f1155a60192a40f6bec24)
-(cd external/tinyxml && git checkout 600ebb441039bcb8a0340df016c6685a688b7647)
-(cd external/tremor && git checkout 0ad0141e864cfbb130db4f22e279d421832e7336)
-(cd external/webkit && git checkout 3607268bbf57cd3af1bb2d67e956821fb8e3c9ec)
-(cd external/wpa_supplicant && git checkout 17800c6dac7ac53c2b348151274071a4cc6e4318)
-(cd external/xdelta3 && git checkout 65fb2b2df617551c42d9bdf7b5bc88168ce6f1ff)
-(cd external/yaffs2 && git checkout d333fc232d7e5ae3370080d5d6f7d88ea9c6b3a1)
-(cd external/zlib && git checkout e860c69e014c1dfed34cf4ee808d200648205f2a)
-(cd frameworks/base && git checkout 94cbba0933e50d593c1c462cff698dd3387ba95b)
-(cd frameworks/opt/com.google.android && git checkout 95252a12ffcf47582ab8b68a35a996ef50cdb523)
-(cd frameworks/opt/com.google.android.googlelogin && git checkout 8f1d2acbab346be5c40d06d24a07bc169ad9c60e)
-(cd frameworks/policies/base && git checkout 880754ac4766e622367a6d65304c0b4176260e0d)
-(cd hardware/libhardware && git checkout 37156b8db0bee9a0e77160a40483d0fad0409bd4)
-(cd hardware/libhardware_legacy && git checkout 5af6317f266c0f7792f6a2fa1c2061f61529aab7)
-(cd hardware/ril && git checkout 154a2efc9b75de255cf9c3916d9d778c445df2ae)
-(cd kernel && git checkout 3c625cce51fadd88b75db8b6766de38f4ce7deaf)
-(cd packages/apps/AlarmClock && git checkout c8208f9f6ff76479da3b1eb0cedbd5500b8be1f4)
-(cd packages/apps/Browser && git checkout c3996145a81b44e27b7fad251e460ccf9c4a5d61)
-(cd packages/apps/Calculator && git checkout d3f7cb4de21253fbeeec0cf4b680bd79e6e62e8a)
-(cd packages/apps/Calendar && git checkout 1c94a74857db16dec676dc16e1ff58f9a4d0385c)
-(cd packages/apps/Camera && git checkout bf1c107ea0bbe8d80769b70d8e9b50dbf8cfcc09)
-(cd packages/apps/Contacts && git checkout cbe59e173d0baf73e98b12ac889ca17172677121)
-(cd packages/apps/Email && git checkout 6f463987544260a770b9203bd412fb665c59d0f9)
-(cd packages/apps/GoogleSearch && git checkout 2134a0d22132a8e68b6914ce466aa2acf28c244a)
-(cd packages/apps/HTMLViewer && git checkout ae36e6ba1ad74a7eb844a41c6c0fc1ecd3c66467)
-(cd packages/apps/IM && git checkout ad1551cc24ebeffda11932c1d2cae0cf1b69a854)
-(cd packages/apps/Launcher && git checkout a3673051acdee1f88b68ffc3a39f0db8529009ff)
-(cd packages/apps/Mms && git checkout 2d9959fea0cfea5fca09d139b66b1fa2cd45bf49)
-(cd packages/apps/Music && git checkout fa0935a617742fe1545bb65202d2b93af8985b6a)
-(cd packages/apps/PackageInstaller && git checkout 3a1faab9685bd0fc39ea7bf5bdc7237805d09c58)
-(cd packages/apps/Phone && git checkout 4974565b48789d5b12c302a846fc090e67039647)
-(cd packages/apps/Settings && git checkout c0a8abbb4f423c0aaa66a1e09bafd4b845837537)
-(cd packages/apps/SoundRecorder && git checkout eb2e5e6a43c0756e9d3e149f46f6a504747175f2)
-(cd packages/apps/Stk && git checkout 4e63a901fb044d270868b4f3abc8abb20d011230)
-(cd packages/apps/Sync && git checkout d8aa470c7fea6a43e269da78e1a2b8c14fb40c70)
-(cd packages/apps/Updater && git checkout 9e0cd9b717f546609ec155f6be3764554ede6408)
-(cd packages/apps/VoiceDialer && git checkout 1ab735e15b6855beabd22f5b87d497f83b3b5b6a)
-(cd packages/providers/CalendarProvider && git checkout 3690a0259f2c62501a47c9a4ecd007f1c1cc599a)
-(cd packages/providers/ContactsProvider && git checkout ef7f8057050027ce57424b69dc697d4127ffc37d)
-(cd packages/providers/DownloadProvider && git checkout b7f50f86e1f424ab05dc8154c3fabbfb3ecd4c47)
-(cd packages/providers/DrmProvider && git checkout 7f08c3d1582a2195fd7b28a3157dedd975230d8b)
-(cd packages/providers/GoogleContactsProvider && git checkout 1a6c0f279fe754b041290768bfa753e5f58e43ad)
-(cd packages/providers/GoogleSubscribedFeedsProvider && git checkout 88f4be5460c130c048e5017999a80275d71a88d6)
-(cd packages/providers/ImProvider && git checkout 8d4eb986192e7682c770449e0695d23d954a5691)
-(cd packages/providers/MediaProvider && git checkout ef92b4dc14a5f8093cb1b58888c213a867504afa)
-(cd packages/providers/TelephonyProvider && git checkout 62f78e4e0ae991f0df285488a1af382bd5105483)
-(cd prebuilt && git checkout 4ef7c54fb1bdfbd5e93d631c7f76ea216ab2d375)
-(cd system/bluetooth && git checkout 36658369459e22152cce54bd1c0660d71a270947)
-(cd system/core && git checkout 4a4c9f6f98055918f1ebff06b3cc1ed622c058fe)
-(cd system/extras && git checkout 1d68e595e72f955a8cd12f59825943ea71daf7d5)
-(cd system/wlan/ti && git checkout 6ff408df1efe9981f20ab8ce6ec36d6ff6f034dc)
-
-Change 127102
-
-	Allow different "Settings > About phone > Contributors" for different products.  The product-specific contributors.{html,css} are copied to /system/etc, and the Contributors activity loads it from there.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/build/core/product.mk#4 edit
-... //branches/cupcake/android/build/core/product_config.mk#9 edit
-
---------
-
-Change 127106
-
-	This removes the patch intended to fix this webkit bug
-	http://bugs.webkit.org/show_bug.cgi?id=16512
-	(orginally reported by this bug: http://b/issue?id=954816)
-	
-	The original bug can no longer be reproduced in webkit.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLAppletElement.cpp#3 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLEmbedElement.cpp#3 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLFormElement.cpp#3 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLFormElement.h#3 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLImageElement.cpp#3 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLImageElement.h#2 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLObjectElement.cpp#3 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLPlugInElement.cpp#2 edit
-... //branches/cupcake/android/external/webkit/WebCore/html/HTMLPlugInElement.h#2 edit
-
---------
-
-Change 127112
-
-	Added RemoteViews.setOnClickPendingIntent() that connects onClick events to launch PendingIntents.  Also exposed un-@hide RemoteViews.setImageViewBitmap().  Also added @RemoteView annotation to Button and ImageButton to allow them across the RemoteView boundary, and added tests to verify this happens.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/api/current.xml#105 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/widget/Button.java#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/widget/ImageButton.java#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/widget/RemoteViews.java#2 edit
-... //branches/cupcake/android/frameworks/base/tests/FrameworkTest/res/layout/remote_view_test_good.xml#2 edit
-... //branches/cupcake/android/frameworks/base/tests/FrameworkTest/tests/src/com/android/frameworktest/view/RemoteViewsActivityTest.java#2 edit
-
---------
-
-Change 127115
-
-	Fix bug where UMS wouldn't enable properly
-	
-
-Affected files ...
-
-... //branches/cupcake/android/system/core/vold/volmgr.c#8 edit
-
---------
-
-Change 127120
-
-	Automated rollback of changelist 127102.
-
-
-Affected files ...
-
-... //branches/cupcake/android/build/core/product.mk#5 edit
-... //branches/cupcake/android/build/core/product_config.mk#10 edit
-
---------
-
-Change 127126
-
-	Add back auto space on candidate selection.
-	Delay key feedback display.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/inputmethodservice/KeyboardView.java#9 edit
-
---------
-
-Change 127129
-
-	Remove the call to is.reset(). This allows callers to embedded data after the encoded bitmap and be able to retrieve it.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/graphics/java/android/graphics/BitmapFactory.java#2 edit
-
---------
-
-Change 127134
-
-	add copyPixelsFromBuffer, to allow developers to write pixels values with no format or alpha transformations that accompany using setPixels.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/development/samples/ApiDemos/AndroidManifest.xml#7 edit
-... //branches/cupcake/android/development/samples/ApiDemos/src/com/example/android/apis/graphics/BitmapPixels.java#1 add
-... //branches/cupcake/android/frameworks/base/api/current.xml#106 edit
-... //branches/cupcake/android/frameworks/base/core/jni/android/graphics/Bitmap.cpp#4 edit
-... //branches/cupcake/android/frameworks/base/graphics/java/android/graphics/Bitmap.java#2 edit
-
---------
-
-Change 127136
-
-	Fix power consumption notification when driver is removed
-	
-
-Affected files ...
-
-... //branches/cupcake/android/system/wlan/ti/sta_dk_4_0_4_32/pform/linux/src/esta_drv.c#10 edit
-
---------
-
-Change 127138
-
-	Enable building dosfstools for all non simulator builds
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/dosfstools/src/Android.mk#2 edit
-
---------
-
-Change 127142
-
-	Use a single button for both the mode indicator and the recording indicator.
-	This makes for a smoother user experience when using the trackball, as the
-	focus highlight stays on the button when you start recording.
-	
-	(Bonus: the code's shorter too. We just switch the button's drawable rather than
-	hiding one button and showing another.)
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Camera/res/layout/video_camera.xml#8 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/VideoCamera.java#25 edit
-
---------
-
-Change 127144
-
-	Fix problem that would leave the "now playing" list empty when removing the currently playing song from it.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Music/src/com/android/music/TrackBrowserActivity.java#13 edit
-
---------
-
-Change 127146
-
-	Handle NPE when search is invoked but no suggestions are
-	provided.  Also, add a field
-	that was missing in the parceling of SearchableInfo.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/app/SearchDialog.java#20 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/server/search/SearchableInfo.java#6 edit
-
---------
-
-Change 127147
-
-	Bug fix - SET UP CALL - sending confirmation result twice. TERMINAL RESPONSE is not needed.
-	
-	When the user's confirmation result is handled by Telephony->StkService, returns immediately after calling CommandInterface.handleCallSetupRequestFromSim(). This will insure that the no termainl response is going to be send.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java#2 edit
-
---------
-
-Change 127155
-
-	Don't switch back to video preview mode when bringing up the menu, except if
-	we're recording.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/VideoCamera.java#26 edit
-
---------
-
-Change 127159
-
-	Change back button behavior when ping-ponging between the still-image camera and
-	the single-image gallery view. Now going from the gallery back to the still-image
-	camera acts like a "back" as far as the activity stack is concerned.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/MenuHelper.java#19 edit
-
---------
-
-Change 127165
-
-	Added a test that attempts to access a nonexistent static field.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/dalvik/tests/064-field-access/expected.txt#2 edit
-... //branches/cupcake/android/dalvik/tests/064-field-access/src/GetNonexistent.java#1 add
-... //branches/cupcake/android/dalvik/tests/064-field-access/src/Holder.java#1 add
-... //branches/cupcake/android/dalvik/tests/064-field-access/src/Main.java#2 edit
-... //branches/cupcake/android/dalvik/tests/064-field-access/src2/Holder.java#1 add
-
---------
-
-Change 127170
-
-	Setup a place to put IMF/IME sample activities. The idea is to try to
-	create situations that we want to test the IMF/IME against, that aren't
-	necessarily represented well by the existing applications. Include an
-	input type test for starters.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/tests/ImfTest/Android.mk#1 add
-... //branches/cupcake/android/frameworks/base/tests/ImfTest/AndroidManifest.xml#1 add
-... //branches/cupcake/android/frameworks/base/tests/ImfTest/res/layout/sample_edit_text.xml#1 add
-... //branches/cupcake/android/frameworks/base/tests/ImfTest/res/values/strings.xml#1 add
-... //branches/cupcake/android/frameworks/base/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java#1 add
-
---------
-
-Change 127176
-
-	Expose API in SDK to remove cache files
-	
-	Add a new public api to free cache in PackageManager. The call back is via a pending intent.
-	Rename the api to freeStorage and change usage in other places.
-	Add a new unit test.
-	Remove DeviceMemoryMonitor from code base.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/cmds/installd/commands.c#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/app/ApplicationContext.java#5 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/content/pm/IPackageManager.aidl#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/content/pm/PackageManager.java#4 edit
-... //branches/cupcake/android/frameworks/base/services/java/com/android/server/DeviceMemoryMonitor.java#2 delete
-... //branches/cupcake/android/frameworks/base/services/java/com/android/server/DeviceStorageMonitorService.java#2 edit
-... //branches/cupcake/android/frameworks/base/services/java/com/android/server/PackageManagerService.java#6 edit
-... //branches/cupcake/android/frameworks/base/test-runner/android/test/mock/MockPackageManager.java#3 edit
-... //branches/cupcake/android/frameworks/base/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java#3 edit
-... //branches/cupcake/android/packages/apps/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java#5 edit
-
---------
-
-Change 127180
-
-	Fix TextAppearanceSpan parceling to write in the same
-	order as it reads.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/text/TextUtils.java#7 edit
-
---------
-
-Change 127182
-
-	* General cleanup
-	* Switch to supporting split file (one for platform, one for product
-	  specific entries).
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Email/res/xml/providers.xml#7 edit
-... //branches/cupcake/android/packages/apps/Email/res/xml/providers_product.xml#1 branch
-... //branches/cupcake/android/packages/apps/Email/src/com/android/email/activity/setup/AccountSetupBasics.java#7 integrate
-
---------
-
-Change 127194
-
-	Fix bug (The camera preview is not in full screen after using the trackball to select the "capture" button).  Also clean up the transitions between fullscreen and non-fullscreen a bit by animating the status bar.
-	Still not perfect, of course. :(
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/view/WindowManagerPolicy.java#2 edit
-... //branches/cupcake/android/frameworks/base/core/res/res/anim/status_bar_enter.xml#1 add
-... //branches/cupcake/android/frameworks/base/core/res/res/anim/status_bar_exit.xml#1 add
-... //branches/cupcake/android/frameworks/base/core/res/res/values/styles.xml#9 edit
-... //branches/cupcake/android/frameworks/base/services/java/com/android/server/WindowManagerService.java#14 edit
-... //branches/cupcake/android/frameworks/base/services/java/com/android/server/status/StatusBarService.java#7 edit
-... //branches/cupcake/android/frameworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.java#2 edit
-... //branches/cupcake/android/frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java#12 edit
-
---------
-
-Change 127197
-
-	Add broadcast intents for the following new external media events:
-	    - Volume is being disk checked
-	    - Volume is blank (no partition table or no supported filesystems)
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/content/Intent.java#11 edit
-
---------
-
-Change 127200
-
-	Camera work:
-	+ Define a standard, albeit currently @hidden, intent-extra for specifying that
-	  videos and/or pictures should be written to a given content URI.
-	  (This had been the hard-coded string "output". We kept the value the same so
-	  that any in-the-wild applications that use this extra will continue to work.)
-	
-	+ Add the ability to specify that a video is recorded to a given content URI.
-	  (Because we can't actually do this at the video camera level yet, we cheat
-	   and implement this feature using a copy-and-delete-the-original-video-file.)
-	
-	+ Add a test to the MarkTest scratch app to test out this new ability.
-	
-	+ Remove mention of the "pick" intent from the camera and video camera activities.
-	  (This was a copy-and-paste error from when the code was originally copied from
-	   the image gallery activities.)
-	
-	+ Wrap use of MediaMetadataRetriever in try / catch clauses because the
-	  media metadata retriever was observed to throw a runtime exception if it was
-	  given a garbage video file.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/provider/MediaStore.java#16 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/Camera.java#30 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/CropImage.java#4 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/ImageManager.java#13 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/MenuHelper.java#20 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/VideoCamera.java#27 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/Wallpaper.java#4 edit
-
---------
-
-Change 127225
-
-	Ensure that the fingerprint doesn't contain spaces.
-	
-	Strip the BoardConfig-defined variable.
-	
-	Fail if the fingerprint doesn't contain exactly one word.
-	
-	Remove an old check that is no longer necessary.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/build/core/Makefile#14 edit
-... //branches/cupcake/android/build/core/main.mk#18 edit
-
---------
-
-Change 127245
-
-	Temporarily disable A2DP and force audio hardware when any audio streams are ringtones, alarms or notifications.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/libs/audioflinger/AudioFlinger.cpp#18 edit
-... //branches/cupcake/android/frameworks/base/libs/audioflinger/AudioFlinger.h#10 edit
-
---------
-
-Change 127247
-
-	When the dom changes, preserve the focus unless the frame structure has
-	changed. The old test was too conservative, and required that the old and
-	new pointers match. With this change, only require that frame's position
-	in the parent hierarchy match.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/webkit/WebKit/android/nav/CachedFrame.cpp#3 edit
-... //branches/cupcake/android/external/webkit/WebKit/android/nav/CachedFrame.h#3 edit
-... //branches/cupcake/android/external/webkit/WebKit/android/nav/WebView.cpp#21 edit
-
---------
-
-Change 127249
-
-	Log a better message when rejecting a class because we're not able
-	to resolve a static field.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/dalvik/vm/analysis/CodeVerify.c#12 edit
-
---------
-
-Change 127250
-
-	Added a unique serial number to class objects.  This allows classes
-	to be uniquely identified in a world where the GC can move objects
-	around.
-	
-	This replaces the hprofSerialNumber that was included when
-	WITH_HPROF_STACK was defined.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/dalvik/vm/Globals.h#4 edit
-... //branches/cupcake/android/dalvik/vm/hprof/HprofClass.c#2 edit
-... //branches/cupcake/android/dalvik/vm/hprof/HprofStackFrame.c#2 edit
-... //branches/cupcake/android/dalvik/vm/mterp/common/asm-constants.h#3 edit
-... //branches/cupcake/android/dalvik/vm/oo/Array.c#3 edit
-... //branches/cupcake/android/dalvik/vm/oo/Class.c#5 edit
-... //branches/cupcake/android/dalvik/vm/oo/Class.h#2 edit
-... //branches/cupcake/android/dalvik/vm/oo/Object.h#3 edit
-... //branches/cupcake/android/dalvik/vm/reflect/Proxy.c#3 edit
-
---------
-
-Change 127253
-
-	Convert microseconds to milliseconds before formatting
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/os/BatteryStats.java#4 edit
-
---------
-
-Change 127254
-
-	Print a log message rather than a stack trace when the shared prefs file is unreadable
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/app/ApplicationContext.java#6 edit
-
---------
-
-Change 127259
-
-	Integration of the latest EAS and JET engine updates from Sonivox.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/sonivox/arm-wt-22k/host_src/jet.h#3 edit
-... //branches/cupcake/android/external/sonivox/arm-wt-22k/lib_src/eas_midi.c#2 edit
-... //branches/cupcake/android/external/sonivox/arm-wt-22k/lib_src/jet.c#3 edit
-... //branches/cupcake/android/external/sonivox/arm-wt-22k/lib_src/jet_data.h#2 edit
-
---------
-
-Change 127263
-
-	Adds the User dictionary settings, available via Settings > Locale and text > User dictionary, allowing you to see or add words to the user dictionary.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Settings/AndroidManifest.xml#14 edit
-... //branches/cupcake/android/packages/apps/Settings/res/drawable/ic_menu_add.png#1 add
-... //branches/cupcake/android/packages/apps/Settings/res/layout/dialog_edittext.xml#1 add
-... //branches/cupcake/android/packages/apps/Settings/res/layout/list_content_with_empty_view.xml#1 add
-... //branches/cupcake/android/packages/apps/Settings/res/values/strings.xml#26 edit
-... //branches/cupcake/android/packages/apps/Settings/res/xml/language_settings.xml#3 edit
-... //branches/cupcake/android/packages/apps/Settings/src/com/android/settings/UserDictionarySettings.java#1 add
-
---------
-
-Change 127270
-
-	Buffer the response data even for redirects. If the redirect turns out
-	to be null, use the buffered data in webcore.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/webkit/LoadListener.java#5 edit
-
---------
-
-Change 127272
-
-	This removes the quarter second delay when passing a set focus message from
-	WebView to WebCore. 
-	
-	The delay was originally added in March of 2008 to help reduce the burden
-	on WebCore when moving across several items with the trackball in quick secession.
-	By delaying the event, it is easier to detect if there are subsequent events
-	before the first is executed, allowing intermediate JavaScript, layout, and 
-	display list builds to be deferred until the user is finished navigating.
-	
-	Since March, JavaScript and display list building are substantially faster.
-	The old design makes it difficult to keep items in order since not all events
-	(e.g. resizing the window) are delayed the same.
-	
-	This change preserves the code that discards navigation events as WebCore
-	falls behind -- the change causes only the first trackball movement to make
-	it to WebCore, where with the delay, the first movement may be ignored.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/webkit/WebView.java#29 edit
-
---------
-
-Change 127273
-
-	Pass the mouse click through to webkit, even if the node hit isn't valid.
-	
-	The node and frame are captured when the nav cache is built. They may not
-	still be around when a later mouse click is processed. If either are not
-	valid, skip special code that deals with image maps and menu lists, but
-	still pass the mouse click to the main frame.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/webkit/WebKit/android/jni/WebViewCore.cpp#16 edit
-
---------
-
-Change 127274
-
-	Overhaul bonding API.
-	
-	- listBondings() is now listBonds() and uses cached values in the system
-	  server
-	- hasBonding() is now getBondState() and uses cached values in the system
-	  server. It also returns an integer state code now to include the
-	  in-progress state (BOND_BONDING)
-	- createBonding() is now createBond() and no longer has an async callback.
-	  Use intents instead.
-	- BONDING_CREATED_ACTION / BONDING_REMOVED_ACTION are now
-	  BOND_STATE_CHANGED_ACTION with state codes, and result codes.
-	- Introduced BluetoothDevice.BOND_RESULT_* result codes so the UI can pick
-	  a nicer error message. TODO(jasonparekh): update the UI to use these result codes.
-	- Removed Setttings App PAIRING_STATUS in favor of BluetoothDevice.BOND_*
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/bluetooth/BluetoothDevice.java#4 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/bluetooth/BluetoothIntent.java#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/bluetooth/IBluetoothDevice.aidl#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/server/BluetoothA2dpService.java#9 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/server/BluetoothDeviceService.java#6 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/server/BluetoothEventLoop.java#4 edit
-... //branches/cupcake/android/frameworks/base/core/jni/android_server_BluetoothDeviceService.cpp#2 edit
-... //branches/cupcake/android/frameworks/base/core/jni/android_server_BluetoothEventLoop.cpp#6 edit
-... //branches/cupcake/android/packages/apps/Phone/src/com/android/phone/BluetoothHeadsetService.java#6 edit
-... //branches/cupcake/android/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothEventRedirector.java#3 edit
-... //branches/cupcake/android/packages/apps/Settings/src/com/android/settings/bluetooth/LocalBluetoothDevice.java#8 edit
-... //branches/cupcake/android/packages/apps/Settings/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java#6 edit
-... //branches/cupcake/android/packages/apps/Settings/src/com/android/settings/bluetooth/LocalBluetoothManager.java#5 edit
-... //branches/cupcake/android/packages/apps/Settings/src/com/android/settings/bluetooth/SettingsBtStatus.java#2 edit
-
---------
-
-Change 127275
-
-	Added class name to "pure-abstract" warning.  Added a test case that
-	exercises "conversion" of the superclass declaration from concrete to
-	abstract.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/dalvik/tests/032-concrete-sub/expected.txt#2 edit
-... //branches/cupcake/android/dalvik/tests/032-concrete-sub/info.txt#2 edit
-... //branches/cupcake/android/dalvik/tests/032-concrete-sub/src/AbstractBase.java#2 edit
-... //branches/cupcake/android/dalvik/tests/032-concrete-sub/src/ConcreteSub.java#2 edit
-... //branches/cupcake/android/dalvik/tests/032-concrete-sub/src/ConcreteSub2.java#1 add
-... //branches/cupcake/android/dalvik/tests/032-concrete-sub/src/Main.java#2 edit
-... //branches/cupcake/android/dalvik/tests/032-concrete-sub/src2/AbstractBase.java#2 edit
-... //branches/cupcake/android/dalvik/vm/analysis/DexOptimize.c#5 edit
-
---------
-
-Change 127278
-
-	Bug 1555561: Make the EditTexts in the "Add Bookmark" dialog
-	single-line so they don't stretch and mess up the layout.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Browser/res/layout/browser_add_bookmark.xml#2 edit
-
---------
-
-Change 127282
-
-	   Fix build.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java#3 edit
-
---------
-
-Change 127283
-
-	   Clean up some old cruft.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/system/core/init/devices.c#7 edit
-
---------
-
-Change 127285
-
-	sync with demetrius r75
-	allow to build with scalar==fixed again
-	remove some unneeded SK_BUILD_FOR_MAC tests
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/skia/include/core/SkBitmap.h#2 edit
-... //branches/cupcake/android/external/skia/src/core/SkFloatBits.cpp#2 edit
-... //branches/cupcake/android/external/skia/src/core/SkGraphics.cpp#4 edit
-... //branches/cupcake/android/external/skia/src/core/SkMath.cpp#3 edit
-... //branches/cupcake/android/external/skia/src/ports/SkFontHost_mac.cpp#3 edit
-
---------
-
-Change 127289
-
-	Increase MMS size to 1MB.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/core/java/android/provider/Settings.java#28 edit
-... //branches/cupcake/android/packages/apps/Mms/src/com/android/mms/model/CarrierContentRestriction.java#2 edit
-... //branches/cupcake/android/packages/apps/Mms/src/com/android/mms/model/ContentRestriction.java#2 edit
-... //branches/cupcake/android/packages/apps/Mms/src/com/android/mms/model/SlideshowModel.java#2 edit
-
---------
-
-Change 127297
-
-	Fixing Socket Spec
-	Fixing a Bug where SecurityManager.checkConnect is called with the
-	host name instead of the host address as it is specified and
-	implemented by the RI.
-	Reenabling comented out code in InetAddress.getLocalHost()
-	Fixed an error in InetAddress.equals() where we were not adhering to the spec.
-	Applied some fixes copied from harmony to not have to deal with dem later.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/dalvik/libcore/luni/src/main/java/java/net/InetAddress.java#5 edit
-... //branches/cupcake/android/dalvik/libcore/luni/src/main/java/java/net/NegCacheElement.java#3 edit
-... //branches/cupcake/android/dalvik/libcore/luni/src/main/java/java/net/NegativeCache.java#3 edit
-... //branches/cupcake/android/dalvik/libcore/luni/src/main/java/java/net/Socket.java#3 edit
-
---------
-
-Change 127310
-
-	Fix ToggleButton. A previous change I made was based on a false assumption about how LayerDrawable works. A LayerDrawable *adds* the padding of all of its layers, each layer being translated by the padding of the layer below it. Surprising, but necessary to make widgets like ToggleButton work.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/graphics/java/android/graphics/drawable/LayerDrawable.java#4 edit
-
---------
-
-Change 127315
-
-	Implement "IME: Add transactions to InputConnection".  Also change the background dim amount, which I forgot to include with my previous check-in. :)
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/api/current.xml#107 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/view/inputmethod/InputConnection.java#11 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/view/inputmethod/InputConnectionWrapper.java#9 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java#22 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/widget/TextView.java#23 edit
-... //branches/cupcake/android/frameworks/base/core/java/com/android/internal/view/IInputConnectionWrapper.java#11 edit
-... //branches/cupcake/android/frameworks/base/core/java/com/android/internal/view/IInputContext.aidl#10 edit
-... //branches/cupcake/android/frameworks/base/core/java/com/android/internal/view/InputConnectionWrapper.java#10 edit
-... //branches/cupcake/android/frameworks/base/core/java/com/android/internal/widget/EditableInputConnection.java#11 edit
-... //branches/cupcake/android/frameworks/base/core/res/res/values/themes.xml#6 edit
-
---------
-
-Change 127338
-
-	Reset variables in bluetooth_start() to fix intermittent glitches resuming A2DP after standby.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/bluez/utils/audio/liba2dp.c#12 edit
-
---------
-
-Change 127341
-
-	ButtonActivity - test to see if softkeyboard responds correctly to button activity.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/tests/ImfTest/AndroidManifest.xml#2 edit
-... //branches/cupcake/android/frameworks/base/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java#1 add
-
---------
-
-Change 127342
-
-	   Make GadgetService get the list of gadgets by querying the package
-	   manager, and having a configuration xml file instead of hard coding
-	   it.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/api/current.xml#108 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/gadget/GadgetManager.java#2 edit
-... //branches/cupcake/android/frameworks/base/core/java/com/android/internal/gadget/IGadgetService.aidl#2 edit
-... //branches/cupcake/android/frameworks/base/core/res/res/values/attrs.xml#32 edit
-... //branches/cupcake/android/frameworks/base/core/res/res/values/public.xml#32 edit
-... //branches/cupcake/android/frameworks/base/services/java/com/android/server/GadgetService.java#2 edit
-... //branches/cupcake/android/frameworks/base/tests/GadgetHost/AndroidManifest.xml#2 edit
-... //branches/cupcake/android/frameworks/base/tests/GadgetHost/src/com/android/gadgethost/GadgetHostActivity.java#2 edit
-... //branches/cupcake/android/frameworks/base/tests/GadgetHost/src/com/android/gadgethost/GadgetPickActivity.java#2 edit
-
---------
-
-Change 127344
-
-	Make sure the music service also stops itself if it got killed and restarted by the system.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Music/src/com/android/music/MediaPlaybackService.java#10 edit
-
---------
-
-Change 127347
-
-	   add the gadget_info xml file
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/tests/GadgetHost/res/xml/gadget_info.xml#1 add
-
---------
-
-Change 127356
-
-	Submit rightly signed 64-bit driver
-	
-
-Affected files ...
-
-... //branches/cupcake/android/development/host/windows/prebuilt/usb/driver_amd_64/androidusb.sys#3 edit
-... //branches/cupcake/android/development/host/windows/prebuilt/usb/driver_amd_64/androidusba64.cat#3 edit
-
---------
-
-Change 127362
-
-	Use mmap to load speech model files.  Use const.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/srec/srec/clib/log_add.h#2 edit
-... //branches/cupcake/android/external/srec/srec/clib/swimodel.c#2 edit
-... //branches/cupcake/android/external/srec/srec/clib/voc_read.c#2 edit
-... //branches/cupcake/android/external/srec/srec/crec/c47mulsp.c#2 edit
-... //branches/cupcake/android/external/srec/srec/crec/get_fram.c#2 edit
-... //branches/cupcake/android/external/srec/srec/crec/srec.c#2 edit
-... //branches/cupcake/android/external/srec/srec/include/c42mul.h#2 edit
-... //branches/cupcake/android/external/srec/srec/include/hmmlib.h#2 edit
-... //branches/cupcake/android/external/srec/srec/include/simapi.h#2 edit
-... //branches/cupcake/android/external/srec/srec/include/srec.h#2 edit
-... //branches/cupcake/android/external/srec/srec/include/swimodel.h#2 edit
-... //branches/cupcake/android/external/srec/tools/grxmlcompile/grph.h#2 edit
-
---------
-
-Change 127363
-
-	Bug 1547138: Add copyright headers to translated strings files.
-	Don't generate files that don't actually contain any translations.
-	Check in code for generating translation console flat-file format.
-	
-
-Affected files ...
-
-[list deleted]
-
---------
-
-Change 127371
-
-	Clean up termination of the GPS network thread.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/location/java/com/android/internal/location/GpsLocationProvider.java#6 edit
-
---------
-
-Change 127377
-
-	Introduce a new Activity callback, onUserLeaving(), that is invoked whenever the user initiates an action that causes the activity to be moved away from being frontmost.
-	
-	Any code that starts activities "silently," without the user having prompted the action, should supply the new Intent.FLAG_ACTIVITY_NO_USER_ACTION flag when calling startActivity().  This instructs the Activity Manager that this focus change is not due to user activity, suppressing the onUserLeaving() callback.  This is important to preserve the reliability of the onUserLeaving() callback indicating a specific user choice to navigate to the new activity.
-	
-	The two known apps in the tree that forcibly start activities without user activity have also been updated to use this new Intent flag:  Phone and AlarmClock.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/frameworks/base/api/current.xml#109 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/app/Activity.java#9 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/app/ActivityThread.java#6 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/app/ApplicationThreadNative.java#3 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/app/IApplicationThread.java#3 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/app/Instrumentation.java#3 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/content/Intent.java#12 edit
-... //branches/cupcake/android/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java#11 edit
-... //branches/cupcake/android/packages/apps/AlarmClock/src/com/android/alarmclock/AlarmReceiver.java#4 edit
-... //branches/cupcake/android/packages/apps/Phone/src/com/android/phone/PhoneApp.java#6 edit
-
---------
-
-Change 127385
-
-	marking bookmarks as untranslatable
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Browser/res/values/strings.xml#15 integrate
-
---------
-
-Change 127387
-
-	Test case to make sure we don't reuse the "this" register in
-	instance methods.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/dalvik/dx/tests/110-dex-preserve-this/Blort.java#1 add
-... //branches/cupcake/android/dalvik/dx/tests/110-dex-preserve-this/expected.txt#1 add
-... //branches/cupcake/android/dalvik/dx/tests/110-dex-preserve-this/info.txt#1 add
-... //branches/cupcake/android/dalvik/dx/tests/110-dex-preserve-this/run#1 add
-
---------
-
-Change 127392
-
-	update the 'update-audio.sh' script that is used to upload a new prebuilt version
-	of the QEMU audio sub-system for Linux.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/qemu/Makefile.android#10 integrate
-... //branches/cupcake/android/external/qemu/distrib/update-audio.sh#2 edit
-... //branches/cupcake/android/prebuilt/linux-x86/emulator/libqemu-audio.a#2 edit
-
---------
-
-Change 127400
-
-	Fix the problem where the build would break looking for "@".
-	
-	built_ota_tools should have been a list of files, not a list
-	of commands to build those files.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/build/core/Makefile#15 edit
-
---------
-
-Change 127406
-
-	Fix bug (Bottom/Menu portion of the screen is appearing black).  There were a bunch of issues with deciding when to show the IME window, and a big issue in the sample keyboard IME with when it was handing starting of input (it would only work if the keyboard view had been created).
-	
-
-Affected files ...
-
-... //branches/cupcake/android/development/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java#6 edit
-... //branches/cupcake/android/frameworks/base/core/java/android/inputmethodservice/InputMethodService.java#21 edit
-
---------
-
-Change 127412
-
-	   Fix timer subtraction when there is > 1 second difference.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/bluez/utils/audio/liba2dp.c#13 edit
-
---------
-
-Change 127433
-
-	Fix Mac build of the emulator
-	
-
-Affected files ...
-
-... //branches/cupcake/android/external/qemu/Makefile.android#11 edit
-
---------
-
-Change 127436
-
-	 Camera: Create a subclass of ImageView that can be used as a camera button.
-	+ Clients can register for notification when the button is pressed, optionally clicked,
-	and released.
-	     - note that you can press a button, then move your finger off of it before releasing,
-	       in which case ther would be a pressed and a released notification, but no clicked
-	       notification.
-	     - The reason we want to do this is so we can emulate the physical camera button, which
-	       has focus down, optional camera down-and-up, and focus up events.
-	+ The pressed, clicked, and released notifications are delivered in that order, both for
-	  touch presses and for trackball/dpad presses. (This was tricky because the UI
-	  framework delivers the underlying notifications in a different order for the two
-	  types of input.)
-	+ Use the new shutter button in the still-image camera. We don't yet need it in the
-	  video camera, but it could be used there as well.
-	
-
-Affected files ...
-
-... //branches/cupcake/android/packages/apps/Camera/res/layout/camera.xml#16 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/Camera.java#31 edit
-... //branches/cupcake/android/packages/apps/Camera/src/com/android/camera/ShutterButton.java#1 add
-
---------
-
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 1bf3c3f..94b0e24 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -26,8 +26,7 @@
 #
 
 PRODUCT_MAKEFILES := \
+    $(LOCAL_DIR)/core.mk \
     $(LOCAL_DIR)/generic.mk \
-    $(LOCAL_DIR)/min_dev.mk \
     $(LOCAL_DIR)/sdk.mk \
-    $(LOCAL_DIR)/sim.mk \
-    $(LOCAL_DIR)/generic_with_google.mk
+    $(LOCAL_DIR)/sim.mk
diff --git a/target/product/core.mk b/target/product/core.mk
index a93ba7c..d8962ea 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -1,7 +1,25 @@
-PRODUCT_BRAND :=
-PRODUCT_NAME :=
-PRODUCT_DEVICE :=
+#
+# 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.
+#
+
+PRODUCT_BRAND := generic
+PRODUCT_DEVICE := generic
+PRODUCT_NAME := core
+
 PRODUCT_POLICY := android.policy_phone
+
 PRODUCT_PROPERTY_OVERRIDES := \
     ro.config.notification_sound=OnTheHunt.ogg \
     ro.config.alarm_alert=Alarm_Classic.ogg
@@ -10,13 +28,12 @@
     framework-res \
     Browser \
     Contacts \
-    Launcher \
+    Home \
     HTMLViewer \
     Phone \
     ApplicationsProvider \
     ContactsProvider \
     DownloadProvider \
-    GoogleSearch \
     MediaProvider \
     PicoTts \
     SettingsProvider \
@@ -25,4 +42,11 @@
     VpnServices \
     UserDictionaryProvider \
     PackageInstaller \
+    DefaultContainerService \
     Bugreport
+
+PRODUCT_PROPERTY_OVERRIDES += \
+    media.stagefright.enable-player=true \
+    media.stagefright.enable-meta=true   \
+    media.stagefright.enable-scan=true   \
+    media.stagefright.enable-http=true
diff --git a/target/product/generic.mk b/target/product/generic.mk
index 8c85ca6..c12f1c6 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -1,10 +1,25 @@
+#
+# 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 that isn't specialized for a specific device.
-# It includes the base Android platform. If you need Google-specific features,
-# you should derive from generic_with_google.mk
+# It includes the base Android platform.
 
 PRODUCT_PACKAGES := \
     AccountAndSyncSettings \
-    AlarmClock \
+    DeskClock \
     AlarmProvider \
     Bluetooth \
     Calculator \
@@ -13,11 +28,12 @@
     CertInstaller \
     DrmProvider \
     Email \
-    Gallery \
     LatinIME \
+    Launcher2 \
     Mms \
     Music \
     Provision \
+    QuickSearchBox \
     Settings \
     Sync \
     Updater \
diff --git a/target/product/generic_with_google.mk b/target/product/generic_with_google.mk
deleted file mode 100644
index ba30f15..0000000
--- a/target/product/generic_with_google.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# This is a generic product that isn't specialized for a specific device.
-# It includes the base Android platform including some Google-specific features.
-# If you do not want to include Google specific features, you should derive 
-# from generic.mk
-
-PRODUCT_PACKAGES := \
-    ContactsProvider \
-    GoogleContactsSyncAdapter \
-    GoogleSubscribedFeedsProvider \
-    com.google.android.gtalkservice \
-    com.google.android.datamessaging \
-    com.google.android.maps
-
-PRODUCT_COPY_FILES := \
-    vendor/google/frameworks/maps/com.google.android.maps.xml:system/etc/permissions/com.google.android.maps.xml \
-    vendor/google/frameworks/datamessaging/com.google.android.datamessaging.xml:system/etc/permissions/com.google.android.datamessaging.xml \
-    vendor/google/apps/GTalkService/com.google.android.gtalkservice.xml:system/etc/permissions/com.google.android.gtalkservice.xml
-
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
-
-# Overrides
-PRODUCT_NAME := generic_with_google
diff --git a/target/product/min_dev.mk b/target/product/min_dev.mk
deleted file mode 100644
index 92ba973..0000000
--- a/target/product/min_dev.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-
-PRODUCT_POLICY := android.policy_phone
-PRODUCT_PROPERTY_OVERRIDES := \
-    ro.config.notification_sound=OnTheHunt.ogg \
-    ro.config.alarm_alert=Alarm_Classic.ogg
-PRODUCT_BRAND := generic
-PRODUCT_NAME := min_dev
-PRODUCT_DEVICE := generic
-
-PRODUCT_PACKAGES := \
-    DownloadProvider \
-    GoogleSearch \
-    MediaProvider \
-    SettingsProvider \
-    PackageInstaller \
-    Bugreport \
-    Launcher \
-    Settings \
-    sqlite3
-
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index e571f9e..ccf7ed1 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -1,3 +1,19 @@
+#
+# 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.
+#
+
 PRODUCT_PROPERTY_OVERRIDES :=
 
 PRODUCT_PACKAGES := \
@@ -11,7 +27,7 @@
 	Fallback \
 	Gallery \
 	GPSEnable \
-	Launcher \
+	Launcher2 \
 	Music \
 	Mms \
 	Settings \
diff --git a/target/product/security/README b/target/product/security/README
index b92693d..24f984c 100644
--- a/target/product/security/README
+++ b/target/product/security/README
@@ -1,13 +1,9 @@
-The following commands were used to generate the test key pair:
+The following commands were used to generate the test key pairs:
 
-  openssl genrsa -3 -out testkey.pem 2048
-
-  openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 \
-    -subj '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
-
-  openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt
-
-Alternatively you can use the "mkkey.sh" command included in this directory.
+  development/tools/make_key testkey  '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
+  development/tools/make_key platform '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
+  development/tools/make_key shared   '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
+  development/tools/make_key media    '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
 
 The following standard test keys are currently included:
 
@@ -28,11 +24,11 @@
    % openssl pkcs8 -inform DER -nocrypt -in testkey.pk8 -out testkey.pem
 
 2. create a signature using the pem format key
-   % openssl dgst -binary -sha1 -sign testkey.pem FILE > FILE.sig 
+   % openssl dgst -binary -sha1 -sign testkey.pem FILE > FILE.sig
 
 extracting public keys for embedding
 ------------------------------------
 it's a Java tool
 but it generates C code
 take a look at commands/recovery/Android.mk
-you'll see it running $(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar
\ No newline at end of file
+you'll see it running $(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar
diff --git a/target/product/security/mkkey.sh b/target/product/security/mkkey.sh
deleted file mode 100644
index 86744f6..0000000
--- a/target/product/security/mkkey.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-if ["$1" == ""]; then
-	echo "Create a test certificate key."
-	echo "Usage: $0 NAME"
-	echo "Will generate NAME.pk8 and NAME.x509.pem"
-	echo "  /C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com"
-	return
-fi
-
-openssl genrsa -3 -out $1.pem 2048
-
-openssl req -new -x509 -key $1.pem -out $1.x509.pem -days 10000 \
-    -subj '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
-
-openssl pkcs8 -in $1.pem -topk8 -outform DER -out $1.pk8 -nocrypt
-
diff --git a/target/product/sim.mk b/target/product/sim.mk
index 4403e46..51b3676 100644
--- a/target/product/sim.mk
+++ b/target/product/sim.mk
@@ -1,6 +1,3 @@
-PRODUCT_PACKAGES := \
-	IM
-
 $(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
 
 # Overrides
diff --git a/tools/adbs b/tools/adbs
index 8b1fac6..815ae10 100755
--- a/tools/adbs
+++ b/tools/adbs
@@ -217,6 +217,7 @@
       SymbolTranslation(groups)
     else:
       print line
+      sys.stdout.flush()
 
   # adb itself aborts
   stream.close()
diff --git a/tools/apicheck/src/com/android/apicheck/ApiInfo.java b/tools/apicheck/src/com/android/apicheck/ApiInfo.java
index 01d8f9e..c237814 100644
--- a/tools/apicheck/src/com/android/apicheck/ApiInfo.java
+++ b/tools/apicheck/src/com/android/apicheck/ApiInfo.java
@@ -26,8 +26,19 @@
         mPackages = new HashMap<String, PackageInfo>();
         mAllClasses = new HashMap<String, ClassInfo>();
     }
+
+    public ClassInfo findClass(String name) {
+        return mAllClasses.get(name);
+    }
+
+    private 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 5405ad2..e62a3d0 100644
--- a/tools/apicheck/src/com/android/apicheck/ClassInfo.java
+++ b/tools/apicheck/src/com/android/apicheck/ClassInfo.java
@@ -26,7 +26,8 @@
     private boolean mIsFinal;
     private String mDeprecated;
     private String mScope;
-    private List<String> mInterfaces;
+    private List<String> mInterfaceNames;
+    private List<ClassInfo> mInterfaces;
     private HashMap<String, MethodInfo> mMethods;
     private HashMap<String, FieldInfo> mFields;
     private HashMap<String, ConstructorInfo> mConstructors;
@@ -48,7 +49,8 @@
         mIsFinal = isFinal;
         mDeprecated = deprecated;
         mScope = visibility;
-        mInterfaces = new ArrayList<String>();
+        mInterfaceNames = new ArrayList<String>();
+        mInterfaces = new ArrayList<ClassInfo>();
         mMethods = new HashMap<String, MethodInfo>();
         mFields = new HashMap<String, FieldInfo>();
         mConstructors = new HashMap<String, ConstructorInfo>();
@@ -109,6 +111,18 @@
         return null;
     }
     
+    // Find a superinterface declaration of the given method.
+    public MethodInfo interfaceMethod(MethodInfo candidate) {
+        for (ClassInfo interfaceInfo : mInterfaces) {
+            for (MethodInfo mi : interfaceInfo.mMethods.values()) {
+                if (mi.matches(candidate)) {
+                    return mi;
+                }
+            }
+        }
+        return (mSuperClass != null) ? mSuperClass.interfaceMethod(candidate) : null;
+    }
+
     public boolean isConsistent(ClassInfo cl) {
         cl.mExistsInBoth = true;
         mExistsInBoth = true;
@@ -120,14 +134,18 @@
                     + " changed class/interface declaration");
             consistent = false;
         }
-        for (String iface : mInterfaces) {
-            if (!cl.mInterfaces.contains(iface)) {
+        for (String iface : mInterfaceNames) {
+            boolean found = false;
+            for (ClassInfo c = cl; c != null && !found; c = c.mSuperClass) {
+                found = c.mInterfaceNames.contains(iface);
+            }
+            if (!found) {
                 Errors.error(Errors.REMOVED_INTERFACE, cl.position(),
                         "Class " + qualifiedName() + " no longer implements " + iface);
             }
         }
-        for (String iface : cl.mInterfaces) {
-          if (!mInterfaces.contains(iface)) {
+        for (String iface : cl.mInterfaceNames) {
+          if (!mInterfaceNames.contains(iface)) {
               Errors.error(Errors.ADDED_INTERFACE, cl.position(),
                       "Added interface " + iface + " to class "
                       + qualifiedName());
@@ -147,6 +165,9 @@
                  */
                 MethodInfo mi = mInfo.containingClass().overriddenMethod(mInfo);
                 if (mi == null) {
+                    mi = mInfo.containingClass().interfaceMethod(mInfo);
+                }
+                if (mi == null) {
                     Errors.error(Errors.REMOVED_METHOD, mInfo.position(),
                             "Removed public method " + mInfo.qualifiedName());
                     consistent = false;
@@ -252,9 +273,15 @@
         
         return consistent;
     }
+
+    public void resolveInterfaces(ApiInfo apiInfo) {
+        for (String interfaceName : mInterfaceNames) {
+            mInterfaces.add(apiInfo.findClass(interfaceName));
+        }
+    }
     
     public void addInterface(String name) {
-        mInterfaces.add(name);
+        mInterfaceNames.add(name);
     }
     
     public void addMethod(MethodInfo mInfo) {
diff --git a/tools/applypatch/Android.mk b/tools/applypatch/Android.mk
deleted file mode 100644
index d20d6c8..0000000
--- a/tools/applypatch/Android.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ifneq ($(TARGET_SIMULATOR),true)
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := applypatch.c bspatch.c freecache.c imgpatch.c utils.c
-LOCAL_MODULE := libapplypatch
-LOCAL_MODULE_TAGS := eng
-LOCAL_C_INCLUDES += external/bzip2 external/zlib bootable/recovery
-LOCAL_STATIC_LIBRARIES += libmtdutils libmincrypt libbz libz
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := main.c
-LOCAL_MODULE := applypatch
-LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz
-LOCAL_SHARED_LIBRARIES += libz libcutils libstdc++ libc
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := main.c
-LOCAL_MODULE := applypatch_static
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE_TAGS := eng
-LOCAL_STATIC_LIBRARIES += libapplypatch libmtdutils libmincrypt libbz
-LOCAL_STATIC_LIBRARIES += libz libcutils libstdc++ libc
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := imgdiff.c utils.c bsdiff.c
-LOCAL_MODULE := imgdiff
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE_TAGS := eng
-LOCAL_C_INCLUDES += external/zlib external/bzip2
-LOCAL_STATIC_LIBRARIES += libz libbz
-
-include $(BUILD_HOST_EXECUTABLE)
-
-endif  # !TARGET_SIMULATOR
diff --git a/tools/applypatch/applypatch.c b/tools/applypatch/applypatch.c
deleted file mode 100644
index e69a2fb..0000000
--- a/tools/applypatch/applypatch.c
+++ /dev/null
@@ -1,895 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "mincrypt/sha.h"
-#include "applypatch.h"
-#include "mtdutils/mtdutils.h"
-
-int SaveFileContents(const char* filename, FileContents file);
-int LoadMTDContents(const char* filename, FileContents* file);
-int ParseSha1(const char* str, uint8_t* digest);
-size_t FileSink(unsigned char* data, size_t len, void* token);
-
-static int mtd_partitions_scanned = 0;
-
-// Read a file into memory; store it and its associated metadata in
-// *file.  Return 0 on success.
-int LoadFileContents(const char* filename, FileContents* file) {
-  file->data = NULL;
-
-  // A special 'filename' beginning with "MTD:" means to load the
-  // contents of an MTD partition.
-  if (strncmp(filename, "MTD:", 4) == 0) {
-    return LoadMTDContents(filename, file);
-  }
-
-  if (stat(filename, &file->st) != 0) {
-    printf("failed to stat \"%s\": %s\n", filename, strerror(errno));
-    return -1;
-  }
-
-  file->size = file->st.st_size;
-  file->data = malloc(file->size);
-
-  FILE* f = fopen(filename, "rb");
-  if (f == NULL) {
-    printf("failed to open \"%s\": %s\n", filename, strerror(errno));
-    free(file->data);
-    file->data = NULL;
-    return -1;
-  }
-
-  size_t bytes_read = fread(file->data, 1, file->size, f);
-  if (bytes_read != file->size) {
-    printf("short read of \"%s\" (%d bytes of %d)\n",
-            filename, bytes_read, file->size);
-    free(file->data);
-    file->data = NULL;
-    return -1;
-  }
-  fclose(f);
-
-  SHA(file->data, file->size, file->sha1);
-  return 0;
-}
-
-static size_t* size_array;
-// comparison function for qsort()ing an int array of indexes into
-// size_array[].
-static int compare_size_indices(const void* a, const void* b) {
-  int aa = *(int*)a;
-  int bb = *(int*)b;
-  if (size_array[aa] < size_array[bb]) {
-    return -1;
-  } else if (size_array[aa] > size_array[bb]) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-// Load the contents of an MTD partition into the provided
-// FileContents.  filename should be a string of the form
-// "MTD:<partition_name>:<size_1>:<sha1_1>:<size_2>:<sha1_2>:...".
-// The smallest size_n bytes for which that prefix of the mtd contents
-// has the corresponding sha1 hash will be loaded.  It is acceptable
-// for a size value to be repeated with different sha1s.  Will return
-// 0 on success.
-//
-// This complexity is needed because if an OTA installation is
-// interrupted, the partition might contain either the source or the
-// target data, which might be of different lengths.  We need to know
-// the length in order to read from MTD (there is no "end-of-file"
-// marker), so the caller must specify the possible lengths and the
-// hash of the data, and we'll do the load expecting to find one of
-// those hashes.
-int LoadMTDContents(const char* filename, FileContents* file) {
-  char* copy = strdup(filename);
-  const char* magic = strtok(copy, ":");
-  if (strcmp(magic, "MTD") != 0) {
-    printf("LoadMTDContents called with bad filename (%s)\n",
-            filename);
-    return -1;
-  }
-  const char* partition = strtok(NULL, ":");
-
-  int i;
-  int colons = 0;
-  for (i = 0; filename[i] != '\0'; ++i) {
-    if (filename[i] == ':') {
-      ++colons;
-    }
-  }
-  if (colons < 3 || colons%2 == 0) {
-    printf("LoadMTDContents called with bad filename (%s)\n",
-            filename);
-  }
-
-  int pairs = (colons-1)/2;     // # of (size,sha1) pairs in filename
-  int* index = malloc(pairs * sizeof(int));
-  size_t* size = malloc(pairs * sizeof(size_t));
-  char** sha1sum = malloc(pairs * sizeof(char*));
-
-  for (i = 0; i < pairs; ++i) {
-    const char* size_str = strtok(NULL, ":");
-    size[i] = strtol(size_str, NULL, 10);
-    if (size[i] == 0) {
-      printf("LoadMTDContents called with bad size (%s)\n", filename);
-      return -1;
-    }
-    sha1sum[i] = strtok(NULL, ":");
-    index[i] = i;
-  }
-
-  // sort the index[] array so it indexes the pairs in order of
-  // increasing size.
-  size_array = size;
-  qsort(index, pairs, sizeof(int), compare_size_indices);
-
-  if (!mtd_partitions_scanned) {
-    mtd_scan_partitions();
-    mtd_partitions_scanned = 1;
-  }
-
-  const MtdPartition* mtd = mtd_find_partition_by_name(partition);
-  if (mtd == NULL) {
-    printf("mtd partition \"%s\" not found (loading %s)\n",
-            partition, filename);
-    return -1;
-  }
-
-  MtdReadContext* ctx = mtd_read_partition(mtd);
-  if (ctx == NULL) {
-    printf("failed to initialize read of mtd partition \"%s\"\n",
-            partition);
-    return -1;
-  }
-
-  SHA_CTX sha_ctx;
-  SHA_init(&sha_ctx);
-  uint8_t parsed_sha[SHA_DIGEST_SIZE];
-
-  // allocate enough memory to hold the largest size.
-  file->data = malloc(size[index[pairs-1]]);
-  char* p = (char*)file->data;
-  file->size = 0;                // # bytes read so far
-
-  for (i = 0; i < pairs; ++i) {
-    // Read enough additional bytes to get us up to the next size
-    // (again, we're trying the possibilities in order of increasing
-    // size).
-    size_t next = size[index[i]] - file->size;
-    size_t read = 0;
-    if (next > 0) {
-      read = mtd_read_data(ctx, p, next);
-      if (next != read) {
-        printf("short read (%d bytes of %d) for partition \"%s\"\n",
-                read, next, partition);
-        free(file->data);
-        file->data = NULL;
-        return -1;
-      }
-      SHA_update(&sha_ctx, p, read);
-      file->size += read;
-    }
-
-    // Duplicate the SHA context and finalize the duplicate so we can
-    // check it against this pair's expected hash.
-    SHA_CTX temp_ctx;
-    memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX));
-    const uint8_t* sha_so_far = SHA_final(&temp_ctx);
-
-    if (ParseSha1(sha1sum[index[i]], parsed_sha) != 0) {
-      printf("failed to parse sha1 %s in %s\n",
-              sha1sum[index[i]], filename);
-      free(file->data);
-      file->data = NULL;
-      return -1;
-    }
-
-    if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_SIZE) == 0) {
-      // we have a match.  stop reading the partition; we'll return
-      // the data we've read so far.
-      printf("mtd read matched size %d sha %s\n",
-             size[index[i]], sha1sum[index[i]]);
-      break;
-    }
-
-    p += read;
-  }
-
-  mtd_read_close(ctx);
-
-  if (i == pairs) {
-    // Ran off the end of the list of (size,sha1) pairs without
-    // finding a match.
-    printf("contents of MTD partition \"%s\" didn't match %s\n",
-            partition, filename);
-    free(file->data);
-    file->data = NULL;
-    return -1;
-  }
-
-  const uint8_t* sha_final = SHA_final(&sha_ctx);
-  for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
-    file->sha1[i] = sha_final[i];
-  }
-
-  // Fake some stat() info.
-  file->st.st_mode = 0644;
-  file->st.st_uid = 0;
-  file->st.st_gid = 0;
-
-  free(copy);
-  free(index);
-  free(size);
-  free(sha1sum);
-
-  return 0;
-}
-
-
-// Save the contents of the given FileContents object under the given
-// filename.  Return 0 on success.
-int SaveFileContents(const char* filename, FileContents file) {
-  int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
-  if (fd < 0) {
-    printf("failed to open \"%s\" for write: %s\n",
-            filename, strerror(errno));
-    return -1;
-  }
-
-  size_t bytes_written = FileSink(file.data, file.size, &fd);
-  if (bytes_written != file.size) {
-    printf("short write of \"%s\" (%d bytes of %d) (%s)\n",
-           filename, bytes_written, file.size, strerror(errno));
-    close(fd);
-    return -1;
-  }
-  fsync(fd);
-  close(fd);
-
-  if (chmod(filename, file.st.st_mode) != 0) {
-    printf("chmod of \"%s\" failed: %s\n", filename, strerror(errno));
-    return -1;
-  }
-  if (chown(filename, file.st.st_uid, file.st.st_gid) != 0) {
-    printf("chown of \"%s\" failed: %s\n", filename, strerror(errno));
-    return -1;
-  }
-
-  return 0;
-}
-
-// Write a memory buffer to target_mtd partition, a string of the form
-// "MTD:<partition>[:...]".  Return 0 on success.
-int WriteToMTDPartition(unsigned char* data, size_t len,
-                        const char* target_mtd) {
-  char* partition = strchr(target_mtd, ':');
-  if (partition == NULL) {
-    printf("bad MTD target name \"%s\"\n", target_mtd);
-    return -1;
-  }
-  ++partition;
-  // Trim off anything after a colon, eg "MTD:boot:blah:blah:blah...".
-  // We want just the partition name "boot".
-  partition = strdup(partition);
-  char* end = strchr(partition, ':');
-  if (end != NULL)
-    *end = '\0';
-
-  if (!mtd_partitions_scanned) {
-    mtd_scan_partitions();
-    mtd_partitions_scanned = 1;
-  }
-
-  const MtdPartition* mtd = mtd_find_partition_by_name(partition);
-  if (mtd == NULL) {
-    printf("mtd partition \"%s\" not found for writing\n", partition);
-    return -1;
-  }
-
-  MtdWriteContext* ctx = mtd_write_partition(mtd);
-  if (ctx == NULL) {
-    printf("failed to init mtd partition \"%s\" for writing\n",
-            partition);
-    return -1;
-  }
-
-  size_t written = mtd_write_data(ctx, (char*)data, len);
-  if (written != len) {
-    printf("only wrote %d of %d bytes to MTD %s\n",
-            written, len, partition);
-    mtd_write_close(ctx);
-    return -1;
-  }
-
-  if (mtd_erase_blocks(ctx, -1) < 0) {
-    printf("error finishing mtd write of %s\n", partition);
-    mtd_write_close(ctx);
-    return -1;
-  }
-
-  if (mtd_write_close(ctx)) {
-    printf("error closing mtd write of %s\n", partition);
-    return -1;
-  }
-
-  free(partition);
-  return 0;
-}
-
-
-// Take a string 'str' of 40 hex digits and parse it into the 20
-// byte array 'digest'.  'str' may contain only the digest or be of
-// the form "<digest>:<anything>".  Return 0 on success, -1 on any
-// error.
-int ParseSha1(const char* str, uint8_t* digest) {
-  int i;
-  const char* ps = str;
-  uint8_t* pd = digest;
-  for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
-    int digit;
-    if (*ps >= '0' && *ps <= '9') {
-      digit = *ps - '0';
-    } else if (*ps >= 'a' && *ps <= 'f') {
-      digit = *ps - 'a' + 10;
-    } else if (*ps >= 'A' && *ps <= 'F') {
-      digit = *ps - 'A' + 10;
-    } else {
-      return -1;
-    }
-    if (i % 2 == 0) {
-      *pd = digit << 4;
-    } else {
-      *pd |= digit;
-      ++pd;
-    }
-  }
-  if (*ps != '\0' && *ps != ':') return -1;
-  return 0;
-}
-
-// Parse arguments (which should be of the form "<sha1>" or
-// "<sha1>:<filename>" into the array *patches, returning the number
-// of Patch objects in *num_patches.  Return 0 on success.
-int ParseShaArgs(int argc, char** argv, Patch** patches, int* num_patches) {
-  *num_patches = argc;
-  *patches = malloc(*num_patches * sizeof(Patch));
-
-  int i;
-  for (i = 0; i < *num_patches; ++i) {
-    if (ParseSha1(argv[i], (*patches)[i].sha1) != 0) {
-      printf("failed to parse sha1 \"%s\"\n", argv[i]);
-      return -1;
-    }
-    if (argv[i][SHA_DIGEST_SIZE*2] == '\0') {
-      (*patches)[i].patch_filename = NULL;
-    } else if (argv[i][SHA_DIGEST_SIZE*2] == ':') {
-      (*patches)[i].patch_filename = argv[i] + (SHA_DIGEST_SIZE*2+1);
-    } else {
-      printf("failed to parse filename \"%s\"\n", argv[i]);
-      return -1;
-    }
-  }
-
-  return 0;
-}
-
-// Search an array of Patch objects for one matching the given sha1.
-// Return the Patch object on success, or NULL if no match is found.
-const Patch* FindMatchingPatch(uint8_t* sha1, Patch* patches, int num_patches) {
-  int i;
-  for (i = 0; i < num_patches; ++i) {
-    if (memcmp(patches[i].sha1, sha1, SHA_DIGEST_SIZE) == 0) {
-      return patches+i;
-    }
-  }
-  return NULL;
-}
-
-// Returns 0 if the contents of the file (argv[2]) or the cached file
-// match any of the sha1's on the command line (argv[3:]).  Returns
-// nonzero otherwise.
-int CheckMode(int argc, char** argv) {
-  if (argc < 3) {
-    printf("no filename given\n");
-    return 2;
-  }
-
-  int num_patches;
-  Patch* patches;
-  if (ParseShaArgs(argc-3, argv+3, &patches, &num_patches) != 0) { return 1; }
-
-  FileContents file;
-  file.data = NULL;
-
-  // It's okay to specify no sha1s; the check will pass if the
-  // LoadFileContents is successful.  (Useful for reading MTD
-  // partitions, where the filename encodes the sha1s; no need to
-  // check them twice.)
-  if (LoadFileContents(argv[2], &file) != 0 ||
-      (num_patches > 0 &&
-       FindMatchingPatch(file.sha1, patches, num_patches) == NULL)) {
-    printf("file \"%s\" doesn't have any of expected "
-            "sha1 sums; checking cache\n", argv[2]);
-
-    free(file.data);
-
-    // If the source file is missing or corrupted, it might be because
-    // we were killed in the middle of patching it.  A copy of it
-    // should have been made in CACHE_TEMP_SOURCE.  If that file
-    // exists and matches the sha1 we're looking for, the check still
-    // passes.
-
-    if (LoadFileContents(CACHE_TEMP_SOURCE, &file) != 0) {
-      printf("failed to load cache file\n");
-      return 1;
-    }
-
-    if (FindMatchingPatch(file.sha1, patches, num_patches) == NULL) {
-      printf("cache bits don't match any sha1 for \"%s\"\n",
-              argv[2]);
-      return 1;
-    }
-  }
-
-  free(file.data);
-  return 0;
-}
-
-int ShowLicenses() {
-  ShowBSDiffLicense();
-  return 0;
-}
-
-size_t FileSink(unsigned char* data, size_t len, void* token) {
-  int fd = *(int *)token;
-  ssize_t done = 0;
-  ssize_t wrote;
-  while (done < (ssize_t) len) {
-    wrote = write(fd, data+done, len-done);
-    if (wrote <= 0) {
-      printf("error writing %d bytes: %s\n", (int)(len-done), strerror(errno));
-      return done;
-    }
-    done += wrote;
-  }
-  printf("wrote %d bytes to output\n", (int)done);
-  return done;
-}
-
-typedef struct {
-  unsigned char* buffer;
-  size_t size;
-  size_t pos;
-} MemorySinkInfo;
-
-size_t MemorySink(unsigned char* data, size_t len, void* token) {
-  MemorySinkInfo* msi = (MemorySinkInfo*)token;
-  if (msi->size - msi->pos < len) {
-    return -1;
-  }
-  memcpy(msi->buffer + msi->pos, data, len);
-  msi->pos += len;
-  return len;
-}
-
-// Return the amount of free space (in bytes) on the filesystem
-// containing filename.  filename must exist.  Return -1 on error.
-size_t FreeSpaceForFile(const char* filename) {
-  struct statfs sf;
-  if (statfs(filename, &sf) != 0) {
-    printf("failed to statfs %s: %s\n", filename, strerror(errno));
-    return -1;
-  }
-  return sf.f_bsize * sf.f_bfree;
-}
-
-// This program applies binary patches to files in a way that is safe
-// (the original file is not touched until we have the desired
-// replacement for it) and idempotent (it's okay to run this program
-// multiple times).
-//
-// - if the sha1 hash of <tgt-file> is <tgt-sha1>, does nothing and exits
-//   successfully.
-//
-// - otherwise, if the sha1 hash of <src-file> is <src-sha1>, applies the
-//   bsdiff <patch> to <src-file> to produce a new file (the type of patch
-//   is automatically detected from the file header).  If that new
-//   file has sha1 hash <tgt-sha1>, moves it to replace <tgt-file>, and
-//   exits successfully.  Note that if <src-file> and <tgt-file> are
-//   not the same, <src-file> is NOT deleted on success.  <tgt-file>
-//   may be the string "-" to mean "the same as src-file".
-//
-// - otherwise, or if any error is encountered, exits with non-zero
-//   status.
-//
-// <src-file> (or <file> in check mode) may refer to an MTD partition
-// to read the source data.  See the comments for the
-// LoadMTDContents() function above for the format of such a filename.
-//
-//
-// As you might guess from the arguments, this function used to be
-// main(); it was split out this way so applypatch could be built as a
-// static library and linked into other executables as well.  In the
-// future only the library form will exist; we will not need to build
-// this as a standalone executable.
-//
-// The arguments to this function are just the command-line of the
-// standalone executable:
-//
-// <src-file> <tgt-file> <tgt-sha1> <tgt-size> [<src-sha1>:<patch> ...]
-//    to apply a patch.  Returns 0 on success, 1 on failure.
-//
-// "-c" <file> [<sha1> ...]
-//    to check a file's contents against zero or more sha1s.  Returns
-//    0 if it matches any of them, 1 if it doesn't.
-//
-// "-s" <bytes>
-//    returns 0 if enough free space is available on /cache; 1 if it
-//    does not.
-//
-// "-l"
-//    shows open-source license information and returns 0.
-//
-// This function returns 2 if the arguments are not understood (in the
-// standalone executable, this causes the usage message to be
-// printed).
-//
-// TODO: make the interface more sensible for use as a library.
-
-int applypatch(int argc, char** argv) {
-  if (argc < 2) {
-    return 2;
-  }
-
-  if (strncmp(argv[1], "-l", 3) == 0) {
-    return ShowLicenses();
-  }
-
-  if (strncmp(argv[1], "-c", 3) == 0) {
-    return CheckMode(argc, argv);
-  }
-
-  if (strncmp(argv[1], "-s", 3) == 0) {
-    if (argc != 3) {
-      return 2;
-    }
-    size_t bytes = strtol(argv[2], NULL, 10);
-    if (MakeFreeSpaceOnCache(bytes) < 0) {
-      printf("unable to make %ld bytes available on /cache\n", (long)bytes);
-      return 1;
-    } else {
-      return 0;
-    }
-  }
-
-  uint8_t target_sha1[SHA_DIGEST_SIZE];
-
-  const char* source_filename = argv[1];
-  const char* target_filename = argv[2];
-  if (target_filename[0] == '-' &&
-      target_filename[1] == '\0') {
-    target_filename = source_filename;
-  }
-
-  printf("\napplying patch to %s\n", source_filename);
-
-  if (ParseSha1(argv[3], target_sha1) != 0) {
-    printf("failed to parse tgt-sha1 \"%s\"\n", argv[3]);
-    return 1;
-  }
-
-  unsigned long target_size = strtoul(argv[4], NULL, 0);
-
-  int num_patches;
-  Patch* patches;
-  if (ParseShaArgs(argc-5, argv+5, &patches, &num_patches) < 0) { return 1; }
-
-  FileContents copy_file;
-  FileContents source_file;
-  const char* source_patch_filename = NULL;
-  const char* copy_patch_filename = NULL;
-  int made_copy = 0;
-
-  // We try to load the target file into the source_file object.
-  if (LoadFileContents(target_filename, &source_file) == 0) {
-    if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
-      // The early-exit case:  the patch was already applied, this file
-      // has the desired hash, nothing for us to do.
-      printf("\"%s\" is already target; no patch needed\n",
-              target_filename);
-      return 0;
-    }
-  }
-
-  if (source_file.data == NULL ||
-      (target_filename != source_filename &&
-       strcmp(target_filename, source_filename) != 0)) {
-    // Need to load the source file:  either we failed to load the
-    // target file, or we did but it's different from the source file.
-    free(source_file.data);
-    LoadFileContents(source_filename, &source_file);
-  }
-
-  if (source_file.data != NULL) {
-    const Patch* to_use =
-        FindMatchingPatch(source_file.sha1, patches, num_patches);
-    if (to_use != NULL) {
-      source_patch_filename = to_use->patch_filename;
-    }
-  }
-
-  if (source_patch_filename == NULL) {
-    free(source_file.data);
-    printf("source file is bad; trying copy\n");
-
-    if (LoadFileContents(CACHE_TEMP_SOURCE, &copy_file) < 0) {
-      // fail.
-      printf("failed to read copy file\n");
-      return 1;
-    }
-
-    const Patch* to_use =
-        FindMatchingPatch(copy_file.sha1, patches, num_patches);
-    if (to_use != NULL) {
-      copy_patch_filename = to_use->patch_filename;
-    }
-
-    if (copy_patch_filename == NULL) {
-      // fail.
-      printf("copy file doesn't match source SHA-1s either\n");
-      return 1;
-    }
-  }
-
-  int retry = 1;
-  SHA_CTX ctx;
-  int output;
-  MemorySinkInfo msi;
-  FileContents* source_to_use;
-  char* outname;
-
-  // assume that target_filename (eg "/system/app/Foo.apk") is located
-  // on the same filesystem as its top-level directory ("/system").
-  // We need something that exists for calling statfs().
-  char target_fs[strlen(target_filename)+1];
-  char* slash = strchr(target_filename+1, '/');
-  if (slash != NULL) {
-    int count = slash - target_filename;
-    strncpy(target_fs, target_filename, count);
-    target_fs[count] = '\0';
-  } else {
-    strcpy(target_fs, target_filename);
-  }
-
-  do {
-    // Is there enough room in the target filesystem to hold the patched
-    // file?
-
-    if (strncmp(target_filename, "MTD:", 4) == 0) {
-      // If the target is an MTD partition, we're actually going to
-      // write the output to /tmp and then copy it to the partition.
-      // statfs() always returns 0 blocks free for /tmp, so instead
-      // we'll just assume that /tmp has enough space to hold the file.
-
-      // We still write the original source to cache, in case the MTD
-      // write is interrupted.
-      if (MakeFreeSpaceOnCache(source_file.size) < 0) {
-        printf("not enough free space on /cache\n");
-        return 1;
-      }
-      if (SaveFileContents(CACHE_TEMP_SOURCE, source_file) < 0) {
-        printf("failed to back up source file\n");
-        return 1;
-      }
-      made_copy = 1;
-      retry = 0;
-    } else {
-      int enough_space = 0;
-      if (retry > 0) {
-        size_t free_space = FreeSpaceForFile(target_fs);
-        int enough_space =
-          (free_space > (target_size * 3 / 2));  // 50% margin of error
-        printf("target %ld bytes; free space %ld bytes; retry %d; enough %d\n",
-               (long)target_size, (long)free_space, retry, enough_space);
-      }
-
-      if (!enough_space) {
-        retry = 0;
-      }
-
-      if (!enough_space && source_patch_filename != NULL) {
-        // Using the original source, but not enough free space.  First
-        // copy the source file to cache, then delete it from the original
-        // location.
-
-        if (strncmp(source_filename, "MTD:", 4) == 0) {
-          // It's impossible to free space on the target filesystem by
-          // deleting the source if the source is an MTD partition.  If
-          // we're ever in a state where we need to do this, fail.
-          printf("not enough free space for target but source is MTD\n");
-          return 1;
-        }
-
-        if (MakeFreeSpaceOnCache(source_file.size) < 0) {
-          printf("not enough free space on /cache\n");
-          return 1;
-        }
-
-        if (SaveFileContents(CACHE_TEMP_SOURCE, source_file) < 0) {
-          printf("failed to back up source file\n");
-          return 1;
-        }
-        made_copy = 1;
-        unlink(source_filename);
-
-        size_t free_space = FreeSpaceForFile(target_fs);
-        printf("(now %ld bytes free for target)\n", (long)free_space);
-      }
-    }
-
-    const char* patch_filename;
-    if (source_patch_filename != NULL) {
-      source_to_use = &source_file;
-      patch_filename = source_patch_filename;
-    } else {
-      source_to_use = &copy_file;
-      patch_filename = copy_patch_filename;
-    }
-
-    SinkFn sink = NULL;
-    void* token = NULL;
-    output = -1;
-    outname = NULL;
-    if (strncmp(target_filename, "MTD:", 4) == 0) {
-      // We store the decoded output in memory.
-      msi.buffer = malloc(target_size);
-      if (msi.buffer == NULL) {
-        printf("failed to alloc %ld bytes for output\n",
-               (long)target_size);
-        return 1;
-      }
-      msi.pos = 0;
-      msi.size = target_size;
-      sink = MemorySink;
-      token = &msi;
-    } else {
-      // We write the decoded output to "<tgt-file>.patch".
-      outname = (char*)malloc(strlen(target_filename) + 10);
-      strcpy(outname, target_filename);
-      strcat(outname, ".patch");
-
-      output = open(outname, O_WRONLY | O_CREAT | O_TRUNC);
-      if (output < 0) {
-        printf("failed to open output file %s: %s\n",
-               outname, strerror(errno));
-        return 1;
-      }
-      sink = FileSink;
-      token = &output;
-    }
-
-#define MAX_HEADER_LENGTH 8
-    unsigned char header[MAX_HEADER_LENGTH];
-    FILE* patchf = fopen(patch_filename, "rb");
-    if (patchf == NULL) {
-      printf("failed to open patch file %s: %s\n",
-             patch_filename, strerror(errno));
-      return 1;
-    }
-    int header_bytes_read = fread(header, 1, MAX_HEADER_LENGTH, patchf);
-    fclose(patchf);
-
-    SHA_init(&ctx);
-
-    int result;
-
-    if (header_bytes_read >= 4 &&
-        header[0] == 0xd6 && header[1] == 0xc3 &&
-        header[2] == 0xc4 && header[3] == 0) {
-      // xdelta3 patches begin "VCD" (with the high bits set) followed
-      // by a zero byte (the version number).
-      printf("error:  xdelta3 patches no longer supported\n");
-      return 1;
-    } else if (header_bytes_read >= 8 &&
-               memcmp(header, "BSDIFF40", 8) == 0) {
-      result = ApplyBSDiffPatch(source_to_use->data, source_to_use->size,
-                                    patch_filename, 0, sink, token, &ctx);
-    } else if (header_bytes_read >= 8 &&
-               memcmp(header, "IMGDIFF", 7) == 0 &&
-               (header[7] == '1' || header[7] == '2')) {
-      result = ApplyImagePatch(source_to_use->data, source_to_use->size,
-                                   patch_filename, sink, token, &ctx);
-    } else {
-      printf("Unknown patch file format\n");
-      return 1;
-    }
-
-    if (output >= 0) {
-      fsync(output);
-      close(output);
-    }
-
-    if (result != 0) {
-      if (retry == 0) {
-        printf("applying patch failed\n");
-        return result;
-      } else {
-        printf("applying patch failed; retrying\n");
-      }
-      if (outname != NULL) {
-        unlink(outname);
-      }
-    } else {
-      // succeeded; no need to retry
-      break;
-    }
-  } while (retry-- > 0);
-
-  const uint8_t* current_target_sha1 = SHA_final(&ctx);
-  if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
-    printf("patch did not produce expected sha1\n");
-    return 1;
-  }
-
-  if (output < 0) {
-    // Copy the temp file to the MTD partition.
-    if (WriteToMTDPartition(msi.buffer, msi.pos, target_filename) != 0) {
-      printf("write of patched data to %s failed\n", target_filename);
-      return 1;
-    }
-    free(msi.buffer);
-  } else {
-    // Give the .patch file the same owner, group, and mode of the
-    // original source file.
-    if (chmod(outname, source_to_use->st.st_mode) != 0) {
-      printf("chmod of \"%s\" failed: %s\n", outname, strerror(errno));
-      return 1;
-    }
-    if (chown(outname, source_to_use->st.st_uid,
-              source_to_use->st.st_gid) != 0) {
-      printf("chown of \"%s\" failed: %s\n", outname, strerror(errno));
-      return 1;
-    }
-
-    // Finally, rename the .patch file to replace the target file.
-    if (rename(outname, target_filename) != 0) {
-      printf("rename of .patch to \"%s\" failed: %s\n",
-              target_filename, strerror(errno));
-      return 1;
-    }
-  }
-
-  // If this run of applypatch created the copy, and we're here, we
-  // can delete it.
-  if (made_copy) unlink(CACHE_TEMP_SOURCE);
-
-  // Success!
-  return 0;
-}
diff --git a/tools/applypatch/applypatch.h b/tools/applypatch/applypatch.h
deleted file mode 100644
index 3701087..0000000
--- a/tools/applypatch/applypatch.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _APPLYPATCH_H
-#define _APPLYPATCH_H
-
-#include <sys/stat.h>
-#include "mincrypt/sha.h"
-
-typedef struct _Patch {
-  uint8_t sha1[SHA_DIGEST_SIZE];
-  const char* patch_filename;
-} Patch;
-
-typedef struct _FileContents {
-  uint8_t sha1[SHA_DIGEST_SIZE];
-  unsigned char* data;
-  size_t size;
-  struct stat st;
-} FileContents;
-
-// When there isn't enough room on the target filesystem to hold the
-// patched version of the file, we copy the original here and delete
-// it to free up space.  If the expected source file doesn't exist, or
-// is corrupted, we look to see if this file contains the bits we want
-// and use it as the source instead.
-#define CACHE_TEMP_SOURCE "/cache/saved.file"
-
-typedef size_t (*SinkFn)(unsigned char*, size_t, void*);
-
-// applypatch.c
-size_t FreeSpaceForFile(const char* filename);
-int applypatch(int argc, char** argv);
-
-// bsdiff.c
-void ShowBSDiffLicense();
-int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
-                     const char* patch_filename, ssize_t offset,
-                     SinkFn sink, void* token, SHA_CTX* ctx);
-int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
-                        const char* patch_filename, ssize_t patch_offset,
-                        unsigned char** new_data, ssize_t* new_size);
-
-// imgpatch.c
-int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
-                    const char* patch_filename,
-                    SinkFn sink, void* token, SHA_CTX* ctx);
-
-// freecache.c
-int MakeFreeSpaceOnCache(size_t bytes_needed);
-
-#endif
diff --git a/tools/applypatch/applypatch.sh b/tools/applypatch/applypatch.sh
deleted file mode 100755
index 88f3025..0000000
--- a/tools/applypatch/applypatch.sh
+++ /dev/null
@@ -1,345 +0,0 @@
-#!/bin/bash
-#
-# A test suite for applypatch.  Run in a client where you have done
-# envsetup, choosecombo, etc.
-#
-# DO NOT RUN THIS ON A DEVICE YOU CARE ABOUT.  It will mess up your
-# system partition.
-#
-#
-# TODO: find some way to get this run regularly along with the rest of
-# the tests.
-
-EMULATOR_PORT=5580
-DATA_DIR=$ANDROID_BUILD_TOP/build/tools/applypatch/testdata
-
-# This must be the filename that applypatch uses for its copies.
-CACHE_TEMP_SOURCE=/cache/saved.file
-
-# Put all binaries and files here.  We use /cache because it's a
-# temporary filesystem in the emulator; it's created fresh each time
-# the emulator starts.
-WORK_DIR=/system
-
-# partition that WORK_DIR is located on, without the leading slash
-WORK_FS=system
-
-# set to 0 to use a device instead
-USE_EMULATOR=1
-
-# ------------------------
-
-tmpdir=$(mktemp -d)
-
-if [ "$USE_EMULATOR" == 1 ]; then
-  emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT &
-  pid_emulator=$!
-  ADB="adb -s emulator-$EMULATOR_PORT "
-else
-  ADB="adb -d "
-fi
-
-echo "waiting to connect to device"
-$ADB wait-for-device
-echo "device is available"
-$ADB remount
-# free up enough space on the system partition for the test to run.
-$ADB shell rm -r /system/media
-
-# run a command on the device; exit with the exit status of the device
-# command.
-run_command() {
-  $ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}'
-}
-
-testname() {
-  echo
-  echo "$1"...
-  testname="$1"
-}
-
-fail() {
-  echo
-  echo FAIL: $testname
-  echo
-  [ "$open_pid" == "" ] || kill $open_pid
-  [ "$pid_emulator" == "" ] || kill $pid_emulator
-  exit 1
-}
-
-sha1() {
-  sha1sum $1 | awk '{print $1}'
-}
-
-free_space() {
-  run_command df | awk "/$1/ {print gensub(/K/, \"\", \"g\", \$6)}"
-}
-
-cleanup() {
-  # not necessary if we're about to kill the emulator, but nice for
-  # running on real devices or already-running emulators.
-  testname "removing test files"
-  run_command rm $WORK_DIR/bloat.dat
-  run_command rm $WORK_DIR/old.file
-  run_command rm $WORK_DIR/patch.bsdiff
-  run_command rm $WORK_DIR/applypatch
-  run_command rm $CACHE_TEMP_SOURCE
-  run_command rm /cache/bloat*.dat
-
-  [ "$pid_emulator" == "" ] || kill $pid_emulator
-
-  rm -rf $tmpdir
-}
-
-cleanup
-
-$ADB push $ANDROID_PRODUCT_OUT/system/bin/applypatch $WORK_DIR/applypatch
-
-BAD1_SHA1=$(printf "%040x" $RANDOM)
-BAD2_SHA1=$(printf "%040x" $RANDOM)
-OLD_SHA1=$(sha1 $DATA_DIR/old.file)
-NEW_SHA1=$(sha1 $DATA_DIR/new.file)
-NEW_SIZE=$(stat -c %s $DATA_DIR/new.file)
-
-# --------------- basic execution ----------------------
-
-testname "usage message"
-run_command $WORK_DIR/applypatch && fail
-
-testname "display license"
-run_command $WORK_DIR/applypatch -l | grep -q -i copyright || fail
-
-
-# --------------- check mode ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-
-testname "check mode single"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
-
-testname "check mode multiple"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
-
-testname "check mode failure"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# put some junk in the old file
-run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
-
-testname "check mode cache (corrupted) single"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
-
-testname "check mode cache (corrupted) multiple"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
-
-testname "check mode cache (corrupted) failure"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
-
-# remove the old file entirely
-run_command rm $WORK_DIR/old.file
-
-testname "check mode cache (missing) single"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
-
-testname "check mode cache (missing) multiple"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
-
-testname "check mode cache (missing) failure"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
-
-
-# --------------- apply patch ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-
-# Check that the partition has enough space to apply the patch without
-# copying.  If it doesn't, we'll be testing the low-space condition
-# when we intend to test the not-low-space condition.
-testname "apply patches (with enough space)"
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS."
-if (( free_kb * 1024 < NEW_SIZE * 3 / 2 )); then
-  echo "Not enough space on /$WORK_FS to patch test file."
-  echo
-  echo "This doesn't mean that applypatch is necessarily broken;"
-  echo "just that /$WORK_FS doesn't have enough free space to"
-  echo "properly run this test."
-  exit 1
-fi
-
-testname "apply bsdiff patch"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-testname "reapply bsdiff patch"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-
-# --------------- apply patch in new location ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-
-# Check that the partition has enough space to apply the patch without
-# copying.  If it doesn't, we'll be testing the low-space condition
-# when we intend to test the not-low-space condition.
-testname "apply patch to new location (with enough space)"
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS."
-if (( free_kb * 1024 < NEW_SIZE * 3 / 2 )); then
-  echo "Not enough space on /$WORK_FS to patch test file."
-  echo
-  echo "This doesn't mean that applypatch is necessarily broken;"
-  echo "just that /$WORK_FS doesn't have enough free space to"
-  echo "properly run this test."
-  exit 1
-fi
-
-run_command rm $WORK_DIR/new.file
-run_command rm $CACHE_TEMP_SOURCE
-
-testname "apply bsdiff patch to new location"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/new.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-testname "reapply bsdiff patch to new location"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/new.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# put some junk in the old file
-run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
-
-testname "apply bsdiff patch to new location with corrupted source"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo || fail
-$ADB pull $WORK_DIR/new.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-# put some junk in the cache copy, too
-run_command dd if=/dev/urandom of=$CACHE_TEMP_SOURCE count=100 bs=1024 || fail
-
-run_command rm $WORK_DIR/new.file
-testname "apply bsdiff patch to new location with corrupted source and copy (no new file)"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo && fail
-
-# put some junk in the new file
-run_command dd if=/dev/urandom of=$WORK_DIR/new.file count=100 bs=1024 || fail
-
-testname "apply bsdiff patch to new location with corrupted source and copy (bad new file)"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo && fail
-
-# --------------- apply patch with low space on /system ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS; we'll soon fix that."
-echo run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail
-run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS now."
-
-testname "apply bsdiff patch with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-testname "reapply bsdiff patch with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-# --------------- apply patch with low space on /system and /cache ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS"
-
-run_command mkdir /cache/subdir
-run_command 'echo > /cache/subdir/a.file'
-run_command 'echo > /cache/a.file'
-run_command mkdir /cache/recovery /cache/recovery/otatest
-run_command 'echo > /cache/recovery/otatest/b.file'
-run_command "echo > $CACHE_TEMP_SOURCE"
-free_kb=$(free_space cache)
-echo "${free_kb}kb free on /cache; we'll soon fix that."
-run_command dd if=/dev/zero of=/cache/bloat_small.dat count=128 bs=1024 || fail
-run_command dd if=/dev/zero of=/cache/bloat_large.dat count=$((free_kb-640)) bs=1024 || fail
-free_kb=$(free_space cache)
-echo "${free_kb}kb free on /cache now."
-
-testname "apply bsdiff patch with low space, full cache, can't delete enough"
-$ADB shell 'cat >> /cache/bloat_large.dat' & open_pid=$!
-echo "open_pid is $open_pid"
-
-# size check should fail even though it deletes some stuff
-run_command $WORK_DIR/applypatch -s $NEW_SIZE && fail
-run_command ls /cache/bloat_small.dat && fail          # was deleted
-run_command ls /cache/a.file && fail                   # was deleted
-run_command ls /cache/recovery/otatest/b.file && fail  # was deleted
-run_command ls /cache/bloat_large.dat || fail          # wasn't deleted because it was open
-run_command ls /cache/subdir/a.file || fail            # wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE || fail              # wasn't deleted because it's the source file copy
-
-# should fail; not enough files can be deleted
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff && fail
-run_command ls /cache/bloat_large.dat || fail   # wasn't deleted because it was open
-run_command ls /cache/subdir/a.file || fail     # wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE || fail       # wasn't deleted because it's the source file copy
-
-kill $open_pid   # /cache/bloat_large.dat is no longer open
-
-testname "apply bsdiff patch with low space, full cache, can delete enough"
-
-# should succeed after deleting /cache/bloat_large.dat
-run_command $WORK_DIR/applypatch -s $NEW_SIZE || fail
-run_command ls /cache/bloat_large.dat && fail   # was deleted
-run_command ls /cache/subdir/a.file || fail     # still wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE || fail       # wasn't deleted because it's the source file copy
-
-# should succeed
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-run_command ls /cache/subdir/a.file || fail     # still wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE && fail       # was deleted because patching overwrote it, then deleted it
-
-# --------------- apply patch from cache ----------------------
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# put some junk in the old file
-run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
-
-testname "apply bsdiff patch from cache (corrupted source) with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# remove the old file entirely
-run_command rm $WORK_DIR/old.file
-
-testname "apply bsdiff patch from cache (missing source) with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-
-# --------------- cleanup ----------------------
-
-cleanup
-
-echo
-echo PASS
-echo
-
diff --git a/tools/applypatch/bsdiff.c b/tools/applypatch/bsdiff.c
deleted file mode 100644
index b6d342b..0000000
--- a/tools/applypatch/bsdiff.c
+++ /dev/null
@@ -1,410 +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.
- */
-
-/*
- * Most of this code comes from bsdiff.c from the bsdiff-4.3
- * distribution, which is:
- */
-
-/*-
- * Copyright 2003-2005 Colin Percival
- * All rights reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-
-#include <bzlib.h>
-#include <err.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define MIN(x,y) (((x)<(y)) ? (x) : (y))
-
-static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h)
-{
-	off_t i,j,k,x,tmp,jj,kk;
-
-	if(len<16) {
-		for(k=start;k<start+len;k+=j) {
-			j=1;x=V[I[k]+h];
-			for(i=1;k+i<start+len;i++) {
-				if(V[I[k+i]+h]<x) {
-					x=V[I[k+i]+h];
-					j=0;
-				};
-				if(V[I[k+i]+h]==x) {
-					tmp=I[k+j];I[k+j]=I[k+i];I[k+i]=tmp;
-					j++;
-				};
-			};
-			for(i=0;i<j;i++) V[I[k+i]]=k+j-1;
-			if(j==1) I[k]=-1;
-		};
-		return;
-	};
-
-	x=V[I[start+len/2]+h];
-	jj=0;kk=0;
-	for(i=start;i<start+len;i++) {
-		if(V[I[i]+h]<x) jj++;
-		if(V[I[i]+h]==x) kk++;
-	};
-	jj+=start;kk+=jj;
-
-	i=start;j=0;k=0;
-	while(i<jj) {
-		if(V[I[i]+h]<x) {
-			i++;
-		} else if(V[I[i]+h]==x) {
-			tmp=I[i];I[i]=I[jj+j];I[jj+j]=tmp;
-			j++;
-		} else {
-			tmp=I[i];I[i]=I[kk+k];I[kk+k]=tmp;
-			k++;
-		};
-	};
-
-	while(jj+j<kk) {
-		if(V[I[jj+j]+h]==x) {
-			j++;
-		} else {
-			tmp=I[jj+j];I[jj+j]=I[kk+k];I[kk+k]=tmp;
-			k++;
-		};
-	};
-
-	if(jj>start) split(I,V,start,jj-start,h);
-
-	for(i=0;i<kk-jj;i++) V[I[jj+i]]=kk-1;
-	if(jj==kk-1) I[jj]=-1;
-
-	if(start+len>kk) split(I,V,kk,start+len-kk,h);
-}
-
-static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize)
-{
-	off_t buckets[256];
-	off_t i,h,len;
-
-	for(i=0;i<256;i++) buckets[i]=0;
-	for(i=0;i<oldsize;i++) buckets[old[i]]++;
-	for(i=1;i<256;i++) buckets[i]+=buckets[i-1];
-	for(i=255;i>0;i--) buckets[i]=buckets[i-1];
-	buckets[0]=0;
-
-	for(i=0;i<oldsize;i++) I[++buckets[old[i]]]=i;
-	I[0]=oldsize;
-	for(i=0;i<oldsize;i++) V[i]=buckets[old[i]];
-	V[oldsize]=0;
-	for(i=1;i<256;i++) if(buckets[i]==buckets[i-1]+1) I[buckets[i]]=-1;
-	I[0]=-1;
-
-	for(h=1;I[0]!=-(oldsize+1);h+=h) {
-		len=0;
-		for(i=0;i<oldsize+1;) {
-			if(I[i]<0) {
-				len-=I[i];
-				i-=I[i];
-			} else {
-				if(len) I[i-len]=-len;
-				len=V[I[i]]+1-i;
-				split(I,V,i,len,h);
-				i+=len;
-				len=0;
-			};
-		};
-		if(len) I[i-len]=-len;
-	};
-
-	for(i=0;i<oldsize+1;i++) I[V[i]]=i;
-}
-
-static off_t matchlen(u_char *old,off_t oldsize,u_char *new,off_t newsize)
-{
-	off_t i;
-
-	for(i=0;(i<oldsize)&&(i<newsize);i++)
-		if(old[i]!=new[i]) break;
-
-	return i;
-}
-
-static off_t search(off_t *I,u_char *old,off_t oldsize,
-		u_char *new,off_t newsize,off_t st,off_t en,off_t *pos)
-{
-	off_t x,y;
-
-	if(en-st<2) {
-		x=matchlen(old+I[st],oldsize-I[st],new,newsize);
-		y=matchlen(old+I[en],oldsize-I[en],new,newsize);
-
-		if(x>y) {
-			*pos=I[st];
-			return x;
-		} else {
-			*pos=I[en];
-			return y;
-		}
-	};
-
-	x=st+(en-st)/2;
-	if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
-		return search(I,old,oldsize,new,newsize,x,en,pos);
-	} else {
-		return search(I,old,oldsize,new,newsize,st,x,pos);
-	};
-}
-
-static void offtout(off_t x,u_char *buf)
-{
-	off_t y;
-
-	if(x<0) y=-x; else y=x;
-
-		buf[0]=y%256;y-=buf[0];
-	y=y/256;buf[1]=y%256;y-=buf[1];
-	y=y/256;buf[2]=y%256;y-=buf[2];
-	y=y/256;buf[3]=y%256;y-=buf[3];
-	y=y/256;buf[4]=y%256;y-=buf[4];
-	y=y/256;buf[5]=y%256;y-=buf[5];
-	y=y/256;buf[6]=y%256;y-=buf[6];
-	y=y/256;buf[7]=y%256;
-
-	if(x<0) buf[7]|=0x80;
-}
-
-// This is main() from bsdiff.c, with the following changes:
-//
-//    - old, oldsize, new, newsize are arguments; we don't load this
-//      data from files.  old and new are owned by the caller; we
-//      don't free them at the end.
-//
-//    - the "I" block of memory is owned by the caller, who passes a
-//      pointer to *I, which can be NULL.  This way if we call
-//      bsdiff() multiple times with the same 'old' data, we only do
-//      the qsufsort() step the first time.
-//
-int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* new, off_t newsize,
-           const char* patch_filename)
-{
-	int fd;
-	off_t *I;
-	off_t scan,pos,len;
-	off_t lastscan,lastpos,lastoffset;
-	off_t oldscore,scsc;
-	off_t s,Sf,lenf,Sb,lenb;
-	off_t overlap,Ss,lens;
-	off_t i;
-	off_t dblen,eblen;
-	u_char *db,*eb;
-	u_char buf[8];
-	u_char header[32];
-	FILE * pf;
-	BZFILE * pfbz2;
-	int bz2err;
-
-        if (*IP == NULL) {
-            off_t* V;
-            *IP = malloc((oldsize+1) * sizeof(off_t));
-            V = malloc((oldsize+1) * sizeof(off_t));
-            qsufsort(*IP, V, old, oldsize);
-            free(V);
-        }
-        I = *IP;
-
-	if(((db=malloc(newsize+1))==NULL) ||
-		((eb=malloc(newsize+1))==NULL)) err(1,NULL);
-	dblen=0;
-	eblen=0;
-
-	/* Create the patch file */
-	if ((pf = fopen(patch_filename, "w")) == NULL)
-              err(1, "%s", patch_filename);
-
-	/* Header is
-		0	8	 "BSDIFF40"
-		8	8	length of bzip2ed ctrl block
-		16	8	length of bzip2ed diff block
-		24	8	length of new file */
-	/* File is
-		0	32	Header
-		32	??	Bzip2ed ctrl block
-		??	??	Bzip2ed diff block
-		??	??	Bzip2ed extra block */
-	memcpy(header,"BSDIFF40",8);
-	offtout(0, header + 8);
-	offtout(0, header + 16);
-	offtout(newsize, header + 24);
-	if (fwrite(header, 32, 1, pf) != 1)
-		err(1, "fwrite(%s)", patch_filename);
-
-	/* Compute the differences, writing ctrl as we go */
-	if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
-		errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
-	scan=0;len=0;
-	lastscan=0;lastpos=0;lastoffset=0;
-	while(scan<newsize) {
-		oldscore=0;
-
-		for(scsc=scan+=len;scan<newsize;scan++) {
-			len=search(I,old,oldsize,new+scan,newsize-scan,
-					0,oldsize,&pos);
-
-			for(;scsc<scan+len;scsc++)
-			if((scsc+lastoffset<oldsize) &&
-				(old[scsc+lastoffset] == new[scsc]))
-				oldscore++;
-
-			if(((len==oldscore) && (len!=0)) ||
-				(len>oldscore+8)) break;
-
-			if((scan+lastoffset<oldsize) &&
-				(old[scan+lastoffset] == new[scan]))
-				oldscore--;
-		};
-
-		if((len!=oldscore) || (scan==newsize)) {
-			s=0;Sf=0;lenf=0;
-			for(i=0;(lastscan+i<scan)&&(lastpos+i<oldsize);) {
-				if(old[lastpos+i]==new[lastscan+i]) s++;
-				i++;
-				if(s*2-i>Sf*2-lenf) { Sf=s; lenf=i; };
-			};
-
-			lenb=0;
-			if(scan<newsize) {
-				s=0;Sb=0;
-				for(i=1;(scan>=lastscan+i)&&(pos>=i);i++) {
-					if(old[pos-i]==new[scan-i]) s++;
-					if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
-				};
-			};
-
-			if(lastscan+lenf>scan-lenb) {
-				overlap=(lastscan+lenf)-(scan-lenb);
-				s=0;Ss=0;lens=0;
-				for(i=0;i<overlap;i++) {
-					if(new[lastscan+lenf-overlap+i]==
-					   old[lastpos+lenf-overlap+i]) s++;
-					if(new[scan-lenb+i]==
-					   old[pos-lenb+i]) s--;
-					if(s>Ss) { Ss=s; lens=i+1; };
-				};
-
-				lenf+=lens-overlap;
-				lenb-=lens;
-			};
-
-			for(i=0;i<lenf;i++)
-				db[dblen+i]=new[lastscan+i]-old[lastpos+i];
-			for(i=0;i<(scan-lenb)-(lastscan+lenf);i++)
-				eb[eblen+i]=new[lastscan+lenf+i];
-
-			dblen+=lenf;
-			eblen+=(scan-lenb)-(lastscan+lenf);
-
-			offtout(lenf,buf);
-			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
-			if (bz2err != BZ_OK)
-				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
-
-			offtout((scan-lenb)-(lastscan+lenf),buf);
-			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
-			if (bz2err != BZ_OK)
-				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
-
-			offtout((pos-lenb)-(lastpos+lenf),buf);
-			BZ2_bzWrite(&bz2err, pfbz2, buf, 8);
-			if (bz2err != BZ_OK)
-				errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
-
-			lastscan=scan-lenb;
-			lastpos=pos-lenb;
-			lastoffset=pos-scan;
-		};
-	};
-	BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
-	if (bz2err != BZ_OK)
-		errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
-
-	/* Compute size of compressed ctrl data */
-	if ((len = ftello(pf)) == -1)
-		err(1, "ftello");
-	offtout(len-32, header + 8);
-
-	/* Write compressed diff data */
-	if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
-		errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
-	BZ2_bzWrite(&bz2err, pfbz2, db, dblen);
-	if (bz2err != BZ_OK)
-		errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
-	BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
-	if (bz2err != BZ_OK)
-		errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
-
-	/* Compute size of compressed diff data */
-	if ((newsize = ftello(pf)) == -1)
-		err(1, "ftello");
-	offtout(newsize - len, header + 16);
-
-	/* Write compressed extra data */
-	if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL)
-		errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err);
-	BZ2_bzWrite(&bz2err, pfbz2, eb, eblen);
-	if (bz2err != BZ_OK)
-		errx(1, "BZ2_bzWrite, bz2err = %d", bz2err);
-	BZ2_bzWriteClose(&bz2err, pfbz2, 0, NULL, NULL);
-	if (bz2err != BZ_OK)
-		errx(1, "BZ2_bzWriteClose, bz2err = %d", bz2err);
-
-	/* Seek to the beginning, write the header, and close the file */
-	if (fseeko(pf, 0, SEEK_SET))
-		err(1, "fseeko");
-	if (fwrite(header, 32, 1, pf) != 1)
-		err(1, "fwrite(%s)", patch_filename);
-	if (fclose(pf))
-		err(1, "fclose");
-
-	/* Free the memory we used */
-	free(db);
-	free(eb);
-
-	return 0;
-}
diff --git a/tools/applypatch/bspatch.c b/tools/applypatch/bspatch.c
deleted file mode 100644
index d5cd617..0000000
--- a/tools/applypatch/bspatch.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file is a nearly line-for-line copy of bspatch.c from the
-// bsdiff-4.3 distribution; the primary differences being how the
-// input and output data are read and the error handling.  Running
-// applypatch with the -l option will display the bsdiff license
-// notice.
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <bzlib.h>
-
-#include "mincrypt/sha.h"
-#include "applypatch.h"
-
-void ShowBSDiffLicense() {
-  puts("The bsdiff library used herein is:\n"
-       "\n"
-       "Copyright 2003-2005 Colin Percival\n"
-       "All rights reserved\n"
-       "\n"
-       "Redistribution and use in source and binary forms, with or without\n"
-       "modification, are permitted providing that the following conditions\n"
-       "are met:\n"
-       "1. Redistributions of source code must retain the above copyright\n"
-       "   notice, this list of conditions and the following disclaimer.\n"
-       "2. Redistributions in binary form must reproduce the above copyright\n"
-       "   notice, this list of conditions and the following disclaimer in the\n"
-       "   documentation and/or other materials provided with the distribution.\n"
-       "\n"
-       "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
-       "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
-       "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
-       "ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n"
-       "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
-       "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
-       "OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n"
-       "HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n"
-       "STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\n"
-       "IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
-       "POSSIBILITY OF SUCH DAMAGE.\n"
-       "\n------------------\n\n"
-       "This program uses Julian R Seward's \"libbzip2\" library, available\n"
-       "from http://www.bzip.org/.\n"
-       );
-}
-
-static off_t offtin(u_char *buf)
-{
-  off_t y;
-
-  y=buf[7]&0x7F;
-  y=y*256;y+=buf[6];
-  y=y*256;y+=buf[5];
-  y=y*256;y+=buf[4];
-  y=y*256;y+=buf[3];
-  y=y*256;y+=buf[2];
-  y=y*256;y+=buf[1];
-  y=y*256;y+=buf[0];
-
-  if(buf[7]&0x80) y=-y;
-
-  return y;
-}
-
-
-int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
-                     const char* patch_filename, ssize_t patch_offset,
-                     SinkFn sink, void* token, SHA_CTX* ctx) {
-
-  unsigned char* new_data;
-  ssize_t new_size;
-  if (ApplyBSDiffPatchMem(old_data, old_size, patch_filename, patch_offset,
-                          &new_data, &new_size) != 0) {
-    return -1;
-  }
-
-  if (sink(new_data, new_size, token) < new_size) {
-    fprintf(stderr, "short write of output: %d (%s)\n", errno, strerror(errno));
-    return 1;
-  }
-  if (ctx) {
-    SHA_update(ctx, new_data, new_size);
-  }
-  free(new_data);
-
-  return 0;
-}
-
-int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
-                        const char* patch_filename, ssize_t patch_offset,
-                        unsigned char** new_data, ssize_t* new_size) {
-
-  FILE* f;
-  if ((f = fopen(patch_filename, "rb")) == NULL) {
-    fprintf(stderr, "failed to open patch file\n");
-    return 1;
-  }
-
-  // File format:
-  //   0       8       "BSDIFF40"
-  //   8       8       X
-  //   16      8       Y
-  //   24      8       sizeof(newfile)
-  //   32      X       bzip2(control block)
-  //   32+X    Y       bzip2(diff block)
-  //   32+X+Y  ???     bzip2(extra block)
-  // with control block a set of triples (x,y,z) meaning "add x bytes
-  // from oldfile to x bytes from the diff block; copy y bytes from the
-  // extra block; seek forwards in oldfile by z bytes".
-
-  fseek(f, patch_offset, SEEK_SET);
-
-  unsigned char header[32];
-  if (fread(header, 1, 32, f) < 32) {
-    fprintf(stderr, "failed to read patch file header\n");
-    return 1;
-  }
-
-  if (memcmp(header, "BSDIFF40", 8) != 0) {
-    fprintf(stderr, "corrupt bsdiff patch file header (magic number)\n");
-    return 1;
-  }
-
-  ssize_t ctrl_len, data_len;
-  ctrl_len = offtin(header+8);
-  data_len = offtin(header+16);
-  *new_size = offtin(header+24);
-
-  if (ctrl_len < 0 || data_len < 0 || *new_size < 0) {
-    fprintf(stderr, "corrupt patch file header (data lengths)\n");
-    return 1;
-  }
-
-  fclose(f);
-
-  int bzerr;
-
-#define OPEN_AT(f, bzf, offset)                                          \
-  FILE* f;                                                               \
-  BZFILE* bzf;                                                           \
-  if ((f = fopen(patch_filename, "rb")) == NULL) {                       \
-    fprintf(stderr, "failed to open patch file\n");                      \
-    return 1;                                                            \
-  }                                                                      \
-  if (fseeko(f, offset+patch_offset, SEEK_SET)) {                        \
-    fprintf(stderr, "failed to seek in patch file\n");                   \
-    return 1;                                                            \
-  }                                                                      \
-  if ((bzf = BZ2_bzReadOpen(&bzerr, f, 0, 0, NULL, 0)) == NULL) {        \
-    fprintf(stderr, "failed to bzReadOpen in patch file (%d)\n", bzerr); \
-    return 1;                                                            \
-  }
-
-  OPEN_AT(cpf, cpfbz2, 32);
-  OPEN_AT(dpf, dpfbz2, 32+ctrl_len);
-  OPEN_AT(epf, epfbz2, 32+ctrl_len+data_len);
-
-#undef OPEN_AT
-
-  *new_data = malloc(*new_size);
-  if (*new_data == NULL) {
-    fprintf(stderr, "failed to allocate %d bytes of memory for output file\n",
-            (int)*new_size);
-    return 1;
-  }
-
-  off_t oldpos = 0, newpos = 0;
-  off_t ctrl[3];
-  off_t len_read;
-  int i;
-  unsigned char buf[8];
-  while (newpos < *new_size) {
-    // Read control data
-    for (i = 0; i < 3; ++i) {
-      len_read = BZ2_bzRead(&bzerr, cpfbz2, buf, 8);
-      if (len_read < 8 || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
-        fprintf(stderr, "corrupt patch (read control)\n");
-        return 1;
-      }
-      ctrl[i] = offtin(buf);
-    }
-
-    // Sanity check
-    if (newpos + ctrl[0] > *new_size) {
-      fprintf(stderr, "corrupt patch (new file overrun)\n");
-      return 1;
-    }
-
-    // Read diff string
-    len_read = BZ2_bzRead(&bzerr, dpfbz2, *new_data + newpos, ctrl[0]);
-    if (len_read < ctrl[0] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
-      fprintf(stderr, "corrupt patch (read diff)\n");
-      return 1;
-    }
-
-    // Add old data to diff string
-    for (i = 0; i < ctrl[0]; ++i) {
-      if ((oldpos+i >= 0) && (oldpos+i < old_size)) {
-        (*new_data)[newpos+i] += old_data[oldpos+i];
-      }
-    }
-
-    // Adjust pointers
-    newpos += ctrl[0];
-    oldpos += ctrl[0];
-
-    // Sanity check
-    if (newpos + ctrl[1] > *new_size) {
-      fprintf(stderr, "corrupt patch (new file overrun)\n");
-      return 1;
-    }
-
-    // Read extra string
-    len_read = BZ2_bzRead(&bzerr, epfbz2, *new_data + newpos, ctrl[1]);
-    if (len_read < ctrl[1] || !(bzerr == BZ_OK || bzerr == BZ_STREAM_END)) {
-      fprintf(stderr, "corrupt patch (read extra)\n");
-      return 1;
-    }
-
-    // Adjust pointers
-    newpos += ctrl[1];
-    oldpos += ctrl[2];
-  }
-
-  BZ2_bzReadClose(&bzerr, cpfbz2);
-  BZ2_bzReadClose(&bzerr, dpfbz2);
-  BZ2_bzReadClose(&bzerr, epfbz2);
-  fclose(cpf);
-  fclose(dpf);
-  fclose(epf);
-
-  return 0;
-}
diff --git a/tools/applypatch/freecache.c b/tools/applypatch/freecache.c
deleted file mode 100644
index 9827fda..0000000
--- a/tools/applypatch/freecache.c
+++ /dev/null
@@ -1,172 +0,0 @@
-#include <errno.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <ctype.h>
-
-#include "applypatch.h"
-
-static int EliminateOpenFiles(char** files, int file_count) {
-  DIR* d;
-  struct dirent* de;
-  d = opendir("/proc");
-  if (d == NULL) {
-    printf("error opening /proc: %s\n", strerror(errno));
-    return -1;
-  }
-  while ((de = readdir(d)) != 0) {
-    int i;
-    for (i = 0; de->d_name[i] != '\0' && isdigit(de->d_name[i]); ++i);
-    if (de->d_name[i]) continue;
-
-    // de->d_name[i] is numeric
-
-    char path[FILENAME_MAX];
-    strcpy(path, "/proc/");
-    strcat(path, de->d_name);
-    strcat(path, "/fd/");
-
-    DIR* fdd;
-    struct dirent* fdde;
-    fdd = opendir(path);
-    if (fdd == NULL) {
-      printf("error opening %s: %s\n", path, strerror(errno));
-      continue;
-    }
-    while ((fdde = readdir(fdd)) != 0) {
-      char fd_path[FILENAME_MAX];
-      char link[FILENAME_MAX];
-      strcpy(fd_path, path);
-      strcat(fd_path, fdde->d_name);
-
-      int count;
-      count = readlink(fd_path, link, sizeof(link)-1);
-      if (count >= 0) {
-        link[count] = '\0';
-
-        // This is inefficient, but it should only matter if there are
-        // lots of files in /cache, and lots of them are open (neither
-        // of which should be true, especially in recovery).
-        if (strncmp(link, "/cache/", 7) == 0) {
-          int j;
-          for (j = 0; j < file_count; ++j) {
-            if (files[j] && strcmp(files[j], link) == 0) {
-              printf("%s is open by %s\n", link, de->d_name);
-              free(files[j]);
-              files[j] = NULL;
-            }
-          }
-        }
-      }
-    }
-    closedir(fdd);
-  }
-  closedir(d);
-
-  return 0;
-}
-
-int FindExpendableFiles(char*** names, int* entries) {
-  DIR* d;
-  struct dirent* de;
-  int size = 32;
-  *entries = 0;
-  *names = malloc(size * sizeof(char*));
-
-  char path[FILENAME_MAX];
-
-  // We're allowed to delete unopened regular files in any of these
-  // directories.
-  const char* dirs[2] = {"/cache", "/cache/recovery/otatest"};
-
-  unsigned int i;
-  for (i = 0; i < sizeof(dirs)/sizeof(dirs[0]); ++i) {
-    d = opendir(dirs[i]);
-    if (d == NULL) {
-      printf("error opening %s: %s\n", dirs[i], strerror(errno));
-      continue;
-    }
-
-    // Look for regular files in the directory (not in any subdirectories).
-    while ((de = readdir(d)) != 0) {
-      strcpy(path, dirs[i]);
-      strcat(path, "/");
-      strcat(path, de->d_name);
-
-      // We can't delete CACHE_TEMP_SOURCE; if it's there we might have
-      // restarted during installation and could be depending on it to
-      // be there.
-      if (strcmp(path, CACHE_TEMP_SOURCE) == 0) continue;
-
-      struct stat st;
-      if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
-        if (*entries >= size) {
-          size *= 2;
-          *names = realloc(*names, size * sizeof(char*));
-        }
-        (*names)[(*entries)++] = strdup(path);
-      }
-    }
-
-    closedir(d);
-  }
-
-  printf("%d regular files in deletable directories\n", *entries);
-
-  if (EliminateOpenFiles(*names, *entries) < 0) {
-    return -1;
-  }
-
-  return 0;
-}
-
-int MakeFreeSpaceOnCache(size_t bytes_needed) {
-  size_t free_now = FreeSpaceForFile("/cache");
-  printf("%ld bytes free on /cache (%ld needed)\n",
-         (long)free_now, (long)bytes_needed);
-
-  if (free_now >= bytes_needed) {
-    return 0;
-  }
-
-  char** names;
-  int entries;
-
-  if (FindExpendableFiles(&names, &entries) < 0) {
-    return -1;
-  }
-
-  if (entries == 0) {
-    // nothing we can delete to free up space!
-    printf("no files can be deleted to free space on /cache\n");
-    return -1;
-  }
-
-  // We could try to be smarter about which files to delete:  the
-  // biggest ones?  the smallest ones that will free up enough space?
-  // the oldest?  the newest?
-  //
-  // Instead, we'll be dumb.
-
-  int i;
-  for (i = 0; i < entries && free_now < bytes_needed; ++i) {
-    if (names[i]) {
-      unlink(names[i]);
-      free_now = FreeSpaceForFile("/cache");
-      printf("deleted %s; now %ld bytes free\n", names[i], (long)free_now);
-      free(names[i]);
-    }
-  }
-
-  for (; i < entries; ++i) {
-    free(names[i]);
-  }
-  free(names);
-
-  return (free_now >= bytes_needed) ? 0 : -1;
-}
diff --git a/tools/applypatch/imgdiff.c b/tools/applypatch/imgdiff.c
deleted file mode 100644
index 6b9ebee..0000000
--- a/tools/applypatch/imgdiff.c
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This program constructs binary patches for images -- such as boot.img
- * and recovery.img -- that consist primarily of large chunks of gzipped
- * data interspersed with uncompressed data.  Doing a naive bsdiff of
- * these files is not useful because small changes in the data lead to
- * large changes in the compressed bitstream; bsdiff patches of gzipped
- * data are typically as large as the data itself.
- *
- * To patch these usefully, we break the source and target images up into
- * chunks of two types: "normal" and "gzip".  Normal chunks are simply
- * patched using a plain bsdiff.  Gzip chunks are first expanded, then a
- * bsdiff is applied to the uncompressed data, then the patched data is
- * gzipped using the same encoder parameters.  Patched chunks are
- * concatenated together to create the output file; the output image
- * should be *exactly* the same series of bytes as the target image used
- * originally to generate the patch.
- *
- * To work well with this tool, the gzipped sections of the target
- * image must have been generated using the same deflate encoder that
- * is available in applypatch, namely, the one in the zlib library.
- * In practice this means that images should be compressed using the
- * "minigzip" tool included in the zlib distribution, not the GNU gzip
- * program.
- *
- * An "imgdiff" patch consists of a header describing the chunk structure
- * of the file and any encoding parameters needed for the gzipped
- * chunks, followed by N bsdiff patches, one per chunk.
- *
- * For a diff to be generated, the source and target images must have the
- * same "chunk" structure: that is, the same number of gzipped and normal
- * chunks in the same order.  Android boot and recovery images currently
- * consist of five chunks:  a small normal header, a gzipped kernel, a
- * small normal section, a gzipped ramdisk, and finally a small normal
- * footer.
- *
- * Caveats:  we locate gzipped sections within the source and target
- * images by searching for the byte sequence 1f8b0800:  1f8b is the gzip
- * magic number; 08 specifies the "deflate" encoding [the only encoding
- * supported by the gzip standard]; and 00 is the flags byte.  We do not
- * currently support any extra header fields (which would be indicated by
- * a nonzero flags byte).  We also don't handle the case when that byte
- * sequence appears spuriously in the file.  (Note that it would have to
- * occur spuriously within a normal chunk to be a problem.)
- *
- *
- * The imgdiff patch header looks like this:
- *
- *    "IMGDIFF1"                  (8)   [magic number and version]
- *    chunk count                 (4)
- *    for each chunk:
- *        chunk type              (4)   [CHUNK_{NORMAL, GZIP, DEFLATE, RAW}]
- *        if chunk type == CHUNK_NORMAL:
- *           source start         (8)
- *           source len           (8)
- *           bsdiff patch offset  (8)   [from start of patch file]
- *        if chunk type == CHUNK_GZIP:      (version 1 only)
- *           source start         (8)
- *           source len           (8)
- *           bsdiff patch offset  (8)   [from start of patch file]
- *           source expanded len  (8)   [size of uncompressed source]
- *           target expected len  (8)   [size of uncompressed target]
- *           gzip level           (4)
- *                method          (4)
- *                windowBits      (4)
- *                memLevel        (4)
- *                strategy        (4)
- *           gzip header len      (4)
- *           gzip header          (gzip header len)
- *           gzip footer          (8)
- *        if chunk type == CHUNK_DEFLATE:   (version 2 only)
- *           source start         (8)
- *           source len           (8)
- *           bsdiff patch offset  (8)   [from start of patch file]
- *           source expanded len  (8)   [size of uncompressed source]
- *           target expected len  (8)   [size of uncompressed target]
- *           gzip level           (4)
- *                method          (4)
- *                windowBits      (4)
- *                memLevel        (4)
- *                strategy        (4)
- *        if chunk type == RAW:             (version 2 only)
- *           target len           (4)
- *           data                 (target len)
- *
- * All integers are little-endian.  "source start" and "source len"
- * specify the section of the input image that comprises this chunk,
- * including the gzip header and footer for gzip chunks.  "source
- * expanded len" is the size of the uncompressed source data.  "target
- * expected len" is the size of the uncompressed data after applying
- * the bsdiff patch.  The next five parameters specify the zlib
- * parameters to be used when compressing the patched data, and the
- * next three specify the header and footer to be wrapped around the
- * compressed data to create the output chunk (so that header contents
- * like the timestamp are recreated exactly).
- *
- * After the header there are 'chunk count' bsdiff patches; the offset
- * of each from the beginning of the file is specified in the header.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#include "zlib.h"
-#include "imgdiff.h"
-#include "utils.h"
-
-typedef struct {
-  int type;             // CHUNK_NORMAL, CHUNK_DEFLATE
-  size_t start;         // offset of chunk in original image file
-
-  size_t len;
-  unsigned char* data;  // data to be patched (uncompressed, for deflate chunks)
-
-  size_t source_start;
-  size_t source_len;
-
-  off_t* I;             // used by bsdiff
-
-  // --- for CHUNK_DEFLATE chunks only: ---
-
-  // original (compressed) deflate data
-  size_t deflate_len;
-  unsigned char* deflate_data;
-
-  char* filename;       // used for zip entries
-
-  // deflate encoder parameters
-  int level, method, windowBits, memLevel, strategy;
-
-  size_t source_uncompressed_len;
-} ImageChunk;
-
-typedef struct {
-  int data_offset;
-  int deflate_len;
-  int uncomp_len;
-  char* filename;
-} ZipFileEntry;
-
-static int fileentry_compare(const void* a, const void* b) {
-  int ao = ((ZipFileEntry*)a)->data_offset;
-  int bo = ((ZipFileEntry*)b)->data_offset;
-  if (ao < bo) {
-    return -1;
-  } else if (ao > bo) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-// from bsdiff.c
-int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* new, off_t newsize,
-           const char* patch_filename);
-
-unsigned char* ReadZip(const char* filename,
-                       int* num_chunks, ImageChunk** chunks,
-                       int include_pseudo_chunk) {
-  struct stat st;
-  if (stat(filename, &st) != 0) {
-    printf("failed to stat \"%s\": %s\n", filename, strerror(errno));
-    return NULL;
-  }
-
-  unsigned char* img = malloc(st.st_size);
-  FILE* f = fopen(filename, "rb");
-  if (fread(img, 1, st.st_size, f) != st.st_size) {
-    printf("failed to read \"%s\" %s\n", filename, strerror(errno));
-    fclose(f);
-    return NULL;
-  }
-  fclose(f);
-
-  // look for the end-of-central-directory record.
-
-  int i;
-  for (i = st.st_size-20; i >= 0 && i > st.st_size - 65600; --i) {
-    if (img[i] == 0x50 && img[i+1] == 0x4b &&
-        img[i+2] == 0x05 && img[i+3] == 0x06) {
-      break;
-    }
-  }
-  // double-check: this archive consists of a single "disk"
-  if (!(img[i+4] == 0 && img[i+5] == 0 && img[i+6] == 0 && img[i+7] == 0)) {
-    printf("can't process multi-disk archive\n");
-    return NULL;
-  }
-
-  int cdcount = Read2(img+i+8);
-  int cdoffset = Read4(img+i+16);
-
-  ZipFileEntry* temp_entries = malloc(cdcount * sizeof(ZipFileEntry));
-  int entrycount = 0;
-
-  unsigned char* cd = img+cdoffset;
-  for (i = 0; i < cdcount; ++i) {
-    if (!(cd[0] == 0x50 && cd[1] == 0x4b && cd[2] == 0x01 && cd[3] == 0x02)) {
-      printf("bad central directory entry %d\n", i);
-      return NULL;
-    }
-
-    int clen = Read4(cd+20);   // compressed len
-    int ulen = Read4(cd+24);   // uncompressed len
-    int nlen = Read2(cd+28);   // filename len
-    int xlen = Read2(cd+30);   // extra field len
-    int mlen = Read2(cd+32);   // file comment len
-    int hoffset = Read4(cd+42);   // local header offset
-
-    char* filename = malloc(nlen+1);
-    memcpy(filename, cd+46, nlen);
-    filename[nlen] = '\0';
-
-    int method = Read2(cd+10);
-
-    cd += 46 + nlen + xlen + mlen;
-
-    if (method != 8) {  // 8 == deflate
-      free(filename);
-      continue;
-    }
-
-    unsigned char* lh = img + hoffset;
-
-    if (!(lh[0] == 0x50 && lh[1] == 0x4b && lh[2] == 0x03 && lh[3] == 0x04)) {
-      printf("bad local file header entry %d\n", i);
-      return NULL;
-    }
-
-    if (Read2(lh+26) != nlen || memcmp(lh+30, filename, nlen) != 0) {
-      printf("central dir filename doesn't match local header\n");
-      return NULL;
-    }
-
-    xlen = Read2(lh+28);   // extra field len; might be different from CD entry?
-
-    temp_entries[entrycount].data_offset = hoffset+30+nlen+xlen;
-    temp_entries[entrycount].deflate_len = clen;
-    temp_entries[entrycount].uncomp_len = ulen;
-    temp_entries[entrycount].filename = filename;
-    ++entrycount;
-  }
-
-  qsort(temp_entries, entrycount, sizeof(ZipFileEntry), fileentry_compare);
-
-#if 0
-  printf("found %d deflated entries\n", entrycount);
-  for (i = 0; i < entrycount; ++i) {
-    printf("off %10d  len %10d unlen %10d   %p %s\n",
-           temp_entries[i].data_offset,
-           temp_entries[i].deflate_len,
-           temp_entries[i].uncomp_len,
-           temp_entries[i].filename,
-           temp_entries[i].filename);
-  }
-#endif
-
-  *num_chunks = 0;
-  *chunks = malloc((entrycount*2+2) * sizeof(ImageChunk));
-  ImageChunk* curr = *chunks;
-
-  if (include_pseudo_chunk) {
-    curr->type = CHUNK_NORMAL;
-    curr->start = 0;
-    curr->len = st.st_size;
-    curr->data = img;
-    curr->filename = NULL;
-    curr->I = NULL;
-    ++curr;
-    ++*num_chunks;
-  }
-
-  int pos = 0;
-  int nextentry = 0;
-
-  while (pos < st.st_size) {
-    if (nextentry < entrycount && pos == temp_entries[nextentry].data_offset) {
-      curr->type = CHUNK_DEFLATE;
-      curr->start = pos;
-      curr->deflate_len = temp_entries[nextentry].deflate_len;
-      curr->deflate_data = img + pos;
-      curr->filename = temp_entries[nextentry].filename;
-      curr->I = NULL;
-
-      curr->len = temp_entries[nextentry].uncomp_len;
-      curr->data = malloc(curr->len);
-
-      z_stream strm;
-      strm.zalloc = Z_NULL;
-      strm.zfree = Z_NULL;
-      strm.opaque = Z_NULL;
-      strm.avail_in = curr->deflate_len;
-      strm.next_in = curr->deflate_data;
-
-      // -15 means we are decoding a 'raw' deflate stream; zlib will
-      // not expect zlib headers.
-      int ret = inflateInit2(&strm, -15);
-
-      strm.avail_out = curr->len;
-      strm.next_out = curr->data;
-      ret = inflate(&strm, Z_NO_FLUSH);
-      if (ret != Z_STREAM_END) {
-        printf("failed to inflate \"%s\"; %d\n", curr->filename, ret);
-        return NULL;
-      }
-
-      inflateEnd(&strm);
-
-      pos += curr->deflate_len;
-      ++nextentry;
-      ++*num_chunks;
-      ++curr;
-      continue;
-    }
-
-    // use a normal chunk to take all the data up to the start of the
-    // next deflate section.
-
-    curr->type = CHUNK_NORMAL;
-    curr->start = pos;
-    if (nextentry < entrycount) {
-      curr->len = temp_entries[nextentry].data_offset - pos;
-    } else {
-      curr->len = st.st_size - pos;
-    }
-    curr->data = img + pos;
-    curr->filename = NULL;
-    curr->I = NULL;
-    pos += curr->len;
-
-    ++*num_chunks;
-    ++curr;
-  }
-
-  free(temp_entries);
-  return img;
-}
-
-/*
- * Read the given file and break it up into chunks, putting the number
- * of chunks and their info in *num_chunks and **chunks,
- * respectively.  Returns a malloc'd block of memory containing the
- * contents of the file; various pointers in the output chunk array
- * will point into this block of memory.  The caller should free the
- * return value when done with all the chunks.  Returns NULL on
- * failure.
- */
-unsigned char* ReadImage(const char* filename,
-                         int* num_chunks, ImageChunk** chunks) {
-  struct stat st;
-  if (stat(filename, &st) != 0) {
-    printf("failed to stat \"%s\": %s\n", filename, strerror(errno));
-    return NULL;
-  }
-
-  unsigned char* img = malloc(st.st_size + 4);
-  FILE* f = fopen(filename, "rb");
-  if (fread(img, 1, st.st_size, f) != st.st_size) {
-    printf("failed to read \"%s\" %s\n", filename, strerror(errno));
-    fclose(f);
-    return NULL;
-  }
-  fclose(f);
-
-  // append 4 zero bytes to the data so we can always search for the
-  // four-byte string 1f8b0800 starting at any point in the actual
-  // file data, without special-casing the end of the data.
-  memset(img+st.st_size, 0, 4);
-
-  size_t pos = 0;
-
-  *num_chunks = 0;
-  *chunks = NULL;
-
-  while (pos < st.st_size) {
-    unsigned char* p = img+pos;
-
-    if (st.st_size - pos >= 4 &&
-        p[0] == 0x1f && p[1] == 0x8b &&
-        p[2] == 0x08 &&    // deflate compression
-        p[3] == 0x00) {    // no header flags
-      // 'pos' is the offset of the start of a gzip chunk.
-
-      *num_chunks += 3;
-      *chunks = realloc(*chunks, *num_chunks * sizeof(ImageChunk));
-      ImageChunk* curr = *chunks + (*num_chunks-3);
-
-      // create a normal chunk for the header.
-      curr->start = pos;
-      curr->type = CHUNK_NORMAL;
-      curr->len = GZIP_HEADER_LEN;
-      curr->data = p;
-      curr->I = NULL;
-
-      pos += curr->len;
-      p += curr->len;
-      ++curr;
-
-      curr->type = CHUNK_DEFLATE;
-      curr->filename = NULL;
-      curr->I = NULL;
-
-      // We must decompress this chunk in order to discover where it
-      // ends, and so we can put the uncompressed data and its length
-      // into curr->data and curr->len.
-
-      size_t allocated = 32768;
-      curr->len = 0;
-      curr->data = malloc(allocated);
-      curr->start = pos;
-      curr->deflate_data = p;
-
-      z_stream strm;
-      strm.zalloc = Z_NULL;
-      strm.zfree = Z_NULL;
-      strm.opaque = Z_NULL;
-      strm.avail_in = st.st_size - pos;
-      strm.next_in = p;
-
-      // -15 means we are decoding a 'raw' deflate stream; zlib will
-      // not expect zlib headers.
-      int ret = inflateInit2(&strm, -15);
-
-      do {
-        strm.avail_out = allocated - curr->len;
-        strm.next_out = curr->data + curr->len;
-        ret = inflate(&strm, Z_NO_FLUSH);
-        curr->len = allocated - strm.avail_out;
-        if (strm.avail_out == 0) {
-          allocated *= 2;
-          curr->data = realloc(curr->data, allocated);
-        }
-      } while (ret != Z_STREAM_END);
-
-      curr->deflate_len = st.st_size - strm.avail_in - pos;
-      inflateEnd(&strm);
-      pos += curr->deflate_len;
-      p += curr->deflate_len;
-      ++curr;
-
-      // create a normal chunk for the footer
-
-      curr->type = CHUNK_NORMAL;
-      curr->start = pos;
-      curr->len = GZIP_FOOTER_LEN;
-      curr->data = img+pos;
-      curr->I = NULL;
-
-      pos += curr->len;
-      p += curr->len;
-      ++curr;
-
-      // The footer (that we just skipped over) contains the size of
-      // the uncompressed data.  Double-check to make sure that it
-      // matches the size of the data we got when we actually did
-      // the decompression.
-      size_t footer_size = Read4(p-4);
-      if (footer_size != curr[-2].len) {
-        printf("Error: footer size %d != decompressed size %d\n",
-                footer_size, curr[-2].len);
-        free(img);
-        return NULL;
-      }
-    } else {
-      // Reallocate the list for every chunk; we expect the number of
-      // chunks to be small (5 for typical boot and recovery images).
-      ++*num_chunks;
-      *chunks = realloc(*chunks, *num_chunks * sizeof(ImageChunk));
-      ImageChunk* curr = *chunks + (*num_chunks-1);
-      curr->start = pos;
-      curr->I = NULL;
-
-      // 'pos' is not the offset of the start of a gzip chunk, so scan
-      // forward until we find a gzip header.
-      curr->type = CHUNK_NORMAL;
-      curr->data = p;
-
-      for (curr->len = 0; curr->len < (st.st_size - pos); ++curr->len) {
-        if (p[curr->len] == 0x1f &&
-            p[curr->len+1] == 0x8b &&
-            p[curr->len+2] == 0x08 &&
-            p[curr->len+3] == 0x00) {
-          break;
-        }
-      }
-      pos += curr->len;
-    }
-  }
-
-  return img;
-}
-
-#define BUFFER_SIZE 32768
-
-/*
- * Takes the uncompressed data stored in the chunk, compresses it
- * using the zlib parameters stored in the chunk, and checks that it
- * matches exactly the compressed data we started with (also stored in
- * the chunk).  Return 0 on success.
- */
-int TryReconstruction(ImageChunk* chunk, unsigned char* out) {
-  size_t p = 0;
-
-#if 0
-  printf("trying %d %d %d %d %d\n",
-          chunk->level, chunk->method, chunk->windowBits,
-          chunk->memLevel, chunk->strategy);
-#endif
-
-  z_stream strm;
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-  strm.opaque = Z_NULL;
-  strm.avail_in = chunk->len;
-  strm.next_in = chunk->data;
-  int ret;
-  ret = deflateInit2(&strm, chunk->level, chunk->method, chunk->windowBits,
-                     chunk->memLevel, chunk->strategy);
-  do {
-    strm.avail_out = BUFFER_SIZE;
-    strm.next_out = out;
-    ret = deflate(&strm, Z_FINISH);
-    size_t have = BUFFER_SIZE - strm.avail_out;
-
-    if (memcmp(out, chunk->deflate_data+p, have) != 0) {
-      // mismatch; data isn't the same.
-      deflateEnd(&strm);
-      return -1;
-    }
-    p += have;
-  } while (ret != Z_STREAM_END);
-  deflateEnd(&strm);
-  if (p != chunk->deflate_len) {
-    // mismatch; ran out of data before we should have.
-    return -1;
-  }
-  return 0;
-}
-
-/*
- * Verify that we can reproduce exactly the same compressed data that
- * we started with.  Sets the level, method, windowBits, memLevel, and
- * strategy fields in the chunk to the encoding parameters needed to
- * produce the right output.  Returns 0 on success.
- */
-int ReconstructDeflateChunk(ImageChunk* chunk) {
-  if (chunk->type != CHUNK_DEFLATE) {
-    printf("attempt to reconstruct non-deflate chunk\n");
-    return -1;
-  }
-
-  size_t p = 0;
-  unsigned char* out = malloc(BUFFER_SIZE);
-
-  // We only check two combinations of encoder parameters:  level 6
-  // (the default) and level 9 (the maximum).
-  for (chunk->level = 6; chunk->level <= 9; chunk->level += 3) {
-    chunk->windowBits = -15;  // 32kb window; negative to indicate a raw stream.
-    chunk->memLevel = 8;      // the default value.
-    chunk->method = Z_DEFLATED;
-    chunk->strategy = Z_DEFAULT_STRATEGY;
-
-    if (TryReconstruction(chunk, out) == 0) {
-      free(out);
-      return 0;
-    }
-  }
-
-  free(out);
-  return -1;
-}
-
-/*
- * Given source and target chunks, compute a bsdiff patch between them
- * by running bsdiff in a subprocess.  Return the patch data, placing
- * its length in *size.  Return NULL on failure.  We expect the bsdiff
- * program to be in the path.
- */
-unsigned char* MakePatch(ImageChunk* src, ImageChunk* tgt, size_t* size) {
-  if (tgt->type == CHUNK_NORMAL) {
-    if (tgt->len <= 160) {
-      tgt->type = CHUNK_RAW;
-      *size = tgt->len;
-      return tgt->data;
-    }
-  }
-
-  char ptemp[] = "/tmp/imgdiff-patch-XXXXXX";
-  mkstemp(ptemp);
-
-  int r = bsdiff(src->data, src->len, &(src->I), tgt->data, tgt->len, ptemp);
-  if (r != 0) {
-    printf("bsdiff() failed: %d\n", r);
-    return NULL;
-  }
-
-  struct stat st;
-  if (stat(ptemp, &st) != 0) {
-    printf("failed to stat patch file %s: %s\n",
-            ptemp, strerror(errno));
-    return NULL;
-  }
-
-  unsigned char* data = malloc(st.st_size);
-
-  if (tgt->type == CHUNK_NORMAL && tgt->len <= st.st_size) {
-    unlink(ptemp);
-
-    tgt->type = CHUNK_RAW;
-    *size = tgt->len;
-    return tgt->data;
-  }
-
-  *size = st.st_size;
-
-  FILE* f = fopen(ptemp, "rb");
-  if (f == NULL) {
-    printf("failed to open patch %s: %s\n", ptemp, strerror(errno));
-    return NULL;
-  }
-  if (fread(data, 1, st.st_size, f) != st.st_size) {
-    printf("failed to read patch %s: %s\n", ptemp, strerror(errno));
-    return NULL;
-  }
-  fclose(f);
-
-  unlink(ptemp);
-
-  tgt->source_start = src->start;
-  switch (tgt->type) {
-    case CHUNK_NORMAL:
-      tgt->source_len = src->len;
-      break;
-    case CHUNK_DEFLATE:
-      tgt->source_len = src->deflate_len;
-      tgt->source_uncompressed_len = src->len;
-      break;
-  }
-
-  return data;
-}
-
-/*
- * Cause a gzip chunk to be treated as a normal chunk (ie, as a blob
- * of uninterpreted data).  The resulting patch will likely be about
- * as big as the target file, but it lets us handle the case of images
- * where some gzip chunks are reconstructible but others aren't (by
- * treating the ones that aren't as normal chunks).
- */
-void ChangeDeflateChunkToNormal(ImageChunk* ch) {
-  if (ch->type != CHUNK_DEFLATE) return;
-  ch->type = CHUNK_NORMAL;
-  free(ch->data);
-  ch->data = ch->deflate_data;
-  ch->len = ch->deflate_len;
-}
-
-/*
- * Return true if the data in the chunk is identical (including the
- * compressed representation, for gzip chunks).
- */
-int AreChunksEqual(ImageChunk* a, ImageChunk* b) {
-    if (a->type != b->type) return 0;
-
-    switch (a->type) {
-        case CHUNK_NORMAL:
-            return a->len == b->len && memcmp(a->data, b->data, a->len) == 0;
-
-        case CHUNK_DEFLATE:
-            return a->deflate_len == b->deflate_len &&
-                memcmp(a->deflate_data, b->deflate_data, a->deflate_len) == 0;
-
-        default:
-            printf("unknown chunk type %d\n", a->type);
-            return 0;
-    }
-}
-
-/*
- * Look for runs of adjacent normal chunks and compress them down into
- * a single chunk.  (Such runs can be produced when deflate chunks are
- * changed to normal chunks.)
- */
-void MergeAdjacentNormalChunks(ImageChunk* chunks, int* num_chunks) {
-  int out = 0;
-  int in_start = 0, in_end;
-  while (in_start < *num_chunks) {
-    if (chunks[in_start].type != CHUNK_NORMAL) {
-      in_end = in_start+1;
-    } else {
-      // in_start is a normal chunk.  Look for a run of normal chunks
-      // that constitute a solid block of data (ie, each chunk begins
-      // where the previous one ended).
-      for (in_end = in_start+1;
-           in_end < *num_chunks && chunks[in_end].type == CHUNK_NORMAL &&
-             (chunks[in_end].start ==
-              chunks[in_end-1].start + chunks[in_end-1].len &&
-              chunks[in_end].data ==
-              chunks[in_end-1].data + chunks[in_end-1].len);
-           ++in_end);
-    }
-
-    if (in_end == in_start+1) {
-#if 0
-      printf("chunk %d is now %d\n", in_start, out);
-#endif
-      if (out != in_start) {
-        memcpy(chunks+out, chunks+in_start, sizeof(ImageChunk));
-      }
-    } else {
-#if 0
-      printf("collapse normal chunks %d-%d into %d\n", in_start, in_end-1, out);
-#endif
-
-      // Merge chunks [in_start, in_end-1] into one chunk.  Since the
-      // data member of each chunk is just a pointer into an in-memory
-      // copy of the file, this can be done without recopying (the
-      // output chunk has the first chunk's start location and data
-      // pointer, and length equal to the sum of the input chunk
-      // lengths).
-      chunks[out].type = CHUNK_NORMAL;
-      chunks[out].start = chunks[in_start].start;
-      chunks[out].data = chunks[in_start].data;
-      chunks[out].len = chunks[in_end-1].len +
-        (chunks[in_end-1].start - chunks[in_start].start);
-    }
-
-    ++out;
-    in_start = in_end;
-  }
-  *num_chunks = out;
-}
-
-ImageChunk* FindChunkByName(const char* name,
-                            ImageChunk* chunks, int num_chunks) {
-  int i;
-  for (i = 0; i < num_chunks; ++i) {
-    if (chunks[i].type == CHUNK_DEFLATE && chunks[i].filename &&
-        strcmp(name, chunks[i].filename) == 0) {
-      return chunks+i;
-    }
-  }
-  return NULL;
-}
-
-void DumpChunks(ImageChunk* chunks, int num_chunks) {
-    int i;
-    for (i = 0; i < num_chunks; ++i) {
-        printf("chunk %d: type %d start %d len %d\n",
-               i, chunks[i].type, chunks[i].start, chunks[i].len);
-    }
-}
-
-int main(int argc, char** argv) {
-  if (argc != 4 && argc != 5) {
-    usage:
-    printf("usage: %s [-z] <src-img> <tgt-img> <patch-file>\n",
-            argv[0]);
-    return 2;
-  }
-
-  int zip_mode = 0;
-
-  if (strcmp(argv[1], "-z") == 0) {
-    zip_mode = 1;
-    --argc;
-    ++argv;
-  }
-
-
-  int num_src_chunks;
-  ImageChunk* src_chunks;
-  int num_tgt_chunks;
-  ImageChunk* tgt_chunks;
-  int i;
-
-  if (zip_mode) {
-    if (ReadZip(argv[1], &num_src_chunks, &src_chunks, 1) == NULL) {
-      printf("failed to break apart source zip file\n");
-      return 1;
-    }
-    if (ReadZip(argv[2], &num_tgt_chunks, &tgt_chunks, 0) == NULL) {
-      printf("failed to break apart target zip file\n");
-      return 1;
-    }
-  } else {
-    if (ReadImage(argv[1], &num_src_chunks, &src_chunks) == NULL) {
-      printf("failed to break apart source image\n");
-      return 1;
-    }
-    if (ReadImage(argv[2], &num_tgt_chunks, &tgt_chunks) == NULL) {
-      printf("failed to break apart target image\n");
-      return 1;
-    }
-
-    // Verify that the source and target images have the same chunk
-    // structure (ie, the same sequence of deflate and normal chunks).
-
-    if (!zip_mode) {
-        // Merge the gzip header and footer in with any adjacent
-        // normal chunks.
-        MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
-        MergeAdjacentNormalChunks(src_chunks, &num_src_chunks);
-    }
-
-    if (num_src_chunks != num_tgt_chunks) {
-      printf("source and target don't have same number of chunks!\n");
-      printf("source chunks:\n");
-      DumpChunks(src_chunks, num_src_chunks);
-      printf("target chunks:\n");
-      DumpChunks(tgt_chunks, num_tgt_chunks);
-      return 1;
-    }
-    for (i = 0; i < num_src_chunks; ++i) {
-      if (src_chunks[i].type != tgt_chunks[i].type) {
-        printf("source and target don't have same chunk "
-                "structure! (chunk %d)\n", i);
-        printf("source chunks:\n");
-        DumpChunks(src_chunks, num_src_chunks);
-        printf("target chunks:\n");
-        DumpChunks(tgt_chunks, num_tgt_chunks);
-        return 1;
-      }
-    }
-  }
-
-  for (i = 0; i < num_tgt_chunks; ++i) {
-    if (tgt_chunks[i].type == CHUNK_DEFLATE) {
-      // Confirm that given the uncompressed chunk data in the target, we
-      // can recompress it and get exactly the same bits as are in the
-      // input target image.  If this fails, treat the chunk as a normal
-      // non-deflated chunk.
-      if (ReconstructDeflateChunk(tgt_chunks+i) < 0) {
-        printf("failed to reconstruct target deflate chunk %d [%s]; "
-               "treating as normal\n", i, tgt_chunks[i].filename);
-        ChangeDeflateChunkToNormal(tgt_chunks+i);
-        if (zip_mode) {
-          ImageChunk* src = FindChunkByName(tgt_chunks[i].filename, src_chunks, num_src_chunks);
-          if (src) {
-            ChangeDeflateChunkToNormal(src);
-          }
-        } else {
-          ChangeDeflateChunkToNormal(src_chunks+i);
-        }
-        continue;
-      }
-
-      // If two deflate chunks are identical (eg, the kernel has not
-      // changed between two builds), treat them as normal chunks.
-      // This makes applypatch much faster -- it can apply a trivial
-      // patch to the compressed data, rather than uncompressing and
-      // recompressing to apply the trivial patch to the uncompressed
-      // data.
-      ImageChunk* src;
-      if (zip_mode) {
-        src = FindChunkByName(tgt_chunks[i].filename, src_chunks, num_src_chunks);
-      } else {
-        src = src_chunks+i;
-      }
-
-      if (src == NULL || AreChunksEqual(tgt_chunks+i, src)) {
-        ChangeDeflateChunkToNormal(tgt_chunks+i);
-        if (src) {
-          ChangeDeflateChunkToNormal(src);
-        }
-      }
-    }
-  }
-
-  // Merging neighboring normal chunks.
-  if (zip_mode) {
-    // For zips, we only need to do this to the target:  deflated
-    // chunks are matched via filename, and normal chunks are patched
-    // using the entire source file as the source.
-    MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
-  } else {
-    // For images, we need to maintain the parallel structure of the
-    // chunk lists, so do the merging in both the source and target
-    // lists.
-    MergeAdjacentNormalChunks(tgt_chunks, &num_tgt_chunks);
-    MergeAdjacentNormalChunks(src_chunks, &num_src_chunks);
-    if (num_src_chunks != num_tgt_chunks) {
-      // This shouldn't happen.
-      printf("merging normal chunks went awry\n");
-      return 1;
-    }
-  }
-
-  // Compute bsdiff patches for each chunk's data (the uncompressed
-  // data, in the case of deflate chunks).
-
-  printf("Construct patches for %d chunks...\n", num_tgt_chunks);
-  unsigned char** patch_data = malloc(num_tgt_chunks * sizeof(unsigned char*));
-  size_t* patch_size = malloc(num_tgt_chunks * sizeof(size_t));
-  for (i = 0; i < num_tgt_chunks; ++i) {
-    if (zip_mode) {
-      ImageChunk* src;
-      if (tgt_chunks[i].type == CHUNK_DEFLATE &&
-          (src = FindChunkByName(tgt_chunks[i].filename, src_chunks,
-                                 num_src_chunks))) {
-        patch_data[i] = MakePatch(src, tgt_chunks+i, patch_size+i);
-      } else {
-        patch_data[i] = MakePatch(src_chunks, tgt_chunks+i, patch_size+i);
-      }
-    } else {
-      patch_data[i] = MakePatch(src_chunks+i, tgt_chunks+i, patch_size+i);
-    }
-    printf("patch %3d is %d bytes (of %d)\n",
-           i, patch_size[i], tgt_chunks[i].source_len);
-  }
-
-  // Figure out how big the imgdiff file header is going to be, so
-  // that we can correctly compute the offset of each bsdiff patch
-  // within the file.
-
-  size_t total_header_size = 12;
-  for (i = 0; i < num_tgt_chunks; ++i) {
-    total_header_size += 4;
-    switch (tgt_chunks[i].type) {
-      case CHUNK_NORMAL:
-        total_header_size += 8*3;
-        break;
-      case CHUNK_DEFLATE:
-        total_header_size += 8*5 + 4*5;
-        break;
-      case CHUNK_RAW:
-        total_header_size += 4 + patch_size[i];
-        break;
-    }
-  }
-
-  size_t offset = total_header_size;
-
-  FILE* f = fopen(argv[3], "wb");
-
-  // Write out the headers.
-
-  fwrite("IMGDIFF2", 1, 8, f);
-  Write4(num_tgt_chunks, f);
-  for (i = 0; i < num_tgt_chunks; ++i) {
-    Write4(tgt_chunks[i].type, f);
-
-    switch (tgt_chunks[i].type) {
-      case CHUNK_NORMAL:
-        printf("chunk %3d: normal   (%10d, %10d)  %10d\n", i,
-               tgt_chunks[i].start, tgt_chunks[i].len, patch_size[i]);
-        Write8(tgt_chunks[i].source_start, f);
-        Write8(tgt_chunks[i].source_len, f);
-        Write8(offset, f);
-        offset += patch_size[i];
-        break;
-
-      case CHUNK_DEFLATE:
-        printf("chunk %3d: deflate  (%10d, %10d)  %10d  %s\n", i,
-               tgt_chunks[i].start, tgt_chunks[i].deflate_len, patch_size[i],
-               tgt_chunks[i].filename);
-        Write8(tgt_chunks[i].source_start, f);
-        Write8(tgt_chunks[i].source_len, f);
-        Write8(offset, f);
-        Write8(tgt_chunks[i].source_uncompressed_len, f);
-        Write8(tgt_chunks[i].len, f);
-        Write4(tgt_chunks[i].level, f);
-        Write4(tgt_chunks[i].method, f);
-        Write4(tgt_chunks[i].windowBits, f);
-        Write4(tgt_chunks[i].memLevel, f);
-        Write4(tgt_chunks[i].strategy, f);
-        offset += patch_size[i];
-        break;
-
-      case CHUNK_RAW:
-        printf("chunk %3d: raw      (%10d, %10d)\n", i,
-               tgt_chunks[i].start, tgt_chunks[i].len);
-        Write4(patch_size[i], f);
-        fwrite(patch_data[i], 1, patch_size[i], f);
-        break;
-    }
-  }
-
-  // Append each chunk's bsdiff patch, in order.
-
-  for (i = 0; i < num_tgt_chunks; ++i) {
-    if (tgt_chunks[i].type != CHUNK_RAW) {
-      fwrite(patch_data[i], 1, patch_size[i], f);
-    }
-  }
-
-  fclose(f);
-
-  return 0;
-}
diff --git a/tools/applypatch/imgdiff.h b/tools/applypatch/imgdiff.h
deleted file mode 100644
index f2069b4..0000000
--- a/tools/applypatch/imgdiff.h
+++ /dev/null
@@ -1,30 +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.
- */
-
-// Image patch chunk types
-#define CHUNK_NORMAL   0
-#define CHUNK_GZIP     1   // version 1 only
-#define CHUNK_DEFLATE  2   // version 2 only
-#define CHUNK_RAW      3   // version 2 only
-
-// The gzip header size is actually variable, but we currently don't
-// support gzipped data with any of the optional fields, so for now it
-// will always be ten bytes.  See RFC 1952 for the definition of the
-// gzip format.
-#define GZIP_HEADER_LEN   10
-
-// The gzip footer size really is fixed.
-#define GZIP_FOOTER_LEN   8
diff --git a/tools/applypatch/imgdiff_test.sh b/tools/applypatch/imgdiff_test.sh
deleted file mode 100755
index dcdb922..0000000
--- a/tools/applypatch/imgdiff_test.sh
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/bash
-#
-# A script for testing imgdiff/applypatch.  It takes two full OTA
-# packages as arguments.  It generates (on the host) patches for all
-# the zip/jar/apk files they have in common, as well as boot and
-# recovery images.  It then applies the patches on the device (or
-# emulator) and checks that the resulting file is correct.
-
-EMULATOR_PORT=5580
-
-# set to 0 to use a device instead
-USE_EMULATOR=0
-
-# where on the device to do all the patching.
-WORK_DIR=/data/local/tmp
-
-START_OTA_PACKAGE=$1
-END_OTA_PACKAGE=$2
-
-# ------------------------
-
-tmpdir=$(mktemp -d)
-
-if [ "$USE_EMULATOR" == 1 ]; then
-  emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT &
-  pid_emulator=$!
-  ADB="adb -s emulator-$EMULATOR_PORT "
-else
-  ADB="adb -d "
-fi
-
-echo "waiting to connect to device"
-$ADB wait-for-device
-
-# run a command on the device; exit with the exit status of the device
-# command.
-run_command() {
-  $ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}'
-}
-
-testname() {
-  echo
-  echo "$1"...
-  testname="$1"
-}
-
-fail() {
-  echo
-  echo FAIL: $testname
-  echo
-  [ "$open_pid" == "" ] || kill $open_pid
-  [ "$pid_emulator" == "" ] || kill $pid_emulator
-  exit 1
-}
-
-sha1() {
-  sha1sum $1 | awk '{print $1}'
-}
-
-size() {
-  stat -c %s $1 | tr -d '\n'
-}
-
-cleanup() {
-  # not necessary if we're about to kill the emulator, but nice for
-  # running on real devices or already-running emulators.
-  testname "removing test files"
-  run_command rm $WORK_DIR/applypatch
-  run_command rm $WORK_DIR/source
-  run_command rm $WORK_DIR/target
-  run_command rm $WORK_DIR/patch
-
-  [ "$pid_emulator" == "" ] || kill $pid_emulator
-
-  rm -rf $tmpdir
-}
-
-$ADB push $ANDROID_PRODUCT_OUT/system/bin/applypatch $WORK_DIR/applypatch
-
-patch_and_apply() {
-  local fn=$1
-  shift
-
-  unzip -p $START_OTA_PACKAGE $fn > $tmpdir/source
-  unzip -p $END_OTA_PACKAGE $fn > $tmpdir/target
-  imgdiff "$@" $tmpdir/source $tmpdir/target $tmpdir/patch
-  bsdiff $tmpdir/source $tmpdir/target $tmpdir/patch.bs
-  echo "patch for $fn is $(size $tmpdir/patch) [of $(size $tmpdir/target)] ($(size $tmpdir/patch.bs) with bsdiff)"
-  echo "$fn $(size $tmpdir/patch) of $(size $tmpdir/target) bsdiff $(size $tmpdir/patch.bs)" >> /tmp/stats.txt
-  $ADB push $tmpdir/source $WORK_DIR/source || fail "source push failed"
-  run_command rm /data/local/tmp/target
-  $ADB push $tmpdir/patch $WORK_DIR/patch || fail "patch push failed"
-  run_command /data/local/tmp/applypatch /data/local/tmp/source \
-    /data/local/tmp/target $(sha1 $tmpdir/target) $(size $tmpdir/target) \
-    $(sha1 $tmpdir/source):/data/local/tmp/patch \
-    || fail "applypatch of $fn failed"
-  $ADB pull /data/local/tmp/target $tmpdir/result
-  diff -q $tmpdir/target $tmpdir/result || fail "patch output not correct!"
-}
-
-# --------------- basic execution ----------------------
-
-for i in $((zipinfo -1 $START_OTA_PACKAGE; zipinfo -1 $END_OTA_PACKAGE) | \
-           sort | uniq -d | egrep -e '[.](apk|jar|zip)$'); do
-  patch_and_apply $i -z
-done
-patch_and_apply boot.img
-patch_and_apply system/recovery.img
-
-
-# --------------- cleanup ----------------------
-
-cleanup
-
-echo
-echo PASS
-echo
-
diff --git a/tools/applypatch/imgpatch.c b/tools/applypatch/imgpatch.c
deleted file mode 100644
index 5322817..0000000
--- a/tools/applypatch/imgpatch.c
+++ /dev/null
@@ -1,364 +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.
- */
-
-// See imgdiff.c in this directory for a description of the patch file
-// format.
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "zlib.h"
-#include "mincrypt/sha.h"
-#include "applypatch.h"
-#include "imgdiff.h"
-#include "utils.h"
-
-/*
- * Apply the patch given in 'patch_filename' to the source data given
- * by (old_data, old_size).  Write the patched output to the 'output'
- * file, and update the SHA context with the output data as well.
- * Return 0 on success.
- */
-int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
-                    const char* patch_filename,
-                    SinkFn sink, void* token, SHA_CTX* ctx) {
-  FILE* f;
-  if ((f = fopen(patch_filename, "rb")) == NULL) {
-    printf("failed to open patch file\n");
-    return -1;
-  }
-
-  unsigned char header[12];
-  if (fread(header, 1, 12, f) != 12) {
-    printf("failed to read patch file header\n");
-    return -1;
-  }
-
-  // IMGDIFF1 uses CHUNK_NORMAL and CHUNK_GZIP.
-  // IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW.
-  if (memcmp(header, "IMGDIFF", 7) != 0 ||
-      (header[7] != '1' && header[7] != '2')) {
-    printf("corrupt patch file header (magic number)\n");
-    return -1;
-  }
-
-  int num_chunks = Read4(header+8);
-
-  int i;
-  for (i = 0; i < num_chunks; ++i) {
-    // each chunk's header record starts with 4 bytes.
-    unsigned char chunk[4];
-    if (fread(chunk, 1, 4, f) != 4) {
-      printf("failed to read chunk %d record\n", i);
-      return -1;
-    }
-
-    int type = Read4(chunk);
-
-    if (type == CHUNK_NORMAL) {
-      unsigned char normal_header[24];
-      if (fread(normal_header, 1, 24, f) != 24) {
-        printf("failed to read chunk %d normal header data\n", i);
-        return -1;
-      }
-
-      size_t src_start = Read8(normal_header);
-      size_t src_len = Read8(normal_header+8);
-      size_t patch_offset = Read8(normal_header+16);
-
-      printf("CHUNK %d:  normal   patch offset %d\n", i, patch_offset);
-
-      ApplyBSDiffPatch(old_data + src_start, src_len,
-                       patch_filename, patch_offset,
-                       sink, token, ctx);
-    } else if (type == CHUNK_GZIP) {
-      // This branch is basically a duplicate of the CHUNK_DEFLATE
-      // branch, with a bit of extra processing for the gzip header
-      // and footer.  I've avoided factoring the common code out since
-      // this branch will just be deleted when we drop support for
-      // IMGDIFF1.
-
-      // gzip chunks have an additional 64 + gzip_header_len + 8 bytes
-      // in their chunk header.
-      unsigned char* gzip = malloc(64);
-      if (fread(gzip, 1, 64, f) != 64) {
-        printf("failed to read chunk %d initial gzip header data\n",
-                i);
-        return -1;
-      }
-      size_t gzip_header_len = Read4(gzip+60);
-      gzip = realloc(gzip, 64 + gzip_header_len + 8);
-      if (fread(gzip+64, 1, gzip_header_len+8, f) != gzip_header_len+8) {
-        printf("failed to read chunk %d remaining gzip header data\n",
-                i);
-        return -1;
-      }
-
-      size_t src_start = Read8(gzip);
-      size_t src_len = Read8(gzip+8);
-      size_t patch_offset = Read8(gzip+16);
-
-      size_t expanded_len = Read8(gzip+24);
-      size_t target_len = Read8(gzip+32);
-      int gz_level = Read4(gzip+40);
-      int gz_method = Read4(gzip+44);
-      int gz_windowBits = Read4(gzip+48);
-      int gz_memLevel = Read4(gzip+52);
-      int gz_strategy = Read4(gzip+56);
-
-      printf("CHUNK %d:  gzip     patch offset %d\n", i, patch_offset);
-
-      // Decompress the source data; the chunk header tells us exactly
-      // how big we expect it to be when decompressed.
-
-      unsigned char* expanded_source = malloc(expanded_len);
-      if (expanded_source == NULL) {
-        printf("failed to allocate %d bytes for expanded_source\n",
-                expanded_len);
-        return -1;
-      }
-
-      z_stream strm;
-      strm.zalloc = Z_NULL;
-      strm.zfree = Z_NULL;
-      strm.opaque = Z_NULL;
-      strm.avail_in = src_len - (gzip_header_len + 8);
-      strm.next_in = (unsigned char*)(old_data + src_start + gzip_header_len);
-      strm.avail_out = expanded_len;
-      strm.next_out = expanded_source;
-
-      int ret;
-      ret = inflateInit2(&strm, -15);
-      if (ret != Z_OK) {
-        printf("failed to init source inflation: %d\n", ret);
-        return -1;
-      }
-
-      // Because we've provided enough room to accommodate the output
-      // data, we expect one call to inflate() to suffice.
-      ret = inflate(&strm, Z_SYNC_FLUSH);
-      if (ret != Z_STREAM_END) {
-        printf("source inflation returned %d\n", ret);
-        return -1;
-      }
-      // We should have filled the output buffer exactly.
-      if (strm.avail_out != 0) {
-        printf("source inflation short by %d bytes\n", strm.avail_out);
-        return -1;
-      }
-      inflateEnd(&strm);
-
-      // Next, apply the bsdiff patch (in memory) to the uncompressed
-      // data.
-      unsigned char* uncompressed_target_data;
-      ssize_t uncompressed_target_size;
-      if (ApplyBSDiffPatchMem(expanded_source, expanded_len,
-                              patch_filename, patch_offset,
-                              &uncompressed_target_data,
-                              &uncompressed_target_size) != 0) {
-        return -1;
-      }
-
-      // Now compress the target data and append it to the output.
-
-      // start with the gzip header.
-      sink(gzip+64, gzip_header_len, token);
-      SHA_update(ctx, gzip+64, gzip_header_len);
-
-      // we're done with the expanded_source data buffer, so we'll
-      // reuse that memory to receive the output of deflate.
-      unsigned char* temp_data = expanded_source;
-      ssize_t temp_size = expanded_len;
-      if (temp_size < 32768) {
-        // ... unless the buffer is too small, in which case we'll
-        // allocate a fresh one.
-        free(temp_data);
-        temp_data = malloc(32768);
-        temp_size = 32768;
-      }
-
-      // now the deflate stream
-      strm.zalloc = Z_NULL;
-      strm.zfree = Z_NULL;
-      strm.opaque = Z_NULL;
-      strm.avail_in = uncompressed_target_size;
-      strm.next_in = uncompressed_target_data;
-      ret = deflateInit2(&strm, gz_level, gz_method, gz_windowBits,
-                         gz_memLevel, gz_strategy);
-      do {
-        strm.avail_out = temp_size;
-        strm.next_out = temp_data;
-        ret = deflate(&strm, Z_FINISH);
-        size_t have = temp_size - strm.avail_out;
-
-        if (sink(temp_data, have, token) != have) {
-          printf("failed to write %d compressed bytes to output\n",
-                  have);
-          return -1;
-        }
-        SHA_update(ctx, temp_data, have);
-      } while (ret != Z_STREAM_END);
-      deflateEnd(&strm);
-
-      // lastly, the gzip footer.
-      sink(gzip+64+gzip_header_len, 8, token);
-      SHA_update(ctx, gzip+64+gzip_header_len, 8);
-
-      free(temp_data);
-      free(uncompressed_target_data);
-      free(gzip);
-    } else if (type == CHUNK_RAW) {
-      unsigned char raw_header[4];
-      if (fread(raw_header, 1, 4, f) != 4) {
-        printf("failed to read chunk %d raw header data\n", i);
-        return -1;
-      }
-
-      size_t data_len = Read4(raw_header);
-
-      printf("CHUNK %d:  raw      data %d\n", i, data_len);
-
-      unsigned char* temp = malloc(data_len);
-      if (fread(temp, 1, data_len, f) != data_len) {
-          printf("failed to read chunk %d raw data\n", i);
-          return -1;
-      }
-      SHA_update(ctx, temp, data_len);
-      if (sink(temp, data_len, token) != data_len) {
-          printf("failed to write chunk %d raw data\n", i);
-          return -1;
-      }
-    } else if (type == CHUNK_DEFLATE) {
-      // deflate chunks have an additional 60 bytes in their chunk header.
-      unsigned char deflate_header[60];
-      if (fread(deflate_header, 1, 60, f) != 60) {
-        printf("failed to read chunk %d deflate header data\n", i);
-        return -1;
-      }
-
-      size_t src_start = Read8(deflate_header);
-      size_t src_len = Read8(deflate_header+8);
-      size_t patch_offset = Read8(deflate_header+16);
-      size_t expanded_len = Read8(deflate_header+24);
-      size_t target_len = Read8(deflate_header+32);
-      int level = Read4(deflate_header+40);
-      int method = Read4(deflate_header+44);
-      int windowBits = Read4(deflate_header+48);
-      int memLevel = Read4(deflate_header+52);
-      int strategy = Read4(deflate_header+56);
-
-      printf("CHUNK %d:  deflate  patch offset %d\n", i, patch_offset);
-
-      // Decompress the source data; the chunk header tells us exactly
-      // how big we expect it to be when decompressed.
-
-      unsigned char* expanded_source = malloc(expanded_len);
-      if (expanded_source == NULL) {
-        printf("failed to allocate %d bytes for expanded_source\n",
-                expanded_len);
-        return -1;
-      }
-
-      z_stream strm;
-      strm.zalloc = Z_NULL;
-      strm.zfree = Z_NULL;
-      strm.opaque = Z_NULL;
-      strm.avail_in = src_len;
-      strm.next_in = (unsigned char*)(old_data + src_start);
-      strm.avail_out = expanded_len;
-      strm.next_out = expanded_source;
-
-      int ret;
-      ret = inflateInit2(&strm, -15);
-      if (ret != Z_OK) {
-        printf("failed to init source inflation: %d\n", ret);
-        return -1;
-      }
-
-      // Because we've provided enough room to accommodate the output
-      // data, we expect one call to inflate() to suffice.
-      ret = inflate(&strm, Z_SYNC_FLUSH);
-      if (ret != Z_STREAM_END) {
-        printf("source inflation returned %d\n", ret);
-        return -1;
-      }
-      // We should have filled the output buffer exactly.
-      if (strm.avail_out != 0) {
-        printf("source inflation short by %d bytes\n", strm.avail_out);
-        return -1;
-      }
-      inflateEnd(&strm);
-
-      // Next, apply the bsdiff patch (in memory) to the uncompressed
-      // data.
-      unsigned char* uncompressed_target_data;
-      ssize_t uncompressed_target_size;
-      if (ApplyBSDiffPatchMem(expanded_source, expanded_len,
-                              patch_filename, patch_offset,
-                              &uncompressed_target_data,
-                              &uncompressed_target_size) != 0) {
-        return -1;
-      }
-
-      // Now compress the target data and append it to the output.
-
-      // we're done with the expanded_source data buffer, so we'll
-      // reuse that memory to receive the output of deflate.
-      unsigned char* temp_data = expanded_source;
-      ssize_t temp_size = expanded_len;
-      if (temp_size < 32768) {
-        // ... unless the buffer is too small, in which case we'll
-        // allocate a fresh one.
-        free(temp_data);
-        temp_data = malloc(32768);
-        temp_size = 32768;
-      }
-
-      // now the deflate stream
-      strm.zalloc = Z_NULL;
-      strm.zfree = Z_NULL;
-      strm.opaque = Z_NULL;
-      strm.avail_in = uncompressed_target_size;
-      strm.next_in = uncompressed_target_data;
-      ret = deflateInit2(&strm, level, method, windowBits, memLevel, strategy);
-      do {
-        strm.avail_out = temp_size;
-        strm.next_out = temp_data;
-        ret = deflate(&strm, Z_FINISH);
-        size_t have = temp_size - strm.avail_out;
-
-        if (sink(temp_data, have, token) != have) {
-          printf("failed to write %d compressed bytes to output\n",
-                  have);
-          return -1;
-        }
-        SHA_update(ctx, temp_data, have);
-      } while (ret != Z_STREAM_END);
-      deflateEnd(&strm);
-
-      free(temp_data);
-      free(uncompressed_target_data);
-    } else {
-      printf("patch chunk %d is unknown type %d\n", i, type);
-      return -1;
-    }
-  }
-
-  return 0;
-}
diff --git a/tools/applypatch/main.c b/tools/applypatch/main.c
deleted file mode 100644
index e08f5c1..0000000
--- a/tools/applypatch/main.c
+++ /dev/null
@@ -1,60 +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.
- */
-
-#include <stdio.h>
-
-extern int applypatch(int argc, char** argv);
-
-// This program applies binary patches to files in a way that is safe
-// (the original file is not touched until we have the desired
-// replacement for it) and idempotent (it's okay to run this program
-// multiple times).
-//
-// - if the sha1 hash of <tgt-file> is <tgt-sha1>, does nothing and exits
-//   successfully.
-//
-// - otherwise, if the sha1 hash of <src-file> is <src-sha1>, applies the
-//   bsdiff <patch> to <src-file> to produce a new file (the type of patch
-//   is automatically detected from the file header).  If that new
-//   file has sha1 hash <tgt-sha1>, moves it to replace <tgt-file>, and
-//   exits successfully.  Note that if <src-file> and <tgt-file> are
-//   not the same, <src-file> is NOT deleted on success.  <tgt-file>
-//   may be the string "-" to mean "the same as src-file".
-//
-// - otherwise, or if any error is encountered, exits with non-zero
-//   status.
-//
-// <src-file> (or <file> in check mode) may refer to an MTD partition
-// to read the source data.  See the comments for the
-// LoadMTDContents() function above for the format of such a filename.
-
-int main(int argc, char** argv) {
-  int result = applypatch(argc, argv);
-  if (result == 2) {
-    printf(
-            "usage: %s <src-file> <tgt-file> <tgt-sha1> <tgt-size> "
-            "[<src-sha1>:<patch> ...]\n"
-            "   or  %s -c <file> [<sha1> ...]\n"
-            "   or  %s -s <bytes>\n"
-            "   or  %s -l\n"
-            "\n"
-            "Filenames may be of the form\n"
-            "  MTD:<partition>:<len_1>:<sha1_1>:<len_2>:<sha1_2>:...\n"
-            "to specify reading from or writing to an MTD partition.\n\n",
-            argv[0], argv[0], argv[0], argv[0]);
-  }
-  return result;
-}
diff --git a/tools/applypatch/testdata/new.file b/tools/applypatch/testdata/new.file
deleted file mode 100644
index cdeb8fd..0000000
--- a/tools/applypatch/testdata/new.file
+++ /dev/null
Binary files differ
diff --git a/tools/applypatch/testdata/old.file b/tools/applypatch/testdata/old.file
deleted file mode 100644
index 166c873..0000000
--- a/tools/applypatch/testdata/old.file
+++ /dev/null
Binary files differ
diff --git a/tools/applypatch/testdata/patch.bsdiff b/tools/applypatch/testdata/patch.bsdiff
deleted file mode 100644
index b78d385..0000000
--- a/tools/applypatch/testdata/patch.bsdiff
+++ /dev/null
Binary files differ
diff --git a/tools/applypatch/utils.c b/tools/applypatch/utils.c
deleted file mode 100644
index 912229b..0000000
--- a/tools/applypatch/utils.c
+++ /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.
- */
-
-#include <stdio.h>
-
-#include "utils.h"
-
-/** Write a 4-byte value to f in little-endian order. */
-void Write4(int value, FILE* f) {
-  fputc(value & 0xff, f);
-  fputc((value >> 8) & 0xff, f);
-  fputc((value >> 16) & 0xff, f);
-  fputc((value >> 24) & 0xff, f);
-}
-
-/** Write an 8-byte value to f in little-endian order. */
-void Write8(long long value, FILE* f) {
-  fputc(value & 0xff, f);
-  fputc((value >> 8) & 0xff, f);
-  fputc((value >> 16) & 0xff, f);
-  fputc((value >> 24) & 0xff, f);
-  fputc((value >> 32) & 0xff, f);
-  fputc((value >> 40) & 0xff, f);
-  fputc((value >> 48) & 0xff, f);
-  fputc((value >> 56) & 0xff, f);
-}
-
-int Read2(unsigned char* p) {
-  return (int)(((unsigned int)p[1] << 8) |
-               (unsigned int)p[0]);
-}
-
-int Read4(unsigned char* p) {
-  return (int)(((unsigned int)p[3] << 24) |
-               ((unsigned int)p[2] << 16) |
-               ((unsigned int)p[1] << 8) |
-               (unsigned int)p[0]);
-}
-
-long long Read8(unsigned char* p) {
-  return (long long)(((unsigned long long)p[7] << 56) |
-                     ((unsigned long long)p[6] << 48) |
-                     ((unsigned long long)p[5] << 40) |
-                     ((unsigned long long)p[4] << 32) |
-                     ((unsigned long long)p[3] << 24) |
-                     ((unsigned long long)p[2] << 16) |
-                     ((unsigned long long)p[1] << 8) |
-                     (unsigned long long)p[0]);
-}
diff --git a/tools/applypatch/utils.h b/tools/applypatch/utils.h
deleted file mode 100644
index d6d6f1d..0000000
--- a/tools/applypatch/utils.h
+++ /dev/null
@@ -1,30 +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.
- */
-
-#ifndef _BUILD_TOOLS_APPLYPATCH_UTILS_H
-#define _BUILD_TOOLS_APPLYPATCH_UTILS_H
-
-#include <stdio.h>
-
-// Read and write little-endian values of various sizes.
-
-void Write4(int value, FILE* f);
-void Write8(long long value, FILE* f);
-int Read2(unsigned char* p);
-int Read4(unsigned char* p);
-long long Read8(unsigned char* p);
-
-#endif //  _BUILD_TOOLS_APPLYPATCH_UTILS_H
diff --git a/tools/dexpreopt/dexpreopt.py b/tools/dexpreopt/dexpreopt.py
index 5dde642..376f135 100755
--- a/tools/dexpreopt/dexpreopt.py
+++ b/tools/dexpreopt/dexpreopt.py
@@ -125,6 +125,10 @@
   else:
     args += ['-shell']
 
+  # This is a work-around for the ARMv7 emulation bug.
+  # XXX: It only works by chance, if any ! A real emulation fix is on the way
+  args += ['-qemu', '-singlestep']
+
   # Ensure that this environment variable isn't set;
   # if it is, the emulator will print the log to stdout.
   if os.environ.get('ANDROID_LOG_TAGS'):
diff --git a/tools/droiddoc/src/Errors.java b/tools/droiddoc/src/Errors.java
index 77852f8..7ba5623 100644
--- a/tools/droiddoc/src/Errors.java
+++ b/tools/droiddoc/src/Errors.java
@@ -115,7 +115,7 @@
     public static Error DEPRECATION_MISMATCH = new Error(13, WARNING);
     public static Error MISSING_COMMENT = new Error(14, WARNING);
     public static Error IO_ERROR = new Error(15, HIDDEN);
-    public static Error NO_SINCE_DATA = new Error(16, WARNING);
+    public static Error NO_SINCE_DATA = new Error(16, HIDDEN);
 
     public static Error[] ERRORS = {
             UNRESOLVED_LINK,
diff --git a/tools/droiddoc/src/MethodInfo.java b/tools/droiddoc/src/MethodInfo.java
index 3211038..7f96b80 100644
--- a/tools/droiddoc/src/MethodInfo.java
+++ b/tools/droiddoc/src/MethodInfo.java
@@ -363,8 +363,17 @@
     public String getHashableName() {
         StringBuilder result = new StringBuilder();
         result.append(name());
-        for (ParameterInfo pInfo : mParameters) {
-            result.append(":").append(pInfo.type().fullName());
+        for (int p = 0; p < mParameters.length; p++) {
+            result.append(":");
+            if (p == mParameters.length - 1 && isVarArgs()) {
+                // TODO: note that this does not attempt to handle hypothetical
+                // vararg methods whose last parameter is a list of arrays, e.g.
+                // "Object[]...".
+                result.append(mParameters[p].type().fullNameNoDimension(typeVariables()))
+                        .append("...");
+            } else {
+                result.append(mParameters[p].type().fullName(typeVariables()));
+            }
         }
         return result.toString();
     }
diff --git a/tools/droiddoc/src/SinceTagger.java b/tools/droiddoc/src/SinceTagger.java
index fb69c04..a1bce55 100644
--- a/tools/droiddoc/src/SinceTagger.java
+++ b/tools/droiddoc/src/SinceTagger.java
@@ -1,8 +1,13 @@
 // Copyright 2009 Google Inc. All Rights Reserved.
 
-import com.android.apicheck.*;
+import com.android.apicheck.ApiCheck;
+import com.android.apicheck.ApiInfo;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Collections;
 
 import org.clearsilver.HDF;
 
@@ -165,31 +170,68 @@
      */
     private void warnForMissingVersions(ClassInfo[] classDocs) {
         for (ClassInfo claz : classDocs) {
+            if (!checkLevelRecursive(claz)) {
+                continue;
+            }
+
             if (claz.getSince() == null) {
                 Errors.error(Errors.NO_SINCE_DATA, claz.position(),
                         "XML missing class " + claz.qualifiedName());
             }
-            for (FieldInfo field : claz.fields()) {
-                if (field.getSince() == null) {
-                    Errors.error(Errors.NO_SINCE_DATA, field.position(),
-                            "XML missing field "
-                                    + claz.qualifiedName() + "#" + field .name());
-                }
+            
+            for (FieldInfo field : missingVersions(claz.fields())) {
+                Errors.error(Errors.NO_SINCE_DATA, field.position(),
+                        "XML missing field " + claz.qualifiedName()
+                                + "#" + field.name());
             }
-            for (MethodInfo constructor : claz.constructors()) {
-                if (constructor.getSince() == null) {
-                    Errors.error(Errors.NO_SINCE_DATA, constructor.position(),
-                            "XML missing constructor "
-                                    + claz.qualifiedName() + "#" + constructor.getHashableName());
-                }
+
+            for (MethodInfo constructor : missingVersions(claz.constructors())) {
+                Errors.error(Errors.NO_SINCE_DATA, constructor.position(),
+                        "XML missing constructor " + claz.qualifiedName()
+                                + "#" + constructor.getHashableName());
             }
-            for (MethodInfo method : claz.methods()) {
-                if (method.getSince() == null) {
-                    Errors.error(Errors.NO_SINCE_DATA, method.position(),
-                            "XML missing method "
-                                    + claz.qualifiedName() + "#" + method .getHashableName());
-                }
+
+            for (MethodInfo method : missingVersions(claz.methods())) {
+                Errors.error(Errors.NO_SINCE_DATA, method.position(),
+                        "XML missing method " + claz.qualifiedName()
+                                + "#" + method.getHashableName());
             }
         }
     }
+
+    /**
+     * Returns the DocInfos in {@code all} that are documented but do not have
+     * since tags.
+     */
+    private <T extends MemberInfo> Iterable<T> missingVersions(T[] all) {
+        List<T> result = Collections.emptyList();
+        for (T t : all) {
+            // if this member has version info or isn't documented, skip it
+            if (t.getSince() != null
+                    || t.isHidden()
+                    || !checkLevelRecursive(t.realContainingClass())) {
+                continue;
+            }
+
+            if (result.isEmpty()) {
+                result = new ArrayList<T>(); // lazily construct a mutable list
+            }
+            result.add(t);
+        }
+        return result;
+    }
+
+    /**
+     * Returns true if {@code claz} and all containing classes are documented.
+     * The result may be used to filter out members that exist in the API
+     * data structure but aren't a part of the API.
+     */
+    private boolean checkLevelRecursive(ClassInfo claz) {
+        for (ClassInfo c = claz; c != null; c = c.containingClass()) {
+            if (!c.checkLevel()) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/tools/droiddoc/templates-pdk/assets/android-developer-core.css b/tools/droiddoc/templates-pdk/assets/android-developer-core.css
new file mode 100644
index 0000000..bb4f806
--- /dev/null
+++ b/tools/droiddoc/templates-pdk/assets/android-developer-core.css
@@ -0,0 +1,1297 @@
+/* file: android-developer-core.css
+   author: smain
+   date: september 2008
+   info: core developer styles (developer.android.com)
+*/
+
+
+/* RESET STYLES */
+
+html,body,div,h1,h2,h3,h4,h5,h6,p,img,
+dl,dt,dd,ol,ul,li,table,caption,tbody,
+tfoot,thead,tr,th,td,form,fieldset,
+embed,object,applet {
+  margin: 0;
+  padding: 0;
+  border: 0;
+}
+
+.rebox {
+  background:#daf3fc;
+  margin-bottom:1.5em;
+  -moz-border-radius:5px;
+  -webkit-border-radius:5px;
+}
+.rebox.lil p img {
+  display:block;
+  margin-bottom:2em;
+}
+
+.rebox .p {
+  padding:1.5em;
+  line-height:1.25em;
+}
+
+.p-r {
+  padding-right:1.5em;
+}
+
+.rebox h2, .rebox h3 {
+  font-size:16px;
+  color:#fff;
+  display:block;
+  background:url('/assets/images/rebox-gradient.gif') no-repeat center bottom #95c0d0;
+  padding:.5em .5em .5em .75em;
+  -moz-border-radius-topright:5px;
+  -moz-border-radius-topleft:5px;
+  -webkit-border-top-right-radius:5px;
+  -webkit-border-top-left-radius:5px;
+}
+
+.rebox.lil {
+}
+.rebox.lil img {
+  float:left;
+  margin:0 1em 0 0;
+  padding:0 0 3em 0;
+}
+
+.rebox.green {
+  background:#d4e9a9;
+}
+
+.rebox.green h2, .rebox.green h3 {
+  background:url('images/rebox-gradient-green.gif') no-repeat center bottom #aaca46;
+  font-weight:bold;
+}
+
+.rebox.green a:link, .rebox.green a:visited {
+  color:#360;
+}
+
+/* BASICS */
+
+html, body {
+  overflow:hidden; /* keeps scrollbar off IE */
+  background-color:#fff;
+}
+
+body {
+  font-family:arial,sans-serif;
+  color:#000;
+  font-size:13px;
+  color:#333;
+  background-image:url(images/bg_fade.jpg); 
+  background-repeat:repeat-x;
+}
+
+a, a code { 
+  color:#006699;
+} 
+
+
+a:active,
+a:active code { 
+  color:#f00;
+} 
+
+a:visited,
+a:visited code { 
+  color:#006699;
+}
+
+input, select,
+textarea, option {
+  font-family:inherit;
+  font-size:inherit;
+  padding:0;
+  margin:0;
+}
+
+option {
+  padding:0 4px;
+}
+
+p {
+  padding:0;
+  margin:0 0 1em;
+}
+
+code, pre {
+  color:#007000;
+  font-family:monospace;
+  line-height:1em;
+}
+
+var {
+  color:#007000;
+  font-style:italic;
+}
+
+pre {
+  border:1px solid #ccc;
+  background-color:#fafafa;
+  padding:10px;
+  margin:0 0 1em 1em;
+  overflow:auto;
+  line-height:inherit; /* fixes vertical scrolling in webkit */
+}
+
+h1,h2,h3,h4,h5 {
+  margin:1em 0;
+  padding:0;
+}
+
+p,ul,ol,dl,dd,dt,li {
+  line-height:1.3em;
+}
+
+ul,ol {
+  margin:0 0 .8em;
+  padding:0 0 0 2em;
+}
+
+li {
+  padding:0 0 .5em;
+}
+
+dl {
+  margin:0 0 1em 0;
+  padding:0;
+}
+
+dt {  
+  margin:0;
+  padding:0;
+}
+
+dd {
+  margin:0 0 1em;
+  padding:0 0 0 2em;
+}
+
+li p {
+  margin:.5em 0 0;
+}
+
+dd p {
+  margin:1em 0 0;
+}
+
+li pre, li table, li img {
+  margin:.5em 0 0 1em;
+}
+
+dd pre, dd table, dd img {
+  margin:1em 0 0 1em;
+}
+
+li ul,
+li ol,
+dd ul,
+dd ol {
+  margin:0;
+  padding: 0 0 0 2em;
+}
+
+li li,
+dd li {
+  margin:0;
+  padding:.5em 0 0;
+}
+
+dl dl,
+ol dl,
+ul dl {
+  margin:0 0 1em;
+  padding:0;
+}
+
+table {
+  font-size:1em;
+  margin:0 0 1em;
+  padding:0;
+  border-collapse:collapse;
+  border-width:0;
+  empty-cells:show;
+}
+
+td,th {
+  border:1px solid #ccc;
+  padding:6px 12px;
+  text-align:left;
+  vertical-align:top;
+  background-color:inherit;
+}
+
+th {
+  background-color:#dee8f1;
+}
+
+hr.blue {
+  background-color:#DDF0F2;
+  border:none;
+  height:5px;
+  margin:20px 0 10px;
+}
+
+/* LAYOUT */
+#body-content {
+  /* "Preliminary" watermark for preview releases and interim builds.
+  background:transparent url(images/preliminary.png) repeat scroll 0 0;  */
+  margin:0;
+  position:relative;
+  width:100%;
+}
+
+#header {
+  height: 114px;
+  position:relative;
+  z-index:100;
+  min-width:576px;
+  padding:0 10px;
+  border-bottom:3px solid #94b922;
+}
+
+#headerLeft{
+  padding: 25px 0 0;
+}
+
+#headerLeft img{
+  height:50px;
+  width:349px;
+}
+
+#headerRight {
+  position:absolute;
+  right:0;
+  top:0;
+  text-align:right;
+}
+
+/* Tabs in the header */
+#header ul {
+  list-style: none;
+  margin: 7px 0 0;  
+  padding: 0;
+  height: 29px;
+}
+
+#header li {
+  float: left;
+  margin: 0px 2px 0px 0px;
+  padding:0;
+}
+
+#header li a {
+  text-decoration: none;
+  display: block;
+  background-image: url(images/bg_images_sprite.png);
+  background-position: 0 -58px;
+  background-repeat: no-repeat;
+  color: #666;
+  font-size: 13px;
+  font-weight: bold;
+  width: 94px;
+  height: 29px;
+  text-align: center;
+  margin: 0px;
+}
+
+#header li a:hover {
+  background-image: url(images/bg_images_sprite.png);
+  background-position: 0 -29px;
+  background-repeat: no-repeat;
+}
+
+#header li a span {
+  position:relative;
+  top:7px;
+}
+
+#header li a span+span {
+  display:none;
+}
+
+/* TAB HIGHLIGHTING */
+.home #home-link a,
+.community #community-link a,
+.porting #porting-link a,
+.source #source-link a,
+.about #about-link a,
+.downloads #downloads-link a,
+.compatibility #compatibility-link a,
+.videos #videos-link a {
+  background-image: url(images/bg_images_sprite.png);
+  background-position: 0 0;
+  background-repeat: no-repeat;
+  color: #fff;
+  font-weight: bold;
+  cursor:default;
+}
+
+.home #home-link a:hover,
+.community #community-link a:hover,
+.home #home-link a:hover,
+.community #community-link a:hover,
+.porting #porting-link a:hover,
+.source #source-link a:hover,
+.about #about-link a:hover,
+.downloads #downloads-link a:hover,
+.compatibility #compatibility-link a:hover,
+.videos #videos-link  a:hover {
+  background-image: url(images/bg_images_sprite.png);
+  background-position: 0 0;
+}
+
+#headerLinks {
+  margin:10px 10px 0 0;
+  height:13px;
+  font-size: 11px;
+  vertical-align: top;
+}
+
+#headerLinks a {
+  color: #7FA9B5;
+}
+
+#headerLinks img {
+  vertical-align:middle;
+}
+
+#language {
+  margin:0 10px 0 4px;
+}
+
+#search {
+  height:45px;
+  margin:15px 10px 0 0;
+}
+
+/* main */
+
+#mainBodyFluid {
+  margin: 20px 10px;
+  color:#333;
+}
+
+#mainBodyFixed {
+  margin: 20px 10px;
+  color: #333;
+  width:930px;
+  position:relative;
+}
+
+#mainBodyFixed h3,
+#mainBodyFluid h3 {
+  color:#336666;
+  font-size:1.25em;
+  margin: 0em 0em 0em 0em;
+  padding-bottom:.5em;
+}
+
+#mainBodyFixed h2,
+#mainBodyFluid h2 { 
+  color:#336666;
+  font-size:1.25em;
+  margin: 0;
+  padding-bottom:.5em;
+}
+
+#mainBodyFixed h1,
+#mainBodyFluid h1 { 
+  color:#435A6E;
+  font-size:1.7em;
+  margin: 1em 0;
+}
+
+#mainBodyFixed .green,
+#mainBodyFluid .green,
+#jd-content .green { 
+  color:#7BB026;
+  background-color:none;
+}
+
+#mainBodyLeft {
+  float: left;
+  width: 600px;
+  margin-right: 20px;  
+  color: #333;
+  position:relative;
+}
+
+div.indent {
+  margin-left: 40px;  
+  margin-right: 70px;
+}
+
+#mainBodyLeft p {
+  color: #333;
+  font-size: 13px;
+}
+
+#mainBodyLeft p.blue {
+  color: #669999;
+}
+
+#mainBodyLeft #communityDiv {
+  float: left;
+  background-image:url(images/bg_community_leftDiv.jpg);
+  background-repeat: no-repeat;
+  width: 581px;
+  height: 347px;
+  padding: 20px 0px 0px 20px;
+}
+
+#mainBodyRight {
+  float: left;
+  width: 300px;
+  color: #333;
+}
+
+#mainBodyRight p {
+  padding-right: 50px;
+  color: #333;
+}
+
+#mainBodyRight table {
+  width: 100%;
+}
+
+#mainBodyRight td {
+  border:0px solid #666;
+  padding:0px 5px;
+  text-align:left;
+}
+
+#mainBodyRight .blueBorderBox {
+  border:5px solid #ddf0f2;
+  padding:18px 18px 18px 18px;
+  text-align:left;
+}
+
+#mainBodyFixed .seperator {
+  background-image:url(images/hr_gray_side.jpg);
+  background-repeat:no-repeat;
+  width: 100%;
+  float: left;
+  clear: both;
+}
+
+#mainBodyBottom {
+  float: left;
+  width: 100%;
+  clear:both;
+  color: #333;
+}
+
+#mainBodyBottom .seperator {
+  background-image:url(images/hr_gray_main.jpg);
+  background-repeat:no-repeat;
+  width: 100%;
+  float: left;
+  clear: both;
+}
+
+/* Footer */
+#footer {
+  float: left;
+  width:90%;
+  margin: 20px;
+  color: #aaa;
+  font-size: 11px;
+}
+
+#footer a {
+  color: #aaa;
+  font-size: 11px;
+}
+
+#footer a:hover {
+  text-decoration: underline;
+  color:#aaa;
+}
+
+#footerlinks {
+  margin-top:2px;
+}
+
+#footerlinks a,
+#footerlinks a:visited {
+  color:#006699;
+}
+
+#homeBottom td {
+  border:0px solid #666;
+  padding: 8px 18px 8px 18px;
+}
+
+#homeBottom table {
+  width: 100%;
+}
+
+
+#homeBottom {
+  padding: 0px 0px 0px 0px;
+  float: left;
+  width: 585px;
+  height: 165px;
+  background-image:url(images/home/bg_home_bottom.jpg);
+  background-repeat: no-repeat;
+}
+
+.groupTable {
+  width: 100%;
+}
+
+.groupTable th {
+  padding: 10px;
+  color: #ffffff;
+  background-color: #6D8293;
+  border: 2px solid #fff;
+}
+
+.groupTable td {
+  padding: 10px;
+  color: #333333;
+  background-color: #d9d9d9;
+  border: 2px solid #fff;
+}
+
+.groupTable .evenRow td {  
+  background-color: #ededed;
+}
+
+span.BigBlue {
+  color:#336666;
+  font-size:1.25em;
+  margin: 0em 0em 0em 0em;
+  padding-bottom:.5em;
+  font-weight: bold;
+}
+
+span.emBlue {
+  color: #336666;
+  font-style:italic;
+}
+
+.pageTable {
+  width: 95%;
+  border: none;
+}
+
+.pageTable img {
+vertical-align: bottom;
+}
+
+.pageTable td {
+  border: none;
+}
+
+.pageTable td.leftNav {
+  width: 100px;
+}
+
+.greenBox {
+  margin: 10px 30px 10px 30px;
+  padding: 10px 20px 10px 20px;
+  background-color: #EBF3DB;
+  width: 75%;
+}
+
+.blueBox {
+  margin: 10px 30px 10px 30px;
+  padding: 10px 20px 10px 20px;
+  background-color: #DDF0F2;
+  width: 75%;
+}
+
+.blueHR {
+  margin: 10px 30px 10px 30px;
+  height: 5px;
+  background-color: #DDF0F2;
+  width: 75%;
+}
+
+/* SEARCH FILTER */
+#search_autocomplete {
+  color:#aaa;
+}
+
+#search-button {
+  display:inline;
+}
+
+#search_filtered_div {
+  position:absolute;
+  margin-top:-1px;
+  z-index:101;
+  border:1px solid #BCCDF0;
+  background-color:#fff;
+}
+
+#search_filtered {
+  min-width:100%;
+}
+#search_filtered td{
+  background-color:#fff;
+  border-bottom: 1px solid #669999;
+  line-height:1.5em;
+}
+
+#search_filtered .jd-selected {
+  background-color: #94b922;
+  cursor:pointer;
+}
+#search_filtered .jd-selected,
+#search_filtered .jd-selected a {
+  color:#fff;
+}
+
+.no-display {
+  display: none;
+}
+
+.jd-autocomplete {
+  font-family: Arial, sans-serif;
+  padding-left: 6px;
+  padding-right: 6px;
+  padding-top: 1px;
+  padding-bottom: 1px;
+  font-size: .8em;
+  border: none;
+  margin: 0;
+  line-height: 1.05em;
+}
+
+.show-row {
+  display: table-row;
+}
+.hide-row {
+  display: hidden;
+}
+
+/* SEARCH */
+
+/* restrict global search form width */
+#searchForm {
+  width:350px;
+}
+
+#searchTxt {
+  width:200px;
+}
+
+/* disable twiddle and size selectors for left column */
+#leftSearchControl div {
+  width: 100%;
+}
+
+#leftSearchControl .gsc-twiddle {
+  background-image : none;
+}
+
+#leftSearchControl td, #searchForm td {
+  border: 0px solid #000;
+}
+
+#leftSearchControl .gsc-resultsHeader .gsc-title {
+  padding-left : 0px;
+  font-weight : bold;
+  font-size : 13px;
+  color:#006699;
+  display : none;
+}
+
+#leftSearchControl .gsc-resultsHeader div.gsc-results-selector {
+  display : none;
+}
+
+#leftSearchControl .gsc-resultsRoot {
+  padding-top : 6px;
+}
+
+#leftSearchControl div.gs-visibleUrl-long {
+  display : block;
+  color:#006699;
+}
+
+.gsc-webResult div.gs-visibleUrl-short,
+table.gsc-branding,
+.gsc-clear-button {
+  display : none;
+}
+
+.gsc-cursor-box .gsc-cursor div.gsc-cursor-page,
+.gsc-cursor-box .gsc-trailing-more-results a.gsc-trailing-more-results,
+#leftSearchControl a, 
+#leftSearchControl a b {
+  color:#006699;
+}
+
+.gsc-resultsHeader {
+  display: none;
+}
+
+/* Disable built in search forms */
+.gsc-control form.gsc-search-box {
+  display : none;
+}
+table.gsc-search-box {
+  margin:6px 0 0 0;
+  border-collapse:collapse;
+}
+
+td.gsc-input {
+  padding:0 2px;
+  width:100%;
+  vertical-align:middle;
+}
+
+input.gsc-input {
+  border:1px solid #BCCDF0;
+  width:99%;
+  padding-left:2px;
+  font-size:.95em;
+}
+
+td.gsc-search-button {
+  text-align: right;
+  padding:0;
+  vertical-align:top;
+}
+
+#search-button {
+  margin:0 0 0 2px;
+  font-size:11px;
+}
+
+/* search result tabs */
+
+#doc-content .gsc-control {
+  position:relative;
+}
+
+#doc-content .gsc-tabsArea {
+  position:relative;
+  white-space:nowrap;
+}
+
+#doc-content .gsc-tabHeader {
+  padding: 3px 6px;
+  position:relative;
+}
+
+#doc-content .gsc-tabHeader.gsc-tabhActive {
+  border-top: 2px solid #94B922;
+}
+
+#doc-content h2#searchTitle {
+  padding:0;
+}
+
+#doc-content .gsc-resultsbox-visible {
+  padding:1em 0 0 6px;
+}
+
+/* CAROUSEL */
+
+#homeMiddle {
+  padding: 0px 0px 0px 0px;
+  float: left;
+  width: 584px;
+  height: 580px;
+  position:relative;
+}
+
+#topAnnouncement {
+  background:url(images/home/bg_home_announcement.png) no-repeat 0 0;
+}
+  
+#homeTitle {
+  padding:15px 15px 0;
+  height:30px;  
+}
+
+#homeTitle h2 {
+  padding:0;
+}
+
+#announcement-block {
+  padding:0 15px 0;
+  overflow:hidden;
+  background: url(images/hr_gray_side.jpg) no-repeat 15px 0;
+  zoom:1;
+}
+
+#announcement-block>* {
+  padding:15px 0 0;
+}
+
+#announcement-block img {
+  float:left;
+  margin:0 30px 0 0;
+}
+
+#announcement {
+  float:left;
+  margin:0;
+}
+
+#carousel {
+  background:url(images/home/bg_home_carousel.png) no-repeat 0 0;
+  position:relative;
+  height:400px;
+}
+
+#carouselMain {
+	background: url(images/home/bg_home_carousel_board.png) 0 0 no-repeat;
+	height:auto;
+  padding: 25px 21px 0;
+  overflow:hidden;
+  position:relative;
+  zoom:1; /*IE6*/
+}
+
+#carouselMain img {
+  margin:0;
+}
+
+#carouselMain .bulletinDesc h3 {
+	margin:0;
+	padding:0;
+}
+
+#carouselMain .bulletinDesc p {
+	margin:0;
+	padding:0.7em 0 0;
+}
+
+#carouselWheel {
+	background: url(images/home/bg_home_carousel_wheel.png) 0 0 no-repeat;
+	padding-top:40px;
+	height:150px;
+}
+
+.clearer { clear:both; }
+
+a#arrow-left, a#arrow-right {
+  float:left;
+  width:42px;
+  height:42px;
+  background-image:url(images/home/carousel_buttons_sprite.png);
+  background-repeat:no-repeat;
+}
+a#arrow-left {
+  margin:35px 3px 0 10px;
+}
+a#arrow-right {
+  margin:35px 10px 0 0;
+}
+a.arrow-left-off,
+a#arrow-left.arrow-left-off:hover { 
+  background-position:0 0;
+}
+a.arrow-right-off, 
+a#arrow-right.arrow-right-off:hover { 
+  background-position:-42px 0;
+}
+a#arrow-left:hover { 
+  background-position:0 -42px;
+}
+a#arrow-right:hover { 
+  background-position:-42px -42px;
+}
+a.arrow-left-on {
+  background-position:0 0;
+}
+a.arrow-right-on {
+  background-position:-42px 0;
+}
+a.arrow-right-off,
+a.arrow-left-off {
+  cursor:default;
+}
+
+.app-list-container {
+  margin:0 20px;
+  position:relative;
+  width:100%;
+}
+
+div#list-clip { 
+  height:110px; 
+  width:438px;
+  overflow:hidden; 
+  position:relative; 
+  float:left; 
+}
+
+div#app-list { 
+  left:0; 
+  z-index:1; 
+  position:absolute;
+  margin:11px 0 0;
+  _margin-top:13px;
+  width:1000%;
+}
+
+#app-list a {
+  display:block;
+  float:left;
+  height:90px;
+  width:90px;
+  margin:0 24px 0;
+  padding:3px;
+  background:#99cccc;
+  -webkit-border-radius:7px;
+  -moz-border-radius:7px;
+  border-radius:7px;
+  text-decoration:none;
+  text-align:center;
+  font-size:11px;
+  line-height:11px;
+}
+
+#app-list a span {
+  position:relative;
+  top:-4px;
+}
+
+#app-list img {  
+  width:90px;
+  height:70px;
+  margin:0;
+}
+
+#app-list a.selected, 
+#app-list a:active.selected, 
+#app-list a:hover.selected {
+  background:#A4C639;
+  color:#fff;
+  cursor:default;
+  text-decoration:none;
+}
+
+#app-list a:hover, 
+#app-list a:active {
+  background:#ff9900;
+}
+
+#app-list a:hover span, 
+#app-list a:active span {
+  text-decoration:underline;
+}
+
+#droid-name {
+  padding-top:.5em;
+  color:#666;
+  padding-bottom:.25em;
+}
+
+/*IE6*/
+* html #app-list a { zoom: 1; margin:0 24px 0 15px;}
+
+* html #list-clip { 
+  width:430px !important;
+}
+
+/*carousel bulletin layouts*/
+/*460px width*/
+/*185px height*/
+.img-left {
+  float:left;
+  width:230px;
+  overflow:hidden;
+  padding:8px 0 8px 8px;
+}
+.desc-right {
+  float:left;
+  width:270px;
+  padding:10px;
+}
+.img-right {
+  float:right;
+  width:220px;
+  overflow:hidden;
+  padding:8px 8px 8px 0;
+}
+.desc-left {
+  float:right;
+  width:280px;
+  padding:10px;
+  text-align:right;
+}
+.img-top {
+  padding:20px 20px 0;
+}
+.desc-bottom {
+  padding:10px;
+}
+
+
+/* VIDEO PAGE */
+
+#mainBodyLeft.videoPlayer {
+  width:570px;
+}
+
+#mainBodyRight.videoPlayer {
+  width:330px;
+}
+
+/* player */
+
+#videoPlayerBox {
+  background-color: #DAF3FC;
+  border-radius:7px;
+  -moz-border-radius:7px;
+  -webkit-border-radius:7px;
+  width:530px;
+  padding:20px;
+  border:1px solid #d3ecf5;
+  box-shadow:2px 3px 1px #eee;
+  -moz-box-shadow:2px 3px 1px #eee;
+  -webkit-box-shadow:2px 3px 1px #eee;
+}
+
+#videoBorder {
+  background-color: #FFF;
+  min-height:399px;
+  height:auto !important;
+  border:1px solid #ccdada;
+  border-radius:7px 7px 0 0;
+  -moz-border-radius:7px 7px 0 0;
+  -webkit-border-top-left-radius:7px;
+  -webkit-border-top-right-radius:7px;
+}
+
+#videoPlayerTitle {
+  width:500px;
+  padding:15px 15px 0;
+}
+
+#videoPlayerTitle h2 {
+  font-weight:bold;
+  font-size:1.2em;
+  color:#336666;
+  margin:0;
+  padding:0;
+}
+
+#objectWrapper {
+  padding:15px 15px;
+  height:334px;
+  width:500px;
+}
+
+/* playlist tabs */
+
+ul#videoTabs {
+  list-style-type:none;
+  padding:0;
+  clear:both;
+  margin:0;
+  padding: 20px 0 0 15px;
+  zoom:1; /* IE7/8, otherwise top-padding is double */
+}
+
+ul#videoTabs li {
+  display:inline;
+  padding:0;
+  margin:0 3px 0 0;
+  line-height:2em;
+}
+
+ul#videoTabs li a {
+  border-radius:7px 7px 0 0;
+  -moz-border-radius:7px 7px 0 0;
+  -webkit-border-top-left-radius:7px;
+  -webkit-border-top-right-radius:7px;
+  background:#95c0d0;
+  color:#fff;
+  text-decoration:none;
+  padding:.45em 1.5em;
+  font-weight:bold;
+}
+
+ul#videoTabs li.selected a {
+  font-weight:bold;
+  text-decoration:none;
+  color:#555;
+  background:#daf3fc;
+  border-bottom:1px solid #daf3fc;
+}
+
+ul#videoTabs li:hover a {
+  background:#85acba;
+}
+
+ul#videoTabs li.selected:hover a {
+  background:#daf3fc;
+}
+
+/* playlists */
+
+#videos {
+  background:#daf3fc;
+  margin-bottom:1.5em;
+  padding:15px;
+  border-radius:5px;
+  -moz-border-radius:5px;
+  -webkit-border-radius:5px;
+  box-shadow:2px 3px 1px #eee;
+  -moz-box-shadow:2px 3px 1px #eee;
+  -webkit-box-shadow:2px 3px 1px #eee;
+}
+
+#videos div {
+  display:none;
+}
+
+#videos div.selected {
+  display:block;
+}
+
+ul.videoPreviews {
+  list-style:none;
+  padding:0;
+  margin:0;
+  zoom:1; /* IE, otherwise, layout doesn't update when showing 'more' */
+}
+
+ul.videoPreviews li {
+  margin:0 0 5px;
+  padding:0;
+  overflow:hidden;
+  position:relative;
+}
+
+#mainBodyFixed ul.videoPreviews h3 {
+  font-size: 12px;
+  margin:0 0 1em 130px;
+  padding:0;
+  font-weight:bold;
+  color:inherit;
+}
+
+ul.videoPreviews a {
+  margin:1px;
+  padding:10px;
+  text-decoration:none;
+  height:90px;
+  display:block;
+  border-radius:5px;
+  -moz-border-radius:5px;
+  -webkit-border-radius:5px;
+  background-color:transparent;
+}
+
+ul.videoPreviews a:hover {
+  background-color:#FFF;
+  border:none; /* IE8, otherwise, bg doesn't work */
+}
+
+ul.videoPreviews a.selected {
+  background-color: #FF9900;
+}
+
+ul.videoPreviews img {
+  float:left;
+  clear:left;
+  margin:0;
+}
+
+ul.videoPreviews h3 {
+  font-size:12px;
+  font-weight:bold;
+  text-decoration:none;
+  margin:0 0 1em 130px;
+  padding:0;
+}
+
+ul.videoPreviews p {
+  font-size: 12px;
+  text-decoration:none;
+  margin:0 0 1.2em 130px;
+}
+
+ul.videoPreviews p.full {
+  display:none;
+}
+
+ul.videoPreviews span.more {
+  padding:0 0 0 12px;
+  background:url(images/arrow_bluelink_down.png) 0 2px no-repeat;
+}
+
+ul.videoPreviews span.less {
+  padding:0 0 0 12px;
+  background:url(images/arrow_bluelink_up.png) 0 2px no-repeat;
+  display:none;
+}
+
+ul.videoPreviews p.toggle {
+  position:absolute;
+  margin:0;
+  margin-top:-23px; /* instead of bottom:23px, because IE won't do it correctly */
+  left:140px;
+}
+
+ul.videoPreviews p.toggle a {
+  height:auto;
+  margin:0;
+  padding:0;
+  zoom:1; /* IE6, otherwise the margin considers the img on redraws */
+}
+
+ul.videoPreviews p.toggle a:hover {
+  text-decoration:underline;
+  background:transparent; /* IE6, otherwise it inherits white */
+}
+
+/* featured videos */
+
+#mainBodyRight h2 {
+  padding:0 0 5px;
+}
+
+#mainBodyRight ul.videoPreviews {
+  margin:10px 0 0;
+}
+
+#mainBodyRight ul.videoPreviews li {
+  font-size:11px;
+  line-height:13px;
+  margin:0 0 5px;
+  padding:0;
+}
+
+#mainBodyRight ul.videoPreviews h3 {
+  padding:0;
+  margin:0;
+}
+
+#mainBodyRight ul.videoPreviews a {
+  text-decoration:none;
+  height:108px;
+  border:1px solid #FFF;
+}
+
+#mainBodyRight ul.videoPreviews a:hover {
+  border:1px solid #CCDADA;
+}
+
+#mainBodyRight ul.videoPreviews a.selected {
+  border:1px solid #FFF;
+}
+
+#mainBodyRight ul.videoPreviews p {
+	line-height:1.2em;
+  padding:0;
+  margin:4px 0 0 130px;
+}
+
+#mainBodyRight ul.videoPreviews img {
+	margin-top:5px;
+}
diff --git a/tools/droiddoc/templates-pdk/assets/android-developer-docs.js b/tools/droiddoc/templates-pdk/assets/android-developer-docs.js
new file mode 100644
index 0000000..59c4192
--- /dev/null
+++ b/tools/droiddoc/templates-pdk/assets/android-developer-docs.js
@@ -0,0 +1,464 @@
+var resizePackagesNav;
+var classesNav;
+var devdocNav;
+var sidenav;
+var content;
+var HEADER_HEIGHT = 117;
+var cookie_namespace = 'android_developer';
+var NAV_PREF_TREE = "tree";
+var NAV_PREF_PANELS = "panels";
+var nav_pref;
+var toRoot;
+var isMobile = false; // true if mobile, so we can adjust some layout
+
+function addLoadEvent(newfun) {
+  var current = window.onload;
+  if (typeof window.onload != 'function') {
+    window.onload = newfun;
+  } else {
+    window.onload = function() {
+      current();
+      newfun();
+    }
+  }
+}
+
+var agent = navigator['userAgent'];
+if ((agent.indexOf("Mobile") != -1) || 
+    (agent.indexOf("BlackBerry") != -1) || 
+    (agent.indexOf("Mini") != -1)) {
+  isMobile = true;
+  addLoadEvent(mobileSetup);
+}
+
+addLoadEvent(function() {
+window.onresize = resizeAll;
+});
+
+function mobileSetup() {
+  $("body").css({'overflow':'auto'});
+  $("html").css({'overflow':'auto'});
+  $("#body-content").css({'position':'relative', 'top':'0'});
+  $("#doc-content").css({'overflow':'visible', 'border-left':'3px solid #DDD'});
+  $("#side-nav").css({'padding':'0'});
+  $("#nav-tree").css({'overflow-y': 'auto'});
+}
+
+/* loads the lists.js file to the page.
+Loading this in the head was slowing page load time */
+addLoadEvent( function() {
+  var lists = document.createElement("script");
+  lists.setAttribute("type","text/javascript");
+  lists.setAttribute("src", toRoot+"reference/lists.js");
+  document.getElementsByTagName("head")[0].appendChild(lists);
+} );
+
+function setToRoot(root) {
+  toRoot = root;
+  // note: toRoot also used by carousel.js
+}
+
+function restoreWidth(navWidth) {
+  var windowWidth = $(window).width() + "px";
+  content.css({marginLeft:parseInt(navWidth) + 6 + "px", //account for 6px-wide handle-bar
+               width:parseInt(windowWidth) - parseInt(navWidth) - 6 + "px"});
+  sidenav.css({width:navWidth});
+  resizePackagesNav.css({width:navWidth});
+  classesNav.css({width:navWidth});
+  $("#packages-nav").css({width:navWidth});
+}
+
+function restoreHeight(packageHeight) {
+  var windowHeight = ($(window).height() - HEADER_HEIGHT);
+  var swapperHeight = windowHeight - 13;
+  $("#swapper").css({height:swapperHeight + "px"});
+  sidenav.css({height:windowHeight + "px"});
+  content.css({height:windowHeight + "px"});
+  resizePackagesNav.css({maxHeight:swapperHeight + "px", height:packageHeight});
+  classesNav.css({height:swapperHeight - parseInt(packageHeight) + "px"});
+  $("#packages-nav").css({height:parseInt(packageHeight) - 6 + "px"}); //move 6px to give space for the resize handle
+  devdocNav.css({height:sidenav.css("height")});
+  $("#nav-tree").css({height:swapperHeight + "px"});
+}
+
+function readCookie(cookie) {
+  var myCookie = cookie_namespace+"_"+cookie+"=";
+  if (document.cookie) {
+    var index = document.cookie.indexOf(myCookie);
+    if (index != -1) {
+      var valStart = index + myCookie.length;
+      var valEnd = document.cookie.indexOf(";", valStart);
+      if (valEnd == -1) {
+        valEnd = document.cookie.length;
+      }
+      var val = document.cookie.substring(valStart, valEnd);
+      return val;
+    }
+  }
+  return 0;
+}
+
+function writeCookie(cookie, val, section, expiration) {
+  if (!val) return;  
+  section = section == null ? "_" : "_"+section+"_";
+  if (expiration == null) {
+    var date = new Date();
+    date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
+    expiration = date.toGMTString();
+  }
+  document.cookie = cookie_namespace+section+cookie+"="+val+"; expires="+expiration+"; path=/";
+} 
+
+function init() {
+  $("#side-nav").css({position:"absolute",left:0});
+  content = $("#doc-content");
+  resizePackagesNav = $("#resize-packages-nav");
+  classesNav = $("#classes-nav");
+  sidenav = $("#side-nav");
+  devdocNav = $("#devdoc-nav");
+
+  if (location.href.indexOf("/reference/") != -1) {
+    var cookiePath = "reference_";
+  } else if (location.href.indexOf("/guide/") != -1) {
+    var cookiePath = "guide_";
+  }
+
+  if (!isMobile) {
+    $("#resize-packages-nav").resizable({handles: "s", resize: function(e, ui) { resizeHeight(); } });
+    $(".side-nav-resizable").resizable({handles: "e", resize: function(e, ui) { resizeWidth(); } });
+    var cookieWidth = readCookie(cookiePath+'width');
+    var cookieHeight = readCookie(cookiePath+'height');
+    if (cookieWidth) {
+      restoreWidth(cookieWidth);
+    } else if ($(".side-nav-resizable").length) {
+      resizeWidth();
+    }
+    if (cookieHeight) {
+      restoreHeight(cookieHeight);
+    } else {
+      resizeHeight();
+    }
+  }
+
+  if (devdocNav.length) { // only dev guide and sdk 
+    highlightNav(location.href); 
+  }
+}
+
+function highlightNav(fullPageName) {
+  fullPageName = fullPageName.replace(/^https?:\/\//, '');
+  var lastSlashPos = fullPageName.lastIndexOf("/");
+  var firstSlashPos = fullPageName.indexOf("/"); 
+  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);
+  var link = $("#devdoc-nav a[href$='"+ pathPageName+"']");
+  if ((link.length == 0) && (fullPageName.indexOf("/guide/") != -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;
+    }
+  }
+  link.parent().addClass('selected');
+  if (link.parent().parent().is(':hidden')) {
+    toggle(link.parent().parent().parent(), false);
+  } else if (link.parent().parent().hasClass('toggle-list')) {
+    toggle(link.parent().parent(), false);
+  }
+}
+
+function resizeHeight() {
+  var windowHeight = ($(window).height() - HEADER_HEIGHT);
+  var swapperHeight = windowHeight - 13;
+  $("#swapper").css({height:swapperHeight + "px"});
+  sidenav.css({height:windowHeight + "px"});
+  content.css({height:windowHeight + "px"});
+  resizePackagesNav.css({maxHeight:swapperHeight + "px"});
+  classesNav.css({height:swapperHeight - parseInt(resizePackagesNav.css("height")) + "px"});
+  $("#packages-nav").css({height:parseInt(resizePackagesNav.css("height")) - 6 + "px"}); //move 6px for handle
+  devdocNav.css({height:sidenav.css("height")});
+  $("#nav-tree").css({height:swapperHeight + "px"});
+  
+  var basePath = getBaseUri(location.pathname);
+  var section = basePath.substring(1,basePath.indexOf("/",1));
+  writeCookie("height", resizePackagesNav.css("height"), section, null);
+}
+
+function resizeWidth() {
+  var windowWidth = $(window).width() + "px";
+  if (sidenav.length) {
+    var sidenavWidth = sidenav.css("width");
+  } else {
+    var sidenavWidth = 0;
+  }
+  content.css({marginLeft:parseInt(sidenavWidth) + 6 + "px", //account for 6px-wide handle-bar
+               width:parseInt(windowWidth) - parseInt(sidenavWidth) - 6 + "px"});
+  resizePackagesNav.css({width:sidenavWidth});
+  classesNav.css({width:sidenavWidth});
+  $("#packages-nav").css({width:sidenavWidth});
+  
+  var basePath = getBaseUri(location.pathname);
+  var section = basePath.substring(1,basePath.indexOf("/",1));
+  writeCookie("width", sidenavWidth, section, null);
+}
+
+function resizeAll() {
+  if (!isMobile) {
+    resizeHeight();
+    if ($(".side-nav-resizable").length) {
+      resizeWidth();
+    }
+  }
+}
+
+function getBaseUri(uri) {
+  var intlUrl = (uri.substring(0,6) == "/intl/");
+  if (intlUrl) {
+    base = uri.substring(uri.indexOf('intl/')+5,uri.length);
+    base = base.substring(base.indexOf('/')+1, base.length);
+      //alert("intl, returning base url: /" + base);
+    return ("/" + base);
+  } else {
+      //alert("not intl, returning uri as found.");
+    return uri;
+  }
+}
+
+function requestAppendHL(uri) {
+//append "?hl=<lang> to an outgoing request (such as to blog)
+  var lang = getLangPref();
+  if (lang) {
+    var q = 'hl=' + lang;
+    uri += '?' + q;
+    window.location = uri;
+    return false;
+  } else {
+    return true;
+  }
+}
+
+function loadLast(cookiePath) {
+  var location = window.location.href;
+  if (location.indexOf("/"+cookiePath+"/") != -1) {
+    return true;
+  }
+  var lastPage = readCookie(cookiePath + "_lastpage");
+  if (lastPage) {
+    window.location = lastPage;
+    return false;
+  }
+  return true;
+}
+
+$(window).unload(function(){
+  var path = getBaseUri(location.pathname);
+  if (path.indexOf("/reference/") != -1) {
+    writeCookie("lastpage", path, "reference", null);
+  } else if (path.indexOf("/guide/") != -1) {
+    writeCookie("lastpage", path, "guide", null);
+  }
+});
+
+function toggle(obj, slide) {
+  var ul = $("ul", obj);
+  var li = ul.parent();
+  if (li.hasClass("closed")) {
+    if (slide) {
+      ul.slideDown("fast");
+    } else {
+      ul.show();
+    }
+    li.removeClass("closed");
+    li.addClass("open");
+    $(".toggle-img", li).attr("title", "hide pages");
+  } else {
+    ul.slideUp("fast");
+    li.removeClass("open");
+    li.addClass("closed");
+    $(".toggle-img", li).attr("title", "show pages");
+  }
+}
+
+function buildToggleLists() {
+  $(".toggle-list").each(
+    function(i) {
+      $("div", this).append("<a class='toggle-img' href='#' title='show pages' onClick='toggle(this.parentNode.parentNode, true); return false;'></a>");
+      $(this).addClass("closed");
+    });
+}
+
+function getNavPref() {
+  var v = readCookie('reference_nav');
+  if (v != NAV_PREF_TREE) {
+    v = NAV_PREF_PANELS;
+  }
+  return v;
+}
+
+function chooseDefaultNav() {
+  nav_pref = getNavPref();
+  if (nav_pref == NAV_PREF_TREE) {
+    $("#nav-panels").toggle();
+    $("#panel-link").toggle();
+    $("#nav-tree").toggle();
+    $("#tree-link").toggle();
+  }
+}
+
+function swapNav() {
+  if (nav_pref == NAV_PREF_TREE) {
+    nav_pref = NAV_PREF_PANELS;
+  } else {
+    nav_pref = NAV_PREF_TREE;
+    init_default_navtree(toRoot);
+  }
+  var date = new Date();
+  date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
+  writeCookie("nav", nav_pref, "reference", date.toGMTString());
+
+  $("#nav-panels").toggle();
+  $("#panel-link").toggle();
+  $("#nav-tree").toggle();
+  $("#tree-link").toggle();
+
+  if ($("#nav-tree").is(':visible')) scrollIntoView("nav-tree");
+  else {
+    scrollIntoView("packages-nav");
+    scrollIntoView("classes-nav");
+  }
+}
+
+function scrollIntoView(nav) {
+  var navObj = $("#"+nav);
+  if (navObj.is(':visible')) {
+    var selected = $(".selected", navObj);
+    if (selected.length == 0) return;
+    if (selected.is("div")) selected = selected.parent();
+
+    var scrolling = document.getElementById(nav);
+    var navHeight = navObj.height();
+    var offsetTop = selected.position().top;
+    if (selected.parent().parent().is(".toggle-list")) offsetTop += selected.parent().parent().position().top;
+    if(offsetTop > navHeight - 92) {
+      scrolling.scrollTop = offsetTop - navHeight + 92;
+    }
+  }
+}
+
+function toggleAllInherited(linkObj, expand) {
+  var a = $(linkObj);
+  var table = $(a.parent().parent().parent());
+  var expandos = $(".jd-expando-trigger", table);
+  if ( (expand == null && a.text() == "[Expand]") || expand ) {
+    expandos.each(function(i) {
+      toggleInherited(this, true);
+    });
+    a.text("[Collapse]");
+  } else if ( (expand == null && a.text() == "[Collapse]") || (expand == false) ) {
+    expandos.each(function(i) {
+      toggleInherited(this, false);
+    });
+    a.text("[Expand]");
+  }
+  return false;
+}
+
+function toggleAllSummaryInherited(linkObj) {
+  var a = $(linkObj);
+  var content = $(a.parent().parent().parent());
+  var toggles = $(".toggle-all", content);
+  if (a.text() == "[Expand All]") {
+    toggles.each(function(i) {
+      toggleAllInherited(this, true);
+    });
+    a.text("[Collapse All]");
+  } else {
+    toggles.each(function(i) {
+      toggleAllInherited(this, false);
+    });
+    a.text("[Expand All]");
+  }
+  return false;
+}
+
+
+function changeTabLang(lang) {
+  var nodes = $("#header-tabs").find("."+lang);
+  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.css("display","inline");
+    } else { //otherwise, show English instead 
+      node.css("display","none");
+      node.siblings().filter(".en").css("display","inline");
+    }
+  }
+}
+
+function changeNavLang(lang) {
+  var nodes = $("#side-nav").find("."+lang);
+  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.css("display","inline");
+    } else { // otherwise, show English instead 
+      node.css("display","none");
+      node.siblings().filter(".en").css("display","inline");
+    }
+  }
+}
+
+function changeDocLang(lang) {
+  changeTabLang(lang);
+  changeNavLang(lang);
+}
+
+function changeLangPref(lang, refresh) {
+  var date = new Date();
+  expires = date.toGMTString(date.setTime(date.getTime()+(10*365*24*60*60*1000))); // keep this for 50 years
+  //alert("expires: " + expires)
+  writeCookie("pref_lang", lang, null, expires);
+  //changeDocLang(lang);
+  if (refresh) {
+    l = getBaseUri(location.pathname);
+    window.location = l;
+  }
+}
+
+function loadLangPref() {
+  var lang = readCookie("pref_lang");
+  if (lang != 0) {
+    $("#language").find("option[value='"+lang+"']").attr("selected",true);
+  }
+}
+
+function getLangPref() {
+  var lang = $("#language").find(":selected").attr("value");
+  if (!lang) {
+    lang = readCookie("pref_lang");
+  }
+  return (lang != 0) ? lang : 'en';
+}
+
+
+function toggleContent(obj) {
+  var button = $(obj);
+  var div = $(obj.parentNode);
+  var toggleMe = $(".toggle-content-toggleme",div);
+  if (button.hasClass("show")) {
+    toggleMe.slideDown();
+    button.removeClass("show").addClass("hide");
+  } else {
+    toggleMe.slideUp();
+    button.removeClass("hide").addClass("show");
+  }
+  $("span", button).toggle();
+}
diff --git a/tools/droiddoc/templates-pdk/assets-pdk/favicon.ico b/tools/droiddoc/templates-pdk/assets/favicon.ico
similarity index 100%
rename from tools/droiddoc/templates-pdk/assets-pdk/favicon.ico
rename to tools/droiddoc/templates-pdk/assets/favicon.ico
Binary files differ
diff --git a/tools/droiddoc/templates-pdk/assets/images/rebox-gradient.gif b/tools/droiddoc/templates-pdk/assets/images/rebox-gradient.gif
new file mode 100644
index 0000000..124e844
--- /dev/null
+++ b/tools/droiddoc/templates-pdk/assets/images/rebox-gradient.gif
Binary files differ
diff --git a/tools/droiddoc/templates-pdk/assets-pdk/placeholder b/tools/droiddoc/templates-pdk/assets/placeholder
similarity index 100%
rename from tools/droiddoc/templates-pdk/assets-pdk/placeholder
rename to tools/droiddoc/templates-pdk/assets/placeholder
diff --git a/tools/droiddoc/templates-pdk/customization.cs b/tools/droiddoc/templates-pdk/customization.cs
index dfebb12..3e9be06 100644
--- a/tools/droiddoc/templates-pdk/customization.cs
+++ b/tools/droiddoc/templates-pdk/customization.cs
@@ -5,23 +5,28 @@
 def:custom_masthead() ?>
   <div id="header">
       <div id="headerLeft">
-          <a href="http://source.android.com" tabindex="-1"><img
-              src="<?cs var:toroot ?>assets/images/open_source.png" alt="Open Source Project: Platform Development Kit" /></a>
-          <ul class="<?cs 
-                  if:releases ?> releases<?cs
-                  elif:guide ?> guide<?cs
-                  elif:licenses ?>licenses <?cs
-                  elif:home ?>home <?cs
-                  elif:community ?>community <?cs /if ?>">
+          <a href="<?cs var:toroot?>" tabindex="-1"><img
+              src="<?cs var:toroot ?>assets/images/open_source.png" alt="Android Open Source Project" /></a>
+          <ul class="<?cs if:home ?>home<?cs
+                      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>
-              <li id="guide-link"><a href="<?cs var:toroot ?>guide/index.html"
-                                  onClick="return loadLast('guide)'"><span>Guide</span></a></li>
-              <li id="releases-ink"><a href="<?cs var:toroot ?>releases/index.html"
-                                  onClick="return loadLast('releases)'"><span>Releases</span></a></li>
-              <li id="licenses-link"><a href="<?cs var:toroot ?>licenses/index.html"
-                                  onClick="return loadLast('licenses)'"><span>Licenses</span></a></li>
+              <li id="source-link"><a href="<?cs var:toroot ?>source/index.html"
+                                  onClick="return loadLast('source')"><span>Source</span></a></li>
+              <li id="porting-link"><a href="<?cs var:toroot ?>porting/index.html"
+                                  onClick="return loadLast('porting')"><span>Porting</span></a></li>
+              <li id="compatibility-link"><a href="<?cs var:toroot ?>compatibility/index.html"
+                                  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>
+                                  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> 
       </div>
       <div id="headerRight">
@@ -37,12 +42,11 @@
 /def ?><?cs # custom_masthead ?>
 
 
-<?cs 
-def:guide_nav() ?>
+<?cs def:community_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/guide/pdk_toc.cs" ?>
+        include:"../../../../development/pdk/docs/community/community_toc.cs" ?>
       </div>
     </div> <!-- end side-nav -->
     <script>
@@ -50,14 +54,14 @@
         scrollIntoView("devdoc-nav");
         });
     </script>
+  </div>
 <?cs /def ?>
 
-<?cs
-def:licenses_nav() ?>
+<?cs def:about_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/licenses/licenses_toc.cs" ?>
+        include:"../../../../development/pdk/docs/about/about_toc.cs" ?>
       </div>
     </div> <!-- end side-nav -->
     <script>
@@ -65,14 +69,14 @@
         scrollIntoView("devdoc-nav");
         });
     </script>
+  </div>
 <?cs /def ?>
 
-<?cs
-def:releases_nav() ?>
+<?cs def:porting_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/releases/releases_toc.cs" ?>
+        include:"../../../../development/pdk/docs/porting/porting_toc.cs" ?>
       </div>
     </div> <!-- end side-nav -->
     <script>
@@ -80,18 +84,71 @@
         scrollIntoView("devdoc-nav");
         });
     </script>
+  </div>
 <?cs /def ?>
 
-<?cs 
-def:custom_left_nav() ?><?cs
-  if:doc.type == "guide" ?><?cs
-    call:guide_nav() ?><?cs
-  elif:doc.type == "licenses" ?><?cs
-    call:licenses_nav() ?><?cs
-  elif:doc.type == "releases" ?><?cs
-    call:releases_nav() ?><?cs
-  /if ?><?cs
-/def ?>
+<?cs def:source_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/source/source_toc.cs" ?>
+      </div>
+    </div> <!-- end side-nav -->
+    <script>
+      addLoadEvent(function() {
+        scrollIntoView("devdoc-nav");
+        });
+    </script>
+  </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">
+      <div id="devdoc-nav"><?cs
+        include:"../../../../development/pdk/docs/compatibility/compatibility_toc.cs" ?>
+      </div>
+    </div> <!-- end side-nav -->
+    <script>
+      addLoadEvent(function() {
+        scrollIntoView("devdoc-nav");
+        });
+    </script>
+  </div>
+<?cs /def ?>
+
+<?cs def:custom_left_nav() ?>
+  <?cs if:doc.hidenav != "true" ?>
+    <?cs if:doc.type == "source" ?>
+      <?cs call:source_nav() ?>
+    <?cs elif:doc.type == "porting" ?>
+      <?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" ?>
+      <?cs call:about_nav() ?>
+    <?cs /if ?>
+  <?cs /if ?>
+<?cs /def ?>
 
 <?cs # appears at the bottom of every page ?><?cs 
 def:custom_cc_copyright() ?>
diff --git a/tools/droiddoc/templates-pdk/head_tag.cs b/tools/droiddoc/templates-pdk/head_tag.cs
index 47b332a..915dc0e 100644
--- a/tools/droiddoc/templates-pdk/head_tag.cs
+++ b/tools/droiddoc/templates-pdk/head_tag.cs
@@ -11,7 +11,6 @@
 <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" />
 <script src="<?cs var:toroot ?>assets/search_autocomplete.js" type="text/javascript"></script>
-<script src="<?cs var:toroot ?>reference/lists.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>
 <script type="text/javascript">
diff --git a/tools/droiddoc/templates-sdk/sdkpage.cs b/tools/droiddoc/templates-sdk/sdkpage.cs
index 604b5ee..1ebfb69 100644
--- a/tools/droiddoc/templates-sdk/sdkpage.cs
+++ b/tools/droiddoc/templates-sdk/sdkpage.cs
@@ -151,6 +151,10 @@
     </a>
   </div>
 
+  <p>If you are new to the Android SDK, please read the <a href="#quickstart">Quick Start</a>,
+  below, for an overview of how to install and set up the SDK.</p>
+  
+  
   <table class="download">
     <tr>
       <th>Platform</th>
@@ -200,14 +204,17 @@
 
 <?cs if:android.whichdoc != "online" && sdk.preview ?>
   <p>Welcome developers! The next release of the Android platform will be
-  Android 1.6 and we are pleased to announce the availability of an early look SDK
-  to give you a head-start on developing applications for it. </p>
+Android <?cs var:sdk.preview.version ?> and we are pleased to announce the
+availability of an early look SDK to give you a head-start on developing
+applications for it. </p>
 
-  <p>The Android 1.6 platform includes a variety of improvements and new features
-  for users and developers. Additionally, the SDK itself introduces several new
-  capabilities that enable you to develop applications more efficiently.
-  See the <a href="http://developer.android.com/sdk/preview/features.html">
-  Android 1.6 Highlights</a> document for a list of highlights.</p>
+  <p>The Android <?cs var:sdk.preview.version ?> platform includes a variety of
+improvements and new features for users and developers. Additionally, the SDK
+itself introduces several new capabilities that enable you to develop
+applications more efficiently. See the <a
+href="http://developer.android.com/sdk/preview/features.html">Android 
+<?cs var:sdk.preview.version ?> Highlights</a> document for a list of
+highlights.</p>
 <?cs /if ?>
 
       <?cs call:tag_list(root.descr) ?>
diff --git a/tools/droiddoc/templates/assets/android-developer-docs.css b/tools/droiddoc/templates/assets/android-developer-docs.css
index 0ab7aab..92163ec 100644
--- a/tools/droiddoc/templates/assets/android-developer-docs.css
+++ b/tools/droiddoc/templates/assets/android-developer-docs.css
@@ -101,10 +101,14 @@
   padding: 0;
 }
 
+/*second level (nested) list*/
 #side-nav li li li a { 
-/*sdk lists*/
   padding: 0 0 0 28px;
-} 
+}
+/*third level (nested) list*/
+#side-nav li li li li a {
+  padding: 0 0 0 38px;
+}
 
 #side-nav .selected {
   background-color: #435a6e;
@@ -121,7 +125,7 @@
   display:block;
 }
 
-#side-nav .toggle-img {
+#side-nav .toggle-list .toggle-img {
   margin:0;
   padding:0;
   position:absolute;
@@ -131,8 +135,13 @@
   width:15px;
   outline-style:none;
 }
+/* second-level toggle */
+#side-nav .toggle-list .toggle-list .toggle-img {
+  left:10px;
+}
 
-#side-nav .closed .toggle-img {
+#side-nav .closed .toggle-img,
+#side-nav .open .closed .toggle-img {
   background:url('images/triangle-closed-small.png') 7px 4px no-repeat;
 }
 #side-nav .open .toggle-img {
@@ -226,7 +235,7 @@
 #doc-content {
   overflow:auto;
 }
-	
+
 #jd-header {
   background-color: #E2E2E2;
   padding: 7px 15px;
@@ -559,6 +568,15 @@
   font-weight:normal;
 }
 
+.caps {
+  font-variant:small-caps;
+  font-size:1.2em;
+}
+
+dl.tag-list dl.atn-list {
+  padding:0 0 0 2em;
+}
+
 .jd-details {
 /*  border:1px solid #669999;
   padding:4px; */
@@ -910,7 +928,7 @@
   margin: 12px 0 0 15px;
   padding:5px 8px 0 12px;
   font-size:90%;
-}	
+}
 
 .sidebox p,
 .sidebox-inner p {
diff --git a/tools/droiddoc/templates/assets/android-developer-docs.js b/tools/droiddoc/templates/assets/android-developer-docs.js
index dfe8fa1..4f27e0e 100644
--- a/tools/droiddoc/templates/assets/android-developer-docs.js
+++ b/tools/droiddoc/templates/assets/android-developer-docs.js
@@ -193,11 +193,25 @@
       if (lastBackstep == 0) break;
     }
   }
+
+  // add 'selected' to the <li> or <div> that wraps this <a>
   link.parent().addClass('selected');
-  if (link.parent().parent().is(':hidden')) {
-    toggle(link.parent().parent().parent(), false);
-  } else if (link.parent().parent().hasClass('toggle-list')) {
-    toggle(link.parent().parent(), false);
+
+  // if we're in a toggleable root link (<li class=toggle-list><div><a>)
+  if (link.parent().parent().hasClass('toggle-list')) {
+    toggle(link.parent().parent(), false); // open our own list
+    // then also check if we're in a third-level nested list that's toggleable
+    if (link.parent().parent().parent().is(':hidden')) {
+      toggle(link.parent().parent().parent().parent(), false); // open the super parent list
+    }
+  }
+  // if we're in a normal nav link (<li><a>) and the parent <ul> is hidden
+  else if (link.parent().parent().is(':hidden')) {
+    toggle(link.parent().parent().parent(), false); // open the parent list
+    // then also check if the parent list is also nested in a hidden list
+    if (link.parent().parent().parent().parent().is(':hidden')) {
+      toggle(link.parent().parent().parent().parent().parent(), false); // open the super parent list
+    }
   }
 }
 
@@ -335,7 +349,7 @@
 });
 
 function toggle(obj, slide) {
-  var ul = $("ul", obj);
+  var ul = $("ul:first", obj);
   var li = ul.parent();
   if (li.hasClass("closed")) {
     if (slide) {
@@ -357,7 +371,7 @@
 function buildToggleLists() {
   $(".toggle-list").each(
     function(i) {
-      $("div", this).append("<a class='toggle-img' href='#' title='show pages' onClick='toggle(this.parentNode.parentNode, true); return false;'></a>");
+      $("div:first", this).append("<a class='toggle-img' href='#' title='show pages' onClick='toggle(this.parentNode.parentNode, true); return false;'></a>");
       $(this).addClass("closed");
     });
 }
diff --git a/tools/event_log_tags.py b/tools/event_log_tags.py
new file mode 100644
index 0000000..81e8b39
--- /dev/null
+++ b/tools/event_log_tags.py
@@ -0,0 +1,127 @@
+# 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.
+
+"""A module for reading and parsing event-log-tags files."""
+
+import re
+import sys
+
+class Tag(object):
+  __slots__ = ["tagnum", "tagname", "description", "filename", "linenum"]
+
+  def __init__(self, tagnum, tagname, description, filename, linenum):
+    self.tagnum = tagnum
+    self.tagname = tagname
+    self.description = description
+    self.filename = filename
+    self.linenum = linenum
+
+
+class TagFile(object):
+  """Read an input event-log-tags file."""
+  def AddError(self, msg, linenum=None):
+    if linenum is None:
+      linenum = self.linenum
+    self.errors.append((self.filename, linenum, msg))
+
+  def AddWarning(self, msg, linenum=None):
+    if linenum is None:
+      linenum = self.linenum
+    self.warnings.append((self.filename, linenum, msg))
+
+  def __init__(self, filename, file_object=None):
+    """'filename' is the name of the file (included in any error
+    messages).  If 'file_object' is None, 'filename' will be opened
+    for reading."""
+    self.errors = []
+    self.warnings = []
+    self.tags = []
+    self.options = {}
+
+    self.filename = filename
+    self.linenum = 0
+
+    if file_object is None:
+      try:
+        file_object = open(filename, "rb")
+      except (IOError, OSError), e:
+        self.AddError(str(e))
+        return
+
+    try:
+      for self.linenum, line in enumerate(file_object):
+        self.linenum += 1
+
+        line = line.strip()
+        if not line or line[0] == '#': continue
+        parts = re.split(r"\s+", line, 2)
+
+        if len(parts) < 2:
+          self.AddError("failed to parse \"%s\"" % (line,))
+          continue
+
+        if parts[0] == "option":
+          self.options[parts[1]] = parts[2:]
+          continue
+
+        if parts[0] == "?":
+          tag = None
+        else:
+          try:
+            tag = int(parts[0])
+          except ValueError:
+            self.AddError("\"%s\" isn't an integer tag or '?'" % (parts[0],))
+            continue
+
+        tagname = parts[1]
+        if len(parts) == 3:
+          description = parts[2]
+        else:
+          description = None
+
+        self.tags.append(Tag(tag, tagname, description,
+                             self.filename, self.linenum))
+    except (IOError, OSError), e:
+      self.AddError(str(e))
+
+
+def BooleanFromString(s):
+  """Interpret 's' as a boolean and return its value.  Raise
+  ValueError if it's not something we can interpret as true or
+  false."""
+  s = s.lower()
+  if s in ("true", "t", "1", "on", "yes", "y"):
+    return True
+  if s in ("false", "f", "0", "off", "no", "n"):
+    return False
+  raise ValueError("'%s' not a valid boolean" % (s,))
+
+
+def WriteOutput(output_file, data):
+  """Write 'data' to the given output filename (which may be None to
+  indicate stdout).  Emit an error message and die on any failure.
+  'data' may be a string or a StringIO object."""
+  if not isinstance(data, str):
+    data = data.getvalue()
+  try:
+    if output_file is None:
+      out = sys.stdout
+      output_file = "<stdout>"
+    else:
+      out = open(output_file, "wb")
+    out.write(data)
+    out.close()
+  except (IOError, OSError), e:
+    print >> sys.stderr, "failed to write %s: %s" % (output_file, e)
+    sys.exit(1)
diff --git a/tools/java-event-log-tags.py b/tools/java-event-log-tags.py
new file mode 100755
index 0000000..c63fa20
--- /dev/null
+++ b/tools/java-event-log-tags.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""
+Usage: java-event-log-tags.py [-o output_file] <input_file> <merged_tags_file>
+
+Generate a java class containing constants for each of the event log
+tags in the given input file.
+
+-h to display this usage message and exit.
+"""
+
+import cStringIO
+import getopt
+import os
+import re
+import sys
+
+import event_log_tags
+
+output_file = None
+
+try:
+  opts, args = getopt.getopt(sys.argv[1:], "ho:")
+except getopt.GetoptError, err:
+  print str(err)
+  print __doc__
+  sys.exit(2)
+
+for o, a in opts:
+  if o == "-h":
+    print __doc__
+    sys.exit(2)
+  elif o == "-o":
+    output_file = a
+  else:
+    print >> sys.stderr, "unhandled option %s" % (o,)
+    sys.exit(1)
+
+if len(args) != 2:
+  print "need exactly two input files, not %d" % (len(args),)
+  print __doc__
+  sys.exit(1)
+
+fn = args[0]
+tagfile = event_log_tags.TagFile(fn)
+
+# Load the merged tag file (which should have numbers assigned for all
+# tags.  Use the numbers from the merged file to fill in any missing
+# numbers from the input file.
+merged_fn = args[1]
+merged_tagfile = event_log_tags.TagFile(merged_fn)
+merged_by_name = dict([(t.tagname, t) for t in merged_tagfile.tags])
+for t in tagfile.tags:
+  if t.tagnum is None:
+    if t.tagname in merged_by_name:
+      t.tagnum = merged_by_name[t.tagname].tagnum
+    else:
+      # We're building something that's not being included in the
+      # product, so its tags don't appear in the merged file.  Assign
+      # them all an arbitrary number so we can emit the java and
+      # compile the (unused) package.
+      t.tagnum = 999999
+
+if "java_package" not in tagfile.options:
+  tagfile.AddError("java_package option not specified", linenum=0)
+
+hide = True
+if "javadoc_hide" in tagfile.options:
+  hide = event_log_tags.BooleanFromString(tagfile.options["javadoc_hide"][0])
+
+if tagfile.errors:
+  for fn, ln, msg in tagfile.errors:
+    print >> sys.stderr, "%s:%d: error: %s" % (fn, ln, msg)
+  sys.exit(1)
+
+buffer = cStringIO.StringIO()
+buffer.write("/* This file is auto-generated.  DO NOT MODIFY.\n"
+             " * Source file: %s\n"
+             " */\n\n" % (fn,))
+
+buffer.write("package %s;\n\n" % (tagfile.options["java_package"][0],))
+
+basename, _ = os.path.splitext(os.path.basename(fn))
+
+if hide:
+  buffer.write("/**\n"
+               " * @hide\n"
+               " */\n")
+buffer.write("public class %s {\n" % (basename,))
+buffer.write("  private %s() { }  // don't instantiate\n" % (basename,))
+
+for t in tagfile.tags:
+  if t.description:
+    buffer.write("\n  /** %d %s %s */\n" % (t.tagnum, t.tagname, t.description))
+  else:
+    buffer.write("\n  /** %d %s */\n" % (t.tagnum, t.tagname))
+
+  buffer.write("  public static final int %s = %d;\n" %
+               (t.tagname.upper(), t.tagnum))
+
+keywords = frozenset(["abstract", "continue", "for", "new", "switch", "assert",
+                      "default", "goto", "package", "synchronized", "boolean",
+                      "do", "if", "private", "this", "break", "double",
+                      "implements", "protected", "throw", "byte", "else",
+                      "import", "public", "throws", "case", "enum",
+                      "instanceof", "return", "transient", "catch", "extends",
+                      "int", "short", "try", "char", "final", "interface",
+                      "static", "void", "class", "finally", "long", "strictfp",
+                      "volatile", "const", "float", "native", "super", "while"])
+
+def javaName(name):
+  out = name[0].lower() + re.sub(r"[^A-Za-z0-9]", "", name.title())[1:]
+  if out in keywords:
+    out += "_"
+  return out
+
+javaTypes = ["ERROR", "int", "long", "String", "Object[]"]
+for t in tagfile.tags:
+  methodName = javaName("write_" + t.tagname)
+  if t.description:
+    args = [arg.strip("() ").split("|") for arg in t.description.split(",")]
+  else:
+    args = []
+  argTypesNames = ", ".join([javaTypes[int(arg[1])] + " " + javaName(arg[0]) for arg in args])
+  argNames = "".join([", " + javaName(arg[0]) for arg in args])
+  buffer.write("\n  public static void %s(%s) {" % (methodName, argTypesNames))
+  buffer.write("\n    android.util.EventLog.writeEvent(%s%s);" % (t.tagname.upper(), argNames))
+  buffer.write("\n  }\n")
+
+
+buffer.write("}\n");
+
+event_log_tags.WriteOutput(output_file, buffer)
diff --git a/tools/merge-event-log-tags.py b/tools/merge-event-log-tags.py
new file mode 100755
index 0000000..25ac697
--- /dev/null
+++ b/tools/merge-event-log-tags.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""
+Usage: merge-event-log-tags.py [-o output_file] [input_files...]
+
+Merge together zero or more event-logs-tags files to produce a single
+output file, stripped of comments.  Checks that no tag numbers conflict
+and fails if they do.
+
+-h to display this usage message and exit.
+"""
+
+import cStringIO
+import getopt
+import md5
+import struct
+import sys
+
+import event_log_tags
+
+errors = []
+warnings = []
+
+output_file = None
+
+# Tags with a tag number of ? are assigned a tag in the range
+# [ASSIGN_START, ASSIGN_LIMIT).
+ASSIGN_START = 900000
+ASSIGN_LIMIT = 1000000
+
+try:
+  opts, args = getopt.getopt(sys.argv[1:], "ho:")
+except getopt.GetoptError, err:
+  print str(err)
+  print __doc__
+  sys.exit(2)
+
+for o, a in opts:
+  if o == "-h":
+    print __doc__
+    sys.exit(2)
+  elif o == "-o":
+    output_file = a
+  else:
+    print >> sys.stderr, "unhandled option %s" % (o,)
+    sys.exit(1)
+
+# Restrictions on tags:
+#
+#   Tag names must be unique.  (If the tag number and description are
+#   also the same, a warning is issued instead of an error.)
+#
+#   Explicit tag numbers must be unique.  (If the tag name is also the
+#   same, no error is issued because the above rule will issue a
+#   warning or error.)
+
+by_tagname = {}
+by_tagnum = {}
+
+for fn in args:
+  tagfile = event_log_tags.TagFile(fn)
+
+  for t in tagfile.tags:
+    tagnum = t.tagnum
+    tagname = t.tagname
+    description = t.description
+
+    if t.tagname in by_tagname:
+      orig = by_tagname[t.tagname]
+
+      if (t.tagnum == orig.tagnum and
+          t.description == orig.description):
+        # if the name and description are identical, issue a warning
+        # instead of failing (to make it easier to move tags between
+        # projects without breaking the build).
+        tagfile.AddWarning("tag \"%s\" (%s) duplicated in %s:%d" %
+                           (t.tagname, t.tagnum, orig.filename, orig.linenum),
+                           linenum=t.linenum)
+      else:
+        tagfile.AddError(
+            "tag name \"%s\" used by conflicting tag %s from %s:%d" %
+            (t.tagname, orig.tagnum, orig.filename, orig.linenum),
+            linenum=t.linenum)
+      continue
+
+    if t.tagnum is not None and t.tagnum in by_tagnum:
+      orig = by_tagnum[t.tagnum]
+
+      if t.tagname != orig.tagname:
+        tagfile.AddError(
+            "tag number %d used by conflicting tag \"%s\" from %s:%d" %
+            (t.tagnum, orig.tagname, orig.filename, orig.linenum),
+            linenum=t.linenum)
+        continue
+
+    by_tagname[t.tagname] = t
+    if t.tagnum is not None:
+      by_tagnum[t.tagnum] = t
+
+  errors.extend(tagfile.errors)
+  warnings.extend(tagfile.warnings)
+
+if errors:
+  for fn, ln, msg in errors:
+    print >> sys.stderr, "%s:%d: error: %s" % (fn, ln, msg)
+  sys.exit(1)
+
+if warnings:
+  for fn, ln, msg in warnings:
+    print >> sys.stderr, "%s:%d: warning: %s" % (fn, ln, msg)
+
+# Python's hash function (a) isn't great and (b) varies between
+# versions of python.  Using md5 is overkill here but is the same from
+# platform to platform and speed shouldn't matter in practice.
+def hashname(str):
+  d = md5.md5(str).digest()[:4]
+  return struct.unpack("!I", d)[0]
+
+# Assign a tag number to all the entries that say they want one
+# assigned.  We do this based on a hash of the tag name so that the
+# numbers should stay relatively stable as tags are added.
+
+for name, t in sorted(by_tagname.iteritems()):
+  if t.tagnum is None:
+    while True:
+      x = (hashname(name) % (ASSIGN_LIMIT - ASSIGN_START - 1)) + ASSIGN_START
+      if x not in by_tagnum:
+        t.tagnum = x
+        by_tagnum[x] = t
+        break
+      name = "_" + name
+
+# by_tagnum should be complete now; we've assigned numbers to all tags.
+
+buffer = cStringIO.StringIO()
+for n, t in sorted(by_tagnum.iteritems()):
+  if t.description:
+    buffer.write("%d %s %s\n" % (t.tagnum, t.tagname, t.description))
+  else:
+    buffer.write("%d %s\n" % (t.tagnum, t.tagname))
+
+event_log_tags.WriteOutput(output_file, buffer)
diff --git a/tools/releasetools/amend_generator.py b/tools/releasetools/amend_generator.py
index f8f4344..b543bf7 100644
--- a/tools/releasetools/amend_generator.py
+++ b/tools/releasetools/amend_generator.py
@@ -100,6 +100,10 @@
     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."""
@@ -192,6 +196,9 @@
     """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
diff --git a/tools/releasetools/both_generator.py b/tools/releasetools/both_generator.py
index df2a659..4ae8d50 100644
--- a/tools/releasetools/both_generator.py
+++ b/tools/releasetools/both_generator.py
@@ -41,6 +41,7 @@
   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)
@@ -55,6 +56,7 @@
   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/check_target_files_signatures b/tools/releasetools/check_target_files_signatures
new file mode 100755
index 0000000..17aebdc
--- /dev/null
+++ b/tools/releasetools/check_target_files_signatures
@@ -0,0 +1,449 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""
+Check the signatures of all APKs in a target_files .zip file.  With
+-c, compare the signatures of each package to the ones in a separate
+target_files (usually a previously distributed build for the same
+device) and flag any changes.
+
+Usage:  check_target_file_signatures [flags] target_files
+
+  -c  (--compare_with)  <other_target_files>
+      Look for compatibility problems between the two sets of target
+      files (eg., packages whose keys have changed).
+
+  -l  (--local_cert_dirs)  <dir,dir,...>
+      Comma-separated list of top-level directories to scan for
+      .x509.pem files.  Defaults to "vendor,build".  Where cert files
+      can be found that match APK signatures, the filename will be
+      printed as the cert name, otherwise a hash of the cert plus its
+      subject string will be printed instead.
+
+  -t  (--text)
+      Dump the certificate information for both packages in comparison
+      mode (this output is normally suppressed).
+
+"""
+
+import sys
+
+if sys.hexversion < 0x02040000:
+  print >> sys.stderr, "Python 2.4 or newer is required."
+  sys.exit(1)
+
+import os
+import re
+import sha
+import shutil
+import subprocess
+import tempfile
+import zipfile
+
+import common
+
+# Work around a bug in python's zipfile module that prevents opening
+# of zipfiles if any entry has an extra field of between 1 and 3 bytes
+# (which is common with zipaligned APKs).  This overrides the
+# ZipInfo._decodeExtra() method (which contains the bug) with an empty
+# version (since we don't need to decode the extra field anyway).
+class MyZipInfo(zipfile.ZipInfo):
+  def _decodeExtra(self):
+    pass
+zipfile.ZipInfo = MyZipInfo
+
+OPTIONS = common.OPTIONS
+
+OPTIONS.text = False
+OPTIONS.compare_with = None
+OPTIONS.local_cert_dirs = ("vendor", "build")
+
+PROBLEMS = []
+PROBLEM_PREFIX = []
+
+def AddProblem(msg):
+  PROBLEMS.append(" ".join(PROBLEM_PREFIX) + " " + msg)
+def Push(msg):
+  PROBLEM_PREFIX.append(msg)
+def Pop():
+  PROBLEM_PREFIX.pop()
+
+
+def Banner(msg):
+  print "-" * 70
+  print "  ", msg
+  print "-" * 70
+
+
+def GetCertSubject(cert):
+  p = common.Run(["openssl", "x509", "-inform", "DER", "-text"],
+                 stdin=subprocess.PIPE,
+                 stdout=subprocess.PIPE)
+  out, err = p.communicate(cert)
+  if err and not err.strip():
+    return "(error reading cert subject)"
+  for line in out.split("\n"):
+    line = line.strip()
+    if line.startswith("Subject:"):
+      return line[8:].strip()
+  return "(unknown cert subject)"
+
+
+class CertDB(object):
+  def __init__(self):
+    self.certs = {}
+
+  def Add(self, cert, name=None):
+    if cert in self.certs:
+      if name:
+        self.certs[cert] = self.certs[cert] + "," + name
+    else:
+      if name is None:
+        name = "unknown cert %s (%s)" % (sha.sha(cert).hexdigest()[:12],
+                                         GetCertSubject(cert))
+      self.certs[cert] = name
+
+  def Get(self, cert):
+    """Return the name for a given cert."""
+    return self.certs.get(cert, None)
+
+  def FindLocalCerts(self):
+    to_load = []
+    for top in OPTIONS.local_cert_dirs:
+      for dirpath, dirnames, filenames in os.walk(top):
+        certs = [os.path.join(dirpath, i)
+                 for i in filenames if i.endswith(".x509.pem")]
+        if certs:
+          to_load.extend(certs)
+
+    for i in to_load:
+      f = open(i)
+      cert = ParseCertificate(f.read())
+      f.close()
+      name, _ = os.path.splitext(i)
+      name, _ = os.path.splitext(name)
+      self.Add(cert, name)
+
+ALL_CERTS = CertDB()
+
+
+def ParseCertificate(data):
+  """Parse a PEM-format certificate."""
+  cert = []
+  save = False
+  for line in data.split("\n"):
+    if "--END CERTIFICATE--" in line:
+      break
+    if save:
+      cert.append(line)
+    if "--BEGIN CERTIFICATE--" in line:
+      save = True
+  cert = "".join(cert).decode('base64')
+  return cert
+
+
+def CertFromPKCS7(data, filename):
+  """Read the cert out of a PKCS#7-format file (which is what is
+  stored in a signed .apk)."""
+  Push(filename + ":")
+  try:
+    p = common.Run(["openssl", "pkcs7",
+                    "-inform", "DER",
+                    "-outform", "PEM",
+                    "-print_certs"],
+                   stdin=subprocess.PIPE,
+                   stdout=subprocess.PIPE)
+    out, err = p.communicate(data)
+    if err and not err.strip():
+      AddProblem("error reading cert:\n" + err)
+      return None
+
+    cert = ParseCertificate(out)
+    if not cert:
+      AddProblem("error parsing cert output")
+      return None
+    return cert
+  finally:
+    Pop()
+
+
+class APK(object):
+  def __init__(self, full_filename, filename):
+    self.filename = filename
+    self.cert = None
+    Push(filename+":")
+    try:
+      self.RecordCert(full_filename)
+      self.ReadManifest(full_filename)
+    finally:
+      Pop()
+
+  def RecordCert(self, full_filename):
+    try:
+      f = open(full_filename)
+      apk = zipfile.ZipFile(f, "r")
+      pkcs7 = None
+      for info in apk.infolist():
+        if info.filename.startswith("META-INF/") and \
+           (info.filename.endswith(".DSA") or info.filename.endswith(".RSA")):
+          if pkcs7 is not None:
+            AddProblem("multiple certs")
+          pkcs7 = apk.read(info.filename)
+          self.cert = CertFromPKCS7(pkcs7, info.filename)
+          ALL_CERTS.Add(self.cert)
+      if not pkcs7:
+        AddProblem("no signature")
+    finally:
+      f.close()
+
+  def ReadManifest(self, full_filename):
+    p = common.Run(["aapt", "dump", "xmltree", full_filename,
+                    "AndroidManifest.xml"],
+                   stdout=subprocess.PIPE)
+    manifest, err = p.communicate()
+    if err:
+      AddProblem("failed to read manifest")
+      return
+
+    self.shared_uid = None
+    self.package = None
+
+    for line in manifest.split("\n"):
+      line = line.strip()
+      m = re.search('A: (\S*?)(?:\(0x[0-9a-f]+\))?="(.*?)" \(Raw', line)
+      if m:
+        name = m.group(1)
+        if name == "android:sharedUserId":
+          if self.shared_uid is not None:
+            AddProblem("multiple sharedUserId declarations")
+          self.shared_uid = m.group(2)
+        elif name == "package":
+          if self.package is not None:
+            AddProblem("multiple package declarations")
+          self.package = m.group(2)
+
+    if self.package is None:
+      AddProblem("no package declaration")
+
+
+class TargetFiles(object):
+  def __init__(self):
+    self.max_pkg_len = 30
+    self.max_fn_len = 20
+
+  def LoadZipFile(self, filename):
+    d = common.UnzipTemp(filename, '*.apk')
+    try:
+      self.apks = {}
+      self.apks_by_basename = {}
+      for dirpath, dirnames, filenames in os.walk(d):
+        for fn in filenames:
+          if fn.endswith(".apk"):
+            fullname = os.path.join(dirpath, fn)
+            displayname = fullname[len(d)+1:]
+            apk = APK(fullname, displayname)
+            self.apks[apk.package] = apk
+            self.apks_by_basename[os.path.basename(apk.filename)] = apk
+
+            self.max_pkg_len = max(self.max_pkg_len, len(apk.package))
+            self.max_fn_len = max(self.max_fn_len, len(apk.filename))
+    finally:
+      shutil.rmtree(d)
+
+    z = zipfile.ZipFile(open(filename, "rb"))
+    self.certmap = common.ReadApkCerts(z)
+    z.close()
+
+  def CheckSharedUids(self):
+    """Look for any instances where packages signed with different
+    certs request the same sharedUserId."""
+    apks_by_uid = {}
+    for apk in self.apks.itervalues():
+      if apk.shared_uid:
+        apks_by_uid.setdefault(apk.shared_uid, []).append(apk)
+
+    for uid in sorted(apks_by_uid.keys()):
+      apks = apks_by_uid[uid]
+      for apk in apks[1:]:
+        if apk.cert != apks[0].cert:
+          break
+      else:
+        # all the certs are the same; this uid is fine
+        continue
+
+      AddProblem("uid %s shared across multiple certs" % (uid,))
+
+      print "uid %s is shared by packages with different certs:" % (uid,)
+      x = [(i.cert, i.package, i) for i in apks]
+      x.sort()
+      lastcert = None
+      for cert, _, apk in x:
+        if cert != lastcert:
+          lastcert = cert
+          print "    %s:" % (ALL_CERTS.Get(cert),)
+        print "        %-*s  [%s]" % (self.max_pkg_len,
+                                      apk.package, apk.filename)
+      print
+
+  def CheckExternalSignatures(self):
+    for apk_filename, certname in self.certmap.iteritems():
+      if certname == "EXTERNAL":
+        # Apps marked EXTERNAL should be signed with the test key
+        # during development, then manually re-signed after
+        # predexopting.  Consider it an error if this app is now
+        # signed with any key that is present in our tree.
+        apk = self.apks_by_basename[apk_filename]
+        name = ALL_CERTS.Get(apk.cert)
+        if not name.startswith("unknown "):
+          Push(apk.filename)
+          AddProblem("hasn't been signed with EXTERNAL cert")
+          Pop()
+
+  def PrintCerts(self):
+    """Display a table of packages grouped by cert."""
+    by_cert = {}
+    for apk in self.apks.itervalues():
+      by_cert.setdefault(apk.cert, []).append((apk.package, apk))
+
+    order = [(-len(v), k) for (k, v) in by_cert.iteritems()]
+    order.sort()
+
+    for _, cert in order:
+      print "%s:" % (ALL_CERTS.Get(cert),)
+      apks = by_cert[cert]
+      apks.sort()
+      for _, apk in apks:
+        if apk.shared_uid:
+          print "  %-*s  %-*s  [%s]" % (self.max_fn_len, apk.filename,
+                                        self.max_pkg_len, apk.package,
+                                        apk.shared_uid)
+        else:
+          print "  %-*s  %-*s" % (self.max_fn_len, apk.filename,
+                                  self.max_pkg_len, apk.package)
+      print
+
+  def CompareWith(self, other):
+    """Look for instances where a given package that exists in both
+    self and other have different certs."""
+
+    all = set(self.apks.keys())
+    all.update(other.apks.keys())
+
+    max_pkg_len = max(self.max_pkg_len, other.max_pkg_len)
+
+    by_certpair = {}
+
+    for i in all:
+      if i in self.apks:
+        if i in other.apks:
+          # in both; should have the same cert
+          if self.apks[i].cert != other.apks[i].cert:
+            by_certpair.setdefault((other.apks[i].cert,
+                                    self.apks[i].cert), []).append(i)
+        else:
+          print "%s [%s]: new APK (not in comparison target_files)" % (
+              i, self.apks[i].filename)
+      else:
+        if i in other.apks:
+          print "%s [%s]: removed APK (only in comparison target_files)" % (
+              i, other.apks[i].filename)
+
+    if by_certpair:
+      AddProblem("some APKs changed certs")
+      Banner("APK signing differences")
+      for (old, new), packages in sorted(by_certpair.items()):
+        print "was", ALL_CERTS.Get(old)
+        print "now", ALL_CERTS.Get(new)
+        for i in sorted(packages):
+          old_fn = other.apks[i].filename
+          new_fn = self.apks[i].filename
+          if old_fn == new_fn:
+            print "  %-*s  [%s]" % (max_pkg_len, i, old_fn)
+          else:
+            print "  %-*s  [was: %s; now: %s]" % (max_pkg_len, i,
+                                                  old_fn, new_fn)
+        print
+
+
+def main(argv):
+  def option_handler(o, a):
+    if o in ("-c", "--compare_with"):
+      OPTIONS.compare_with = a
+    elif o in ("-l", "--local_cert_dirs"):
+      OPTIONS.local_cert_dirs = [i.strip() for i in a.split(",")]
+    elif o in ("-t", "--text"):
+      OPTIONS.text = True
+    else:
+      return False
+    return True
+
+  args = common.ParseOptions(argv, __doc__,
+                             extra_opts="c:l:t",
+                             extra_long_opts=["compare_with=",
+                                              "local_cert_dirs="],
+                             extra_option_handler=option_handler)
+
+  if len(args) != 1:
+    common.Usage(__doc__)
+    sys.exit(1)
+
+  ALL_CERTS.FindLocalCerts()
+
+  Push("input target_files:")
+  try:
+    target_files = TargetFiles()
+    target_files.LoadZipFile(args[0])
+  finally:
+    Pop()
+
+  compare_files = None
+  if OPTIONS.compare_with:
+    Push("comparison target_files:")
+    try:
+      compare_files = TargetFiles()
+      compare_files.LoadZipFile(OPTIONS.compare_with)
+    finally:
+      Pop()
+
+  if OPTIONS.text or not compare_files:
+    Banner("target files")
+    target_files.PrintCerts()
+  target_files.CheckSharedUids()
+  target_files.CheckExternalSignatures()
+  if compare_files:
+    if OPTIONS.text:
+      Banner("comparison files")
+      compare_files.PrintCerts()
+    target_files.CompareWith(compare_files)
+
+  if PROBLEMS:
+    print "%d problem(s) found:\n" % (len(PROBLEMS),)
+    for p in PROBLEMS:
+      print p
+    return 1
+
+  return 0
+
+
+if __name__ == '__main__':
+  try:
+    r = main(sys.argv[1:])
+    sys.exit(r)
+  except common.ExternalError, e:
+    print
+    print "   ERROR: %s" % (e,)
+    print
+    sys.exit(1)
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 26f216d..ab6678a 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -37,6 +37,11 @@
 OPTIONS.device_specific = None
 OPTIONS.extras = {}
 
+
+# Values for "certificate" in apkcerts that mean special things.
+SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL")
+
+
 class ExternalError(RuntimeError): pass
 
 
@@ -141,12 +146,15 @@
   BuildAndAddBootableImage(os.path.join(OPTIONS.input_tmp, "BOOT"),
                            "boot.img", output_zip)
 
-def UnzipTemp(filename):
+def UnzipTemp(filename, pattern=None):
   """Unzip the given archive into a temporary directory and return the name."""
 
   tmp = tempfile.mkdtemp(prefix="targetfiles-")
   OPTIONS.tempfiles.append(tmp)
-  p = Run(["unzip", "-o", "-q", filename, "-d", tmp], stdout=subprocess.PIPE)
+  cmd = ["unzip", "-o", "-q", filename, "-d", tmp]
+  if pattern is not None:
+    cmd.append(pattern)
+  p = Run(cmd, stdout=subprocess.PIPE)
   p.communicate()
   if p.returncode != 0:
     raise ExternalError("failed to unzip input target-files \"%s\"" %
@@ -163,9 +171,8 @@
   need_passwords = []
   devnull = open("/dev/null", "w+b")
   for k in sorted(keylist):
-    # An empty-string key is used to mean don't re-sign this package.
-    # Obviously we don't need a password for this non-key.
-    if not k:
+    # We don't need a password for things that aren't really keys.
+    if k in SPECIAL_CERT_STRINGS:
       no_passwords.append(k)
       continue
 
@@ -251,6 +258,28 @@
     print "  ", msg
 
 
+def ReadApkCerts(tf_zip):
+  """Given a target_files ZipFile, parse the META/apkcerts.txt file
+  and return a {package: cert} dict."""
+  certmap = {}
+  for line in tf_zip.read("META/apkcerts.txt").split("\n"):
+    line = line.strip()
+    if not line: continue
+    m = re.match(r'^name="(.*)"\s+certificate="(.*)"\s+'
+                 r'private_key="(.*)"$', line)
+    if m:
+      name, cert, privkey = m.groups()
+      if cert in SPECIAL_CERT_STRINGS and not privkey:
+        certmap[name] = cert
+      elif (cert.endswith(".x509.pem") and
+            privkey.endswith(".pk8") and
+            cert[:-9] == privkey[:-4]):
+        certmap[name] = cert[:-9]
+      else:
+        raise ValueError("failed to parse line from apkcerts.txt:\n" + line)
+  return certmap
+
+
 COMMON_DOCSTRING = """
   -p  (--path)  <dir>
       Prepend <dir>/bin to the list of places to search for binaries
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index d1902e1..68b0850 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -112,11 +112,19 @@
 
   def PatchCheck(self, filename, *sha1):
     """Check that the given file (or MTD reference) has one of the
-    given *sha1 hashes."""
+    given *sha1 hashes, checking the version saved in cache if the
+    file does not match."""
     self.script.append('assert(apply_patch_check("%s"' % (filename,) +
                        "".join([', "%s"' % (i,) for i in sha1]) +
                        '));')
 
+  def FileCheck(self, filename, *sha1):
+    """Check that the given file (or MTD reference) has one of the
+    given *sha1 hashes."""
+    self.script.append('assert(sha1_check(read_file("%s")' % (filename,) +
+                       "".join([', "%s"' % (i,) for i in sha1]) +
+                       '));')
+
   def CacheFreeSpaceCheck(self, amount):
     """Check that there's at least 'amount' space that can be made
     available on /cache."""
@@ -164,7 +172,7 @@
     cmd = ['apply_patch("%s",\0"%s",\0%s,\0%d'
            % (srcfile, tgtfile, tgtsha1, tgtsize)]
     for i in range(0, len(patchpairs), 2):
-      cmd.append(',\0"%s:%s"' % patchpairs[i:i+2])
+      cmd.append(',\0%s, package_extract_file("%s")' % patchpairs[i:i+2])
     cmd.append(');')
     cmd = "".join(cmd)
     self.script.append(self._WordWrap(cmd))
@@ -213,14 +221,18 @@
     """Append text verbatim to the output script."""
     self.script.append(extra)
 
+  def UnmountAll(self):
+    for p in sorted(self.mounts):
+      self.script.append('unmount("%s");' % (p,))
+    self.mounts = set()
+
   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 the 'updater' binary needed to run
     script.  If input_path is not None, it will be used as a local
     path for the binary instead of input_zip."""
 
-    for p in sorted(self.mounts):
-      self.script.append('unmount("%s");' % (p,))
+    self.UnmountAll()
 
     common.ZipWriteStr(output_zip, "META-INF/com/google/android/updater-script",
                        "\n".join(self.script) + "\n")
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
index f129da1..70ab55f 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -340,6 +340,7 @@
 
   device_specific = common.DeviceSpecificParams(
       input_zip=input_zip,
+      input_version=GetRecoveryAPIVersion(input_zip),
       output_zip=output_zip,
       script=script,
       input_tmp=OPTIONS.input_tmp)
@@ -393,6 +394,7 @@
   if OPTIONS.extra_script is not None:
     script.AppendExtra(OPTIONS.extra_script)
 
+  script.UnmountAll()
   script.AddToZip(input_zip, output_zip)
 
 
@@ -562,6 +564,7 @@
 
 def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
   source_version = GetRecoveryAPIVersion(source_zip)
+  target_version = GetRecoveryAPIVersion(target_zip)
 
   if OPTIONS.script_mode == 'amend':
     script = amend_generator.AmendGenerator()
@@ -580,7 +583,9 @@
 
   device_specific = common.DeviceSpecificParams(
       source_zip=source_zip,
+      source_version=source_version,
       target_zip=target_zip,
+      target_version=target_version,
       output_zip=output_zip,
       script=script)
 
@@ -622,7 +627,7 @@
       verbatim_targets.append((tf.name, tf.size))
     else:
       common.ZipWriteStr(output_zip, "patch/" + tf.name + ".p", d)
-      patch_list.append((tf.name, tf, sf, tf.size))
+      patch_list.append((tf.name, tf, sf, tf.size, sha.sha(d).hexdigest()))
       largest_source_size = max(largest_source_size, sf.size)
 
   source_fp = GetBuildProp("ro.build.fingerprint", source_zip)
@@ -664,7 +669,7 @@
     total_verify_size += source_boot.size
   so_far = 0
 
-  for fn, tf, sf, size in patch_list:
+  for fn, tf, sf, size, patch_sha in patch_list:
     script.PatchCheck("/"+fn, tf.sha1, sf.sha1)
     so_far += sf.size
     script.SetProgress(so_far / total_verify_size)
@@ -685,8 +690,6 @@
 
   if patch_list or updating_recovery or updating_boot:
     script.CacheFreeSpaceCheck(largest_source_size)
-    script.Print("Unpacking patches...")
-    script.UnpackPackageDir("patch", "/tmp/patchtmp")
 
   device_specific.IncrementalOTA_VerifyEnd()
 
@@ -709,9 +712,8 @@
   so_far = 0
 
   script.Print("Patching system files...")
-  for fn, tf, sf, size in patch_list:
-    script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1,
-                      sf.sha1, "/tmp/patchtmp/"+fn+".p")
+  for fn, tf, sf, size, _ in patch_list:
+    script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1, sf.sha1, "patch/"+fn+".p")
     so_far += tf.size
     script.SetProgress(so_far / total_patch_size)
 
@@ -725,7 +727,7 @@
                          target_boot.size, target_boot.sha1),
                       "-",
                       target_boot.size, target_boot.sha1,
-                      source_boot.sha1, "/tmp/patchtmp/boot.img.p")
+                      source_boot.sha1, "patch/boot.img.p")
     so_far += target_boot.size
     script.SetProgress(so_far / total_patch_size)
     print "boot image changed; including."
@@ -746,7 +748,8 @@
     # as fodder for constructing the recovery image.
     recovery_sh_item = MakeRecoveryPatch(output_zip,
                                          target_recovery, target_boot)
-    script.UnpackPackageDir("recovery", "/system")
+    script.DeleteFiles(["/system/recovery-from-boot.p",
+                        "/system/etc/install-recovery.sh"])
     print "recovery image changed; including as patch from boot."
   else:
     print "recovery image unchanged; skipping."
@@ -782,6 +785,10 @@
     script.Print("Unpacking new files...")
     script.UnpackPackageDir("system", "/system")
 
+  if updating_recovery:
+    script.Print("Unpacking new recovery...")
+    script.UnpackPackageDir("recovery", "/system")
+
   script.Print("Symlinks and permissions...")
 
   # Create all the symlinks that don't already exist, or point to
diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks
index 9d296d8..5fca691 100755
--- a/tools/releasetools/sign_target_files_apks
+++ b/tools/releasetools/sign_target_files_apks
@@ -83,17 +83,18 @@
 OPTIONS.tag_changes = ("-test-keys", "+release-keys")
 
 def GetApkCerts(tf_zip):
-  certmap = {}
-  for line in tf_zip.read("META/apkcerts.txt").split("\n"):
-    line = line.strip()
-    if not line: continue
-    m = re.match(r'^name="(.*)"\s+certificate="(.*)\.x509\.pem"\s+'
-                 r'private_key="\2\.pk8"$', line)
-    if not m:
-      raise SigningError("failed to parse line from apkcerts.txt:\n" + line)
-    certmap[m.group(1)] = OPTIONS.key_map.get(m.group(2), m.group(2))
-  for apk, cert in OPTIONS.extra_apks.iteritems():
+  certmap = common.ReadApkCerts(tf_zip)
+
+  # apply the key remapping to the contents of the file
+  for apk, cert in certmap.iteritems():
     certmap[apk] = OPTIONS.key_map.get(cert, cert)
+
+  # apply all the -e options, overriding anything in the file
+  for apk, cert in OPTIONS.extra_apks.iteritems():
+    if not cert:
+      cert = "PRESIGNED"
+    certmap[apk] = OPTIONS.key_map.get(cert, cert)
+
   return certmap
 
 
@@ -114,68 +115,6 @@
     sys.exit(1)
 
 
-def SharedUserForApk(data):
-  tmp = tempfile.NamedTemporaryFile()
-  tmp.write(data)
-  tmp.flush()
-
-  p = common.Run(["aapt", "dump", "xmltree", tmp.name, "AndroidManifest.xml"],
-                 stdout=subprocess.PIPE)
-  data, _ = p.communicate()
-  if p.returncode != 0:
-    raise ExternalError("failed to run aapt dump")
-  lines = data.split("\n")
-  for i in lines:
-    m = re.match(r'^\s*A: android:sharedUserId\([0-9a-fx]*\)="([^"]*)" .*$', i)
-    if m:
-      return m.group(1)
-  return None
-
-
-def CheckSharedUserIdsConsistent(input_tf_zip, apk_key_map):
-  """Check that all packages that request the same shared user id are
-  going to be signed with the same key."""
-
-  shared_user_apks = {}
-  maxlen = len("(unknown key)")
-
-  for info in input_tf_zip.infolist():
-    if info.filename.endswith(".apk"):
-      data = input_tf_zip.read(info.filename)
-
-      name = os.path.basename(info.filename)
-      shared_user = SharedUserForApk(data)
-      key = apk_key_map[name]
-      maxlen = max(maxlen, len(key))
-
-      if shared_user is not None:
-        shared_user_apks.setdefault(
-            shared_user, {}).setdefault(key, []).append(name)
-
-  errors = []
-  for k, v in shared_user_apks.iteritems():
-    # each shared user should have exactly one key used for all the
-    # apks that want that user.
-    if len(v) > 1:
-      errors.append((k, v))
-
-  if not errors: return
-
-  print "ERROR:  shared user inconsistency.  All apks wanting to use"
-  print "        a given shared user must be signed with the same key."
-  print
-  errors.sort()
-  for user, keys in errors:
-    print 'shared user id "%s":' % (user,)
-    for key, apps in keys.iteritems():
-      print '  %-*s   %s' % (maxlen, key or "(unknown key)", apps[0])
-      for a in apps[1:]:
-        print (' ' * (maxlen+5)) + a
-    print
-
-  sys.exit(1)
-
-
 def SignApk(data, keyname, pw):
   unsigned = tempfile.NamedTemporaryFile()
   unsigned.write(data)
@@ -203,7 +142,7 @@
     if info.filename.endswith(".apk"):
       name = os.path.basename(info.filename)
       key = apk_key_map[name]
-      if key:
+      if key not in common.SPECIAL_CERT_STRINGS:
         print "    signing: %-*s (%s)" % (maxsize, name, key)
         signed_data = SignApk(data, key, key_passwords[key])
         output_tf_zip.writestr(out_info, signed_data)
@@ -221,6 +160,18 @@
       output_tf_zip.writestr(out_info, data)
 
 
+def EditTags(tags):
+  """Given a string containing comma-separated tags, apply the edits
+  specified in OPTIONS.tag_changes and return the updated string."""
+  tags = set(tags.split(","))
+  for ch in OPTIONS.tag_changes:
+    if ch[0] == "-":
+      tags.discard(ch[1:])
+    elif ch[0] == "+":
+      tags.add(ch[1:])
+  return ",".join(sorted(tags))
+
+
 def RewriteProps(data):
   output = []
   for line in data.split("\n"):
@@ -229,24 +180,17 @@
     if line and line[0] != '#':
       key, value = line.split("=", 1)
       if key == "ro.build.fingerprint":
-        pieces = line.split("/")
-        tags = set(pieces[-1].split(","))
-        for ch in OPTIONS.tag_changes:
-          if ch[0] == "-":
-            tags.discard(ch[1:])
-          elif ch[0] == "+":
-            tags.add(ch[1:])
-        line = "/".join(pieces[:-1] + [",".join(sorted(tags))])
+        pieces = value.split("/")
+        pieces[-1] = EditTags(pieces[-1])
+        value = "/".join(pieces)
       elif key == "ro.build.description":
-        pieces = line.split(" ")
+        pieces = value.split(" ")
         assert len(pieces) == 5
-        tags = set(pieces[-1].split(","))
-        for ch in OPTIONS.tag_changes:
-          if ch[0] == "-":
-            tags.discard(ch[1:])
-          elif ch[0] == "+":
-            tags.add(ch[1:])
-        line = " ".join(pieces[:-1] + [",".join(sorted(tags))])
+        pieces[-1] = EditTags(pieces[-1])
+        value = " ".join(pieces)
+      elif key == "ro.build.tags":
+        value = EditTags(value)
+      line = key + "=" + value
     if line != original_line:
       print "  replace: ", original_line
       print "     with: ", line
@@ -350,7 +294,6 @@
 
   apk_key_map = GetApkCerts(input_zip)
   CheckAllApksSigned(input_zip, apk_key_map)
-  CheckSharedUserIdsConsistent(input_zip, apk_key_map)
 
   key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
   SignApks(input_zip, output_zip, apk_key_map, key_passwords)