Merge "Compile each proto file separately"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 5240837..62a3a09 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -102,6 +102,7 @@
 $(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 c3c3abd..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.
@@ -1098,6 +1113,7 @@
 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
@@ -1420,7 +1436,7 @@
 			-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 && \
 		HOST_OUT_EXECUTABLES=$(HOST_OUT_EXECUTABLES) HOST_OS=$(HOST_OS) \
diff --git a/core/build_id.mk b/core/build_id.mk
index e415e8d..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 := ICS_FACTORYROM
+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/cleanbuild.mk b/core/cleanbuild.mk
index 2639cae..e6db5cb 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -118,7 +118,7 @@
 endif
 
 # A change in the list of aapt configs warrants an installclean, too.
-aapt_config_list := $(strip $(PRODUCT_AAPT_CONFIG))
+aapt_config_list := $(strip $(PRODUCT_AAPT_CONFIG) $(PRODUCT_AAPT_PREF_CONFIG))
 
 current_build_config := \
     $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)$(building_sdk)-{$(aapt_config_list)}
@@ -186,7 +186,8 @@
 	$(PRODUCT_OUT)/root \
 	$(PRODUCT_OUT)/system \
 	$(PRODUCT_OUT)/dex_bootjars \
-	$(PRODUCT_OUT)/obj/JAVA_LIBRARIES
+	$(PRODUCT_OUT)/obj/JAVA_LIBRARIES \
+	$(PRODUCT_OUT)/obj/FAKE
 
 # The files/dirs to delete during a dataclean, which removes any files
 # in the staging and emulator data partitions.
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 f385b74..683ae16 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1561,6 +1561,7 @@
 define add-assets-to-package
 $(hide) $(AAPT) package -u $(PRIVATE_AAPT_FLAGS) \
     $(addprefix -c , $(PRIVATE_PRODUCT_AAPT_CONFIG)) \
+    $(addprefix --preferred-configurations , $(PRIVATE_PRODUCT_AAPT_PREF_CONFIG)) \
     $(addprefix -M , $(PRIVATE_ANDROID_MANIFEST)) \
     $(addprefix -S , $(PRIVATE_RESOURCE_DIR)) \
     $(addprefix -A , $(PRIVATE_ASSET_DIR)) \
@@ -1587,10 +1588,9 @@
 define add-dex-to-package
 $(if $(filter classes.dex,$(notdir $(PRIVATE_DEX_FILE))),\
 $(hide) $(AAPT) add -k $@ $(PRIVATE_DEX_FILE),\
-$(eval _adtp_classes.dex := $(dir $(PRIVATE_DEX_FILE))/classes.dex)\
-$(hide) cp $(PRIVATE_DEX_FILE) $(_adtp_classes.dex) && \
-$(AAPT) add -k $@ $(_adtp_classes.dex) && \
-rm -f $(_adtp_classes.dex))
+$(hide) _adtp_classes_dex=$(dir $(PRIVATE_DEX_FILE))classes.dex; \
+cp $(PRIVATE_DEX_FILE) $$_adtp_classes_dex && \
+$(AAPT) add -k $@ $$_adtp_classes_dex && rm -f $$_adtp_classes_dex)
 endef
 
 define add-java-resources-to-package
diff --git a/core/main.mk b/core/main.mk
index 6841b36..5f01238 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -664,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/package.mk b/core/package.mk
index 9f54bb0..c60558c 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -227,6 +227,7 @@
 # add-assets-to-package looks at PRODUCT_AAPT_CONFIG, but this target
 # can't know anything about PRODUCT.  Clear it out just for this target.
 $(resource_export_package): PRIVATE_PRODUCT_AAPT_CONFIG :=
+$(resource_export_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
 $(resource_export_package): $(all_res_assets) $(full_android_manifest) $(RenderScript_file_stamp) $(AAPT)
 	@echo "target Export Resources: $(PRIVATE_MODULE) ($@)"
 	$(create-empty-package)
@@ -289,6 +290,18 @@
       $(addsuffix $(so_suffix), \
         $(LOCAL_JNI_SHARED_LIBRARIES)))
 
+# App explicitly requires the prebuilt NDK libstlport_shared.so.
+# libstlport_shared.so should never go to the system image.
+# Instead it should be packaged into the apk.
+ifeq (stlport_shared,$(LOCAL_NDK_STL_VARIANT))
+ifndef LOCAL_NDK_VERSION
+$(error LOCAL_NDK_VERSION has to be defined together with LOCAL_NDK_STL_VARIANT, \
+    LOCAL_PACKAGE_NAME=$(LOCAL_PACKAGE_NAME))
+endif
+jni_shared_libraries += \
+    $(HISTORICAL_NDK_VERSIONS_ROOT)/android-ndk-r$(LOCAL_NDK_VERSION)/sources/cxx-stl/stlport/libs/$(TARGET_CPU_ABI)/libstlport_shared.so
+endif
+
 # Set the abi directory used by the local JNI shared libraries.
 # (Doesn't change how the local shared libraries are compiled, just
 # sets where they are stored in the apk.)
@@ -304,20 +317,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
@@ -343,8 +356,10 @@
 endif
 ifeq ($(LOCAL_AAPT_INCLUDE_ALL_RESOURCES),true)
     $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_CONFIG :=
+    $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
 else
     $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_CONFIG := $(PRODUCT_AAPT_CONFIG)
+    $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := $(PRODUCT_AAPT_PREF_CONFIG)
 endif
 $(LOCAL_BUILT_MODULE): $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)
 	@echo "target Package: $(PRIVATE_MODULE) ($@)"
diff --git a/core/prebuilt.mk b/core/prebuilt.mk
index 935bce1..54a7fa9 100644
--- a/core/prebuilt.mk
+++ b/core/prebuilt.mk
@@ -54,11 +54,61 @@
 
 PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
 
-# Ensure that prebuilt .apks have been aligned.
+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)
 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),)
 $(built_module) : $(LOCAL_PATH)/$(LOCAL_SRC_FILES)
 	$(transform-prebuilt-to-target-strip-comments)
@@ -86,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..26f365d 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -64,6 +64,7 @@
     PRODUCT_MODEL \
     PRODUCT_LOCALES \
     PRODUCT_AAPT_CONFIG \
+    PRODUCT_AAPT_PREF_CONFIG \
     PRODUCT_PACKAGES \
     PRODUCT_DEVICE \
     PRODUCT_MANUFACTURER \
@@ -76,13 +77,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 +234,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..c455723 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)
@@ -228,12 +228,14 @@
 # Add PRODUCT_LOCALES to PRODUCT_AAPT_CONFIG
 PRODUCT_AAPT_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_CONFIG))
 PRODUCT_AAPT_CONFIG := $(PRODUCT_LOCALES) $(PRODUCT_AAPT_CONFIG)
+PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_AAPT_PREF_CONFIG))
 
 # 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))
+PRODUCT_AAPT_PREF_CONFIG := $(strip $(PRODUCT_AAPT_PREF_CONFIG))
 
 # Everyone gets nodpi assets which are density-independent.
 PRODUCT_AAPT_CONFIG += nodpi
@@ -241,7 +243,9 @@
 # Convert spaces to commas.
 comma := ,
 PRODUCT_AAPT_CONFIG := \
-	$(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
+    $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
+PRODUCT_AAPT_PREF_CONFIG := \
+    $(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_PREF_CONFIG)))
 
 PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
 
@@ -251,7 +255,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 +267,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 +284,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 +308,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 d09a2cd..2e7017e 100644
--- a/core/user_tags.mk
+++ b/core/user_tags.mk
@@ -500,7 +500,6 @@
 	vm-tests \
 	vold \
 	wdsclient \
-	whisperd \
 	wpa_supplicant \
 	yuv420sp2rgb \
 	zipalign
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 15176b9..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 := 4.0
+  PLATFORM_VERSION := 4.0.1
 endif
 
 ifeq "" "$(PLATFORM_SDK_VERSION)"
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index f247bca..229ea9c 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -31,5 +31,11 @@
 # 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_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 84b28ca..1a1bc80 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -21,5 +21,11 @@
 # 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/core.mk b/target/product/core.mk
index ef34eee..aac703e 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -26,7 +26,6 @@
     ApplicationsProvider \
     BackupRestoreConfirmation \
     Browser \
-    Bugreport \
     Contacts \
     ContactsProvider \
     DefaultContainerService \
@@ -39,12 +38,10 @@
     PackageInstaller \
     PicoTts \
     SettingsProvider \
+    SharedStorageBackup \
     TelephonyProvider \
-    TtsService \
     UserDictionaryProvider \
-    VpnServices \
     apache-xml \
-    bluetooth-health \
     bouncycastle \
     bu \
     cacerts \
@@ -62,7 +59,6 @@
     ext \
     filterfw \
     framework-res \
-    hostapd \
     hprof-conv \
     icu.dat \
     installd \
@@ -74,7 +70,6 @@
     libOpenSLES \
     libaudiopreprocessing \
     libcrypto \
-    libdex \
     libdvm \
     libexpat \
     libfilterfw \
@@ -82,7 +77,6 @@
     libgabi++ \
     libicui18n \
     libicuuc \
-    libjavacore \
     libnativehelper \
     libnfc_ndef \
     libpowermanager \
@@ -91,7 +85,6 @@
     libssl \
     libstagefright_soft_aacdec \
     libstagefright_soft_amrdec \
-    libstagefright_soft_avcdec \
     libstagefright_soft_g711dec \
     libstagefright_soft_mp3dec \
     libstagefright_soft_mpeg4dec \
@@ -102,8 +95,7 @@
     libwilhelm \
     libz \
     screencap \
-    sensorservice \
-    wpa_supplicant.conf
+    sensorservice
 
 # host-only dependencies
 ifeq ($(WITH_HOST_DALVIK),true)
@@ -111,6 +103,5 @@
         apache-xml-hostdex \
         bouncycastle-hostdex \
         core-hostdex \
-        libjavacore-host \
         dalvik
 endif
diff --git a/target/product/full_base.mk b/target/product/full_base.mk
index a8a32fe..d89af51 100644
--- a/target/product/full_base.mk
+++ b/target/product/full_base.mk
@@ -25,7 +25,6 @@
     libdrmframework_jni \
     libfwdlockengine \
     OpenWnn \
-    PhotoEditor \
     PinyinIME \
     libWnnEngDic \
     libWnnJpnDic \
@@ -53,4 +52,3 @@
 
 # Get everything else from the parent package
 $(call inherit-product, $(SRC_TARGET_DIR)/product/generic_no_telephony.mk)
-
diff --git a/target/product/generic_armv5.mk b/target/product/generic_armv5.mk
index d419e70..daa321a 100644
--- a/target/product/generic_armv5.mk
+++ b/target/product/generic_armv5.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_armv5
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index 6e052fd..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 \
@@ -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/languages_full.mk b/target/product/languages_full.mk
index b18f78f..e494fad 100644
--- a/target/product/languages_full.mk
+++ b/target/product/languages_full.mk
@@ -21,5 +21,5 @@
 
 # Those are all the locales that have translations and are displayable
 # by TextView in this branch.
-PRODUCT_LOCALES := en_US fr_FR it_IT es_ES de_DE nl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TR pt_PT pt_BR rm_CH sv_SE bg_BG ca_ES en_GB fi_FI hr_HR hu_HU in_ID iw_IL lt_LT lv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH ar_EG fa_IR th_TH sw_TZ ms_MY af_ZA zu_ZA
+PRODUCT_LOCALES := en_US fr_FR it_IT es_ES de_DE nl_NL cs_CZ pl_PL ja_JP zh_TW zh_CN ru_RU ko_KR nb_NO es_US da_DK el_GR tr_TR pt_PT pt_BR rm_CH sv_SE bg_BG ca_ES en_GB fi_FI hi_IN hr_HR hu_HU in_ID iw_IL lt_LT lv_LV ro_RO sk_SK sl_SI sr_RS uk_UA vi_VN tl_PH ar_EG fa_IR th_TH sw_TZ ms_MY af_ZA zu_ZA
 # We don't have the fonts to display am_ET yet
diff --git a/target/product/large_emu_hw.mk b/target/product/large_emu_hw.mk
index 9224130..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 \
@@ -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 aaef0b9..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 \
@@ -61,7 +58,9 @@
 	jsilver \
 	librs_jni \
 	ConnectivityTest \
-	GpsLocationTest
+	GpsLocationTest \
+	CalendarProvider \
+	Calendar
 
 
 # Host tools that are parts of the SDK.
@@ -151,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/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 3af4eb1..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 {
diff --git a/tools/droiddoc/templates-sdk/assets/android-developer-docs.js b/tools/droiddoc/templates-sdk/assets/android-developer-docs.js
index 153f5e0..0cac2fc 100644
--- a/tools/droiddoc/templates-sdk/assets/android-developer-docs.js
+++ b/tools/droiddoc/templates-sdk/assets/android-developer-docs.js
@@ -232,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);
diff --git a/tools/droiddoc/templates-sdk/assets/android-developer-reference.js b/tools/droiddoc/templates-sdk/assets/android-developer-reference.js
index 5561cc9..ba47d4d 100644
--- a/tools/droiddoc/templates-sdk/assets/android-developer-reference.js
+++ b/tools/droiddoc/templates-sdk/assets/android-developer-reference.js
@@ -38,7 +38,9 @@
 
   minLevel = parseInt($("body").attr("class"));
   // Handle provisional api levels; the provisional level will always be the highest possible level
-  if (isNaN(minLevel)) {
+  // 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);
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/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures
index 1325ef4..4e83129 100755
--- a/tools/releasetools/check_target_files_signatures
+++ b/tools/releasetools/check_target_files_signatures
@@ -187,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)
@@ -203,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:
@@ -281,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):
@@ -319,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()
@@ -352,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)
@@ -368,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/ota_from_target_files b/tools/releasetools/ota_from_target_files
index 4264efa..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
@@ -72,7 +77,7 @@
 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",))
@@ -794,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()