Merge "Add BOARD_CUSTOM_BOOTIMG_MK for custom bootimg building"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 6d81733..8109ebb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -127,6 +127,11 @@
 
 $(call add-clean-step, rm -f $(OUT_DIR)/versions_checked.mk)
 
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/*.o)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 1c4288d..013efb8 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -23,8 +23,13 @@
 $(if $(filter %.apk, $(1)),$(error \
     Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))
 endef
-unique_product_copy_files_destinations :=
+# filter out the duplicate <source file>:<dest file> pairs.
+unique_product_copy_files_pairs :=
 $(foreach cf,$(PRODUCT_COPY_FILES), \
+    $(if $(filter $(unique_product_copy_files_pairs),$(cf)),,\
+        $(eval unique_product_copy_files_pairs += $(cf))))
+unique_product_copy_files_destinations :=
+$(foreach cf,$(unique_product_copy_files_pairs), \
     $(eval _src := $(call word-colon,1,$(cf))) \
     $(eval _dest := $(call word-colon,2,$(cf))) \
     $(call check-product-copy-files,$(cf)) \
@@ -36,6 +41,7 @@
             $(eval $(call copy-one-file,$(_src),$(_fulldest)))) \
         $(eval ALL_DEFAULT_INSTALLED_MODULES += $(_fulldest)) \
         $(eval unique_product_copy_files_destinations += $(_dest))))
+unique_product_copy_files_pairs :=
 unique_product_copy_files_destinations :=
 
 # -----------------------------------------------------------------
@@ -1431,7 +1437,8 @@
 	$(atree_dir)/sdk.atree \
 	$(sdk_tools_atree_files) \
 	$(HOST_OUT_EXECUTABLES)/atree \
-    $(HOST_OUT_EXECUTABLES)/line_endings
+	$(ALL_HOST_INSTALLED_FILES) \
+	$(HOST_OUT_EXECUTABLES)/line_endings
 
 INTERNAL_SDK_TARGET := $(sdk_dir)/$(sdk_name).zip
 $(INTERNAL_SDK_TARGET): PRIVATE_NAME := $(sdk_name)
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 51fb398..6724c22 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -50,59 +50,36 @@
 #$(shell rm -f tag-list.csv)
 #tag-list-first-time := false
 #endif
-#comma := ,
-#empty :=
-#space := $(empty) $(empty)
 #$(shell echo $(lastword $(filter-out config/% out/%,$(MAKEFILE_LIST))),$(LOCAL_MODULE),$(strip $(LOCAL_MODULE_CLASS)),$(subst $(space),$(comma),$(sort $(LOCAL_MODULE_TAGS))) >> tag-list.csv)
 
 LOCAL_UNINSTALLABLE_MODULE := $(strip $(LOCAL_UNINSTALLABLE_MODULE))
 LOCAL_MODULE_TAGS := $(sort $(LOCAL_MODULE_TAGS))
 ifeq (,$(LOCAL_MODULE_TAGS))
-ifeq (true,$(LOCAL_UNINSTALLABLE_MODULE))
-LOCAL_MODULE_TAGS := optional
-else
-# Installable modules without tags fall back to user (which is changed to user eng below)
-LOCAL_MODULE_TAGS := user
+  LOCAL_MODULE_TAGS := optional
 endif
-#$(warning default tags: $(lastword $(filter-out config/% out/%,$(MAKEFILE_LIST))))
+
+# User tags are not allowed anymore.  Fail early because it will not be installed
+# like it used to be.
+ifneq ($(filter $(LOCAL_MODULE_TAGS),user),)
+  $(warning *** Module name: $(LOCAL_MODULE))
+  $(warning *** Makefile location: $(LOCAL_MODULE_MAKEFILE))
+  $(warning * )
+  $(warning * Module is attempting to use the 'user' tag.  This)
+  $(warning * used to cause the module to be installed automatically.)
+  $(warning * Now, the module must be listed in the PRODUCT_PACKAGES)
+  $(warning * section of a product makefile to have it installed.)
+  $(warning * )
+  $(error user tag detected on module.)
 endif
 
 # Only the tags mentioned in this test are expected to be set by module
 # makefiles. Anything else is either a typo or a source of unexpected
 # behaviors.
-ifneq ($(filter-out user debug eng tests optional samples shell_ash shell_mksh,$(LOCAL_MODULE_TAGS)),)
+ifneq ($(filter-out debug eng tests optional samples shell_ash shell_mksh,$(LOCAL_MODULE_TAGS)),)
 $(warning unusual tags $(LOCAL_MODULE_TAGS) on $(LOCAL_MODULE) at $(LOCAL_PATH))
 endif
 
-ifneq ($(filter $(LOCAL_MODULE_TAGS),user),)
-  ifeq ($(filter $(GRANDFATHERED_USER_MODULES),$(LOCAL_MODULE)),)
-    $(warning *** Module name: $(LOCAL_MODULE))
-    $(warning *** Makefile location: $(LOCAL_PATH))
-    $(warning * )
-    $(warning * Each module must use a LOCAL_MODULE_TAGS in its)
-    $(warning * Android.mk. Possible tags declared by a module:)
-    $(warning * )
-    $(warning *     optional, debug, eng, tests, samples)
-    $(warning * )
-    $(warning * If the module is expected to be in all builds)
-    $(warning * of a product, then it should use the)
-    $(warning * "optional" tag: )
-    $(warning * )
-    $(warning *    Add "LOCAL_MODULE_TAGS := optional" in the)
-    $(warning *    Android.mk for the affected module, and add)
-    $(warning *    the LOCAL_MODULE value for that component)
-    $(warning *    into the PRODUCT_PACKAGES section of product)
-    $(warning *    makefile(s) where it's necessary, if)
-    $(warning *    appropriate.)
-    $(warning * )
-    $(warning * If the component should be in EVERY build of ALL)
-    $(warning * products, then add its LOCAL_MODULE value to the)
-    $(warning * PRODUCT_PACKAGES section of)
-    $(warning * build/target/product/core.mk)
-    $(warning * )
-    $(error user tag detected on new module - user tags are only supported on legacy modules)
-  endif
-endif
+
 
 # Add implicit tags.
 #
@@ -117,27 +94,11 @@
   ALL_GPL_MODULE_LICENSE_FILES := $(sort $(ALL_GPL_MODULE_LICENSE_FILES) $(gpl_license_file))
 endif
 
-#
-# If this module is listed on CUSTOM_MODULES, promote it to "user"
-# so that it will be installed in $(TARGET_OUT).
-#
-ifneq (,$(filter $(LOCAL_MODULE),$(CUSTOM_MODULES)))
-  LOCAL_MODULE_TAGS := $(sort $(LOCAL_MODULE_TAGS) user)
-endif
-
 LOCAL_MODULE_CLASS := $(strip $(LOCAL_MODULE_CLASS))
 ifneq ($(words $(LOCAL_MODULE_CLASS)),1)
   $(error $(LOCAL_PATH): LOCAL_MODULE_CLASS must contain exactly one word, not "$(LOCAL_MODULE_CLASS)")
 endif
 
-# Those used to be implicitly ignored, but aren't any more.
-# As of 20100110 there are no apps with the user tag.
-ifeq ($(LOCAL_MODULE_CLASS),APPS)
-  ifneq ($(filter $(LOCAL_MODULE_TAGS),user),)
-    $(warning user tag on app $(LOCAL_MODULE) at $(LOCAL_PATH) - add your app to core.mk instead)
-  endif
-endif
-
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 ifdef LOCAL_IS_HOST_MODULE
   partition_tag :=
@@ -544,6 +505,16 @@
 $(LOCAL_INSTALLED_MODULE) : $(installed_odex)
 endif
 
+# All host modules that are not tagged with optional are automatically installed.
+# Save the installed files in ALL_HOST_INSTALLED_FILES.
+ifeq ($(LOCAL_IS_HOST_MODULE),true)
+  ALL_HOST_INSTALLED_FILES += $(LOCAL_INSTALLED_MODULE)
+  ifneq ($(filter debug eng tests, $(LOCAL_MODULE_TAGS)),)
+    $(warning $(LOCAL_MODULE_MAKEFILE): Module "$(LOCAL_MODULE)" has useless module tags: $(filter debug eng tests, $(LOCAL_MODULE_TAGS)). It will be installed anyway.)
+    LOCAL_MODULE_TAGS := $(filter-out debug eng tests, $(LOCAL_MODULE_TAGS))
+  endif
+endif
+
 endif # !LOCAL_UNINSTALLABLE_MODULE
 
 
@@ -593,6 +564,8 @@
     $(ALL_MODULES.$(LOCAL_MODULE).EVENT_LOG_TAGS) $(event_log_tags)
 ALL_MODULES.$(LOCAL_MODULE).INTERMEDIATE_SOURCE_DIR := \
     $(ALL_MODULES.$(LOCAL_MODULE).INTERMEDIATE_SOURCE_DIR) $(LOCAL_INTERMEDIATE_SOURCE_DIR)
+ALL_MODULES.$(LOCAL_MODULE).MAKEFILE := \
+    $(ALL_MODULES.$(LOCAL_MODULE).MAKEFILE) $(LOCAL_MODULE_MAKEFILE)
 ifdef LOCAL_MODULE_OWNER
 ALL_MODULES.$(LOCAL_MODULE).OWNER := \
     $(strip $(ALL_MODULES.$(LOCAL_MODULE).OWNER) $(LOCAL_MODULE_OWNER))
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index e6db5cb..1b662b9 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -78,6 +78,10 @@
     $(info Clean step: $(INTERNAL_CLEAN_STEP.$(step))) \
     $(shell $(INTERNAL_CLEAN_STEP.$(step))) \
    )
+  # If we are running mm/mmm, we should copy over the other clean steps too.
+  ifneq ($(ONE_SHOT_MAKEFILE),)
+    INTERNAL_CLEAN_STEPS := $(strip $(CURRENT_CLEAN_STEPS) $(steps))
+  endif
   steps :=
 endif
 CURRENT_CLEAN_BUILD_VERSION :=
diff --git a/core/cleanspec.mk b/core/cleanspec.mk
index d4a8eed..a3eb7cd 100644
--- a/core/cleanspec.mk
+++ b/core/cleanspec.mk
@@ -63,7 +63,13 @@
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
 
+ifneq ($(ONE_SHOT_MAKEFILE),)
+cs_subdirs := $(dir $(ONE_SHOT_MAKEFILE))
+else
+cs_subdirs := .
+endif
 subdir_cleanspecs := \
-    $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git . CleanSpec.mk)
+    $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(cs_subdirs) CleanSpec.mk)
 include $(subdir_cleanspecs)
+cs_subdirs :=
 subdir_cleanspecs :=
diff --git a/core/combo/HOST_darwin-x86.mk b/core/combo/HOST_darwin-x86.mk
index 85bb2cd..668998f 100644
--- a/core/combo/HOST_darwin-x86.mk
+++ b/core/combo/HOST_darwin-x86.mk
@@ -29,20 +29,46 @@
 HOST_GLOBAL_LDFLAGS += -m32
 endif # BUILD_HOST_64bit
 
+ifneq ($(strip $(BUILD_HOST_static)),)
+# Statically-linked binaries are desirable for sandboxed environment
+HOST_GLOBAL_LDFLAGS += -static
+endif # BUILD_HOST_static
+
 build_mac_version := $(shell sw_vers -productVersion)
-mac_sdk_version := 10.6
+
+ifneq ($(strip $(BUILD_MAC_SDK_EXPERIMENTAL)),)
+# SDK 10.7 and higher is not fully compatible with Android.
+mac_sdk_versions_supported :=  10.7 10.8
+else
+mac_sdk_versions_supported :=  10.6
+endif # BUILD_MAC_SDK_EXPERIMENTAL
+mac_sdk_versions_installed := $(shell xcodebuild -showsdks |grep macosx | sort | sed -e "s/.*macosx//g")
+mac_sdk_version := $(firstword $(filter $(mac_sdk_versions_installed), $(mac_sdk_versions_supported)))
+ifeq ($(mac_sdk_version),)
+mac_sdk_version := $(firstword $(mac_sdk_versions_supported))
+endif
+
+mac_sdk_path := $(shell xcode-select -print-path)
+ifeq ($(findstring /Applications,$(mac_sdk_path)),)
+# Legacy Xcode
 mac_sdk_root := /Developer/SDKs/MacOSX$(mac_sdk_version).sdk
+else
+#  Xcode 4.4(App Store) or higher
+# /Applications/Xcode*.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.?.sdk
+mac_sdk_root := $(mac_sdk_path)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$(mac_sdk_version).sdk
+endif
+
 ifeq ($(wildcard $(mac_sdk_root)),)
-recent_xcode4_mac_sdk_root := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX$(mac_sdk_version).sdk
-ifeq ($(wildcard $(recent_xcode4_mac_sdk_root)),)
 $(warning *****************************************************)
 $(warning * Can not find SDK $(mac_sdk_version) at $(mac_sdk_root))
-$(warning * or $(recent_xcode4_mac_sdk_root))
+ifeq ($(strip $(BUILD_MAC_SDK_EXPERIMENTAL)),)
+$(warning * If you wish to build using higher version of SDK, )
+$(warning * try setting BUILD_MAC_SDK_EXPERIMENTAL=1 before )
+$(warning * rerunning this command )
+endif
 $(warning *****************************************************)
 $(error Stop.)
 endif
-mac_sdk_root := $(recent_xcode4_mac_sdk_root)
-endif
 
 HOST_GLOBAL_CFLAGS += -isysroot $(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version)
 HOST_GLOBAL_LDFLAGS += -isysroot $(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version)
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index a4da5ce..b369199 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -52,6 +52,11 @@
 HOST_GLOBAL_LDFLAGS += -m32
 endif # BUILD_HOST_64bit
 
+ifneq ($(strip $(BUILD_HOST_static)),)
+# Statically-linked binaries are desirable for sandboxed environment
+HOST_GLOBAL_LDFLAGS += -static
+endif # BUILD_HOST_static
+
 HOST_GLOBAL_CFLAGS += -fPIC
 HOST_GLOBAL_CFLAGS += \
 	-include $(call select-android-config-h,linux-x86)
diff --git a/core/combo/HOST_windows-x86.mk b/core/combo/HOST_windows-x86.mk
index fe4bd66..85bc1e0 100644
--- a/core/combo/HOST_windows-x86.mk
+++ b/core/combo/HOST_windows-x86.mk
@@ -46,6 +46,10 @@
 
 HOST_GLOBAL_CFLAGS += -include $(call select-android-config-h,windows)
 HOST_GLOBAL_LDFLAGS += --enable-stdcall-fixup
+ifneq ($(strip $(BUILD_HOST_static)),)
+# Statically-linked binaries are desirable for sandboxed environment
+HOST_GLOBAL_LDFLAGS += -static
+endif # BUILD_HOST_static
 
 # when building under Cygwin, ensure that we use Mingw compilation by default.
 # you can disable this (i.e. to generate Cygwin executables) by defining the
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 14c3d28..75b2742 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -118,7 +118,7 @@
 # We cannot turn it off blindly since the option is not available
 # in gcc-4.4.x.  We also want to disable sincos optimization globally
 # by turning off the builtin sin function.
-ifneq ($(filter 4.6.%, $(shell $(TARGET_CC) --version)),)
+ifneq ($(filter 4.6 4.6.%, $(shell $(TARGET_CC) --version)),)
 TARGET_GLOBAL_CFLAGS += -Wno-unused-but-set-variable -fno-builtin-sin \
 			-fno-strict-volatile-bitfields
 endif
@@ -252,8 +252,8 @@
 	-Wl,--gc-sections \
 	-Wl,-shared,-Bsymbolic \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
-	$(PRIVATE_ALL_OBJECTS) \
 	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_SO_O)) \
+	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
 	-Wl,--no-whole-archive \
diff --git a/core/combo/TARGET_linux-mips.mk b/core/combo/TARGET_linux-mips.mk
index a3a891e..1e649ec 100644
--- a/core/combo/TARGET_linux-mips.mk
+++ b/core/combo/TARGET_linux-mips.mk
@@ -84,7 +84,7 @@
 TARGET_GLOBAL_CFLAGS += \
 			$(TARGET_mips_CFLAGS) \
 			-Ulinux -U__unix -U__unix__ -Umips \
-			-fpic \
+			-fpic -fPIE\
 			-ffunction-sections \
 			-fdata-sections \
 			-funwind-tables \
@@ -96,7 +96,7 @@
 # This warning causes dalvik not to build with gcc 4.6.x and -Werror.
 # We cannot turn it off blindly since the option is not available
 # in gcc-4.4.x.
-ifneq ($(filter 4.6.%, $(shell $(TARGET_CC) --version)),)
+ifneq ($(filter 4.6 4.6.%, $(shell $(TARGET_CC) --version)),)
 TARGET_GLOBAL_CFLAGS += -Wno-unused-but-set-variable \
                         -fno-strict-volatile-bitfields
 endif
@@ -244,7 +244,7 @@
 endef
 
 define transform-o-to-executable-inner
-$(hide) $(PRIVATE_CXX) -nostdlib -Bdynamic \
+$(hide) $(PRIVATE_CXX) -nostdlib -Bdynamic -fPIE -pie \
 	-Wl,-dynamic-linker,/system/bin/linker \
 	-Wl,--gc-sections \
 	-Wl,-z,nocopyreloc \
diff --git a/core/combo/TARGET_linux-x86.mk b/core/combo/TARGET_linux-x86.mk
index 9c0f7b9..9a6e08e 100644
--- a/core/combo/TARGET_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -94,6 +94,7 @@
 			-fstrict-aliasing \
 			-funswitch-loops \
 			-funwind-tables \
+			-fstack-protector \
 			-include $(call select-android-config-h,target_linux-x86)
 
 # XXX: Not sure this is still needed. Must check with our toolchains.
@@ -186,14 +187,11 @@
 endef
 
 
-# Add -fuse-ld=bfd because ld.gold doesn't support "--copy-dt-needed-entries".
 define transform-o-to-executable-inner
 $(hide) $(PRIVATE_CXX) \
 	$(TARGET_GLOBAL_LDFLAGS) \
 	-nostdlib -Bdynamic \
 	-Wl,-dynamic-linker,/system/bin/linker \
-	-Wl,--copy-dt-needed-entries \
-	-fuse-ld=bfd \
 	-Wl,-z,nocopyreloc \
 	-fPIE -pie \
 	-o $@ \
diff --git a/core/combo/select.mk b/core/combo/select.mk
index 803cfc0..e485d00 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -60,6 +60,23 @@
 include $(BUILD_COMBOS)/$(combo_target)$(combo_os_arch).mk
 
 ifneq ($(USE_CCACHE),)
+  # The default check uses size and modification time, causing false misses
+  # since the mtime depends when the repo was checked out
+  export CCACHE_COMPILERCHECK := content
+
+  # See man page, optimizations to get more cache hits
+  # implies that __DATE__ and __TIME__ are not critical for functionality.
+  # Ignore include file modification time since it will depend on when
+  # the repo was checked out
+  export CCACHE_SLOPPINESS := time_macros,include_file_mtime,file_macro
+
+  # Turn all preprocessor absolute paths into relative paths.
+  # Fixes absolute paths in preprocessed source due to use of -g.
+  # We don't really use system headers much so the rootdir is
+  # fine; ensures these paths are relative for all Android trees
+  # on a workstation.
+  export CCACHE_BASEDIR := /
+
   CCACHE_HOST_TAG := $(HOST_PREBUILT_TAG)
   # If we are cross-compiling Windows binaries on Linux
   # then use the linux ccache binary instead.
diff --git a/core/config.mk b/core/config.mk
index 03e4245..a894444 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -14,6 +14,11 @@
 SHELL := /bin/bash
 endif
 
+# Utility variables.
+empty :=
+space := $(empty) $(empty)
+comma := ,
+
 # Tell python not to spam the source tree with .pyc files.  This
 # only has an effect on python 2.6 and above.
 export PYTHONDONTWRITEBYTECODE := 1
diff --git a/core/definitions.mk b/core/definitions.mk
index c1757f3..d5c83d5 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -55,6 +55,11 @@
 # its sub-variables.)
 ALL_MODULE_NAME_TAGS:=
 
+# All host modules are automatically installed (i.e. outside
+# of the product configuration scheme).  This is a list of the
+# install targets (LOCAL_INSTALLED_MODULE).
+ALL_HOST_INSTALLED_FILES:=
+
 # Full paths to all prebuilt files that will be copied
 # (used to make the dependency on acp)
 ALL_PREBUILT:=
@@ -173,7 +178,7 @@
 define all-java-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) -name "*.java" -and -not -name ".*") \
+          find -L $(1) -name "*.java" -and -not -name ".*") \
  )
 endef
 
@@ -195,7 +200,7 @@
 define all-c-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) -name "*.c" -and -not -name ".*") \
+          find -L $(1) -name "*.c" -and -not -name ".*") \
  )
 endef
 
@@ -217,7 +222,7 @@
 define all-Iaidl-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) -name "I*.aidl" -and -not -name ".*") \
+          find -L $(1) -name "I*.aidl" -and -not -name ".*") \
  )
 endef
 
@@ -238,7 +243,7 @@
 define all-logtags-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) -name "*.logtags" -and -not -name ".*") \
+          find -L $(1) -name "*.logtags" -and -not -name ".*") \
   )
 endef
 
@@ -251,7 +256,7 @@
 define all-proto-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) -name "*.proto" -and -not -name ".*") \
+          find -L $(1) -name "*.proto" -and -not -name ".*") \
   )
 endef
 
@@ -264,7 +269,7 @@
 define all-renderscript-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) -name "*.rs" -and -not -name ".*") \
+          find -L $(1) -name "*.rs" -and -not -name ".*") \
   )
 endef
 
@@ -277,7 +282,7 @@
 define all-html-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) -name "*.html" -and -not -name ".*") \
+          find -L $(1) -name "*.html" -and -not -name ".*") \
  )
 endef
 
@@ -296,7 +301,7 @@
 ###########################################################
 
 define find-subdir-files
-$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find $(1)))
+$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find -L $(1)))
 endef
 
 ###########################################################
@@ -309,7 +314,7 @@
 
 define find-subdir-subdir-files
 $(filter-out $(patsubst %,$(1)/%,$(3)),$(patsubst ./%,%,$(shell cd \
-            $(LOCAL_PATH) ; find $(1) -maxdepth 1 -name $(2))))
+            $(LOCAL_PATH) ; find -L $(1) -maxdepth 1 -name $(2))))
 endef
 
 ###########################################################
@@ -569,10 +574,6 @@
 ###########################################################
 ## Convert "a b c" into "a:b:c"
 ###########################################################
-
-empty :=
-space := $(empty) $(empty)
-
 define normalize-path-list
 $(subst $(space),:,$(strip $(1)))
 endef
@@ -756,12 +757,17 @@
 ###########################################################
 ## Commands for munging the dependency files GCC generates
 ###########################################################
+# $(1): the input .d file
+# $(2): the output .P file
+define transform-d-to-p-args
+$(hide) cp $(1) $(2); \
+	sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
+		-e '/^$$/ d' -e 's/$$/ :/' < $(1) >> $(2); \
+	rm -f $(1)
+endef
 
 define transform-d-to-p
-$(hide) cp $(@:%.o=%.d) $(@:%.o=%.P); \
-	sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-		-e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \
-	rm -f $(@:%.o=%.d)
+$(call transform-d-to-p-args,$(@:%.o=%.d),$(@:%.o=%.P))
 endef
 
 ###########################################################
@@ -2040,10 +2046,6 @@
 # when requested.
 include $(BUILD_SYSTEM)/distdir.mk
 
-# -----------------------------------------------------------------
-# The modules allowed to use a user tag
-include $(BUILD_SYSTEM)/user_tags.mk
-
 # broken:
 #	$(foreach file,$^,$(if $(findstring,.a,$(suffix $file)),-l$(file),$(file)))
 
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index e312965..9f42933 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -85,8 +85,6 @@
 full_java_lib_deps += $(addprefix $(LOCAL_PATH)/,$(LOCAL_STATIC_JAVA_LIBRARIES)) $(LOCAL_CLASSPATH)
 endif
 
-empty :=
-space := $(empty) $(empty)
 $(full_target): PRIVATE_CLASSPATH := $(subst $(space),:,$(full_java_libs))
 
 endif # !LOCAL_IS_HOST_MODULE
diff --git a/core/envsetup.mk b/core/envsetup.mk
index ce222a9..97b4467 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -114,10 +114,10 @@
 # variables that we need in order to locate the output files.
 include $(BUILD_SYSTEM)/product_config.mk
 
-build_variant := $(filter-out eng user userdebug tests,$(TARGET_BUILD_VARIANT))
+build_variant := $(filter-out user userdebug eng tests,$(TARGET_BUILD_VARIANT))
 ifneq ($(build_variant)-$(words $(TARGET_BUILD_VARIANT)),-1)
 $(warning bad TARGET_BUILD_VARIANT: $(TARGET_BUILD_VARIANT))
-$(error must be empty or one of: eng user userdebug tests)
+$(error must be empty or one of: user userdebug eng tests)
 endif
 
 # ---------------------------------------------------------------
diff --git a/core/main.mk b/core/main.mk
index 6516fa6..77f9fc5 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -224,13 +224,11 @@
 # Bring in dex_preopt.mk
 include $(BUILD_SYSTEM)/dex_preopt.mk
 
-ifneq ($(filter eng user userdebug,$(MAKECMDGOALS)),)
+ifneq ($(filter user userdebug eng,$(MAKECMDGOALS)),)
 $(info ***************************************************************)
 $(info ***************************************************************)
-$(info Don't pass '$(filter eng user userdebug tests,$(MAKECMDGOALS))' on \
+$(info Do not pass '$(filter user userdebug eng tests,$(MAKECMDGOALS))' on \
 		the make command line.)
-# XXX The single quote on this line fixes gvim's syntax highlighting.
-# Without which, the rest of this file is impossible to read.
 $(info Set TARGET_BUILD_VARIANT in buildspec.mk, or use lunch or)
 $(info choosecombo.)
 $(info ***************************************************************)
@@ -279,13 +277,13 @@
 
 ## user/userdebug ##
 
-user_variant := $(filter userdebug user,$(TARGET_BUILD_VARIANT))
+user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
 enable_target_debugging := true
+tags_to_install :=
 ifneq (,$(user_variant))
   # Target is secure in user builds.
   ADDITIONAL_DEFAULT_PROPERTIES += ro.secure=1
 
-  tags_to_install := user
   ifeq ($(user_variant),userdebug)
     # Pick up some extra useful tools
     tags_to_install += debug
@@ -333,7 +331,7 @@
 ## eng ##
 
 ifeq ($(TARGET_BUILD_VARIANT),eng)
-tags_to_install := user debug eng
+tags_to_install := debug eng
 ifneq ($(filter ro.setupwizard.mode=ENABLED, $(call collapse-pairs, $(ADDITIONAL_BUILD_PROPERTIES))),)
   # Don't require the setup wizard on eng builds
   ADDITIONAL_BUILD_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\
@@ -345,7 +343,7 @@
 ## tests ##
 
 ifeq ($(TARGET_BUILD_VARIANT),tests)
-tags_to_install := user debug eng tests
+tags_to_install := debug eng tests
 endif
 
 ## sdk ##
@@ -362,7 +360,7 @@
 
 # TODO: this should be eng I think.  Since the sdk is built from the eng
 # variant.
-tags_to_install := user debug eng
+tags_to_install := debug eng
 ADDITIONAL_BUILD_PROPERTIES += xmpp.auto-presence=true
 ADDITIONAL_BUILD_PROPERTIES += ro.config.nocheckin=yes
 else # !sdk
@@ -591,42 +589,46 @@
 
 # -------------------------------------------------------------------
 # Figure out our module sets.
-
+#
 # Of the modules defined by the component makefiles,
 # determine what we actually want to build.
-Default_MODULES := $(sort $(ALL_DEFAULT_INSTALLED_MODULES) \
-                          $(CUSTOM_MODULES))
-# TODO: Remove the 3 places in the tree that use
-# ALL_DEFAULT_INSTALLED_MODULES and get rid of it from this list.
 
 ifdef FULL_BUILD
   # The base list of modules to build for this product is specified
   # by the appropriate product definition file, which was included
   # by product_config.make.
-  user_PACKAGES := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)
-  $(call expand-required-modules,user_PACKAGES,$(user_PACKAGES))
-  user_PACKAGES := $(call module-installed-files, $(user_PACKAGES))
+  product_MODULES := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)
+  $(call expand-required-modules,product_MODULES,$(product_MODULES))
+  product_FILES := $(call module-installed-files, $(product_MODULES))
+  ifeq (0,1)
+    $(info product_FILES for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)
+    $(foreach p,$(product_FILES),$(info :   $(p)))
+    $(error done)
+  endif
 else
   # We're not doing a full build, and are probably only including
   # a subset of the module makefiles.  Don't try to build any modules
   # requested by the product, because we probably won't have rules
   # to build them.
-  user_PACKAGES :=
+  product_FILES :=
 endif
-# Use tags to get the non-APPS user modules.  Use the product
-# definition files to get the APPS user modules.
-user_MODULES := $(sort $(call get-tagged-modules,user shell_$(TARGET_SHELL)))
-user_MODULES := $(user_MODULES) $(user_PACKAGES)
 
-eng_MODULES := $(sort $(call get-tagged-modules,eng))
+# When modules are tagged with debug eng or tests, they are installed
+# for those variants regardless of what the product spec says.
 debug_MODULES := $(sort $(call get-tagged-modules,debug))
+eng_MODULES := $(sort $(call get-tagged-modules,eng))
 tests_MODULES := $(sort $(call get-tagged-modules,tests))
 
-ifeq ($(strip $(tags_to_install)),)
-$(error ASSERTION FAILED: tags_to_install should not be empty)
-endif
-modules_to_install := $(sort $(Default_MODULES) \
-          $(foreach tag,$(tags_to_install),$($(tag)_MODULES)))
+# TODO: Remove the 3 places in the tree that use ALL_DEFAULT_INSTALLED_MODULES
+# and get rid of it from this list.
+# TODO: The shell is chosen by magic.  Do we still need this?
+modules_to_install := $(sort \
+    $(ALL_DEFAULT_INSTALLED_MODULES) \
+    $(product_FILES) \
+    $(foreach tag,$(tags_to_install),$($(tag)_MODULES)) \
+    $(call get-tagged-modules, shell_$(TARGET_SHELL)) \
+    $(CUSTOM_MODULES) \
+  )
 
 # Some packages may override others using LOCAL_OVERRIDES_PACKAGES.
 # Filter out (do not install) any overridden packages.
@@ -657,9 +659,11 @@
   # 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!)))
+          $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES has nothing to install!)))
 endif
 
+# Install all of the host modules
+modules_to_install += $(sort $(modules_to_install) $(ALL_HOST_INSTALLED_FILES))
 
 # build/core/Makefile contains extra stuff that we don't want to pollute this
 # top-level makefile with.  It expects that ALL_DEFAULT_INSTALLED_MODULES
@@ -672,6 +676,7 @@
 
 endif # dont_bother
 
+
 # These are additional goals that we build, in order to make sure that there
 # is as little code as possible in the tree that doesn't build.
 modules_to_check := $(foreach m,$(ALL_MODULES),$(ALL_MODULES.$(m).CHECKED))
@@ -705,7 +710,6 @@
 .PHONY: files
 files: prebuilt \
         $(modules_to_install) \
-        $(modules_to_check) \
         $(INSTALLED_ANDROID_INFO_TXT_TARGET)
 
 # -------------------------------------------------------------------
@@ -871,3 +875,7 @@
 .PHONY: showcommands
 showcommands:
 	@echo >/dev/null
+
+.PHONY: nothing
+nothing:
+	@echo Successfully read the makefiles.
diff --git a/core/node_fns.mk b/core/node_fns.mk
index 40abff7..ccfcc25 100644
--- a/core/node_fns.mk
+++ b/core/node_fns.mk
@@ -94,8 +94,6 @@
 # - Replace "|||" with spaces, breaking haystack back into
 #   individual words.
 #
-empty :=
-space := $(empty) $(empty)
 define uniq-word
 $(strip \
   $(if $(filter-out 0 1,$(words $(filter $(2),$(1)))), \
diff --git a/core/product.mk b/core/product.mk
index d9e4186..81042a1 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -16,7 +16,12 @@
 
 #
 # Functions for including AndroidProducts.mk files
-#
+# PRODUCT_MAKEFILES is set up in AndroidProducts.mks.
+# Format of PRODUCT_MAKEFILES:
+# <product_name>:<path_to_the_product_makefile>
+# If the <product_name> is the same as the base file name (without dir
+# and the .mk suffix) of the product makefile, "<product_name>:" can be
+# omitted.
 
 #
 # Returns the list of all AndroidProducts.mk files.
diff --git a/core/product_config.mk b/core/product_config.mk
index ea3e517..de1c863 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -181,17 +181,54 @@
 include $(BUILD_SYSTEM)/device.mk
 
 ifneq ($(strip $(TARGET_BUILD_APPS)),)
-  # An unbundled app build needs only the core product makefiles.
-  $(call import-products,$(call get-product-makefiles,\
-      $(SRC_TARGET_DIR)/product/AndroidProducts.mk))
+# An unbundled app build needs only the core product makefiles.
+all_product_configs := $(call get-product-makefiles,\
+    $(SRC_TARGET_DIR)/product/AndroidProducts.mk)
 else
-  # Read in all of the product definitions specified by the AndroidProducts.mk
-  # files in the tree.
-  #
-  #TODO: when we start allowing direct pointers to product files,
-  #    guarantee that they're in this list.
-  $(call import-products, $(get-all-product-makefiles))
-endif # TARGET_BUILD_APPS
+# Read in all of the product definitions specified by the AndroidProducts.mk
+# files in the tree.
+all_product_configs := $(get-all-product-makefiles)
+endif
+
+# Find the product config makefile for the current product.
+# all_product_configs consists items like:
+# <product_name>:<path_to_the_product_makefile>
+# or just <path_to_the_product_makefile> in case the product name is the
+# same as the base filename of the product config makefile.
+current_product_makefile :=
+all_product_makefiles :=
+$(foreach f, $(all_product_configs),\
+    $(eval _cpm_words := $(subst :,$(space),$(f)))\
+    $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
+    $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
+    $(if $(_cpm_word2),\
+        $(eval all_product_makefiles += $(_cpm_word2))\
+        $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
+            $(eval current_product_makefile += $(_cpm_word2)),),\
+        $(eval all_product_makefiles += $(f))\
+        $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
+            $(eval current_product_makefile += $(f)),)))
+_cpm_words :=
+_cpm_word1 :=
+_cpm_word2 :=
+current_product_makefile := $(strip $(current_product_makefile))
+all_product_makefiles := $(strip $(all_product_makefiles))
+
+ifneq (,$(filter product-graph dump-products, $(MAKECMDGOALS)))
+# Import all product makefiles.
+$(call import-products, $(all_product_makefiles))
+else
+# Import just the current product.
+ifndef current_product_makefile
+$(error Can not locate config makefile for product "$(TARGET_PRODUCT)")
+endif
+ifneq (1,$(words $(current_product_makefile)))
+$(error Product "$(TARGET_PRODUCT)" ambiguous: matches $(current_product_makefile))
+endif
+$(call import-products, $(current_product_makefile))
+endif  # Import all or just the current product makefile
+
+# Sanity check
 $(check-all-products)
 
 ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
@@ -203,7 +240,12 @@
 # file defining that product.
 #
 INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))
-#$(error TARGET_PRODUCT $(TARGET_PRODUCT) --> $(INTERNAL_PRODUCT))
+ifneq ($(current_product_makefile),$(INTERNAL_PRODUCT))
+$(error PRODUCT_NAME inconsistent in $(current_product_makefile) and $(INTERNAL_PRODUCT))
+endif
+current_product_makefile :=
+all_product_makefiles :=
+all_product_configs :=
 
 # Find the device that this product maps to.
 TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 4f624d8..108e30b 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -25,7 +25,7 @@
 CTS_TF_EXEC_PATH := $(HOST_OUT_EXECUTABLES)/cts-tradefed
 CTS_TF_README_PATH := $(cts_tools_src_dir)/tradefed-host/README
 
-VMTESTSTF_INTERMEDIATES :=$(call intermediates-dir-for,EXECUTABLES,vm-tests-tf,1,)
+VMTESTSTF_INTERMEDIATES :=$(call intermediates-dir-for,JAVA_LIBRARIES,vm-tests-tf,HOST)
 VMTESTSTF_JAR := $(VMTESTSTF_INTERMEDIATES)/android.core.vm-tests-tf.jar
 
 CTS_CORE_CASE_LIST := \
diff --git a/core/tasks/product-graph.mk b/core/tasks/product-graph.mk
index 6442252..1ccb20b 100644
--- a/core/tasks/product-graph.mk
+++ b/core/tasks/product-graph.mk
@@ -14,35 +14,127 @@
 # limitations under the License.
 #
 
-products_pdf := $(OUT_DIR)/products.pdf
-products_graph := $(products_pdf:%.pdf=%.dot)
+# the foreach and the if remove the single space entries that creep in because of the evals
+define gather-all-products
+$(sort $(foreach p, \
+	$(eval _all_products_visited := )
+  $(call all-products-inner, $(ALL_PRODUCTS)) \
+	, $(if $(strip $(p)),$(strip $(p)),)) \
+)
+endef
 
-$(products_graph):
-	@echo Product graph DOT: $@
+define all-products-inner
+	$(foreach p,$(1),\
+		$(if $(filter $(p),$(_all_products_visited)),, \
+			$(p) \
+			$(eval _all_products_visited += $(p)) \
+			$(call all-products-inner, $(PRODUCTS.$(strip $(p)).INHERITS_FROM))
+		) \
+	)
+endef
+
+
+this_makefile := build/core/tasks/product-graph.mk
+
+products_svg := $(OUT_DIR)/products.svg
+products_pdf := $(OUT_DIR)/products.pdf
+products_graph := $(OUT_DIR)/products.dot
+ifeq ($(strip $(ANDROID_PRODUCT_GRAPH)),)
+products_list := $(INTERNAL_PRODUCT)
+else
+ifeq ($(strip $(ANDROID_PRODUCT_GRAPH)),--all)
+products_list := --all
+else
+products_list := $(foreach prod,$(ANDROID_PRODUCT_GRAPH),$(call resolve-short-product-name,$(prod)))
+endif
+endif
+
+really_all_products := $(call gather-all-products)
+
+$(products_graph): PRIVATE_PRODUCTS := $(really_all_products)
+$(products_graph): PRIVATE_PRODUCTS_FILTER := $(products_list)
+
+$(products_graph): $(this_makefile)
+	@echo Product graph DOT: $@ for $(PRIVATE_PRODUCTS_FILTER)
 	$(hide) ( \
 		echo 'digraph {'; \
 		echo 'graph [ ratio=.5 ];'; \
-		$(foreach p,$(ALL_PRODUCTS), \
-			$(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), \
-			echo \"$(d)\" -\> \"$(p)\";)) \
-		$(foreach prod, \
-			$(sort $(foreach p,$(ALL_PRODUCTS), \
-				$(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), \
-					$(d))) \
-				$(foreach p,$(ALL_PRODUCTS),$(p))), \
-			echo \"$(prod)\" [ label=\"$(dir $(prod))\\n$(notdir $(prod))\"];) \
+		$(foreach p,$(PRIVATE_PRODUCTS), \
+			$(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), echo \"$(d)\" -\> \"$(p)\";)) \
+		$(foreach prod, $(PRIVATE_PRODUCTS), \
+			echo \"$(prod)\" [ \
+					label=\"$(dir $(prod))\\n$(notdir $(prod))\\n\\n$(PRODUCTS.$(strip $(prod)).PRODUCT_MODEL)\\n$(PRODUCTS.$(strip $(prod)).PRODUCT_DEVICE)\" \
+					$(if $(filter $(prod),$(PRIVATE_PRODUCTS_FILTER)), style=\"filled\" fillcolor=\"#FFFDB0\",) \
+					fontcolor=\"darkblue\" href=\"products/$(prod).html\" \
+				];) \
 		echo '}' \
-	) > $@
+	) \
+	| ./build/tools/filter-product-graph.py $(PRIVATE_PRODUCTS_FILTER) \
+	> $@
 
-# This rule doesn't include any nodes that don't inherit from
-# anything or don't have anything inherit from them, to make the
-# graph more readable.  To add that, add this line to the rule
-# below:
-#		$(foreach p,$(ALL_PRODUCTS), echo \"$(p)\";) \
+# Evaluates to the name of the product file
+# $(1) product file
+define product-debug-filename
+$(OUT_DIR)/products/$(strip $(1)).html
+endef
+
+# Makes a rule for the product debug info
+# $(1) product file
+define transform-product-debug
+$(OUT_DIR)/products/$(strip $(1)).txt: $(this_makefile)
+	@echo Product debug info file: $$@
+	$(hide) rm -f $$@
+	$(hide) mkdir -p $$(dir $$@)
+	$(hide) echo 'FILE=$(strip $(1))' >> $$@
+	$(hide) echo 'PRODUCT_NAME=$$(PRODUCTS.$(strip $(1)).PRODUCT_NAME)' >> $$@
+	$(hide) echo 'PRODUCT_MODEL=$$(PRODUCTS.$(strip $(1)).PRODUCT_MODEL)' >> $$@
+	$(hide) echo 'PRODUCT_LOCALES=$$(PRODUCTS.$(strip $(1)).PRODUCT_LOCALES)' >> $$@
+	$(hide) echo 'PRODUCT_AAPT_CONFIG=$$(PRODUCTS.$(strip $(1)).PRODUCT_AAPT_CONFIG)' >> $$@
+	$(hide) echo 'PRODUCT_AAPT_PREF_CONFIG=$$(PRODUCTS.$(strip $(1)).PRODUCT_AAPT_PREF_CONFIG)' >> $$@
+	$(hide) echo 'PRODUCT_PACKAGES=$$(PRODUCTS.$(strip $(1)).PRODUCT_PACKAGES)' >> $$@
+	$(hide) echo 'PRODUCT_DEVICE=$$(PRODUCTS.$(strip $(1)).PRODUCT_DEVICE)' >> $$@
+	$(hide) echo 'PRODUCT_MANUFACTURER=$$(PRODUCTS.$(strip $(1)).PRODUCT_MANUFACTURER)' >> $$@
+	$(hide) echo 'PRODUCT_PROPERTY_OVERRIDES=$$(PRODUCTS.$(strip $(1)).PRODUCT_PROPERTY_OVERRIDES)' >> $$@
+	$(hide) echo 'PRODUCT_DEFAULT_PROPERTY_OVERRIDES=$$(PRODUCTS.$(strip $(1)).PRODUCT_DEFAULT_PROPERTY_OVERRIDES)' >> $$@
+	$(hide) echo 'PRODUCT_CHARACTERISTICS=$$(PRODUCTS.$(strip $(1)).PRODUCT_CHARACTERISTICS)' >> $$@
+	$(hide) echo 'PRODUCT_COPY_FILES=$$(PRODUCTS.$(strip $(1)).PRODUCT_COPY_FILES)' >> $$@
+	$(hide) echo 'PRODUCT_OTA_PUBLIC_KEYS=$$(PRODUCTS.$(strip $(1)).PRODUCT_OTA_PUBLIC_KEYS)' >> $$@
+	$(hide) echo 'PRODUCT_EXTRA_RECOVERY_KEYS=$$(PRODUCTS.$(strip $(1)).PRODUCT_EXTRA_RECOVERY_KEYS)' >> $$@
+	$(hide) echo 'PRODUCT_PACKAGE_OVERLAYS=$$(PRODUCTS.$(strip $(1)).PRODUCT_PACKAGE_OVERLAYS)' >> $$@
+	$(hide) echo 'DEVICE_PACKAGE_OVERLAYS=$$(PRODUCTS.$(strip $(1)).DEVICE_PACKAGE_OVERLAYS)' >> $$@
+	$(hide) echo 'PRODUCT_TAGS=$$(PRODUCTS.$(strip $(1)).PRODUCT_TAGS)' >> $$@
+	$(hide) echo 'PRODUCT_SDK_ADDON_NAME=$$(PRODUCTS.$(strip $(1)).PRODUCT_SDK_ADDON_NAME)' >> $$@
+	$(hide) echo 'PRODUCT_SDK_ADDON_COPY_FILES=$$(PRODUCTS.$(strip $(1)).PRODUCT_SDK_ADDON_COPY_FILES)' >> $$@
+	$(hide) echo 'PRODUCT_SDK_ADDON_COPY_MODULES=$$(PRODUCTS.$(strip $(1)).PRODUCT_SDK_ADDON_COPY_MODULES)' >> $$@
+	$(hide) echo 'PRODUCT_SDK_ADDON_DOC_MODULES=$$(PRODUCTS.$(strip $(1)).PRODUCT_SDK_ADDON_DOC_MODULES)' >> $$@
+	$(hide) echo 'PRODUCT_DEFAULT_WIFI_CHANNELS=$$(PRODUCTS.$(strip $(1)).PRODUCT_DEFAULT_WIFI_CHANNELS)' >> $$@
+	$(hide) echo 'PRODUCT_DEFAULT_DEV_CERTIFICATE=$$(PRODUCTS.$(strip $(1)).PRODUCT_DEFAULT_DEV_CERTIFICATE)' >> $$@
+	$(hide) echo 'PRODUCT_RESTRICT_VENDOR_FILES=$$(PRODUCTS.$(strip $(1)).PRODUCT_RESTRICT_VENDOR_FILES)' >> $$@
+	$(hide) echo 'PRODUCT_FACTORY_RAMDISK_MODULES=$$(PRODUCTS.$(strip $(1)).PRODUCT_FACTORY_RAMDISK_MODULES)' >> $$@
+	$(hide) echo 'PRODUCT_VENDOR_KERNEL_HEADERS=$$(PRODUCTS.$(strip $(1)).PRODUCT_VENDOR_KERNEL_HEADERS)' >> $$@
+
+$(call product-debug-filename, $(p)): \
+			$(OUT_DIR)/products/$(strip $(1)).txt \
+			build/tools/product_debug.py \
+			$(this_makefile)
+	@echo Product debug html file: $$@
+	$(hide) mkdir -p $$(dir $$@)
+	$(hide) cat $$< | build/tools/product_debug.py > $$@
+endef
+
+product_debug_files:=
+$(foreach p,$(really_all_products), \
+			$(eval $(call transform-product-debug, $(p))) \
+			$(eval product_debug_files += $(call product-debug-filename, $(p))) \
+   )
 
 $(products_pdf): $(products_graph)
 	@echo Product graph PDF: $@
 	dot -Tpdf -Nshape=box -o $@ $<
 
-product-graph: $(products_pdf)
+$(products_svg): $(products_graph) $(product_debug_files)
+	@echo Product graph SVG: $@
+	dot -Tsvg -Nshape=box -o $@ $<
+
+product-graph: $(products_pdf) $(products_svg)
 
diff --git a/core/user_tags.mk b/core/user_tags.mk
deleted file mode 100644
index e13969c..0000000
--- a/core/user_tags.mk
+++ /dev/null
@@ -1,499 +0,0 @@
-#
-# Copyright (C) 2010 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 the list of modules grandfathered to use a user tag
-
-# DO NOT ADD ANY NEW MODULE TO THIS FILE
-#
-# user modules are hard to control and audit and we don't want
-# to add any new such module in the system
-
-GRANDFATHERED_USER_MODULES :=
-
--include vendor/google/user_tags.mk
-
-GRANDFATHERED_USER_MODULES += \
-	20-dns.conf \
-	95-configured \
-	aapt \
-	acp \
-	adb \
-	AdbWinApi \
-	AdbWinUsbApi \
-	adbd \
-	aidl \
-	am \
-	android \
-	android-common \
-	android-common-carousel \
-	android.policy \
-	androidprefs \
-	android.test.runner \
-	ant \
-	antlr-2.7.7 \
-	anttasks \
-	apicheck \
-	apkcheck \
-	applypatch \
-	app_process \
-	archquery \
-	atree \
-	audio \
-	badblocks \
-	badblocks_host \
-	bb2sym \
-	bb_dump \
-	bbprof \
-	bcc \
-	bison \
-	bluetoothd \
-	bmgr \
-	bootanimation \
-	brcm_patchram_plus \
-	bugreport \
-	cfassembler \
-	check_stack \
-	check_trace \
-	com.android.phone.common \
-	com.android.vcard \
-	commons-compress-1.0 \
-	content \
-	copybit.qsd8k \
-	copybit.s5pc110 \
-	coverage \
-	cpufeatures \
-	cts \
-	CtsAppSecurityTests \
-	cts-dalvik-buildutil \
-	dasm \
-	dbus-daemon \
-	ddmlib \
-	ddmlib-prebuilt \
-	ddmlibTests \
-	ddms \
-	ddmuilib \
-	debuggerd \
-	descGen \
-	dexgen \
-	dexpreopt \
-	dex-tools \
-	dhcpcd \
-	dhcpcd.conf \
-	dhcpcd-run-hooks \
-	dictTest \
-	dnsmasq \
-	doclava \
-	draw9patch \
-	dumpeventlog \
-	dumpkey \
-	dump_regions \
-	dumpstate \
-	dumpsys \
-	dx-tests \
-	e2fsck \
-	e2fsck_host \
-	easymock \
-	easymocklib \
-	edify \
-	elftree \
-	emmalib \
-	emulator \
-	emulator-arm \
-	emulator-mips \
-	emulator-core \
-	emulator-elff \
-	emulator-hw \
-	emulator-memcheck \
-	emulator-tcg \
-	emulator-ui \
-	etc1tool \
-	eventanalyzer \
-	exc_dump \
-	fastboot \
-	framework \
-	FrameworkCoreHostTests \
-	frameworks-core-util-lib \
-	fsck_msdos \
-	fs_get_stats \
-	fw_bcm4329_apsta.bin \
-	fw_bcm4329.bin \
-	genext2fs \
-	gps.mahimahi \
-	gralloc.default \
-	gralloc.qsd8k \
-	groovy-all-1.7.0 \
-	grxmlcompile \
-	guava \
-	guavalib \
-	gzip \
-	hciattach \
-	hierarchyviewer \
-	hierarchyviewer1 \
-	hierarchyviewer2 \
-	hierarchyviewerlib \
-	hist_trace \
-	hosttestlib \
-	icudata \
-	idegen \
-	ime \
-	init \
-	input \
-	ip \
-	jarjar \
-	javax.obex \
-	jcommon-1.0.12 \
-	jdiff \
-	jdwpspy \
-	jfreechart-1.0.9 \
-	jfreechart-1.0.9-swt \
-	jsilver \
-	jsr305 \
-	jsr305lib \
-	junit \
-	jython \
-	kxml2-2.3.0 \
-	launch-wrapper \
-	layoutlib \
-	layoutlib_api \
-	layoutlib_create \
-	layoutlib_utils \
-	liba2dp \
-	libabi \
-	libandroid \
-	libandroid_runtime \
-	libandroid_servers \
-	libarity \
-	libastl \
-	libastl_host \
-	libaudio \
-	libaudioeffect_jni \
-	libaudioflinger \
-	libaudiointerface \
-	libaudiopolicy \
-	libaudiopolicybase \
-	libbinder \
-	libbluedroid \
-	libbluetooth \
-	libbluetoothd \
-	libbuiltinplugin \
-	libbundlewrapper \
-	libbz \
-	libc \
-	libcamera_client \
-	libcameraservice \
-	libcamerastub \
-	libc_common \
-	libchromium_net \
-	libc_nomalloc \
-	libctest \
-	libcutils \
-	libdb \
-	libdbus \
-	libdiskconfig \
-	libdiskconfig_host \
-	libdl \
-	libdrm1 \
-	libdrm1_jni \
-	libebl \
-	libebl_arm \
-	libebl_sh \
-	libebl_mips \
-	libedify \
-	libeffects \
-	libEGL \
-	libelf \
-	libESR_Portable \
-	libESR_Shared \
-	libETC1 \
-	libext \
-	libext2_blkid \
-	libext2_blkid_host \
-	libext2_com_err \
-	libext2_com_err_host \
-	libext2_e2p \
-	libext2_e2p_host \
-	libext2fs \
-	libext2fs_host \
-	libext2_profile \
-	libext2_profile_host \
-	libext2_uuid \
-	libext2_uuid_host \
-	libfdlibm \
-	libfdlibm-host \
-	libFFTEm \
-	libfst \
-	libft2 \
-	libgdbus_static \
-	libgif \
-	libGLES_android \
-	libGLESv1_CM \
-	libGLESv2 \
-	libglib \
-	libgui \
-	libhardware \
-	libhardware_legacy \
-	libhost \
-	libhyphenation \
-	libiprouteutil \
-	libiptc \
-	libjnigraphics \
-	libjni_latinime \
-	libjpeg \
-	libjs \
-	liblinenoise \
-	libloc_api-rpc \
-	liblog \
-	libm \
-	libmedia \
-	libmedia_jni \
-	libmediaplayerservice \
-	libmincrypt \
-	libminelf \
-	libminui \
-	libminzip \
-	libmtdutils \
-	libmtp \
-	libmusicbundle \
-	libneo_cgi \
-	libneo_cs \
-	libneo_util \
-	libnetlink \
-	libnetutils \
-	libop \
-	libOpenSLES \
-	libopensles_helper \
-	libOpenSLESUT \
-	libpcap \
-	libpixelflinger \
-	libpixelflinger_static \
-	libpng \
-	libpopt \
-	libpower \
-	libprotobuf-cpp-2.3.0-full \
-	libprotobuf-cpp-2.3.0-lite \
-	libprotobuf-java-2.3.0-lite \
-	libprotobuf-java-2.3.0-micro \
-	librecovery_ui_htc \
-	libreference-ril \
-	libreverb \
-	libreverbwrapper \
-	libril \
-	librilproto-java \
-	librpc \
-	librtp_jni \
-	libsafe_iop \
-	libSDL \
-	libSDLmain \
-	libsensorservice \
-	libskia \
-	libskiagl \
-	libsonivox \
-	libsoundpool \
-	libspeex \
-	libsqlite \
-	libsqlite3_android \
-	libSR_AcousticModels \
-	libSR_AcousticState \
-	libSR_AudioIn \
-	libSR_Core \
-	libSR_EventLog \
-	libSR_G2P \
-	libSR_Grammar \
-	libSR_Nametag \
-	libSR_Recognizer \
-	libSR_Semproc \
-	libSR_Session \
-	libSR_Vocabulary \
-	libstagefright \
-	libstagefright_aacdec \
-	libstagefright_aacenc \
-	libstagefright_amrnb_common \
-	libstagefright_amrnbdec \
-	libstagefright_amrnbenc \
-	libstagefright_amrwbdec \
-	libstagefright_amrwbenc \
-	libstagefright_avc_common \
-	libstagefright_avcdec \
-	libstagefright_avcenc \
-	libstagefright_color_conversion \
-	libstagefright_enc_common \
-	libstagefright_foundation \
-	libstagefright_g711dec \
-	libstagefright_httplive \
-	libstagefrighthw \
-	libstagefright_id3 \
-	libstagefright_m4vh263dec \
-	libstagefright_m4vh263enc \
-	libstagefright_matroska \
-	libstagefright_mp3dec \
-	libstagefright_mpeg2ts \
-	libstagefright_omx \
-	libstagefright_rtsp \
-	libstagefright_vorbisdec \
-	libstagefright_vpxdec \
-	libstagefright_yuv \
-	libstdc++ \
-	libstlport \
-	libstlport_static \
-	libstorage \
-	libsurfaceflinger \
-	libsurfaceflinger_client \
-	libsvoxpico \
-	libsystem_server \
-	libsysutils \
-	libthread_db \
-	libtinyxml \
-	libtomcrypt \
-	libtommath \
-	libttspico \
-	libttssynthproxy \
-	libui \
-	libunz \
-	libusbhost \
-	libutil \
-	libutils \
-	libv8 \
-	libvisualizer \
-	libvorbisidec \
-	libvpx \
-	libwebcore \
-	libwpa_client \
-	libwrapsim \
-	libxml2 \
-	libxslt \
-	libzipfile \
-	lights.kraken \
-	lights.qsd8k \
-	line_endings \
-	linker \
-	llvm-rs-link \
-	localize \
-	logcat \
-	logwrapper \
-	lsd \
-	make_cfst \
-	makedict \
-	make_ext4fs \
-	make_g2g \
-	makekeycodes \
-	make_ve_grammar \
-	mediaserver \
-	minigzip \
-	mkbootfs \
-	mkbootimg \
-	mke2fs \
-	mke2fs_host \
-	mksdcard \
-	mksnapshot \
-	mkstubs \
-	mkuserimg.sh \
-	mkyaffs2image \
-	mockrilcontroller \
-	monkey \
-	monkeyrunner \
-	MonkeyRunnerTest \
-	mtp \
-	mtpd \
-	ndc \
-	netcfg \
-	netd \
-	network \
-	ninepatch \
-	oauth \
-	obbtool \
-	omx_tests \
-	org.eclipse.core.commands_3.4.0.I20080509-2000 \
-	org.eclipse.equinox.common_3.4.0.v20080421-2006 \
-	org.eclipse.jface_3.4.2.M20090107-0800 \
-	org-netbeans-api-visual \
-	org-openide-util \
-	osgi \
-	pand \
-	parseStringTest \
-	ping \
-	platform.xml \
-	pm \
-	post_trace \
-	pppd \
-	preload \
-	profile_pid \
-	profile_trace \
-	q2dm \
-	q2g \
-	qemu-android \
-	racoon \
-	read_addr \
-	read_method \
-	read_pid \
-	read_trace \
-	resize2fs \
-	resize2fs_host \
-	rgb2565 \
-	rsg-generator \
-	run-as \
-	runtime \
-	schedtest \
-	screenshot \
-	screenshot2 \
-	sdcard \
-	sdklauncher \
-	sdklib \
-	sdkmanager \
-	sdkstats \
-	sdkuilib \
-	sdk_v4 \
-	sdk_v5 \
-	sdk_v6 \
-	sdk_v7 \
-	sdk_v8 \
-	sdptool \
-	service \
-	servicemanager \
-	services \
-	sig \
-	sig-check \
-	sig-create \
-	signapk \
-	signature-tools \
-	spec-progress \
-	sqlite3 \
-	stack_dump \
-	stringtemplate \
-	surfaceflinger \
-	svc \
-	swing-worker-1.1 \
-	swt \
-	system_server \
-	tblgen \
-	tc \
-	temp_layoutlib \
-	test_g2g \
-	test-progress \
-	test-progress-new \
-	test_swiarb \
-	test_zipfile \
-	toolbox \
-	traceview \
-	tune2fs \
-	tune2fs_host \
-	usbtest \
-	vdc \
-	vm-tests \
-	vold \
-	wdsclient \
-	wpa_supplicant \
-	yuv420sp2rgb \
-	zipalign
diff --git a/envsetup.sh b/envsetup.sh
index 2da629d..4a1321a 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -784,7 +784,7 @@
        fi
 
        echo >|"$OUT_ROOT/gdbclient.cmds" "set solib-absolute-prefix $OUT_SYMBOLS"
-       echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $OUT_SO_SYMBOLS:$OUT_SO_SYMBOLS/hw:$OUT_SO_SYMBOLS/ssl/engines"
+       echo >>"$OUT_ROOT/gdbclient.cmds" "set solib-search-path $OUT_SO_SYMBOLS:$OUT_SO_SYMBOLS/hw:$OUT_SO_SYMBOLS/ssl/engines:$OUT_SO_SYMBOLS/drm:$OUT_SO_SYMBOLS/egl:$OUT_SO_SYMBOLS/soundfx"
        echo >>"$OUT_ROOT/gdbclient.cmds" "target remote $PORT"
        echo >>"$OUT_ROOT/gdbclient.cmds" ""
 
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 9279633..e8ce9df 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -18,6 +18,12 @@
 # This file should set PRODUCT_MAKEFILES to a list of product makefiles
 # to expose to the build system.  LOCAL_DIR will already be set to
 # the directory containing this file.
+# PRODUCT_MAKEFILES is set up in AndroidProducts.mks.
+# Format of PRODUCT_MAKEFILES:
+# <product_name>:<path_to_the_product_makefile>
+# If the <product_name> is the same as the base file name (without dir
+# and the .mk suffix) of the product makefile, "<product_name>:" can be
+# omitted.
 #
 # This file may not rely on the value of any variable other than
 # LOCAL_DIR; do not use any conditionals, and do not look up the
diff --git a/target/product/base.mk b/target/product/base.mk
new file mode 100644
index 0000000..afde9b5
--- /dev/null
+++ b/target/product/base.mk
@@ -0,0 +1,147 @@
+#
+# Copyright (C) 2012 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.
+#
+
+# Base modules (will move elsewhere, previously user tagged)
+PRODUCT_PACKAGES += \
+    20-dns.conf \
+    95-configured \
+    adb \
+    adbd \
+    am \
+    android.policy \
+    android.test.runner \
+    app_process \
+    applypatch \
+    bmgr \
+    bootanimation \
+    bugreport \
+    content \
+    dbus-daemon \
+    debuggerd \
+    dhcpcd \
+    dhcpcd-run-hooks \
+    dnsmasq \
+    dumpstate \
+    dumpsys \
+    framework \
+    fsck_msdos \
+    gralloc.default \
+    gzip \
+    ime \
+    init \
+    input \
+    javax.obex \
+    libEGL \
+    libETC1 \
+    libFFTEm \
+    libGLES_android \
+    libGLESv1_CM \
+    libGLESv2 \
+    libSR_AudioIn \
+    libandroid \
+    libandroid_runtime \
+    libandroid_servers \
+    libaudioeffect_jni \
+    libaudioflinger \
+    libbinder \
+    libbundlewrapper \
+    libc \
+    libcamera_client \
+    libcameraservice \
+    libchromium_net \
+    libctest \
+    libcutils \
+    libdbus \
+    libdl \
+    libdrm1 \
+    libdrm1_jni \
+    libeffects \
+    libgui \
+    libhardware \
+    libhardware_legacy \
+    libiprouteutil \
+    libjni_latinime \
+    libjnigraphics \
+    libjpeg \
+    liblog \
+    libm \
+    libmedia \
+    libmedia_jni \
+    libmediaplayerservice \
+    libmtp \
+    libnetlink \
+    libnetutils \
+    libpixelflinger \
+    libpower \
+    libreference-ril \
+    libreverbwrapper \
+    libril \
+    librtp_jni \
+    libsensorservice \
+    libskia \
+    libsonivox \
+    libsoundpool \
+    libsqlite \
+    libstagefright \
+    libstagefright_amrnb_common \
+    libstagefright_avc_common \
+    libstagefright_enc_common \
+    libstagefright_foundation \
+    libstagefright_omx \
+    libstagefright_yuv \
+    libstdc++ \
+    libstlport \
+    libsurfaceflinger \
+    libsurfaceflinger_client \
+    libsystem_server \
+    libsysutils \
+    libthread_db \
+    libui \
+    libusbhost \
+    libutils \
+    libvisualizer \
+    libvorbisidec \
+    libwebcore \
+    libwpa_client \
+    linker \
+    logcat \
+    logwrapper \
+    mediaserver \
+    monkey \
+    mtpd \
+    ndc \
+    netcfg \
+    netd \
+    ping \
+    platform.xml \
+    pppd \
+    pm \
+    racoon \
+    run-as \
+    schedtest \
+    screenshot \
+    sdcard \
+    service \
+    servicemanager \
+    services \
+    surfaceflinger \
+    svc \
+    system_server \
+    tc \
+    toolbox \
+    vdc \
+    vold
+
diff --git a/target/product/core.mk b/target/product/core.mk
index d637bd4..87872d6 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -22,7 +22,7 @@
     ro.config.notification_sound=OnTheHunt.ogg \
     ro.config.alarm_alert=Alarm_Classic.ogg
 
-PRODUCT_PACKAGES := \
+PRODUCT_PACKAGES += \
     ApplicationsProvider \
     BackupRestoreConfirmation \
     Browser \
@@ -114,6 +114,7 @@
     libwebrtc_audio_preprocessing \
     libwilhelm \
     libz \
+    make_ext4fs \
     mdnsd \
     requestsync \
     screencap \
@@ -157,3 +158,6 @@
         property_contexts \
         mac_permissions.xml
 endif
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)
+
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index 0c6e9ac..049d7c0 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -45,6 +45,22 @@
     wpa_supplicant.conf
 
 PRODUCT_PACKAGES += \
+    audio \
+    bluetoothd \
+    brcm_patchram_plus \
+    dhcpcd.conf \
+    hciattach \
+    libbluedroid \
+    libbluetooth \
+    libbluetoothd \
+    libglib \
+    network \
+    pand \
+    pppd \
+    sdptool \
+    wpa_supplicant
+
+PRODUCT_PACKAGES += \
     icu.dat
 
 PRODUCT_PACKAGES += \
diff --git a/target/product/mini.mk b/target/product/mini.mk
index 8a74428..5db6f3d 100644
--- a/target/product/mini.mk
+++ b/target/product/mini.mk
@@ -51,6 +51,7 @@
     ro.config.notification_sound=OnTheHunt.ogg \
     ro.config.alarm_alert=Alarm_Classic.ogg
 
+# Please keep this list sorted alphabetically
 PRODUCT_PACKAGES += \
     ApplicationsProvider \
     ContactsProvider \
@@ -63,6 +64,8 @@
     TelephonyProvider \
     UserDictionaryProvider \
     apache-xml \
+    audio \
+    bluetoothd \
     bouncycastle \
     bu \
     cacerts \
@@ -80,6 +83,7 @@
     dx \
     ext \
     framework-res \
+    hciattach \
     hprof-conv \
     icu.dat \
     installd \
@@ -133,11 +137,15 @@
     libwebrtc_audio_preprocessing \
     libwilhelm \
     libz \
+    lint \
     mdnsd \
+    network \
+    pand \
     requestsync \
     screencap \
+    sdptool \
     sensorservice \
-    lint
+    wpa_supplicant
 
 PRODUCT_COPY_FILES += \
     system/core/rootdir/init.usb.rc:root/init.usb.rc \
@@ -202,6 +210,7 @@
     ro.config.ringtone=Ring_Synth_04.ogg \
     ro.config.notification_sound=pixiedust.ogg
 
+$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)
 $(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk)
 $(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk)
 $(call inherit-product-if-exists, frameworks/base/data/sounds/AudioPackage5.mk)
diff --git a/tools/check_builds.sh b/tools/check_builds.sh
index fd380dd..c255bf0 100644
--- a/tools/check_builds.sh
+++ b/tools/check_builds.sh
@@ -41,7 +41,7 @@
     do
         rm -rf $TEST_BUILD_DIR/$PREFIX-$1
         make PRODUCT-$(echo $1 | sed "s/-.*//" )-installclean
-        make -j6 PRODUCT-$1 dist DIST_DIR=$TEST_BUILD_DIR/$PREFIX-$1
+        make -j16 PRODUCT-$1 dist DIST_DIR=$TEST_BUILD_DIR/$PREFIX-$1
         if [ $? -ne 0 ] ; then
             echo FAILED
             return
diff --git a/tools/filter-product-graph.py b/tools/filter-product-graph.py
new file mode 100755
index 0000000..b3a5b42
--- /dev/null
+++ b/tools/filter-product-graph.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# vim: ts=2 sw=2 nocindent
+
+import re
+import sys
+
+def choose_regex(regs, line):
+  for func,reg in regs:
+    m = reg.match(line)
+    if m:
+      return (func,m)
+  return (None,None)
+
+def gather(included, deps):
+  result = set()
+  for inc in included:
+    result.add(inc)
+    for d in deps:
+      if inc == d[1]:
+        result.add(d[0])
+  return result
+
+def main():
+  deps = []
+  infos = []
+  def dependency(m):
+    deps.append((m.group(1), m.group(2)))
+  def info(m):
+    infos.append((m.group(1), m.group(2)))
+
+  REGS = [
+      (dependency, re.compile(r'"(.*)"\s*->\s*"(.*)"')), 
+      (info, re.compile(r'"(.*)"(\s*\[.*\])')), 
+    ]
+
+  lines = sys.stdin.readlines()
+  lines = [line.strip() for line in lines]
+
+  for line in lines:
+    func,m = choose_regex(REGS, line)
+    if func:
+      func(m)
+
+  # filter
+  sys.stderr.write("argv: " + str(sys.argv) + "\n")
+  if not (len(sys.argv) == 2 and sys.argv[1] == "--all"):
+    targets = sys.argv[1:]
+
+    included = set(targets)
+    prevLen = -1
+    while prevLen != len(included):
+      prevLen = len(included)
+      included = gather(included, deps)
+
+    deps = [dep for dep in deps if dep[1] in included]
+    infos = [info for info in infos if info[0] in included]
+
+  print "digraph {"
+  print "graph [ ratio=.5 ];"
+  for dep in deps:
+    print '"%s" -> "%s"' % dep
+  for info in infos:
+    print '"%s"%s' % info
+  print "}"
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/findleaves.py b/tools/findleaves.py
index 52c4d9f..3a9e508 100755
--- a/tools/findleaves.py
+++ b/tools/findleaves.py
@@ -28,7 +28,7 @@
   pruneleaves = set(map(lambda x: os.path.split(x)[1], prune))
   for rootdir in dirlist:
     rootdepth = rootdir.count("/")
-    for root, dirs, files in os.walk(rootdir):
+    for root, dirs, files in os.walk(rootdir, followlinks=True):
       # prune
       check_prune = False
       for d in dirs:
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
index 5486bc2..5ef32dd 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -18,6 +18,5 @@
 LOCAL_SRC_FILES := fs_config.c
 LOCAL_MODULE := fs_config
 LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE_TAGS := eng
 
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/parsedeps.py b/tools/parsedeps.py
new file mode 100755
index 0000000..32d8ad7
--- /dev/null
+++ b/tools/parsedeps.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+# vim: ts=2 sw=2
+
+import optparse
+import re
+import sys
+
+
+class Dependency:
+  def __init__(self, tgt):
+    self.tgt = tgt
+    self.pos = ""
+    self.prereqs = set()
+    self.visit = 0
+
+  def add(self, prereq):
+    self.prereqs.add(prereq)
+
+
+class Dependencies:
+  def __init__(self):
+    self.lines = {}
+    self.__visit = 0
+    self.count = 0
+
+  def add(self, tgt, prereq):
+    t = self.lines.get(tgt)
+    if not t:
+      t = Dependency(tgt)
+      self.lines[tgt] = t
+    p = self.lines.get(prereq)
+    if not p:
+      p = Dependency(prereq)
+      self.lines[prereq] = p
+    t.add(p)
+    self.count = self.count + 1
+
+  def setPos(self, tgt, pos):
+    t = self.lines.get(tgt)
+    if not t:
+      t = Dependency(tgt)
+      self.lines[tgt] = t
+    t.pos = pos
+
+  def get(self, tgt):
+    if self.lines.has_key(tgt):
+      return self.lines[tgt]
+    else:
+      return None
+
+  def __iter__(self):
+    return self.lines.iteritems()
+
+  def trace(self, tgt, prereq):
+    self.__visit = self.__visit + 1
+    d = self.lines.get(tgt)
+    if not d:
+      return
+    return self.__trace(d, prereq)
+
+  def __trace(self, d, prereq):
+    if d.visit == self.__visit:
+      return d.trace
+    if d.tgt == prereq:
+      return [ [ d ], ]
+    d.visit = self.__visit
+    result = []
+    for pre in d.prereqs:
+      recursed = self.__trace(pre, prereq)
+      for r in recursed:
+        result.append([ d ] + r)
+    d.trace = result
+    return result
+
+def help():
+  print "Commands:"
+  print "  dep TARGET             Print the prerequisites for TARGET"
+  print "  trace TARGET PREREQ    Print the paths from TARGET to PREREQ"
+
+
+def main(argv):
+  opts = optparse.OptionParser()
+  opts.add_option("-i", "--interactive", action="store_true", dest="interactive",
+                    help="Interactive mode")
+  (options, args) = opts.parse_args()
+
+  deps = Dependencies()
+
+  filename = args[0]
+  print "Reading %s" % filename
+
+  if True:
+    f = open(filename)
+    for line in f:
+      line = line.strip()
+      if len(line) > 0:
+        if line[0] == '#':
+          pos,tgt = line.rsplit(":", 1)
+          pos = pos[1:].strip()
+          tgt = tgt.strip()
+          deps.setPos(tgt, pos)
+        else:
+          (tgt,prereq) = line.split(':', 1)
+          tgt = tgt.strip()
+          prereq = prereq.strip()
+          deps.add(tgt, prereq)
+    f.close()
+
+  print "Read %d dependencies. %d targets." % (deps.count, len(deps.lines))
+  while True:
+    line = raw_input("target> ")
+    if not line.strip():
+      continue
+    split = line.split()
+    cmd = split[0]
+    if len(split) == 2 and cmd == "dep":
+      tgt = split[1]
+      d = deps.get(tgt)
+      if d:
+        for prereq in d.prereqs:
+          print prereq.tgt
+    elif len(split) == 3 and cmd == "trace":
+      tgt = split[1]
+      prereq = split[2]
+      if False:
+        print "from %s to %s" % (tgt, prereq)
+      trace = deps.trace(tgt, prereq)
+      if trace:
+        width = 0
+        for g in trace:
+          for t in g:
+            if len(t.tgt) > width:
+              width = len(t.tgt)
+        for g in trace:
+          for t in g:
+            if t.pos:
+              print t.tgt, " " * (width-len(t.tgt)), "  #", t.pos
+            else:
+              print t.tgt
+          print
+    else:
+      help()
+
+if __name__ == "__main__":
+  try:
+    main(sys.argv)
+  except KeyboardInterrupt:
+    print
+  except EOFError:
+    print
+
diff --git a/tools/product_debug.py b/tools/product_debug.py
new file mode 100755
index 0000000..661c5b7
--- /dev/null
+++ b/tools/product_debug.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import re
+import sys
+
+def break_lines(key, val):
+  # these don't get split
+  if key in ("PRODUCT_MODEL"):
+    return (key,val)
+  return (key, "\n".join(val.split()))
+
+def split_line(line):
+  words = line.split("=", 1)
+  if len(words) == 1:
+    return (words[0], "")
+  else:
+    return (words[0], words[1])
+
+def sort_lines(text):
+  lines = text.split()
+  lines.sort()
+  return "\n".join(lines)
+
+def parse_variables(lines):
+  return [split_line(line) for line in lines if line.strip()]
+
+def render_variables(variables):
+  variables = dict(variables)
+  del variables["FILE"]
+  variables = list(variables.iteritems())
+  variables.sort(lambda a, b: cmp(a[0], b[0]))
+  return ("<table id='variables'>"
+      + "\n".join([ "<tr><th>%(key)s</th><td>%(val)s</td></tr>" % { "key": key, "val": val }
+        for key,val in variables])
+      +"</table>")
+
+def linkify_inherit(variables, text, func_name):
+  groups = re.split("(\\$\\(call " + func_name + ",.*\\))", text)
+  result = ""
+  for i in range(0,len(groups)/2):
+    i = i * 2
+    result = result + groups[i]
+    s = groups[i+1]
+    href = s.split(",", 1)[1].strip()[:-1]
+    href = href.replace("$(SRC_TARGET_DIR)", "build/target")
+    href = ("../" * variables["FILE"].count("/")) + href + ".html"
+    result = result + "<a href=\"%s\">%s</a>" % (href,s)
+  result = result + groups[-1]
+  return result
+
+def render_original(variables, text):
+  text = linkify_inherit(variables, text, "inherit-product")
+  text = linkify_inherit(variables, text, "inherit-product-if-exists")
+  return text
+
+def read_file(fn):
+  f = file(fn)
+  text = f.read()
+  f.close()
+  return text
+
+def main(argv):
+  # read the variables
+  lines = sys.stdin.readlines()
+  variables = parse_variables(lines)
+
+  # format the variables
+  variables = [break_lines(key,val) for key,val in variables]
+
+  # now it's a dict
+  variables = dict(variables)
+
+  sorted_vars = (
+      "PRODUCT_COPY_FILES",
+      "PRODUCT_PACKAGES",
+      "PRODUCT_LOCALES",
+      "PRODUCT_FACTORY_RAMDISK_MODULES",
+      "PRODUCT_PROPERTY_OVERRIDES",
+    )
+
+  for key in sorted_vars:
+    variables[key] = sort_lines(variables[key])
+
+  # the original file
+  original = read_file(variables["FILE"])
+
+  # formatting
+  values = dict(variables)
+  values.update({
+    "variables": render_variables(variables),
+    "original": render_original(variables, original),
+  })
+  print """<html>
+
+
+<head>
+  <title>%(FILE)s</title>
+  <style type="text/css">
+    body {
+      font-family: Helvetica, Arial, sans-serif;
+      padding-bottom: 20px;
+    }
+    #variables {
+      border-collapse: collapse;
+    }
+    #variables th, #variables td {
+      vertical-align: top;
+      text-align: left;
+      border-top: 1px solid #c5cdde;
+      border-bottom: 1px solid #c5cdde;
+      padding: 2px 10px 2px 10px;
+    }
+    #variables th {
+      font-size: 10pt;
+      background-color: #e2ecff
+    }
+    #variables td {
+      background-color: #ebf2ff;
+      white-space: pre;
+      font-size: 10pt;
+    }
+    #original {
+      background-color: #ebf2ff;
+      border-top: 1px solid #c5cdde;
+      border-bottom: 1px solid #c5cdde;
+      padding: 2px 10px 2px 10px;
+      white-space: pre;
+      font-size: 10pt;
+    }
+  </style>
+</head>
+<body>
+<h1>%(FILE)s</h1>
+<a href="#Original">Original</a>
+<a href="#Variables">Variables</a>
+<h2><a name="Original"></a>Original</h2>
+<div id="original">%(original)s</div>
+<h2><a name="Variables"></a>Variables</h2>
+%(variables)s
+</body>
+</html>
+""" % values
+
+if __name__ == "__main__":
+  main(sys.argv)
diff --git a/tools/zipalign/Android.mk b/tools/zipalign/Android.mk
index 9763bd2..089c68b 100644
--- a/tools/zipalign/Android.mk
+++ b/tools/zipalign/Android.mk
@@ -28,6 +28,10 @@
 LOCAL_LDLIBS += -lz
 endif
 
+ifneq ($(strip $(BUILD_HOST_static)),)
+LOCAL_LDLIBS += -lpthread
+endif # BUILD_HOST_static
+
 LOCAL_MODULE := zipalign
 
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index c2d8159..8b2d1af 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -125,7 +125,7 @@
             ZipFile::kOpenReadWrite|ZipFile::kOpenCreate|ZipFile::kOpenTruncate)
         != NO_ERROR)
     {
-        fprintf(stderr, "Unable to open '%s' as zip archive\n", inFileName);
+        fprintf(stderr, "Unable to open '%s' as zip archive\n", outFileName);
         return 1;
     }