Merge "Use shell variable to eliminate $(eval) in commands."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 70a053f..62a3a09 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -96,6 +96,14 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/librtp_jni_intermediates)
 
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/android-info.txt)
+$(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 $(PRODUCT_OUT)/data/app/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/JAVA_LIBRARIES/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 14de987..a81c981 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -16,10 +16,16 @@
 # 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 the same dest"
+#$(1): the src:dest pair
+define check-product-copy-files
+$(if $(filter %.apk, $(1)),$(error \
+    Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))
+endef
 unique_product_copy_files_destinations :=
 $(foreach cf,$(PRODUCT_COPY_FILES), \
     $(eval _src := $(call word-colon,1,$(cf))) \
     $(eval _dest := $(call word-colon,2,$(cf))) \
+    $(call check-product-copy-files,$(cf)) \
     $(if $(filter $(unique_product_copy_files_destinations),$(_dest)),, \
         $(eval _fulldest := $(call append-path,$(PRODUCT_OUT),$(_dest))) \
         $(eval $(call copy-one-file,$(_src),$(_fulldest))) \
@@ -71,9 +77,16 @@
 ifeq ($(TARGET_BUILD_TYPE),debug)
   BUILD_VERSION_TAGS += debug
 endif
-# Apps are always signed with test keys, and may be re-signed in a post-build
-# step.  If that happens, the "test-keys" tag will be removed by that step.
+# The "test-keys" tag marks builds signed with the old test keys,
+# which are available in the SDK.  "dev-keys" marks builds signed with
+# non-default dev keys (usually private keys from a vendor directory).
+# Both of these tags will be removed and replaced with "release-keys"
+# when the target-files is signed in a post-build step.
+ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
 BUILD_VERSION_TAGS += test-keys
+else
+BUILD_VERSION_TAGS += dev-keys
+endif
 BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
 
 # A human-readable string that descibes this build in detail.
@@ -234,6 +247,8 @@
 	         private_key=""' >> $@;,\
 	    echo 'name="$(p).apk" certificate="$(PACKAGES.$(p).CERTIFICATE)" \
 	         private_key="$(PACKAGES.$(p).PRIVATE_KEY)"' >> $@;))
+	# In case $(PACKAGES) is empty.
+	$(hide) touch $@
 
 .PHONY: apkcerts-list
 apkcerts-list: $(APKCERTS_FILE)
@@ -258,11 +273,11 @@
 
 # -----------------------------------------------------------------
 
-# The test key is used to sign this package, and as the key required
+# The dev key is used to sign this package, and as the key required
 # for future OTA packages installed by this system.  Actual product
 # deliverables will be re-signed by hand.  We expect this file to
 # exist with the suffixes ".x509.pem" and ".pk8".
-DEFAULT_KEY_CERT_PAIR := $(SRC_TARGET_DIR)/product/security/testkey
+DEFAULT_KEY_CERT_PAIR := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
 
 
 # Rules that need to be present for the all targets, even
@@ -649,9 +664,9 @@
 endif
 
 # Keys authorized to sign OTA packages this build will accept.  The
-# build always uses test-keys for this; release packaging tools will
+# build always uses dev-keys for this; release packaging tools will
 # substitute other keys for this one.
-OTA_PUBLIC_KEYS := $(SRC_TARGET_DIR)/product/security/testkey.x509.pem
+OTA_PUBLIC_KEYS := $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem
 
 # Generate a file containing the keys that will be read by the
 # recovery binary.
@@ -723,9 +738,6 @@
 # -----------------------------------------------------------------
 # system image
 #
-systemimage_intermediates := \
-	$(call intermediates-dir-for,PACKAGING,systemimage)
-BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
 
 INTERNAL_SYSTEMIMAGE_FILES := $(filter $(TARGET_OUT)/%, \
 	$(ALL_PREBUILT) \
@@ -733,6 +745,33 @@
 	$(ALL_GENERATED_SOURCES) \
 	$(ALL_DEFAULT_INSTALLED_MODULES))
 
+FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)
+# -----------------------------------------------------------------
+# installed file list
+# Depending on anything that $(BUILT_SYSTEMIMAGE) depends on.
+# We put installed-files.txt ahead of image itself in the dependency graph
+# so that we can get the size stat even if the build fails due to too large
+# system image.
+INSTALLED_FILES_FILE := $(PRODUCT_OUT)/installed-files.txt
+$(INSTALLED_FILES_FILE): $(FULL_SYSTEMIMAGE_DEPS)
+	@echo Installed file list: $@
+	@mkdir -p $(dir $@)
+	@rm -f $@
+	$(hide) build/tools/fileslist.py $(TARGET_OUT) > $@
+
+.PHONY: installed-file-list
+installed-file-list: $(INSTALLED_FILES_FILE)
+ifneq ($(filter sdk win_sdk,$(MAKECMDGOALS)),)
+$(call dist-for-goals, sdk win_sdk, $(INSTALLED_FILES_FILE))
+endif
+ifneq ($(filter sdk_addon,$(MAKECMDGOALS)),)
+$(call dist-for-goals, sdk_addon, $(INSTALLED_FILES_FILE))
+endif
+
+systemimage_intermediates := \
+	$(call intermediates-dir-for,PACKAGING,systemimage)
+BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
+
 ifeq ($(INTERNAL_USERIMAGES_USE_EXT),true)
 ## generate an ext image
 # $(1): output file
@@ -752,7 +791,7 @@
 endef
 endif # INTERNAL_USERIMAGES_USE_EXT
 
-$(BUILT_SYSTEMIMAGE): $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)
+$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE)
 	$(call build-systemimage-target,$@)
 
 INSTALLED_SYSTEMIMAGE := $(PRODUCT_OUT)/system.img
@@ -964,6 +1003,7 @@
 	$(call intermediates-dir-for,EXECUTABLES,applypatch)/applypatch \
 	$(call intermediates-dir-for,EXECUTABLES,applypatch_static)/applypatch_static \
 	$(call intermediates-dir-for,EXECUTABLES,check_prereq)/check_prereq \
+	$(call intermediates-dir-for,EXECUTABLES,sqlite3)/sqlite3 \
 	$(call intermediates-dir-for,EXECUTABLES,updater)/updater
 $(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)
 
@@ -1073,14 +1113,17 @@
 ifdef INTERNAL_USERIMAGES_SPARSE_EXT_FLAG
 	$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(zip_root)/META/misc_info.txt
 endif
+	$(hide) echo "default_system_dev_certificate=$(DEFAULT_SYSTEM_DEV_CERTIFICATE)" >> $(zip_root)/META/misc_info.txt
 ifdef PRODUCT_EXTRA_RECOVERY_KEYS
 	$(hide) echo "extra_recovery_keys=$(PRODUCT_EXTRA_RECOVERY_KEYS)" >> $(zip_root)/META/misc_info.txt
 endif
 	@# Zip everything up, preserving symlinks
 	$(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .)
-	@# Run fs_config on all the system files in the zip, and save the output
-	$(hide) zipinfo -1 $@ | awk -F/ 'BEGIN { OFS="/" } /^SYSTEM\// {$$1 = "system"; print}' | $(HOST_OUT_EXECUTABLES)/fs_config > $(zip_root)/META/filesystem_config.txt
-	$(hide) (cd $(zip_root) && zip -q ../$(notdir $@) META/filesystem_config.txt)
+	@# Run fs_config on all the system, boot ramdisk, and recovery ramdisk files in the zip, and save the output
+	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config > $(zip_root)/META/filesystem_config.txt
+	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config > $(zip_root)/META/boot_filesystem_config.txt
+	$(hide) zipinfo -1 $@ | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config > $(zip_root)/META/recovery_filesystem_config.txt
+	$(hide) (cd $(zip_root) && zip -q ../$(notdir $@) META/*filesystem_config.txt)
 
 
 target-files-package: $(BUILT_TARGET_FILES_PACKAGE)
@@ -1148,26 +1191,6 @@
 endif    # TARGET_PRODUCT != sdk
 
 # -----------------------------------------------------------------
-# installed file list
-# Depending on $(INSTALLED_SYSTEMIMAGE) ensures that it
-# gets the DexOpt one if we're doing that.
-INSTALLED_FILES_FILE := $(PRODUCT_OUT)/installed-files.txt
-$(INSTALLED_FILES_FILE): $(INSTALLED_SYSTEMIMAGE)
-	@echo Installed file list: $@
-	@mkdir -p $(dir $@)
-	@rm -f $@
-	$(hide) build/tools/fileslist.py $(TARGET_OUT) $(TARGET_OUT_DATA) > $@
-
-.PHONY: installed-file-list
-installed-file-list: $(INSTALLED_FILES_FILE)
-ifneq ($(filter sdk win_sdk,$(MAKECMDGOALS)),)
-$(call dist-for-goals, sdk win_sdk, $(INSTALLED_FILES_FILE))
-endif
-ifneq ($(filter sdk_addon,$(MAKECMDGOALS)),)
-$(call dist-for-goals, sdk_addon, $(INSTALLED_FILES_FILE))
-endif
-
-# -----------------------------------------------------------------
 # A zip of the tests that are built when running "make tests".
 # This is very similar to BUILT_TARGET_FILES_PACKAGE, but we
 # only grab SYSTEM and DATA, and it's called "*-tests-*.zip".
@@ -1387,12 +1410,6 @@
 #
 #SDK_GNU_ERROR := true
 
-ifeq ($(HOST_OS),darwin)
-HOST_STRIP_SDK_LLVM := strip
-else
-HOST_STRIP_SDK_LLVM := strip --strip-all
-endif
-
 $(INTERNAL_SDK_TARGET): $(deps)
 	@echo "Package SDK: $@"
 	$(hide) rm -rf $(PRIVATE_DIR) $@
@@ -1416,14 +1433,12 @@
 			-v "OUT_DIR=$(OUT_DIR)" \
 			-v "TARGET_ARCH=$(TARGET_ARCH)" \
 			-v "TARGET_CPU_ABI=$(TARGET_CPU_ABI)" \
+			-v "DLL_EXTENSION=$(HOST_SHLIB_SUFFIX)" \
 			-o $(PRIVATE_DIR) && \
 		cp -f $(target_notice_file_txt) \
-				$(PRIVATE_DIR)/platforms/android-$(PLATFORM_VERSION)/images/$(TARGET_CPU_ABI)/NOTICE.txt && \
+				$(PRIVATE_DIR)/system-images/android-$(PLATFORM_VERSION)/$(TARGET_CPU_ABI)/NOTICE.txt && \
 		cp -f $(tools_notice_file_txt) $(PRIVATE_DIR)/tools/NOTICE.txt && \
 		cp -f $(tools_notice_file_txt) $(PRIVATE_DIR)/platform-tools/NOTICE.txt && \
-		for f in $(PRIVATE_DIR)/platform-tools/llvm-rs-cc-* ; do \
-			if [ -f "$$f" ]; then $(HOST_STRIP_SDK_LLVM) "$$f"; fi; \
-		done && \
 		HOST_OUT_EXECUTABLES=$(HOST_OUT_EXECUTABLES) HOST_OS=$(HOST_OS) \
 			development/build/tools/sdk_clean.sh $(PRIVATE_DIR) && \
 		chmod -R ug+rwX $(PRIVATE_DIR) && \
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 635a256..e18b6ec 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -122,12 +122,16 @@
   LOCAL_MODULE_TAGS := $(sort $(LOCAL_MODULE_TAGS) user)
 endif
 
-# The definition of should-install-to-system will be different depending
-# on which goal (e.g., sdk or just droid) is being built.
 ifdef LOCAL_IS_HOST_MODULE
-  use_data :=
+  partition_tag :=
 else
-  use_data := $(if $(call should-install-to-system,$(LOCAL_MODULE_TAGS)),,_DATA)
+ifeq (true,$(LOCAL_PROPRIETARY_MODULE))
+  partition_tag := _VENDOR
+else
+  # The definition of should-install-to-system will be different depending
+  # on which goal (e.g., sdk or just droid) is being built.
+  partition_tag := $(if $(call should-install-to-system,$(LOCAL_MODULE_TAGS)),,_DATA)
+endif
 endif
 
 LOCAL_MODULE_CLASS := $(strip $(LOCAL_MODULE_CLASS))
@@ -145,7 +149,7 @@
 
 LOCAL_MODULE_PATH := $(strip $(LOCAL_MODULE_PATH))
 ifeq ($(LOCAL_MODULE_PATH),)
-  LOCAL_MODULE_PATH := $($(my_prefix)OUT$(use_data)_$(LOCAL_MODULE_CLASS))
+  LOCAL_MODULE_PATH := $($(my_prefix)OUT$(partition_tag)_$(LOCAL_MODULE_CLASS))
   ifeq ($(strip $(LOCAL_MODULE_PATH)),)
     $(error $(LOCAL_PATH): unhandled LOCAL_MODULE_CLASS "$(LOCAL_MODULE_CLASS)")
   endif
@@ -194,14 +198,8 @@
 LOCAL_BUILT_MODULE := $(built_module_path)/$(LOCAL_BUILT_MODULE_STEM)
 built_module_path :=
 
-# LOCAL_UNINSTALLABLE_MODULE is only allowed to be used by the
-# internal STATIC_LIBRARIES build files.
 LOCAL_UNINSTALLABLE_MODULE := $(strip $(LOCAL_UNINSTALLABLE_MODULE))
-ifdef LOCAL_UNINSTALLABLE_MODULE
-  ifeq (,$(filter $(LOCAL_MODULE_CLASS),JAVA_LIBRARIES STATIC_LIBRARIES))
-    $(error $(LOCAL_PATH): Illegal use of LOCAL_UNINSTALLABLE_MODULE)
-  endif
-else
+ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
   LOCAL_INSTALLED_MODULE := $(LOCAL_MODULE_PATH)/$(LOCAL_INSTALLED_MODULE_STEM)
 endif
 
diff --git a/core/binary.mk b/core/binary.mk
index dadfd5e..e488200 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -56,13 +56,70 @@
     endif
   else
     # LOCAL_NDK_STL_VARIANT is gnustl_static
-    my_ndk_stl_include_path := $(my_ndk_source_root)/cxx-stl/gnu-libstdc++/include
+    my_ndk_stl_include_path := $(my_ndk_source_root)/cxx-stl/gnu-libstdc++/libs/$(TARGET_CPU_ABI)/include \
+                               $(my_ndk_source_root)/cxx-stl/gnu-libstdc++/include
     my_ndk_stl_static_lib := $(my_ndk_source_root)/cxx-stl/gnu-libstdc++/libs/$(TARGET_CPU_ABI)/libstdc++.a
   endif
   endif
-
 endif
 
+##################################################
+# Compute the dependency of the shared libraries
+##################################################
+# On the target, we compile with -nostdlib, so we must add in the
+# default system shared libraries, unless they have requested not
+# to by supplying a LOCAL_SYSTEM_SHARED_LIBRARIES value.  One would
+# supply that, for example, when building libc itself.
+ifdef LOCAL_IS_HOST_MODULE
+  ifeq ($(LOCAL_SYSTEM_SHARED_LIBRARIES),none)
+      LOCAL_SYSTEM_SHARED_LIBRARIES :=
+  endif
+else
+  ifeq ($(LOCAL_SYSTEM_SHARED_LIBRARIES),none)
+      LOCAL_SYSTEM_SHARED_LIBRARIES := $(TARGET_DEFAULT_SYSTEM_SHARED_LIBRARIES)
+  endif
+endif
+
+# Logging used to be part of libcutils (target) and libutils (sim);
+# hack modules that use those other libs to also include liblog.
+# All of this complexity is to make sure that liblog only appears
+# once, and appears just before libcutils or libutils on the link
+# line.
+# TODO: remove this hack and change all modules to use liblog
+# when necessary.
+define insert-liblog
+  $(if $(filter liblog,$(1)),$(1), \
+    $(if $(filter libcutils,$(1)), \
+      $(patsubst libcutils,liblog libcutils,$(1)) \
+     , \
+      $(patsubst libutils,liblog libutils,$(1)) \
+     ) \
+   )
+endef
+ifneq (,$(filter libcutils libutils,$(LOCAL_SHARED_LIBRARIES)))
+  LOCAL_SHARED_LIBRARIES := $(call insert-liblog,$(LOCAL_SHARED_LIBRARIES))
+endif
+ifneq (,$(filter libcutils libutils,$(LOCAL_STATIC_LIBRARIES)))
+  LOCAL_STATIC_LIBRARIES := $(call insert-liblog,$(LOCAL_STATIC_LIBRARIES))
+endif
+ifneq (,$(filter libcutils libutils,$(LOCAL_WHOLE_STATIC_LIBRARIES)))
+  LOCAL_WHOLE_STATIC_LIBRARIES := $(call insert-liblog,$(LOCAL_WHOLE_STATIC_LIBRARIES))
+endif
+
+ifdef LOCAL_NDK_VERSION
+  # Get the list of INSTALLED libraries as module names.
+  # We can not compute the full path of the LOCAL_SHARED_LIBRARIES for
+  # they may cusomize their install path with LOCAL_MODULE_PATH
+  installed_shared_library_module_names := \
+      $(LOCAL_SHARED_LIBRARIES)
+else
+  installed_shared_library_module_names := \
+      $(LOCAL_SYSTEM_SHARED_LIBRARIES) $(LOCAL_SHARED_LIBRARIES)
+endif
+# The real dependency will be added after all Android.mks are loaded and the install paths
+# of the shared libraries are determined.
+LOCAL_REQUIRED_MODULES += $(installed_shared_library_module_names)
+
 #######################################
 include $(BUILD_SYSTEM)/base_rules.mk
 #######################################
@@ -445,47 +502,7 @@
 
 ###########################################################
 # Standard library handling.
-#
-# On the target, we compile with -nostdlib, so we must add in the
-# default system shared libraries, unless they have requested not
-# to by supplying a LOCAL_SYSTEM_SHARED_LIBRARIES value.  One would
-# supply that, for example, when building libc itself.
 ###########################################################
-ifdef LOCAL_IS_HOST_MODULE
-  ifeq ($(LOCAL_SYSTEM_SHARED_LIBRARIES),none)
-    LOCAL_SYSTEM_SHARED_LIBRARIES :=
-  endif
-else
-  ifeq ($(LOCAL_SYSTEM_SHARED_LIBRARIES),none)
-    LOCAL_SYSTEM_SHARED_LIBRARIES := $($(my_prefix)DEFAULT_SYSTEM_SHARED_LIBRARIES)
-  endif
-endif
-
-# Logging used to be part of libcutils (target) and libutils (sim);
-# hack modules that use those other libs to also include liblog.
-# All of this complexity is to make sure that liblog only appears
-# once, and appears just before libcutils or libutils on the link
-# line.
-# TODO: remove this hack and change all modules to use liblog
-# when necessary.
-define insert-liblog
-  $(if $(filter liblog,$(1)),$(1), \
-    $(if $(filter libcutils,$(1)), \
-      $(patsubst libcutils,liblog libcutils,$(1)) \
-     , \
-      $(patsubst libutils,liblog libutils,$(1)) \
-     ) \
-   )
-endef
-ifneq (,$(filter libcutils libutils,$(LOCAL_SHARED_LIBRARIES)))
-  LOCAL_SHARED_LIBRARIES := $(call insert-liblog,$(LOCAL_SHARED_LIBRARIES))
-endif
-ifneq (,$(filter libcutils libutils,$(LOCAL_STATIC_LIBRARIES)))
-  LOCAL_STATIC_LIBRARIES := $(call insert-liblog,$(LOCAL_STATIC_LIBRARIES))
-endif
-ifneq (,$(filter libcutils libutils,$(LOCAL_WHOLE_STATIC_LIBRARIES)))
-  LOCAL_WHOLE_STATIC_LIBRARIES := $(call insert-liblog,$(LOCAL_WHOLE_STATIC_LIBRARIES))
-endif
 
 ###########################################################
 # The list of libraries that this module will link against are in
@@ -522,12 +539,6 @@
       $(addsuffix $(so_suffix), \
         $(LOCAL_SHARED_LIBRARIES)))
 
-# Get the list of INSTALLED libraries.  Strip off the various
-# intermediates directories and point to the common lib dirs.
-installed_shared_libraries := \
-    $(addprefix $($(my_prefix)OUT_SHARED_LIBRARIES)/, \
-      $(notdir $(built_shared_libraries)))
-
 my_system_shared_libraries_fullpath := \
     $(my_ndk_stl_shared_lib_fullpath) \
     $(addprefix $(my_ndk_version_root)/usr/lib/, \
@@ -541,10 +552,6 @@
     $(addprefix $($(my_prefix)OUT_INTERMEDIATE_LIBRARIES)/, \
       $(addsuffix $(so_suffix), \
         $(LOCAL_SHARED_LIBRARIES)))
-
-installed_shared_libraries := \
-    $(addprefix $($(my_prefix)OUT_SHARED_LIBRARIES)/, \
-      $(notdir $(built_shared_libraries)))
 endif
 
 built_static_libraries := \
@@ -605,12 +612,6 @@
     $(built_static_libraries) \
     $(built_whole_libraries)
 
-# Make LOCAL_INSTALLED_MODULE depend on the installed versions of the
-# libraries so they get installed along with it.  We don't need to
-# rebuild it when installing it, though, so this can be an order-only
-# dependency.
-$(LOCAL_INSTALLED_MODULE): | $(installed_shared_libraries)
-
 # Also depend on the notice files for any static libraries that
 # are linked into this module.  This will force them to be installed
 # when this module is.
diff --git a/core/build_id.mk b/core/build_id.mk
index 40bb35d..6da16e0 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 := MASTER
+BUILD_ID := ICS_MR0
 
 # DISPLAY_BUILD_NUMBER should only be set for development branches,
 # If set, the BUILD_NUMBER (cl) is appended to the BUILD_ID for
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index bc085f5..643a138 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -93,6 +93,7 @@
 LOCAL_DX_FLAGS:=
 LOCAL_CERTIFICATE:=
 LOCAL_SDK_VERSION:=
+LOCAL_SDK_RES_VERSION:=
 LOCAL_NDK_VERSION:=
 LOCAL_NDK_STL_VARIANT:=
 LOCAL_NO_EMMA_INSTRUMENT:=
@@ -104,12 +105,15 @@
 LOCAL_WARNINGS_ENABLE:=
 LOCAL_MANIFEST_FILE:=
 LOCAL_RENDERSCRIPT_INCLUDES:=
+LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE:=
 LOCAL_RENDERSCRIPT_CC:=
+LOCAL_RENDERSCRIPT_TARGET_API:=
 LOCAL_BUILD_HOST_DEX:=
 LOCAL_DEX_PREOPT:=
 LOCAL_PROTOC_OPTIMIZE_TYPE:= # lite(default),micro,full
 LOCAL_PROTOC_FLAGS:=
 LOCAL_NO_CRT:=
+LOCAL_PROPRIETARY_MODULE:=
 
 # Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to
 # iterate over thousands of entries every time.
diff --git a/core/combo/TARGET_linux-x86.mk b/core/combo/TARGET_linux-x86.mk
index 0d05dd2..0fb6edc 100644
--- a/core/combo/TARGET_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -92,10 +92,6 @@
 #TARGET_GLOBAL_CFLAGS += \
 #			-DNDEBUG
 
-
-# Fix this after ssp.c is fixed for x86
-# TARGET_GLOBAL_CFLAGS += -fstack-protector
-
 TARGET_GLOBAL_CPPFLAGS += \
 			-fno-use-cxa-atexit
 
diff --git a/core/config.mk b/core/config.mk
index c4f08fd..41e60ea 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -288,6 +288,13 @@
 APICHECK_CLASSPATH := $(APICHECK_CLASSPATH):$(HOST_OUT_JAVA_LIBRARIES)/jsilver$(COMMON_JAVA_PACKAGE_SUFFIX)
 APICHECK_COMMAND := $(APICHECK) -JXmx1024m -J"classpath $(APICHECK_CLASSPATH)"
 
+# The default key if not set as LOCAL_CERTIFICATE
+ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
+  DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE)
+else
+  DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
+endif
+
 # ###############################################################
 # Set up final options.
 # ###############################################################
diff --git a/core/definitions.mk b/core/definitions.mk
index 9bbc939..99682fd 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -312,7 +312,7 @@
 
 define find-subdir-assets
 $(if $(1),$(patsubst ./%,%, \
-	$(shell if [ -d $(1) ] ; then cd $(1) ; find ./ -type f -and -not -type l ; fi)), \
+	$(shell if [ -d $(1) ] ; then cd $(1) ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi)), \
 	$(warning Empty argument supplied to find-subdir-assets) \
 )
 endef
@@ -801,6 +801,7 @@
   -p $(PRIVATE_RS_OUTPUT_DIR)/src \
   -d $(PRIVATE_RS_OUTPUT_DIR) \
   -a $@ -MD \
+  $(addprefix -target-api , $(PRIVATE_RS_TARGET_API)) \
   $(foreach inc,$(PRIVATE_RS_INCLUDES),$(addprefix -I , $(inc))) \
   $(PRIVATE_RS_SOURCE_FILES)
 #$(hide) $(LLVM_RS_LINK) \
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 9f44c32..b801ac2 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -4,7 +4,7 @@
 ####################################
 
 # TODO: replace it with device's BOOTCLASSPATH
-DEXPREOPT_BOOT_JARS := core:apache-xml:bouncycastle:ext:framework:android.policy:services:core-junit
+DEXPREOPT_BOOT_JARS := core:core-junit:bouncycastle:ext:framework:android.policy:services:apache-xml:filterfw
 DEXPREOPT_BOOT_JARS_MODULES := $(subst :, ,$(DEXPREOPT_BOOT_JARS))
 
 DEXPREOPT_BUILD_DIR := $(OUT_DIR)
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 016560a..c3ae3b0 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -206,6 +206,14 @@
 TARGET_OUT_DATA_STATIC_LIBRARIES:= $(TARGET_OUT_STATIC_LIBRARIES)
 TARGET_OUT_DATA_NATIVE_TESTS := $(TARGET_OUT_DATA)/nativetest
 
+TARGET_OUT_VENDOR := $(PRODUCT_OUT)/system/vendor
+TARGET_OUT_VENDOR_EXECUTABLES:= $(TARGET_OUT_VENDOR)/bin
+TARGET_OUT_VENDOR_OPTIONAL_EXECUTABLES:= $(TARGET_OUT_VENDOR)/xbin
+TARGET_OUT_VENDOR_SHARED_LIBRARIES:= $(TARGET_OUT_VENDOR)/lib
+TARGET_OUT_VENDOR_JAVA_LIBRARIES:= $(TARGET_OUT_VENDOR)/framework
+TARGET_OUT_VENDOR_APPS:= $(TARGET_OUT_VENDOR)/app
+TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc
+
 TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols
 TARGET_OUT_EXECUTABLES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/bin
 TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib
diff --git a/core/java.mk b/core/java.mk
index 5324e7d..1cde62b 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -29,7 +29,7 @@
   endif
 else
   ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-    LOCAL_JAVA_LIBRARIES := core core-junit ext framework $(LOCAL_JAVA_LIBRARIES)
+    LOCAL_JAVA_LIBRARIES := core core-junit ext framework filterfw $(LOCAL_JAVA_LIBRARIES)
   endif
 endif
 
@@ -135,6 +135,23 @@
 RenderScript_file_stamp := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/RenderScript.stamp
 renderscript_intermediate := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/renderscript
 
+renderscript_target_api :=
+
+ifneq (,$(LOCAL_RENDERSCRIPT_TARGET_API))
+renderscript_target_api := $(LOCAL_RENDERSCRIPT_TARGET_API)
+else
+ifneq (,$(LOCAL_SDK_VERSION))
+# Set target-api for LOCAL_SDK_VERSIONs other than current.
+ifneq (,$(filter-out current, $(LOCAL_SDK_VERSION)))
+renderscript_target_api := $(LOCAL_SDK_VERSION)
+endif
+endif  # LOCAL_SDK_VERSION is set
+endif  # LOCAL_RENDERSCRIPT_TARGET_API is set
+
+ifeq ($(LOCAL_RENDERSCRIPT_CC),)
+LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
+endif
+
 # prepend the RenderScript system include path
 ifneq ($(filter-out current,$(LOCAL_SDK_VERSION)),)
 LOCAL_RENDERSCRIPT_INCLUDES := \
@@ -143,13 +160,13 @@
     $(LOCAL_RENDERSCRIPT_INCLUDES)
 else
 LOCAL_RENDERSCRIPT_INCLUDES := \
-     $(TOPDIR)external/clang/lib/Headers \
-     $(TOPDIR)frameworks/base/libs/rs/scriptc \
-     $(LOCAL_RENDERSCRIPT_INCLUDES)
+    $(TOPDIR)external/clang/lib/Headers \
+    $(TOPDIR)frameworks/base/libs/rs/scriptc \
+    $(LOCAL_RENDERSCRIPT_INCLUDES)
 endif
 
-ifeq ($(LOCAL_RENDERSCRIPT_CC),)
-LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
+ifneq ($(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE),)
+LOCAL_RENDERSCRIPT_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE)
 endif
 
 $(RenderScript_file_stamp): PRIVATE_RS_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES)
@@ -158,6 +175,7 @@
 # By putting the generated java files into $(LOCAL_INTERMEDIATE_SOURCE_DIR), they will be
 # automatically found by the java compiling function transform-java-to-classes.jar.
 $(RenderScript_file_stamp): PRIVATE_RS_OUTPUT_DIR := $(renderscript_intermediate)
+$(RenderScript_file_stamp): PRIVATE_RS_TARGET_API := $(renderscript_target_api)
 $(RenderScript_file_stamp): $(renderscript_sources_fullpath) $(LOCAL_RENDERSCRIPT_CC)
 	$(transform-renderscripts-to-java-and-bc)
 
@@ -334,23 +352,6 @@
 # Override PRIVATE_INTERMEDIATES_DIR so that install-dex-debug
 # will work even when intermediates != intermediates.COMMON.
 $(built_dex_intermediate): PRIVATE_INTERMEDIATES_DIR := $(intermediates.COMMON)
-
-ifeq (,$(filter --target-api=%, $(LOCAL_DX_FLAGS)))
-possible_dx_target_api :=
-ifneq (,$(LOCAL_MANIFEST_FILE))
-  manifest_min_sdk_version := \
-      $(shell grep -o 'android:minSdkVersion="[0-9]\{1,\}"' $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE) 2>/dev/null)
-  possible_dx_target_api := $(patsubst android:minSdkVersion="%",%,$(firstword $(manifest_min_sdk_version)))
-endif
-ifeq (,$(possible_dx_target_api))
-# In case minSdkVersion is not available, eg shared library built against SDK,
-# LOCAL_SDK_VERSION may be a good guess
-ifneq (,$(filter-out current, $(LOCAL_SDK_VERSION)))
-  possible_dx_target_api := $(LOCAL_SDK_VERSION)
-endif
-endif
-LOCAL_DX_FLAGS += $(addprefix --target-api=, $(possible_dx_target_api))
-endif # --target-api not defined in LOCAL_DX_FLAGS
 $(built_dex_intermediate): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
 # If you instrument class files that have local variable debug information in
 # them emma does not correctly maintain the local variable table.
diff --git a/core/main.mk b/core/main.mk
index 959cd83..5f01238 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -113,14 +113,17 @@
 
 
 # Check for the correct version of java
-java_version := $(shell java -version 2>&1 | head -n 1 | grep '[ "]1\.6[\. "$$]')
+java_version := $(shell java -version 2>&1 | head -n 1 | grep '^java .*[ "]1\.6[\. "$$]')
+ifneq ($(shell java -version 2>&1 | grep -i openjdk),)
+java_version :=
+endif
 ifeq ($(strip $(java_version)),)
 $(info ************************************************************)
 $(info You are attempting to build with the incorrect version)
 $(info of java.)
 $(info $(space))
 $(info Your version is: $(shell java -version 2>&1 | head -n 1).)
-$(info The correct version is: 1.6.)
+$(info The correct version is: Java SE 1.6.)
 $(info $(space))
 $(info Please follow the machine setup instructions at)
 $(info $(space)$(space)$(space)$(space)http://source.android.com/source/download.html)
@@ -401,6 +404,7 @@
 	development/host \
 	development/tools/etc1tool \
 	development/tools/line_endings \
+	development/tools/emulator/opengl \
 	external/clang \
 	external/easymock \
 	external/expat \
@@ -411,6 +415,7 @@
 	external/zlib \
 	frameworks/base \
 	frameworks/compile \
+	sdk/avdlauncher \
 	sdk/emulator/mksdcard \
 	sdk/sdklauncher \
 	system/core/adb \
@@ -429,6 +434,7 @@
 	sdk/archquery \
 	sdk/androidprefs \
 	sdk/apkbuilder \
+	sdk/assetstudio \
 	sdk/common \
 	sdk/ddms \
 	sdk/hierarchyviewer2 \
@@ -437,9 +443,11 @@
 	sdk/layoutlib_api \
 	sdk/layoutopt \
 	sdk/ninepatch \
+	sdk/rule_api \
 	sdk/sdkstats \
 	sdk/sdkmanager \
 	sdk/swtmenubar \
+	sdk/traceview \
 	development/apps \
 	development/tools/mkstubs \
 	packages
@@ -466,6 +474,7 @@
 	build/libs \
 	build/target \
 	build/tools/acp \
+	external/mksh \
 	external/yaffs2 \
 	external/zlib
 else	# !BUILD_TINY_ANDROID
@@ -655,6 +664,11 @@
   $(info Removing from sdk:)$(foreach d,$(target_gnu_MODULES),$(info : $(d)))
   modules_to_install := \
               $(filter-out $(target_gnu_MODULES),$(modules_to_install))
+
+  # Ensure every module listed in PRODUCT_PACKAGES gets something installed
+  $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES), \
+      $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
+          $(error Module '$(m)' in PRODUCT_PACKAGES has nothing to install!)))
 endif
 
 
diff --git a/core/multi_prebuilt.mk b/core/multi_prebuilt.mk
index 7602673..50a4a38 100644
--- a/core/multi_prebuilt.mk
+++ b/core/multi_prebuilt.mk
@@ -22,6 +22,7 @@
 prebuilt_static_java_libraries := $(LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES)
 prebuilt_is_host := $(LOCAL_IS_HOST_MODULE)
 prebuilt_module_tags := $(LOCAL_MODULE_TAGS)
+prebuilt_strip_module := $(LOCAL_STRIP_MODULE)
 
 
 ifndef multi_prebuilt_once
@@ -34,6 +35,7 @@
 # $(5): OVERRIDE_BUILT_MODULE_PATH
 # $(6): UNINSTALLABLE_MODULE
 # $(7): BUILT_MODULE_STEM
+# $(8): LOCAL_STRIP_MODULE
 #
 # Elements in the file list may be bare filenames,
 # or of the form "<modulename>:<filename>".
@@ -65,6 +67,8 @@
     $(eval LOCAL_BUILT_MODULE_STEM := $(notdir $(LOCAL_SRC_FILES))) \
    ) \
   $(eval LOCAL_MODULE_SUFFIX := $(suffix $(LOCAL_SRC_FILES))) \
+  $(if $(filter user,$(TARGET_BUILD_VARIANT)), \
+    $(eval LOCAL_STRIP_MODULE := $(8))) \
   $(eval include $(BUILD_PREBUILT)) \
  )
 endef
@@ -85,7 +89,10 @@
     $(prebuilt_is_host), \
     SHARED_LIBRARIES, \
     $(prebuilt_module_tags), \
-    $($(if $(prebuilt_is_host),HOST,TARGET)_OUT_INTERMEDIATE_LIBRARIES))
+    $($(if $(prebuilt_is_host),HOST,TARGET)_OUT_INTERMEDIATE_LIBRARIES), \
+    , \
+    , \
+    $(prebuilt_strip_module))
 
 $(call auto-prebuilt-boilerplate, \
     $(prebuilt_executables), \
diff --git a/core/package.mk b/core/package.mk
index e79059a..398e487 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -161,6 +161,11 @@
 include $(BUILD_SYSTEM)/java.mk
 #################################
 
+LOCAL_SDK_RES_VERSION:=$(strip $(LOCAL_SDK_RES_VERSION))
+ifeq ($(LOCAL_SDK_RES_VERSION),)
+  LOCAL_SDK_RES_VERSION:=$(LOCAL_SDK_VERSION)
+endif
+
 full_android_manifest := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE)
 $(LOCAL_INTERMEDIATE_TARGETS): \
     PRIVATE_ANDROID_MANIFEST := $(full_android_manifest)
@@ -250,12 +255,12 @@
 # Most packages should link against the resources defined by framework-res.
 # Even if they don't have their own resources, they may use framework
 # resources.
-ifneq ($(filter-out current,$(LOCAL_SDK_VERSION)),)
+ifneq ($(filter-out current,$(LOCAL_SDK_RES_VERSION)),)
 # for released sdk versions, the platform resources were built into android.jar.
 framework_res_package_export := \
-    $(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_VERSION)/android.jar
+    $(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar
 framework_res_package_export_deps := $(framework_res_package_export)
-else # LOCAL_SDK_VERSION
+else # LOCAL_SDK_RES_VERSION
 framework_res_package_export := \
     $(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
 # We can't depend directly on the export.apk file; it won't get its
@@ -263,7 +268,7 @@
 # corresponding R.stamp file, which lists the export.apk as a dependency.
 framework_res_package_export_deps := \
     $(dir $(framework_res_package_export))src/R.stamp
-endif # LOCAL_SDK_VERSION
+endif # LOCAL_SDK_RES_VERSION
 $(R_file_stamp): $(framework_res_package_export_deps)
 $(LOCAL_INTERMEDIATE_TARGETS): \
     PRIVATE_AAPT_INCLUDES := $(framework_res_package_export)
@@ -299,20 +304,20 @@
 # Secure release builds will have their packages signed after the fact,
 # so it's ok for these private keys to be in the clear.
 ifeq ($(LOCAL_CERTIFICATE),)
-    LOCAL_CERTIFICATE := testkey
+    LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
 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
+  # default devkey, apply predexopt, but then expect the final .apk
   # (after dexopting) to be signed by an outside tool.
-  LOCAL_CERTIFICATE := testkey
+  LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
   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)
+    LOCAL_CERTIFICATE := $(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))$(LOCAL_CERTIFICATE)
 endif
 private_key := $(LOCAL_CERTIFICATE).pk8
 certificate := $(LOCAL_CERTIFICATE).x509.pem
diff --git a/core/prebuilt.mk b/core/prebuilt.mk
index 07ecf64..54a7fa9 100644
--- a/core/prebuilt.mk
+++ b/core/prebuilt.mk
@@ -16,14 +16,15 @@
 $(error dont use LOCAL_PREBUILT_JAVA_LIBRARIES anymore LOCAL_PATH=$(LOCAL_PATH))
 endif
 
-ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
-ifeq (true,$(WITH_DEXPREOPT))
-ifeq (,$(TARGET_BUILD_APPS))
-ifndef LOCAL_DEX_PREOPT
-LOCAL_DEX_PREOPT := true
+ifdef LOCAL_IS_HOST_MODULE
+  my_prefix:=HOST_
+else
+  my_prefix:=TARGET_
 endif
-endif
-endif
+ifeq (SHARED_LIBRARIES,$(LOCAL_MODULE_CLASS))
+  # Put the built targets of all shared libraries in a common directory
+  # to simplify the link line.
+  OVERRIDE_BUILT_MODULE_PATH := $($(my_prefix)OUT_INTERMEDIATE_LIBRARIES)
 endif
 
 ifeq ($(LOCAL_STRIP_MODULE),true)
@@ -53,21 +54,59 @@
 
 PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
 
-# Ensure that prebuilt .apks have been aligned.
-ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
-ifeq ($(LOCAL_DEX_PREOPT),true)
-# Make sure the boot jars get dexpreopt-ed first
-$(built_module): $(DEXPREOPT_BOOT_ODEXS) | $(DEXPREOPT) $(DEXOPT) $(AAPT)
+ifeq ($(LOCAL_CERTIFICATE),EXTERNAL)
+  # The magic string "EXTERNAL" means this package will be signed with
+  # the default dev 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 := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
+  PACKAGES.$(LOCAL_MODULE).EXTERNAL_KEY := 1
+
+  $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+  $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
 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 := $(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))$(LOCAL_CERTIFICATE)
+  endif
+
+  PACKAGES.$(LOCAL_MODULE).PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+  PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
+  PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
+
+  $(built_module) : PRIVATE_PRIVATE_KEY := $(LOCAL_CERTIFICATE).pk8
+  $(built_module) : PRIVATE_CERTIFICATE := $(LOCAL_CERTIFICATE).x509.pem
+endif
+
+ifneq ($(filter APPS,$(LOCAL_MODULE_CLASS)),)
+ifeq ($(LOCAL_CERTIFICATE),PRESIGNED)
+# Ensure that presigned .apks have been aligned.
 $(built_module) : $(LOCAL_PATH)/$(LOCAL_SRC_FILES) | $(ZIPALIGN)
 	$(transform-prebuilt-to-target-with-zipalign)
-ifeq ($(LOCAL_DEX_PREOPT),true)
-	$(hide) rm -f $(patsubst %.apk,%.odex,$@)
-	$(call dexpreopt-one-file,$@,$(patsubst %.apk,%.odex,$@))
-	$(call dexpreopt-remove-classes.dex,$@)
-
-built_odex := $(basename $(built_module)).odex
-$(built_odex): $(built_module)
+else
+# Sign and align non-presigned .apks.
+$(built_module) : $(LOCAL_PATH)/$(LOCAL_SRC_FILES) | $(ACP) $(ZIPALIGN) $(SIGNAPK_JAR)
+	$(transform-prebuilt-to-target)
+	$(sign-package)
+	$(align-package)
 endif
 else
 ifneq ($(LOCAL_PREBUILT_STRIP_COMMENTS),)
@@ -97,42 +136,6 @@
 $(built_module) : $(common_javalib_jar)
 endif # TARGET JAVA_LIBRARIES
 
-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)
-endif
-
 ifneq ($(prebuilt_module_is_a_library),)
   ifneq ($(LOCAL_IS_HOST_MODULE),)
 	$(transform-host-ranlib-copy-hack)
diff --git a/core/product.mk b/core/product.mk
index 2efc446..8b76243 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -76,13 +76,14 @@
     PRODUCT_EXTRA_RECOVERY_KEYS \
     PRODUCT_PACKAGE_OVERLAYS \
     DEVICE_PACKAGE_OVERLAYS \
-    PRODUCT_CONTRIBUTORS_FILE \
     PRODUCT_TAGS \
     PRODUCT_SDK_ADDON_NAME \
     PRODUCT_SDK_ADDON_COPY_FILES \
     PRODUCT_SDK_ADDON_COPY_MODULES \
     PRODUCT_SDK_ADDON_DOC_MODULE \
-    PRODUCT_DEFAULT_WIFI_CHANNELS
+    PRODUCT_DEFAULT_WIFI_CHANNELS \
+    PRODUCT_DEFAULT_DEV_CERTIFICATE \
+
 
 define dump-product
 $(info ==== $(1) ====)\
@@ -232,6 +233,9 @@
 	BOARD_INSTALLER_CMDLINE \
 
 
+_product_stash_var_list += \
+	DEFAULT_SYSTEM_DEV_CERTIFICATE
+
 #
 # Stash vaues of the variables in _product_stash_var_list.
 # $(1): Renamed prefix
diff --git a/core/product_config.mk b/core/product_config.mk
index 1567f6d..23e06ea 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -112,8 +112,8 @@
   # The build server wants to do make PRODUCT-dream-installclean
   # which really means TARGET_PRODUCT=dream make installclean.
   ifneq ($(filter-out $(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)
-	MAKECMDGOALS := $(MAKECMDGOALS) $(TARGET_BUILD_VARIANT)
-	TARGET_BUILD_VARIANT := eng
+    MAKECMDGOALS := $(MAKECMDGOALS) $(TARGET_BUILD_VARIANT)
+    TARGET_BUILD_VARIANT := eng
     default_goal_substitution :=
   else
     default_goal_substitution := $(DEFAULT_GOAL)
@@ -232,8 +232,8 @@
 # Default to medium-density assets.
 # (Can be overridden in the device config, e.g.: PRODUCT_AAPT_CONFIG += hdpi)
 PRODUCT_AAPT_CONFIG := $(strip \
-	$(PRODUCT_AAPT_CONFIG) \
-	$(if $(filter %dpi,$(PRODUCT_AAPT_CONFIG)),,mdpi))
+    $(PRODUCT_AAPT_CONFIG) \
+    $(if $(filter %dpi,$(PRODUCT_AAPT_CONFIG)),,mdpi))
 
 # Everyone gets nodpi assets which are density-independent.
 PRODUCT_AAPT_CONFIG += nodpi
@@ -241,7 +241,7 @@
 # Convert spaces to commas.
 comma := ,
 PRODUCT_AAPT_CONFIG := \
-	$(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
+    $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
 
 PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
 
@@ -251,7 +251,7 @@
 endif
 
 PRODUCT_MANUFACTURER := \
-	$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MANUFACTURER))
 ifndef PRODUCT_MANUFACTURER
   PRODUCT_MANUFACTURER := unknown
 endif
@@ -263,7 +263,16 @@
 endif
 
 PRODUCT_DEFAULT_WIFI_CHANNELS := \
-	$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_WIFI_CHANNELS))
+
+PRODUCT_DEFAULT_DEV_CERTIFICATE := \
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_DEV_CERTIFICATE))
+ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
+ifneq (1,$(words $(PRODUCT_DEFAULT_DEV_CERTIFICATE)))
+    $(error PRODUCT_DEFAULT_DEV_CERTIFICATE='$(PRODUCT_DEFAULT_DEV_CERTIFICATE)', \
+      only 1 certificate is allowed.)
+endif
+endif
 
 # A list of words like <source path>:<destination path>.  The file at
 # the source path should be copied to the destination path when building
@@ -271,26 +280,22 @@
 # it should look like, e.g., "system/etc/file.xml".  The rules
 # for these copy steps are defined in config/Makefile.
 PRODUCT_COPY_FILES := \
-	$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))
-
-# The HTML file containing the contributors to the project.
-PRODUCT_CONTRIBUTORS_FILE := \
-	$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CONTRIBUTORS_FILE))
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))
 
 # A list of property assignments, like "key = value", with zero or more
 # whitespace characters on either side of the '='.
 PRODUCT_PROPERTY_OVERRIDES := \
-	$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PROPERTY_OVERRIDES))
 
 # A list of property assignments, like "key = value", with zero or more
 # whitespace characters on either side of the '='.
 # used for adding properties to default.prop
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES := \
-	$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
 
 # Should we use the default resources or add any product specific overlays
 PRODUCT_PACKAGE_OVERLAYS := \
-	$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))
+    $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))
 DEVICE_PACKAGE_OVERLAYS := \
         $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).DEVICE_PACKAGE_OVERLAYS))
 
@@ -299,8 +304,8 @@
 
 # Add the product-defined properties to the build properties.
 ADDITIONAL_BUILD_PROPERTIES := \
-	$(ADDITIONAL_BUILD_PROPERTIES) \
-	$(PRODUCT_PROPERTY_OVERRIDES)
+    $(ADDITIONAL_BUILD_PROPERTIES) \
+    $(PRODUCT_PROPERTY_OVERRIDES)
 
 # The OTA key(s) specified by the product config, if any.  The names
 # of these keys are stored in the target-files zip so that post-build
diff --git a/core/tasks/sdk-addon.mk b/core/tasks/sdk-addon.mk
index 797314a..f3aec65 100644
--- a/core/tasks/sdk-addon.mk
+++ b/core/tasks/sdk-addon.mk
@@ -58,6 +58,7 @@
         $(BUILT_SYSTEMIMAGE):images/$(TARGET_CPU_ABI)/system.img \
         $(BUILT_USERDATAIMAGE_TARGET):images/$(TARGET_CPU_ABI)/userdata.img \
         $(BUILT_RAMDISK_TARGET):images/$(TARGET_CPU_ABI)/ramdisk.img \
+        $(PRODUCT_OUT)/system/build.prop:images/$(TARGET_CPU_ABI)/build.prop \
         $(target_notice_file_txt):images/$(TARGET_CPU_ABI)/NOTICE.txt
 
 # Generate rules to copy the requested files
diff --git a/core/user_tags.mk b/core/user_tags.mk
index 6b77bec..d09a2cd 100644
--- a/core/user_tags.mk
+++ b/core/user_tags.mk
@@ -69,7 +69,6 @@
 	check_stack \
 	check_trace \
 	cmu2nuance \
-	com.android.inputmethod.pinyin.lib \
 	com.android.phone.common \
 	com.android.vcard \
 	commons-compress-1.0 \
@@ -153,7 +152,6 @@
 	init \
 	input \
 	ip \
-	iptables \
 	jarjar \
 	javax.obex \
 	jcommon-1.0.12 \
@@ -255,7 +253,6 @@
 	libiptc \
 	libjnigraphics \
 	libjni_latinime \
-	libjni_pinyinime \
 	libjpeg \
 	libjs \
 	liblinenoise \
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 986dac9..6773635 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 := IceCreamSandwich
+  PLATFORM_VERSION := 4.0.1
 endif
 
 ifeq "" "$(PLATFORM_SDK_VERSION)"
@@ -53,13 +53,13 @@
   # intermediate builds).  During development, this number remains at the
   # SDK version the branch is based on and PLATFORM_VERSION_CODENAME holds
   # the code-name of the new development work.
-  PLATFORM_SDK_VERSION := 13
+  PLATFORM_SDK_VERSION := 14
 endif
 
 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 := IceCreamSandwich
+  PLATFORM_VERSION_CODENAME := REL
 endif
 
 ifeq "" "$(DEFAULT_APP_TARGET_SDK)"
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index d02205b..229ea9c 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -30,3 +30,12 @@
 
 # Set /system/bin/sh to ash, not mksh, to make sure we can switch back.
 TARGET_SHELL := ash
+
+# Enable dex-preoptimization to speed up the first boot sequence
+# of an SDK AVD. Note that this operation only works on Linux for now
+ifeq ($(HOST_OS),linux)
+WITH_DEXPREOPT := true
+endif
+
+# Build OpenGLES emulation guest and host libraries
+BUILD_EMULATOR_OPENGL := true
diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk
index f57a0dc..8b187d5 100644
--- a/target/board/generic/device.mk
+++ b/target/board/generic/device.mk
@@ -23,7 +23,8 @@
 
 PRODUCT_COPY_FILES := \
     development/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
-    development/data/etc/vold.conf:system/etc/vold.conf
+    development/data/etc/vold.conf:system/etc/vold.conf \
+    development/tools/emulator/system/camera/media_profiles.xml:system/etc/media_profiles.xml \
 
 PRODUCT_PACKAGES := \
     audio.primary.goldfish
diff --git a/target/board/generic_armv5/AndroidBoard.mk b/target/board/generic_armv5/AndroidBoard.mk
new file mode 100644
index 0000000..7daff27
--- /dev/null
+++ b/target/board/generic_armv5/AndroidBoard.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2011 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 build/target/board/generic/AndroidBoard.mk
diff --git a/target/board/generic_armv5/BoardConfig.mk b/target/board/generic_armv5/BoardConfig.mk
new file mode 100644
index 0000000..d8fa2fe
--- /dev/null
+++ b/target/board/generic_armv5/BoardConfig.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2011 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 build/target/board/generic/BoardConfig.mk
+
+TARGET_ARCH_VARIANT :=
+TARGET_CPU_ABI := armeabi
+TARGET_CPU_ABI2 :=
+
+WITH_DEXPREOPT := false
diff --git a/target/board/generic_armv5/README.txt b/target/board/generic_armv5/README.txt
new file mode 100644
index 0000000..25d590a
--- /dev/null
+++ b/target/board/generic_armv5/README.txt
@@ -0,0 +1,5 @@
+The "generic_armv5" product defines a non-hardware-specific target
+without a kernel or bootloader.
+
+It is not a product "base class"; no other products inherit
+from it or use it in any way.
diff --git a/target/board/generic_armv5/device.mk b/target/board/generic_armv5/device.mk
new file mode 100644
index 0000000..7c4aaf2
--- /dev/null
+++ b/target/board/generic_armv5/device.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2011 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 build/target/board/generic/device.mk
diff --git a/target/board/generic_armv5/system.prop b/target/board/generic_armv5/system.prop
new file mode 100644
index 0000000..137a0f9
--- /dev/null
+++ b/target/board/generic_armv5/system.prop
@@ -0,0 +1,6 @@
+#
+# system.prop for generic sdk
+#
+
+rild.libpath=/system/lib/libreference-ril.so
+rild.libargs=-d /dev/ttyS0
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 7277908..1a1bc80 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -20,3 +20,12 @@
 
 # Set /system/bin/sh to ash, not mksh, to make sure we can switch back.
 TARGET_SHELL := ash
+
+# Enable dex-preoptimization to speed up the first boot sequence
+# of an SDK AVD. Note that this operation only works on Linux for now
+ifeq ($(HOST_OS),linux)
+WITH_DEXPREOPT := true
+endif
+
+# Build OpenGLES emulation host and guest libraries
+BUILD_EMULATOR_OPENGL := true
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 0b4dc27..1055cba 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -23,4 +23,5 @@
 
 PRODUCT_COPY_FILES := \
     development/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
-    development/data/etc/vold.conf:system/etc/vold.conf
+    development/data/etc/vold.conf:system/etc/vold.conf \
+    development/tools/emulator/system/camera/media_profiles.xml:system/etc/media_profiles.xml \
diff --git a/target/board/vbox_x86/device.mk b/target/board/vbox_x86/device.mk
index a028b98..a76d8fa 100644
--- a/target/board/vbox_x86/device.mk
+++ b/target/board/vbox_x86/device.mk
@@ -28,6 +28,7 @@
 PRODUCT_COPY_FILES := \
     development/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
     development/data/etc/vold.conf:system/etc/vold.conf \
+    development/tools/emulator/system/camera/media_profiles.xml:system/etc/media_profiles.xml \
     build/target/board/vbox_x86/init.rc:root/init.rc \
     build/target/board/vbox_x86/init.vbox_x86.rc:root/init.vbox_x86.rc \
     $(LOCAL_KERNEL):kernel
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 44b9000..e77c783 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -35,6 +35,7 @@
 PRODUCT_MAKEFILES := \
     $(LOCAL_DIR)/core.mk \
     $(LOCAL_DIR)/generic.mk \
+    $(LOCAL_DIR)/generic_armv5.mk \
     $(LOCAL_DIR)/generic_x86.mk \
     $(LOCAL_DIR)/full.mk \
     $(LOCAL_DIR)/full_x86.mk \
diff --git a/target/product/core.mk b/target/product/core.mk
index 0f1455e..aac703e 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -23,10 +23,27 @@
     ro.config.alarm_alert=Alarm_Classic.ogg
 
 PRODUCT_PACKAGES := \
+    ApplicationsProvider \
+    BackupRestoreConfirmation \
+    Browser \
+    Contacts \
+    ContactsProvider \
+    DefaultContainerService \
+    DownloadProvider \
+    DownloadProviderUi \
+    HTMLViewer \
+    Home \
+    KeyChain \
+    MediaProvider \
+    PackageInstaller \
+    PicoTts \
+    SettingsProvider \
+    SharedStorageBackup \
+    TelephonyProvider \
+    UserDictionaryProvider \
     apache-xml \
     bouncycastle \
     bu \
-    bluetooth-health \
     cacerts \
     com.android.location.provider \
     com.android.location.provider.xml \
@@ -45,63 +62,40 @@
     hprof-conv \
     icu.dat \
     installd \
+    ip \
     ip-up-vpn \
+    ip6tables \
+    iptables \
+    libOpenMAXAL \
+    libOpenSLES \
+    libaudiopreprocessing \
     libcrypto \
-    libdex \
     libdvm \
     libexpat \
+    libfilterfw \
+    libfilterpack_imageproc \
     libgabi++ \
     libicui18n \
     libicuuc \
-    libjavacore \
     libnativehelper \
     libnfc_ndef \
-    libOpenMAXAL \
-    libOpenSLES \
+    libpowermanager \
+    libspeexresampler \
     libsqlite_jni \
     libssl \
-    libvariablespeed \
     libstagefright_soft_aacdec \
     libstagefright_soft_amrdec \
-    libstagefright_soft_avcdec \
     libstagefright_soft_g711dec \
     libstagefright_soft_mp3dec \
     libstagefright_soft_mpeg4dec \
     libstagefright_soft_vorbisdec \
     libstagefright_soft_vpxdec \
-    libwilhelm \
-    libfilterfw \
-    libfilterpack_imageproc \
-    libz \
-    wpa_supplicant.conf \
-    KeyChain \
-    Browser \
-    Contacts \
-    Home \
-    HTMLViewer \
-    ApplicationsProvider \
-    BackupRestoreConfirmation \
-    ContactsProvider \
-    VoicemailProvider \
-    DownloadProvider \
-    DownloadProviderUi \
-    MediaProvider \
-    PicoTts \
-    SettingsProvider \
-    TelephonyProvider \
-    TtsService \
-    VpnServices \
-    UserDictionaryProvider \
-    PackageInstaller \
-    DefaultContainerService \
-    Bugreport \
-    ip \
-    screencap \
-    sensorservice \
-    libspeexresampler \
+    libvariablespeed \
     libwebrtc_audio_preprocessing \
-    libaudiopreprocessing \
-    hostapd
+    libwilhelm \
+    libz \
+    screencap \
+    sensorservice
 
 # host-only dependencies
 ifeq ($(WITH_HOST_DALVIK),true)
@@ -109,6 +103,5 @@
         apache-xml-hostdex \
         bouncycastle-hostdex \
         core-hostdex \
-        libjavacore-host \
         dalvik
 endif
diff --git a/target/product/generic_armv5.mk b/target/product/generic_armv5.mk
new file mode 100644
index 0000000..daa321a
--- /dev/null
+++ b/target/product/generic_armv5.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2011 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.
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
+
+# Overrides
+PRODUCT_BRAND := generic_armv5
+PRODUCT_DEVICE := generic_armv5
+PRODUCT_NAME := generic_armv5
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index c31e5f7..d165b0f 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -20,7 +20,6 @@
 PRODUCT_POLICY := android.policy_phone
 
 PRODUCT_PACKAGES := \
-    AccountAndSyncSettings \
     DeskClock \
     AlarmProvider \
     Bluetooth \
@@ -30,7 +29,7 @@
     DrmProvider \
     Email \
     Exchange \
-    GalleryNew3D \
+    Gallery2 \
     LatinIME \
     Launcher2 \
     Music \
@@ -44,7 +43,10 @@
     Updater \
     CalendarProvider \
     SyncProvider \
-    VpnDialogs
+    VpnDialogs \
+    bluetooth-health \
+    hostapd \
+    wpa_supplicant.conf
 
 PRODUCT_PACKAGES += \
     icu.dat
@@ -68,6 +70,7 @@
         frameworks/base/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf
 
 $(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk)
+$(call inherit-product-if-exists, external/lohit-fonts/fonts.mk)
 $(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
 
diff --git a/target/product/generic_x86.mk b/target/product/generic_x86.mk
index 7e77a27..86710c4 100644
--- a/target/product/generic_x86.mk
+++ b/target/product/generic_x86.mk
@@ -18,7 +18,6 @@
 # It includes the base Android platform.
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
 
 # Overrides
 PRODUCT_BRAND := generic_x86
diff --git a/target/product/large_emu_hw.mk b/target/product/large_emu_hw.mk
index f38ef61..15b1bed 100644
--- a/target/product/large_emu_hw.mk
+++ b/target/product/large_emu_hw.mk
@@ -20,7 +20,6 @@
 PRODUCT_POLICY := android.policy_mid
 
 PRODUCT_PACKAGES := \
-    AccountAndSyncSettings \
     CarHome \
     DeskClock \
     AlarmProvider \
@@ -32,7 +31,7 @@
     DrmProvider \
     Email \
     Exchange \
-    GalleryNew3D \
+    Gallery2 \
     LatinIME \
     Launcher2 \
     Music \
@@ -42,7 +41,11 @@
     Sync \
     Updater \
     CalendarProvider \
-    SyncProvider
+    SyncProvider \
+    bluetooth-health \
+    hostapd \
+    wpa_supplicant.conf
+
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
 
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index d942cde..c4abc51 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -30,21 +30,18 @@
 	libWnnEngDic \
 	libWnnJpnDic \
 	libwnndict \
-        Phone \
+	Phone \
 	PinyinIME \
 	Protips \
 	SoftKeyboard \
 	SystemUI \
 	Launcher2 \
-	AccountAndSyncSettings \
 	Development \
 	DrmProvider \
 	Fallback \
-	GPSEnable \
 	Settings \
 	SdkSetup \
 	CustomLocale \
-	gpstest \
 	sqlite3 \
 	LatinIME \
 	CertInstaller \
@@ -60,7 +57,10 @@
 	jython \
 	jsilver \
 	librs_jni \
-	ConnectivityTest
+	ConnectivityTest \
+	GpsLocationTest \
+	CalendarProvider \
+	Calendar
 
 
 # Host tools that are parts of the SDK.
@@ -125,6 +125,11 @@
 	sdkuilib-tests \
 	layoutlib-tests
 
+# audio libraries.
+PRODUCT_PACKAGES += \
+	audio.primary.goldfish \
+	audio_policy.default
+
 PRODUCT_PACKAGE_OVERLAYS := development/sdk_overlay
 
 PRODUCT_COPY_FILES := \
@@ -145,10 +150,11 @@
 # locale + densities. en_US is both first and in alphabetical order to
 # ensure this is the default locale.
 PRODUCT_LOCALES = \
+	en_US \
 	ldpi \
 	hdpi \
 	mdpi \
-	en_US \
+	xhdpi \
 	ar_EG \
 	ar_IL \
 	bg_BG \
diff --git a/tools/atree/atree.cpp b/tools/atree/atree.cpp
index aee2b3c..2ba284f 100644
--- a/tools/atree/atree.cpp
+++ b/tools/atree/atree.cpp
@@ -1,6 +1,8 @@
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <stdarg.h>
 #include "options.h"
 #include "files.h"
 #include "fs.h"
@@ -10,7 +12,7 @@
 
 using namespace std;
 
-bool g_debug = false;
+bool g_debug = getenv("ATREE_DEBUG") != NULL;
 vector<string> g_listFiles;
 vector<string> g_inputBases;
 map<string, string> g_variables;
@@ -33,6 +35,7 @@
 "  -m DEPENDENCY  Output a make-formatted file containing the list.\n"
 "                 of files included.  It sets the variable ATREE_FILES.\n"
 "  -v VAR=VAL     Replaces ${VAR} by VAL when reading input files.\n"
+"  -d             Verbose debug mode.\n"
 "\n"
 "FILELIST file format:\n"
 "  The FILELIST files contain the list of files that will end up\n"
@@ -42,11 +45,13 @@
 "  In a FILELIST file, comment lines start with a #.  Other lines\n"
 "  are of the format:\n"
 "\n"
-"    DEST\n"
-"    SRC DEST\n"
+"    [rm|strip] DEST\n"
+"    SRC [strip] DEST\n"
 "    -SRCPATTERN\n"
 "\n"
 "  DEST should be path relative to the output directory.\n"
+"  'rm DEST' removes the destination file and fails if it's missing.\n"
+"  'strip DEST' strips the binary destination file.\n"
 "  If SRC is supplied, the file names can be different.\n"
 "  SRCPATTERN is a pattern for the filenames.\n"
 "\n";
@@ -72,13 +77,26 @@
     return true;
 }
 
+static void
+debug_printf(const char* format, ...)
+{
+    if (g_debug) {
+        fflush(stderr);
+        va_list ap;
+        va_start(ap, format);
+        vprintf(format, ap);
+        va_end(ap);
+        fflush(stdout);
+    }
+}
+
 int
 main(int argc, char* const* argv)
 {
     int err;
     bool done = false;
     while (!done) {
-        int opt = getopt(argc, argv, "f:I:o:hlm:v:");
+        int opt = getopt(argc, argv, "f:I:o:hlm:v:d");
         switch (opt)
         {
             case -1:
@@ -117,6 +135,9 @@
                     return usage();
                 }
                 break;
+            case 'd':
+                g_debug = true;
+                break;
             default:
             case '?':
             case 'h':
@@ -169,7 +190,7 @@
 
     // read file lists
     for (vector<string>::iterator it=g_listFiles.begin();
-                                it!=g_listFiles.end(); it++) {
+                                 it!=g_listFiles.end(); it++) {
         err = read_list_file(*it, g_variables, &files, &excludes);
         if (err != 0) {
             return err;
@@ -181,9 +202,8 @@
     for (vector<FileRecord>::iterator it=files.begin();
                                 it!=files.end(); it++) {
         err |= locate(&(*it), g_inputBases);
-
     }
-    
+
     // expand the directories that we should copy into a list of files
     for (vector<FileRecord>::iterator it=files.begin();
                                 it!=files.end(); it++) {
@@ -219,8 +239,8 @@
         }
     }
 
-    // gather files that should become directores and directories that should
-    // become files
+    // gather files that should become directores
+    // and directories that should become files
     for (vector<FileRecord>::iterator it=files.begin();
                                 it!=files.end(); it++) {
         if (it->outMod != 0 && it->sourceIsDir != it->outIsDir) {
@@ -231,48 +251,66 @@
     // delete files
     for (set<string>::iterator it=deleted.begin();
                                 it!=deleted.end(); it++) {
-        if (g_debug) {
-            printf("deleting %s\n", it->c_str());
-        }
+        debug_printf("deleting %s\n", it->c_str());
         err = remove_recursively(*it);
         if (err != 0) {
             return err;
         }
     }
 
+    // remove all files or directories as requested from the input atree file.
+    // must be done before create new directories.
+    for (vector<FileRecord>::iterator it=files.begin();
+                                it!=files.end(); it++) {
+        if (!it->sourceIsDir) {
+            if (it->fileOp == FILE_OP_REMOVE &&
+                    deleted.count(it->outPath) == 0) {
+                debug_printf("remove %s\n", it->outPath.c_str());
+                err = remove_recursively(it->outPath);
+                if (err != 0) {
+                    return err;
+                }
+            }
+        }
+    }
+
     // make directories
     for (set<string>::iterator it=directories.begin();
                                 it!=directories.end(); it++) {
-        if (g_debug) {
-            printf("mkdir %s\n", it->c_str());
-        }
+        debug_printf("mkdir %s\n", it->c_str());
         err = mkdir_recursively(*it);
         if (err != 0) {
             return err;
         }
     }
 
-    // copy (or link) files
+    // copy (or link) files that are newer or of different size
     for (vector<FileRecord>::iterator it=files.begin();
                                 it!=files.end(); it++) {
         if (!it->sourceIsDir) {
-            if (g_debug) {
-                printf("copy %s(%ld) ==> %s(%ld)", it->sourcePath.c_str(),
-                    it->sourceMod, it->outPath.c_str(), it->outMod);
-                fflush(stdout);
+            if (it->fileOp == FILE_OP_REMOVE) {
+                continue;
             }
 
-            if (it->outMod < it->sourceMod) {
+            debug_printf("copy %s(%ld) ==> %s(%ld)",
+                it->sourcePath.c_str(), it->sourceMod,
+                it->outPath.c_str(), it->outMod);
+
+            if (it->outSize != it->sourceSize || it->outMod < it->sourceMod) {
                 err = copy_file(it->sourcePath, it->outPath);
-                if (g_debug) {
-                    printf(" done.\n");
-                }
+                debug_printf(" done.\n");
                 if (err != 0) {
                     return err;
                 }
             } else {
-                if (g_debug) {
-                    printf(" skipping.\n");
+                debug_printf(" skipping.\n");
+            }
+
+            if (it->fileOp == FILE_OP_STRIP) {
+                debug_printf("strip %s\n", it->outPath.c_str());
+                err = strip_file(it->outPath);
+                if (err != 0) {
+                    return err;
                 }
             }
         }
diff --git a/tools/atree/files.cpp b/tools/atree/files.cpp
index d4866d4..df3e987 100644
--- a/tools/atree/files.cpp
+++ b/tools/atree/files.cpp
@@ -62,7 +62,7 @@
 split_line(const char* p, vector<string>* out)
 {
     const char* q = p;
-    enum { WHITE, TEXT } state = WHITE;
+    enum { WHITE, TEXT, IN_QUOTE } state = WHITE;
     while (*p) {
         if (*p == '#') {
             break;
@@ -73,13 +73,25 @@
             case WHITE:
                 if (!isspace(*p)) {
                     q = p;
-                    state = TEXT;
+                    state = (*p == '"') ? IN_QUOTE : TEXT;
                 }
                 break;
+            case IN_QUOTE:
+                if (*p == '"') {
+                    state = TEXT;
+                    break;
+                }
+                // otherwise fall-through to TEXT case
             case TEXT:
-                if (isspace(*p)) {
+                if (state != IN_QUOTE && isspace(*p)) {
                     if (q != p) {
-                        out->push_back(string(q, p-q));
+                        const char* start = q;
+                        size_t len = p-q;
+                        if (len > 2 && *start == '"' && start[len - 1] == '"') {
+                            start++;
+                            len -= 2;
+                        }
+                        out->push_back(string(start, len));
                     }
                     state = WHITE;
                 }
@@ -88,17 +100,25 @@
         p++;
     }
     if (state == TEXT) {
-        out->push_back(string(q, p-q));
+        const char* start = q;
+        size_t len = p-q;
+        if (len > 2 && *start == '"' && start[len - 1] == '"') {
+            start++;
+            len -= 2;
+        }
+        out->push_back(string(start, len));
     }
 }
 
 static void
-add_file(vector<FileRecord>* files, const string& listFile, int listLine,
+add_file(vector<FileRecord>* files, const FileOpType fileOp,
+            const string& listFile, int listLine,
             const string& sourceName, const string& outName)
 {
     FileRecord rec;
     rec.listFile = listFile;
     rec.listLine = listLine;
+    rec.fileOp = fileOp;
     rec.sourceName = sourceName;
     rec.outName = outName;
     files->push_back(rec);
@@ -182,7 +202,7 @@
         err = errno;
         goto cleanup;
     }
-    
+
     size = ftell(f);
 
     err = fseek(f, 0, SEEK_SET);
@@ -245,35 +265,52 @@
             }
             printf("]\n");
 #endif
-            
-            if (words.size() == 1) {
-                // pattern: DEST
-                bool error = false;
-                string w0 = replace_variables(words[0], variables, &error);
-                if (error) {
-                    err = 1;
-                    goto cleanup;
+            FileOpType op = FILE_OP_COPY;
+            string paths[2];
+            int pcount = 0;
+            string errstr;
+            for (vector<string>::iterator it = words.begin(); it != words.end(); ++it) {
+                const string& word = *it;
+                if (word == "rm") {
+                    if (op != FILE_OP_COPY) {
+                        errstr = "Error: you can only specifiy 'rm' or 'strip' once per line.";
+                        break;
+                    }
+                    op = FILE_OP_REMOVE;
+                } else if (word == "strip") {
+                    if (op != FILE_OP_COPY) {
+                        errstr = "Error: you can only specifiy 'rm' or 'strip' once per line.";
+                        break;
+                    }
+                    op = FILE_OP_STRIP;
+                } else if (pcount < 2) {
+                    bool error = false;
+                    paths[pcount++] = replace_variables(word, variables, &error);
+                    if (error) {
+                        err = 1;
+                        goto cleanup;
+                    }
+                } else {
+                    errstr = "Error: More than 2 paths per line.";
+                    break;
                 }
-                add_file(files, filename, i+1, w0, w0);
             }
-            else if (words.size() == 2) {
-                // pattern: SRC DEST
-                bool error = false;
-                string w0, w1;
-                w0 = replace_variables(words[0], variables, &error);
-                if (!error) {
-                    w1 = replace_variables(words[1], variables, &error);
-                }
-                if (error) {
-                    err = 1;
-                    goto cleanup;
-                }
-                add_file(files, filename, i+1, w0, w1);
+
+            if (pcount == 0 && !errstr.empty()) {
+                errstr = "Error: No path found on line.";
             }
-            else {
-                fprintf(stderr, "%s:%d: bad format: %s\n", filename.c_str(),
-                        i+1, p);
+
+            if (!errstr.empty()) {
+                fprintf(stderr, "%s:%d: bad format: %s\n%s\nExpected: [SRC] [rm|strip] DEST\n",
+                        filename.c_str(), i+1, p, errstr.c_str());
                 err = 1;
+            } else {
+                if (pcount == 1) {
+                    // pattern: [rm|strip] DEST
+                    paths[1] = paths[0];
+                }
+
+                add_file(files, op, filename, i+1, paths[0], paths[1]);
             }
         }
         p = q;
@@ -293,6 +330,14 @@
 int
 locate(FileRecord* rec, const vector<string>& search)
 {
+    if (rec->fileOp == FILE_OP_REMOVE) {
+        // Don't touch source files when removing a destination.
+        rec->sourceMod = 0;
+        rec->sourceSize = 0;
+        rec->sourceIsDir = false;
+        return 0;
+    }
+
     int err;
 
     for (vector<string>::const_iterator it=search.begin();
@@ -304,6 +349,7 @@
             rec->sourceBase = *it;
             rec->sourcePath = full;
             rec->sourceMod = st.st_mtime;
+            rec->sourceSize = st.st_size;
             rec->sourceIsDir = S_ISDIR(st.st_mode);
             return 0;
         }
@@ -324,9 +370,11 @@
     err = stat(rec->outPath.c_str(), &st);
     if (err == 0) {
         rec->outMod = st.st_mtime;
+        rec->outSize = st.st_size;
         rec->outIsDir = S_ISDIR(st.st_mode);
     } else {
         rec->outMod = 0;
+        rec->outSize = 0;
         rec->outIsDir = false;
     }
 }
@@ -427,3 +475,8 @@
 {
     return list_dir("", rec, excludes, files);
 }
+
+FileRecord::FileRecord() {
+    fileOp = FILE_OP_COPY;
+}
+
diff --git a/tools/atree/files.h b/tools/atree/files.h
index 6480c98..f6bf8a6 100644
--- a/tools/atree/files.h
+++ b/tools/atree/files.h
@@ -8,8 +8,16 @@
 
 using namespace std;
 
+enum FileOpType {
+    FILE_OP_COPY = 0,
+    FILE_OP_REMOVE,
+    FILE_OP_STRIP
+};
+
 struct FileRecord
 {
+    FileRecord();
+
     string listFile;
     int listLine;
 
@@ -18,9 +26,12 @@
     string sourcePath;
     bool sourceIsDir;
     time_t sourceMod;
+    off_t  sourceSize;
+    FileOpType fileOp;
 
     string outName;
     string outPath;
+    off_t  outSize;
     time_t outMod;
     bool outIsDir;
     unsigned int mode;
diff --git a/tools/atree/fs.cpp b/tools/atree/fs.cpp
index 9971879..b648394 100644
--- a/tools/atree/fs.cpp
+++ b/tools/atree/fs.cpp
@@ -1,7 +1,9 @@
 #include "fs.h"
 #include "files.h"
 #include <unistd.h>
+#include <stdlib.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <dirent.h>
 #include <string>
 #include <vector>
@@ -64,10 +66,10 @@
 #ifdef HAVE_DIRENT_D_TYPE
             bool is_directory = (ent->d_type == DT_DIR);
 #else
-	    	// If dirent.d_type is missing, then use stat instead
-			struct stat stat_buf;
-			stat(full.c_str(), &stat_buf);
-			bool is_directory = S_ISDIR(stat_buf.st_mode);
+            // If dirent.d_type is missing, then use stat instead
+            struct stat stat_buf;
+            stat(full.c_str(), &stat_buf);
+            bool is_directory = S_ISDIR(stat_buf.st_mode);
 #endif
             if (is_directory) {
                 dirs.push_back(full);
@@ -146,3 +148,27 @@
                     COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS);
     return err;
 }
+
+int
+strip_file(const string& path)
+{
+    // Default strip command to run is "strip" unless overridden by the STRIP env var.
+    const char* strip_cmd = getenv("STRIP");
+    if (!strip_cmd || !strip_cmd[0]) {
+        strip_cmd = "strip";
+    }
+    pid_t pid = fork();
+    if (pid == -1) {
+        // Fork failed. errno should be set.
+        return -1;
+    } else if (pid == 0) {
+        // Exec in the child. Only returns if execve failed.
+        return execlp(strip_cmd, strip_cmd, path.c_str(), (char *)NULL);
+    } else {
+        // Wait for child pid and return its exit code.
+        int status;
+        waitpid(pid, &status, 0);
+        return status;
+    }
+}
+
diff --git a/tools/atree/fs.h b/tools/atree/fs.h
index 4080880..fd4ae3e 100644
--- a/tools/atree/fs.h
+++ b/tools/atree/fs.h
@@ -8,5 +8,6 @@
 int remove_recursively(const string& path);
 int mkdir_recursively(const string& path);
 int copy_file(const string& src, const string& dst);
+int strip_file(const string& path);
 
 #endif // FS_H
diff --git a/tools/droiddoc/templates-sdk/assets/android-developer-core.css b/tools/droiddoc/templates-sdk/assets/android-developer-core.css
index 565f173..f548a6c 100644
--- a/tools/droiddoc/templates-sdk/assets/android-developer-core.css
+++ b/tools/droiddoc/templates-sdk/assets/android-developer-core.css
@@ -649,6 +649,7 @@
 #doc-content .gsc-tabHeader {
   padding: 3px 6px;
   position:relative;
+  width:auto;
 }
 
 #doc-content .gsc-tabHeader.gsc-tabhActive {
diff --git a/tools/droiddoc/templates-sdk/assets/android-developer-docs.css b/tools/droiddoc/templates-sdk/assets/android-developer-docs.css
index 22d010a..20871b9 100644
--- a/tools/droiddoc/templates-sdk/assets/android-developer-docs.css
+++ b/tools/droiddoc/templates-sdk/assets/android-developer-docs.css
@@ -718,6 +718,17 @@
   padding:0;
 }
 
+#jd-content div.special.reference h2,
+#jd-content div.special.reference h3,
+#jd-content div.special.reference h4 {
+  color:#000;
+  font-size:1em;
+  border:none;
+  font-weight:bold;
+  margin:.5em 0;
+  padding:0;
+}
+
 p.note, div.note,
 p.caution, div.caution,
 p.warning, div.warning {
@@ -1005,6 +1016,82 @@
 
 /* End sidebox sidebar element styles */
 
+/* BEGIN developer training bar styles */
+
+div#tb-wrapper {
+  float: right;
+  width:480px; /* +25px padding = 505 */
+  background-color:#fff;
+  margin:-48px 0 2px 0;
+  padding:0 0 20px 25px;
+}
+
+div#tb {
+  margin:0;
+  padding:15px;
+  width:450px; /* +15px padding = 480 */
+  font-size:.9em;
+  background:#e9e9e9;
+  border-radius:5px;
+  -moz-border-radius:5px;
+  -webkit-border-radius:5px;
+}
+
+div#tb h2 {
+  font-size:1.3em;
+  font-weight:bold;
+  margin:12px 0 .25em 0;
+  padding:10px 0;
+  background-color:transparent;
+  border:none;
+}
+
+div.download-box a.button {
+  color:#eee;
+  font-weight:bold;
+  font-size:1.1em;
+  text-decoration:none;
+  height:40px;
+  line-height:40px;
+  padding:5px 10px;
+  border:2px solid #99be27;
+  border-radius:5px;
+  -moz-border-radius:5px;
+  -webkit-border-radius:5px;
+  /* thanks http://www.colorzilla.com/gradient-editor/ */
+  background: #aed33c; /* Old browsers */
+  background: -moz-linear-gradient(top, #aed33c 20%, #a1c730 80%); /* FF3.6+ */
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(20%,#aed33c), color-stop(80%,#a1c730)); /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #aed33c 20%,#a1c730 80%); /* Chrome10+,Safari5.1+ */
+  background: -o-linear-gradient(top, #aed33c 20%,#a1c730 80%); /* Opera11.10+ */
+  background: -ms-linear-gradient(top, #aed33c 20%,#a1c730 80%); /* IE10+ */
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#AED33C', endColorstr='#A1C730',GradientType=0 ); /* IE6-9 */
+  background: linear-gradient(top, #aed33c 20%,#a1c730 80%); /* W3C */
+}
+
+div.download-box a.button:hover {
+  border:2px solid #b2d841;
+}
+
+div.download-box a.button:active {
+  background: #a1c730; /* Old browsers */
+  background: -moz-linear-gradient(top, #a1c730 15%, #aed33c 70%); /* FF3.6+ */
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(15%,#a1c730), color-stop(70%,#aed33c)); /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #a1c730 15%,#aed33c 70%); /* Chrome10+,Safari5.1+ */
+  background: -o-linear-gradient(top, #a1c730 15%,#aed33c 70%); /* Opera11.10+ */
+  background: -ms-linear-gradient(top, #a1c730 15%,#aed33c 70%); /* IE10+ */
+  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a1c730', endColorstr='#aed33c',GradientType=0 ); /* IE6-9 */
+  background: linear-gradient(top, #a1c730 15%,#aed33c 70%); /* W3C */
+}
+
+div.download-box p.filename {
+  font-size:0.8em;
+  color:#888;
+  margin:0 0 0 12px;
+}
+
+/* End developer training bar */
+
 /* BEGIN image and caption styles (originally for UI Guidelines docs) */
 
 table.image-caption {
diff --git a/tools/droiddoc/templates-sdk/assets/android-developer-docs.js b/tools/droiddoc/templates-sdk/assets/android-developer-docs.js
index e353236..0cac2fc 100644
--- a/tools/droiddoc/templates-sdk/assets/android-developer-docs.js
+++ b/tools/droiddoc/templates-sdk/assets/android-developer-docs.js
@@ -143,7 +143,8 @@
     cookiePath = "guide_";
   } else if (location.href.indexOf("/sdk/") != -1) {
     cookiePath = "sdk_";
-  } else if (location.href.indexOf("/resources/") != -1) {
+  } else if ((location.href.indexOf("/resources/") != -1) || 
+             (location.href.indexOf("/training/") != -1)) {
     cookiePath = "resources_";
   }
 
@@ -231,6 +232,9 @@
         if (tags[j] == 'new') {
           listItemNode.get(0).innerHTML += '&nbsp;<span class="new">new!</span>';
           break;
+        } else if (tags[j] == 'updated') {
+          listItemNode.get(0).innerHTML += '&nbsp;<span class="new">updated!</span>';
+          break;
         }
       }
       listNode.append(listItemNode);
@@ -251,6 +255,8 @@
     firstSlashPos = fullPageName.indexOf("/sdk/");
   } else if (fullPageName.indexOf("/resources/") != -1) {
     firstSlashPos = fullPageName.indexOf("/resources/");
+  } else if (fullPageName.indexOf("/training/") != -1) {
+    firstSlashPos = fullPageName.indexOf("/training/");
   }
   if (lastSlashPos == (fullPageName.length - 1)) { // if the url ends in slash (add 'index.html')
     fullPageName = fullPageName + "index.html";
diff --git a/tools/droiddoc/templates-sdk/assets/android-developer-reference.js b/tools/droiddoc/templates-sdk/assets/android-developer-reference.js
index 31a702b..ba47d4d 100644
--- a/tools/droiddoc/templates-sdk/assets/android-developer-reference.js
+++ b/tools/droiddoc/templates-sdk/assets/android-developer-reference.js
@@ -5,6 +5,7 @@
 var API_LEVEL_ENABLED_COOKIE = "api_level_enabled";
 var API_LEVEL_COOKIE = "api_level";
 var minLevel = 1;
+var maxLevel = 1;
 
 function toggleApiLevelSelector(checkbox) {
   var date = new Date();
@@ -23,9 +24,9 @@
 }
 
 function buildApiLevelSelector() {
-  var maxLevel = SINCE_DATA.length;
+  maxLevel = SINCE_DATA.length;
   var userApiLevelEnabled = readCookie(API_LEVEL_ENABLED_COOKIE);
-  var userApiLevel = readCookie(API_LEVEL_COOKIE);
+  var userApiLevel = parseInt(readCookie(API_LEVEL_COOKIE));
   userApiLevel = userApiLevel == 0 ? maxLevel : userApiLevel; // If there's no cookie (zero), use the max by default
 
   if (userApiLevelEnabled == 0) {
@@ -34,41 +35,47 @@
     $("#apiLevelCheckbox").attr("checked","checked");
     $("#api-level-toggle label").removeClass("disabled");
   }
-  
-  minLevel = $("body").attr("class");
+
+  minLevel = parseInt($("body").attr("class"));
+  // Handle provisional api levels; the provisional level will always be the highest possible level
+  // Provisional api levels will also have a length; other stuff that's just missing a level won't,
+  // so leave those kinds of entities at the default level of 1 (for example, the R.styleable class)
+  if (isNaN(minLevel) && minLevel.length) {
+    minLevel = maxLevel;
+  }
   var select = $("#apiLevelSelector").html("").change(changeApiLevel);
   for (var i = maxLevel-1; i >= 0; i--) {
     var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]);
   //  if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
     select.append(option);
   }
-  
+
   // get the DOM element and use setAttribute cuz IE6 fails when using jquery .attr('selected',true)
   var selectedLevelItem = $("#apiLevelSelector option[value='"+userApiLevel+"']").get(0);
   selectedLevelItem.setAttribute('selected',true);
 }
 
 function changeApiLevel() {
-  var maxLevel = SINCE_DATA.length;
+  maxLevel = SINCE_DATA.length;
   var userApiLevelEnabled = readCookie(API_LEVEL_ENABLED_COOKIE);
   var selectedLevel = maxLevel;
-  
+
   if (userApiLevelEnabled == 0) {
     toggleVisisbleApis(selectedLevel, "body");
   } else {
     selectedLevel = parseInt($("#apiLevelSelector option:selected").val());
     toggleVisisbleApis(selectedLevel, "body");
-    
+
     var date = new Date();
     date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
     var expiration = date.toGMTString();
     writeCookie(API_LEVEL_COOKIE, selectedLevel, null, expiration);
   }
-  
+
   if (selectedLevel < minLevel) {
     var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class";
     $("#naMessage").show().html("<div><p><strong>This " + thing + " is not available with API Level " + selectedLevel + ".</strong></p>"
-                              + "<p>To use this " + thing + ", your application must specify API Level " + minLevel + " or higher in its manifest "
+                              + "<p>To use this " + thing + ", your application must specify API Level \"" + $("body").attr("class") + "\" or higher in its manifest "
                               + "and be compiled against a version of the Android library that supports an equal or higher API Level. To reveal this "
                               + "document, change the value of the API Level filter above.</p>"
                               + "<p><a href='" +toRoot+ "guide/appendix/api-levels.html'>What is the API Level?</a></p></div>");
@@ -86,7 +93,21 @@
     var apiLevelEndIndex = className.indexOf(" ", apiLevelIndex);
     apiLevelEndIndex = apiLevelEndIndex != -1 ? apiLevelEndIndex : className.length;
     var apiLevel = className.substring(apiLevelIndex, apiLevelEndIndex);
-    if (apiLevel > selectedLevel) obj.addClass("absent").attr("title","Requires API Level "+apiLevel+" or higher");
+    if (apiLevel.length == 0) { // for odd cases when the since data is actually missing, just bail
+      return;
+    }
+    apiLevel = parseInt(apiLevel);
+
+    // Handle provisional api levels; if this item's level is the provisional one, set it to the max
+    var selectedLevelNum = parseInt(selectedLevel)
+    var apiLevelNum = parseInt(apiLevel);
+    if (isNaN(apiLevelNum)) {
+        apiLevelNum = maxLevel;
+    }
+
+    // Grey things out that aren't available and give a tooltip title
+    if (apiLevelNum > selectedLevelNum) obj.addClass("absent").attr("title","Requires API Level \""
+            + apiLevel + "\" or higher");
     else obj.removeClass("absent").removeAttr("title");
   });
 }
@@ -184,7 +205,7 @@
     }
     node.plus_img.src = me.toroot + "assets/images/triangle-opened-small.png";
     node.expanded = true;
-    
+
     // perform api level toggling because new nodes are new to the DOM
     var selectedLevel = $("#apiLevelSelector option:selected").val();
     toggleVisisbleApis(selectedLevel, "#side-nav");
diff --git a/tools/droiddoc/templates-sdk/assets/images/home/ics-android.png b/tools/droiddoc/templates-sdk/assets/images/home/ics-android.png
new file mode 100644
index 0000000..be62ca8
--- /dev/null
+++ b/tools/droiddoc/templates-sdk/assets/images/home/ics-android.png
Binary files differ
diff --git a/tools/droiddoc/templates-sdk/assets/images/icon_market.jpg b/tools/droiddoc/templates-sdk/assets/images/icon_market.jpg
index cb1ff0b..0fbb197 100644
--- a/tools/droiddoc/templates-sdk/assets/images/icon_market.jpg
+++ b/tools/droiddoc/templates-sdk/assets/images/icon_market.jpg
Binary files differ
diff --git a/tools/fileslist.py b/tools/fileslist.py
index ae1b4b6..a11efaa 100755
--- a/tools/fileslist.py
+++ b/tools/fileslist.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 #
 
-import os, sys
+import operator, os, sys
 
 def get_file_size(path):
   st = os.lstat(path)
@@ -37,9 +37,9 @@
           output.append(row)
         except os.error:
           pass
+  output.sort(key=operator.itemgetter(0), reverse=True)
   for row in output:
     print "%12d  %s" % row
 
 if __name__ == '__main__':
   main(sys.argv)
-
diff --git a/tools/findleaves.py b/tools/findleaves.py
index 0adf188..52c4d9f 100755
--- a/tools/findleaves.py
+++ b/tools/findleaves.py
@@ -89,9 +89,9 @@
     usage()
   dirlist = argv[i:-1]
   filename = argv[-1]
-  results = perform_find(mindepth, prune, dirlist, filename)
+  results = list(set(perform_find(mindepth, prune, dirlist, filename)))
   results.sort()
-  for r in set(results):
+  for r in results:
     print r
 
 if __name__ == "__main__":
diff --git a/tools/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures
index 2c97e2e..4e83129 100755
--- a/tools/releasetools/check_target_files_signatures
+++ b/tools/releasetools/check_target_files_signatures
@@ -52,6 +52,11 @@
 import tempfile
 import zipfile
 
+try:
+  from hashlib import sha1 as sha1
+except ImportError:
+  from sha import sha as sha1
+
 import common
 
 # Work around a bug in python's zipfile module that prevents opening
@@ -182,7 +187,7 @@
 class APK(object):
   def __init__(self, full_filename, filename):
     self.filename = filename
-    self.cert = None
+    self.certs = set()
     Push(filename+":")
     try:
       self.RecordCert(full_filename)
@@ -198,11 +203,10 @@
       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)
+          cert = CertFromPKCS7(pkcs7, info.filename)
+          self.certs.add(cert)
+          ALL_CERTS.Add(cert)
       if not pkcs7:
         AddProblem("no signature")
     finally:
@@ -276,24 +280,19 @@
     for uid in sorted(apks_by_uid.keys()):
       apks = apks_by_uid[uid]
       for apk in apks[1:]:
-        if apk.cert != apks[0].cert:
+        if apk.certs != apks[0].certs:
           break
       else:
-        # all the certs are the same; this uid is fine
+        # all packages have the same set of certs; this uid is fine.
         continue
 
-      AddProblem("uid %s shared across multiple certs" % (uid,))
+      AddProblem("different cert sets for packages with uid %s" % (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 "uid %s is shared by packages with different cert sets:" % (uid,)
+      for apk in apks:
+        print "%-*s  [%s]" % (self.max_pkg_len, apk.package, apk.filename)
+        for cert in apk.certs:
+          print "   ", ALL_CERTS.Get(cert)
       print
 
   def CheckExternalSignatures(self):
@@ -314,7 +313,8 @@
     """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))
+      for cert in apk.certs:
+        by_cert.setdefault(cert, []).append((apk.package, apk))
 
     order = [(-len(v), k) for (k, v) in by_cert.iteritems()]
     order.sort()
@@ -347,10 +347,10 @@
     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)
+          # in both; should have at least one cert in common
+          if not (self.apks[i].cert & other.apks[i].cert):
+            by_certpair.setdefault((other.apks[i].certs,
+                                    self.apks[i].certs), []).append(i)
         else:
           print "%s [%s]: new APK (not in comparison target_files)" % (
               i, self.apks[i].filename)
@@ -363,8 +363,16 @@
       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, o in enumerate(old):
+          if i == 0:
+            print "was", ALL_CERTS.Get(o)
+          else:
+            print "   ", ALL_CERTS.Get(o)
+        for i, n in enumerate(new):
+          if i == 0:
+            print "now", ALL_CERTS.Get(n)
+          else:
+            print "   ", ALL_CERTS.Get(n)
         for i in sorted(packages):
           old_fn = other.apks[i].filename
           new_fn = self.apks[i].filename
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 40da73a..2cb5680 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -29,11 +29,9 @@
 import zipfile
 
 try:
-  import hashlib
-  sha1 = hashlib.sha1
+  from hashlib import sha1 as sha1
 except ImportError:
-  import sha
-  sha1 = sha.sha
+  from sha import sha as sha1
 
 # missing in Python 2.4 and before
 if not hasattr(os, "SEEK_SET"):
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
index 8f5c3fe..0a27a19 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -24,9 +24,14 @@
   -b  (--board_config)  <file>
       Deprecated.
 
-  -k  (--package_key)  <key>
-      Key to use to sign the package (default is
-      "build/target/product/security/testkey").
+  -k (--package_key) <key> Key to use to sign the package (default is
+      the value of default_system_dev_certificate from the input
+      target-files's META/misc_info.txt, or
+      "build/target/product/security/testkey" if that value is not
+      specified).
+
+      For incremental OTAs, the default value is based on the source
+      target-file, not the target build.
 
   -i  (--incremental_from)  <file>
       Generate an incremental OTA using the given target-files zip as
@@ -63,11 +68,16 @@
 import time
 import zipfile
 
+try:
+  from hashlib import sha1 as sha1
+except ImportError:
+  from sha import sha as sha1
+
 import common
 import edify_generator
 
 OPTIONS = common.OPTIONS
-OPTIONS.package_key = "build/target/product/security/testkey"
+OPTIONS.package_key = None
 OPTIONS.incremental_source = None
 OPTIONS.require_verbatim = set()
 OPTIONS.prohibit_verbatim = set(("system/build.prop",))
@@ -608,7 +618,12 @@
   so_far = 0
 
   script.Print("Patching system files...")
-  for fn, tf, sf, size, _ in patch_list:
+  deferred_patch_list = []
+  for item in patch_list:
+    fn, tf, sf, size, _ = item
+    if tf.name == "system/build.prop":
+      deferred_patch_list.append(item)
+      continue
     script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1, sf.sha1, "patch/"+fn+".p")
     so_far += tf.size
     script.SetProgress(so_far / total_patch_size)
@@ -710,6 +725,15 @@
   if OPTIONS.extra_script is not None:
     script.AppendExtra(OPTIONS.extra_script)
 
+  # Patch the build.prop file last, so if something fails but the
+  # device can still come up, it appears to be the old build and will
+  # get set the OTA package again to retry.
+  script.Print("Patching remaining system files...")
+  for item in deferred_patch_list:
+    fn, tf, sf, size, _ = item
+    script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1, sf.sha1, "patch/"+fn+".p")
+  script.SetPermissions("/system/build.prop", 0, 0, 0644)
+
   script.AddToZip(target_zip, output_zip)
   WriteMetadata(metadata, output_zip)
 
@@ -775,30 +799,34 @@
     OPTIONS.device_specific = os.path.normpath(OPTIONS.device_specific)
     print "using device-specific extensions in", OPTIONS.device_specific
 
-  if OPTIONS.package_key:
-    temp_zip_file = tempfile.NamedTemporaryFile()
-    output_zip = zipfile.ZipFile(temp_zip_file, "w",
-                                 compression=zipfile.ZIP_DEFLATED)
-  else:
-    output_zip = zipfile.ZipFile(args[1], "w",
-                                 compression=zipfile.ZIP_DEFLATED)
+  temp_zip_file = tempfile.NamedTemporaryFile()
+  output_zip = zipfile.ZipFile(temp_zip_file, "w",
+                               compression=zipfile.ZIP_DEFLATED)
 
   if OPTIONS.incremental_source is None:
     WriteFullOTAPackage(input_zip, output_zip)
+    if OPTIONS.package_key is None:
+      OPTIONS.package_key = OPTIONS.info_dict.get(
+          "default_system_dev_certificate",
+          "build/target/product/security/testkey")
   else:
     print "unzipping source target-files..."
     OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source)
     OPTIONS.target_info_dict = OPTIONS.info_dict
     OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
+    if OPTIONS.package_key is None:
+      OPTIONS.package_key = OPTIONS.source_info_dict.get(
+          "default_system_dev_certificate",
+          "build/target/product/security/testkey")
     if OPTIONS.verbose:
       print "--- source info ---"
       common.DumpInfoDict(OPTIONS.source_info_dict)
     WriteIncrementalOTAPackage(input_zip, source_zip, output_zip)
 
   output_zip.close()
-  if OPTIONS.package_key:
-    SignOutput(temp_zip_file.name, args[1])
-    temp_zip_file.close()
+
+  SignOutput(temp_zip_file.name, args[1])
+  temp_zip_file.close()
 
   common.Cleanup()
 
diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks
index 5353063..eaad8a4 100755
--- a/tools/releasetools/sign_target_files_apks
+++ b/tools/releasetools/sign_target_files_apks
@@ -36,10 +36,16 @@
   -d  (--default_key_mappings)  <dir>
       Set up the following key mappings:
 
-        build/target/product/security/testkey   ==>  $dir/releasekey
-        build/target/product/security/media     ==>  $dir/media
-        build/target/product/security/shared    ==>  $dir/shared
-        build/target/product/security/platform  ==>  $dir/platform
+        $devkey/devkey    ==>  $dir/releasekey
+        $devkey/testkey   ==>  $dir/releasekey
+        $devkey/media     ==>  $dir/media
+        $devkey/shared    ==>  $dir/shared
+        $devkey/platform  ==>  $dir/platform
+
+      where $devkey is the directory part of the value of
+      default_system_dev_certificate from the input target-files's
+      META/misc_info.txt.  (Defaulting to "build/target/product/security"
+      if the value is not present in misc_info.
 
       -d and -k options are added to the set of mappings in the order
       in which they appear on the command line.
@@ -55,7 +61,7 @@
       the last component of the build fingerprint).  Prefix each with
       '+' or '-' to indicate whether that tag should be added or
       removed.  Changes are processed in the order they appear.
-      Default value is "-test-keys,+release-keys".
+      Default value is "-test-keys,-dev-keys,+release-keys".
 
 """
 
@@ -80,7 +86,7 @@
 OPTIONS.extra_apks = {}
 OPTIONS.key_map = {}
 OPTIONS.replace_ota_keys = False
-OPTIONS.tag_changes = ("-test-keys", "+release-keys")
+OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys")
 
 def GetApkCerts(tf_zip):
   certmap = common.ReadApkCerts(tf_zip)
@@ -198,14 +204,12 @@
   return "\n".join(output) + "\n"
 
 
-def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
+def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info):
   try:
     keylist = input_tf_zip.read("META/otakeys.txt").split()
   except KeyError:
     raise ExternalError("can't read META/otakeys.txt from input")
 
-  misc_info = common.LoadInfoDict(input_tf_zip)
-
   extra_recovery_keys = misc_info.get("extra_recovery_keys", None)
   if extra_recovery_keys:
     extra_recovery_keys = [OPTIONS.key_map.get(k, k) + ".x509.pem"
@@ -227,10 +231,10 @@
     print "using:\n   ", "\n   ".join(mapped_keys)
     print "for OTA package verification"
   else:
+    devkey = misc_info.get("default_system_dev_certificate",
+                           "build/target/product/security/testkey")
     mapped_keys.append(
-        OPTIONS.key_map.get("build/target/product/security/testkey",
-                            "build/target/product/security/testkey")
-        + ".x509.pem")
+        OPTIONS.key_map.get(devkey, devkey) + ".x509.pem")
     print "META/otakeys.txt has no keys; using", mapped_keys[0]
 
   # recovery uses a version of the key that has been slightly
@@ -259,8 +263,28 @@
                      tempfile.getvalue())
 
 
+def BuildKeyMap(misc_info, key_mapping_options):
+  for s, d in key_mapping_options:
+    if s is None:   # -d option
+      devkey = misc_info.get("default_system_dev_certificate",
+                             "build/target/product/security/testkey")
+      devkeydir = os.path.dirname(devkey)
+
+      OPTIONS.key_map.update({
+          devkeydir + "/testkey":  d + "/releasekey",
+          devkeydir + "/devkey":   d + "/releasekey",
+          devkeydir + "/media":    d + "/media",
+          devkeydir + "/shared":   d + "/shared",
+          devkeydir + "/platform": d + "/platform",
+          })
+    else:
+      OPTIONS.key_map[s] = d
+
+
 def main(argv):
 
+  key_mapping_options = []
+
   def option_handler(o, a):
     if o in ("-e", "--extra_apks"):
       names, key = a.split("=")
@@ -268,15 +292,9 @@
       for n in names:
         OPTIONS.extra_apks[n] = key
     elif o in ("-d", "--default_key_mappings"):
-      OPTIONS.key_map.update({
-          "build/target/product/security/testkey": "%s/releasekey" % (a,),
-          "build/target/product/security/media": "%s/media" % (a,),
-          "build/target/product/security/shared": "%s/shared" % (a,),
-          "build/target/product/security/platform": "%s/platform" % (a,),
-          })
+      key_mapping_options.append((None, a))
     elif o in ("-k", "--key_mapping"):
-      s, d = a.split("=")
-      OPTIONS.key_map[s] = d
+      key_mapping_options.append(a.split("=", 1))
     elif o in ("-o", "--replace_ota_keys"):
       OPTIONS.replace_ota_keys = True
     elif o in ("-t", "--tag_changes"):
@@ -307,6 +325,10 @@
   input_zip = zipfile.ZipFile(args[0], "r")
   output_zip = zipfile.ZipFile(args[1], "w")
 
+  misc_info = common.LoadInfoDict(input_zip)
+
+  BuildKeyMap(misc_info, key_mapping_options)
+
   apk_key_map = GetApkCerts(input_zip)
   CheckAllApksSigned(input_zip, apk_key_map)
 
@@ -314,7 +336,7 @@
   SignApks(input_zip, output_zip, apk_key_map, key_passwords)
 
   if OPTIONS.replace_ota_keys:
-    ReplaceOtaKeys(input_zip, output_zip)
+    ReplaceOtaKeys(input_zip, output_zip, misc_info)
 
   input_zip.close()
   output_zip.close()