Merge "load SYSTEM/build.prop into the info_dict" into jb-mr1-dev
diff --git a/core/Makefile b/core/Makefile
index 4dde9f4..3d0bf5a 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1416,7 +1416,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 09c2586..808b952 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -58,51 +58,30 @@
 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 necessary, if 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.
 #
 # If the local directory or one of its parents contains a MODULE_LICENSE_GPL
@@ -116,27 +95,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 :=
@@ -543,6 +506,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
 
 
@@ -592,6 +565,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/binary.mk b/core/binary.mk
index e17efa4..e10ec9c 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -161,31 +161,29 @@
 ###########################################################
 ## Define PRIVATE_ variables from global vars
 ###########################################################
-ifeq ($(strip $(LOCAL_CLANG)),true)
-my_target_global_cflags := $(TARGET_GLOBAL_CLANG_FLAGS)
-else
-my_target_global_cflags := $(TARGET_GLOBAL_CFLAGS)
-endif
-
 ifdef LOCAL_SDK_VERSION
 my_target_project_includes :=
 my_target_c_includes := $(my_ndk_stl_include_path) $(my_ndk_version_root)/usr/include
-# TODO: more reliable way to remove platform stuff.
-my_target_global_cflags := $(filter-out -include -I system/%, $(my_target_global_cflags))
-my_target_global_cppflags := $(filter-out -include -I system/%, $(TARGET_GLOBAL_CPPFLAGS))
+
+# filter out including of AndroidConfig.h in system/core.
+TARGET_GLOBAL_CFLAGS_NO_ANDCONF ?= $(subst $(TARGET_ANDROID_CONFIG_CFLAGS),,\
+    $(TARGET_GLOBAL_CFLAGS))
+my_target_global_cflags := $(TARGET_GLOBAL_CFLAGS_NO_ANDCONF)
 else
 my_target_project_includes := $(TARGET_PROJECT_INCLUDES)
 my_target_c_includes := $(TARGET_C_INCLUDES)
-my_target_global_cflags := $(my_target_global_cflags)
-my_target_global_cppflags := $(TARGET_GLOBAL_CPPFLAGS)
 ifeq ($(strip $(LOCAL_CLANG)),true)
-  my_target_c_includes += $(CLANG_CONFIG_EXTRA_TARGET_C_INCLUDES)
-endif
-endif
+my_target_c_includes += $(CLANG_CONFIG_EXTRA_TARGET_C_INCLUDES)
+my_target_global_cflags := $(TARGET_GLOBAL_CLANG_FLAGS)
+else
+my_target_global_cflags := $(TARGET_GLOBAL_CFLAGS)
+endif # LOCAL_CLANG
+endif # LOCAL_SDK_VERSION
+
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_PROJECT_INCLUDES := $(my_target_project_includes)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_C_INCLUDES := $(my_target_c_includes)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CFLAGS := $(my_target_global_cflags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CPPFLAGS := $(my_target_global_cppflags)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_GLOBAL_CPPFLAGS := $(TARGET_GLOBAL_CPPFLAGS)
 
 ###########################################################
 ## Define PRIVATE_ variables used by multiple module types
diff --git a/core/combo/HOST_darwin-x86.mk b/core/combo/HOST_darwin-x86.mk
index d263869..9e14b51 100644
--- a/core/combo/HOST_darwin-x86.mk
+++ b/core/combo/HOST_darwin-x86.mk
@@ -64,8 +64,10 @@
 HOST_SHLIB_SUFFIX := .dylib
 HOST_JNILIB_SUFFIX := .jnilib
 
+ifeq (,$(TARGET_BUILD_APPS))
 HOST_GLOBAL_CFLAGS += \
     -include $(call select-android-config-h,darwin-x86)
+endif
 ifneq ($(filter 10.7 10.7.% 10.8 10.8.%, $(build_mac_version)),)
        HOST_RUN_RANLIB_AFTER_COPYING := false
 else
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index b369199..cb5f004 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -58,8 +58,10 @@
 endif # BUILD_HOST_static
 
 HOST_GLOBAL_CFLAGS += -fPIC
+ifeq (,$(TARGET_BUILD_APPS))
 HOST_GLOBAL_CFLAGS += \
 	-include $(call select-android-config-h,linux-x86)
+endif
 
 # Disable new longjmp in glibc 2.11 and later. See bug 2967937.
 HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 71f2d5a..d47f95f 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -60,7 +60,7 @@
         TARGET_STRIP_COMMAND = $(TARGET_STRIP) --strip-all $< -o $@
     else
         TARGET_STRIP_COMMAND = $(TARGET_STRIP) --strip-all $< -o $@ && \
-	    $(TARGET_OBJCOPY) --add-gnu-debuglink=$< $@
+            $(TARGET_OBJCOPY) --add-gnu-debuglink=$< $@
     endif
 endif
 
@@ -98,9 +98,6 @@
   TARGET_thumb_CFLAGS += -marm -fno-omit-frame-pointer
 endif
 
-android_config_h := $(call select-android-config-h,linux-arm)
-arch_include_dir := $(dir $(android_config_h))
-
 TARGET_GLOBAL_CFLAGS += \
 			-msoft-float -fpic -fPIE \
 			-ffunction-sections \
@@ -111,9 +108,11 @@
 			-Werror=format-security \
 			-D_FORTIFY_SOURCE=1 \
 			-fno-short-enums \
-			$(arch_variant_cflags) \
-			-include $(android_config_h) \
-			-I $(arch_include_dir)
+			$(arch_variant_cflags)
+
+android_config_h := $(call select-android-config-h,linux-arm)
+TARGET_ANDROID_CONFIG_CFLAGS := -include $(android_config_h) -I $(dir $(android_config_h))
+TARGET_GLOBAL_CFLAGS += $(TARGET_ANDROID_CONFIG_CFLAGS)
 
 # 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
@@ -147,9 +146,9 @@
 # since sometimes thumb-interwork appears to be default), we
 # specifically disable when thumb support is unavailable.
 ifeq ($(ARCH_ARM_HAVE_THUMB_SUPPORT),true)
-TARGET_GLOBAL_CFLAGS +=	-mthumb-interwork
+TARGET_GLOBAL_CFLAGS += -mthumb-interwork
 else
-TARGET_GLOBAL_CFLAGS +=	-mno-thumb-interwork
+TARGET_GLOBAL_CFLAGS += -mno-thumb-interwork
 endif
 
 TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
@@ -274,7 +273,7 @@
 define transform-o-to-executable-inner
 $(hide) $(PRIVATE_CXX) -nostdlib -Bdynamic -fPIE -pie \
 	-Wl,-dynamic-linker,/system/bin/linker \
-    -Wl,--gc-sections \
+	-Wl,--gc-sections \
 	-Wl,-z,nocopyreloc \
 	-o $@ \
 	$(TARGET_GLOBAL_LD_DIRS) \
@@ -297,7 +296,7 @@
 
 define transform-o-to-static-executable-inner
 $(hide) $(PRIVATE_CXX) -nostdlib -Bstatic \
-    -Wl,--gc-sections \
+	-Wl,--gc-sections \
 	-o $@ \
 	$(TARGET_GLOBAL_LD_DIRS) \
 	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(TARGET_CRTBEGIN_STATIC_O)) \
diff --git a/core/combo/TARGET_linux-mips.mk b/core/combo/TARGET_linux-mips.mk
index f89873e..0cf7964 100644
--- a/core/combo/TARGET_linux-mips.mk
+++ b/core/combo/TARGET_linux-mips.mk
@@ -60,7 +60,7 @@
         TARGET_STRIP_COMMAND = $(TARGET_STRIP) --strip-all $< -o $@
     else
         TARGET_STRIP_COMMAND = $(TARGET_STRIP) --strip-all $< -o $@ && \
-	    $(TARGET_OBJCOPY) --add-gnu-debuglink=$< $@
+            $(TARGET_OBJCOPY) --add-gnu-debuglink=$< $@
     endif
 endif
 
@@ -78,9 +78,6 @@
   TARGET_mips_CFLAGS += -fno-omit-frame-pointer
 endif
 
-android_config_h := $(call select-android-config-h,linux-mips)
-arch_include_dir := $(dir $(android_config_h))
-
 TARGET_GLOBAL_CFLAGS += \
 			$(TARGET_mips_CFLAGS) \
 			-Ulinux -U__unix -U__unix__ -Umips \
@@ -89,9 +86,11 @@
 			-fdata-sections \
 			-funwind-tables \
 			-Werror=format-security \
-			$(arch_variant_cflags) \
-			-include $(android_config_h) \
-			-I $(arch_include_dir)
+			$(arch_variant_cflags)
+
+android_config_h := $(call select-android-config-h,linux-mips)
+TARGET_ANDROID_CONFIG_CFLAGS := -include $(android_config_h) -I $(dir $(android_config_h))
+TARGET_GLOBAL_CFLAGS += $(TARGET_ANDROID_CONFIG_CFLAGS)
 
 # 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
diff --git a/core/combo/TARGET_linux-x86.mk b/core/combo/TARGET_linux-x86.mk
index bf6daf8..396bc3a 100644
--- a/core/combo/TARGET_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -93,8 +93,11 @@
 			-fno-short-enums \
 			-fstrict-aliasing \
 			-funswitch-loops \
-			-funwind-tables \
-			-include $(call select-android-config-h,target_linux-x86)
+			-funwind-tables
+
+android_config_h := $(call select-android-config-h,target_linux-x86)
+TARGET_ANDROID_CONFIG_CFLAGS := -include $(android_config_h) -I $(dir $(android_config_h))
+TARGET_GLOBAL_CFLAGS += $(TARGET_ANDROID_CONFIG_CFLAGS)
 
 # XXX: Not sure this is still needed. Must check with our toolchains.
 TARGET_GLOBAL_CPPFLAGS += \
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/definitions.mk b/core/definitions.mk
index bf8ce58..0f9dc30 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:=
@@ -2054,10 +2059,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/envsetup.mk b/core/envsetup.mk
index aa4ea77..2ad6801 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 49367ec..def9f62 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,51 +589,55 @@
 
 # -------------------------------------------------------------------
 # 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) \
-        $(call module-installed-files, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_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) \
         $(call module-installed-files, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG)) \
     )
+eng_MODULES := $(sort \
+        $(call get-tagged-modules,eng) \
+        $(call module-installed-files, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_ENG)) \
+    )
 tests_MODULES := $(sort \
         $(call get-tagged-modules,tests) \
         $(call module-installed-files, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_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.
@@ -666,19 +668,21 @@
   # Ensure every module listed in PRODUCT_PACKAGES* gets something installed
   # TODO: Should we do this for all builds and not just the sdk?
   $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES), \
-      $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
-          $(error Module '$(m)' in PRODUCT_PACKAGES has nothing to install!)))
+    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
+      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES has nothing to install!)))
   $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_DEBUG), \
-      $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
-          $(error Module '$(m)' in PRODUCT_PACKAGES_DEBUG has nothing to install!)))
+    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
+      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_DEBUG has nothing to install!)))
   $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_ENG), \
-      $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
-          $(error Module '$(m)' in PRODUCT_PACKAGES_ENG has nothing to install!)))
+    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
+      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_ENG has nothing to install!)))
   $(foreach m, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES_TESTS), \
-      $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
-          $(error Module '$(m)' in PRODUCT_PACKAGES_TESTS has nothing to install!)))
+    $(if $(strip $(ALL_MODULES.$(m).INSTALLED)),,\
+      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_TESTS 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
@@ -691,6 +695,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))
@@ -903,3 +908,7 @@
 .PHONY: showcommands
 showcommands:
 	@echo >/dev/null
+
+.PHONY: nothing
+nothing:
+	@echo Successfully read the makefiles.
diff --git a/core/product_config.mk b/core/product_config.mk
index ea3e517..9c85d2c 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -199,6 +199,12 @@
 $(error done)
 endif
 
+ifeq (a,b)
+$(info PRODUCTS -----------)
+$(foreach product, $(PRODUCTS), $(info $(PRODUCTS.$(product).PRODUCT_NAME)))# $(product)))
+$(error stop)
+endif
+
 # Convert a short name like "sooner" into the path to the product
 # file defining that product.
 #
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 517af49..0000000
--- a/core/user_tags.mk
+++ /dev/null
@@ -1,498 +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_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/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 4c2ca92..0b4dbea 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 \
@@ -163,3 +163,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 3f0242b..3987e88 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -47,6 +47,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 668bf89..e3fc1b7 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 \
@@ -64,6 +65,8 @@
     UserDictionaryProvider \
     abcc \
     apache-xml \
+    audio \
+    bluetoothd \
     bouncycastle \
     bu \
     cacerts \
@@ -81,6 +84,7 @@
     dx \
     ext \
     framework-res \
+    hciattach \
     hprof-conv \
     icu.dat \
     installd \
@@ -138,13 +142,17 @@
     libwebrtc_audio_preprocessing \
     libwilhelm \
     libz \
+    lint \
     mdnsd \
+    mms-common \
+    network \
+    pand \
     requestsync \
     screencap \
+    sdptool \
     sensorservice \
-    lint \
     telephony-common \
-    mms-common
+    wpa_supplicant
 
 PRODUCT_COPY_FILES += \
     system/core/rootdir/init.usb.rc:root/init.usb.rc \
@@ -211,6 +219,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/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)