am c80298b0: am 557528a1: am 3f5fee62: am c942e879: fix sac search

* commit 'c80298b08d47023fd5c259ce066089149ff7b6e3':
  fix sac search
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 59b7d68..998be2a 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -152,6 +152,12 @@
 
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
 
+# GCC 4.7
+$(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 7e6dead..507a198 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -156,7 +156,14 @@
 endef
 
 BUILDINFO_SH := build/tools/buildinfo.sh
-$(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
+
+ifdef TARGET_SYSTEM_PROP
+system_prop_file := $(TARGET_SYSTEM_PROP)
+else
+system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
+endif
+
+$(INSTALLED_BUILD_PROP_TARGET): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file)
 	@echo Target buildinfo: $@
 	@mkdir -p $(dir $@)
 	$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
@@ -183,8 +190,8 @@
 			TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
 			TARGET_AAPT_CHARACTERISTICS="$(TARGET_AAPT_CHARACTERISTICS)" \
 	        bash $(BUILDINFO_SH) > $@
-	$(hide) if [ -f $(TARGET_DEVICE_DIR)/system.prop ]; then \
-	          cat $(TARGET_DEVICE_DIR)/system.prop >> $@; \
+	$(hide) if [ -f "$(system_prop_file)" ]; then \
+	          cat $(system_prop_file) >> $@; \
 	        fi
 	$(if $(ADDITIONAL_BUILD_PROPERTIES), \
 		$(hide) echo >> $@; \
@@ -240,6 +247,12 @@
 
 # -----------------------------------------------------------------
 # Cert-to-package mapping.  Used by the post-build signing tools.
+# Use a macro to add newline to each echo command
+define _apkcerts_echo_with_newline
+$(hide) echo $(1)
+
+endef
+
 name := $(TARGET_PRODUCT)
 ifeq ($(TARGET_BUILD_TYPE),debug)
   name := $(name)_debug
@@ -254,13 +267,15 @@
 	@echo APK certs list: $@
 	@mkdir -p $(dir $@)
 	@rm -f $@
-	$(hide) $(foreach p,$(PACKAGES),\
-          $(if $(PACKAGES.$(p).EXTERNAL_KEY),\
-	    echo 'name="$(p).apk" certificate="EXTERNAL" \
-	         private_key=""' >> $@;,\
-	    echo 'name="$(p).apk" certificate="$(PACKAGES.$(p).CERTIFICATE)" \
-	         private_key="$(PACKAGES.$(p).PRIVATE_KEY)"' >> $@;))
-	# In case $(PACKAGES) is empty.
+	$(foreach p,$(PACKAGES),\
+	  $(if $(PACKAGES.$(p).EXTERNAL_KEY),\
+	    $(call _apkcerts_echo_with_newline,\
+	      'name="$(p).apk" certificate="EXTERNAL" \
+	      private_key=""' >> $@),\
+	    $(call _apkcerts_echo_with_newline,\
+	      'name="$(p).apk" certificate="$(PACKAGES.$(p).CERTIFICATE)" \
+	      private_key="$(PACKAGES.$(p).PRIVATE_KEY)"' >> $@)))
+	# In case value of PACKAGES is empty.
 	$(hide) touch $@
 
 .PHONY: apkcerts-list
@@ -562,6 +577,9 @@
 endif
 INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS)))
 
+SELINUX_FC := $(TARGET_ROOT_OUT)/file_contexts
+INTERNAL_USERIMAGES_DEPS += $(SELINUX_FC)
+
 # $(1): the path of the output dictionary file
 define generate-userimage-prop-dictionary
 $(if $(INTERNAL_USERIMAGES_EXT_VARIANT),$(hide) echo "fs_type=$(INTERNAL_USERIMAGES_EXT_VARIANT)" >> $(1))
@@ -571,7 +589,7 @@
 $(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1))
 $(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1))
 $(if $(mkyaffs2_extra_flags),$(hide) echo "mkyaffs2_extra_flags=$(mkyaffs2_extra_flags)" >> $(1))
-$(if $(filter true, $(strip $(HAVE_SELINUX))), echo "selinux_fc=$(TARGET_ROOT_OUT)/file_contexts" >> $(1))
+$(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(1)
 endef
 
 # -----------------------------------------------------------------
@@ -591,7 +609,11 @@
 recovery_resources_private := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery/res))
 recovery_resource_deps := $(shell find $(recovery_resources_common) \
   $(recovery_resources_private) -type f)
+ifdef TARGET_RECOVERY_FSTAB
+recovery_fstab := $(TARGET_RECOVERY_FSTAB)
+else
 recovery_fstab := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery.fstab))
+endif
 # Named '.dat' so we don't attempt to use imgdiff for patching it.
 RECOVERY_RESOURCE_ZIP := $(TARGET_OUT)/etc/recovery-resource.dat
 
@@ -1432,7 +1454,6 @@
 	$(atree_dir)/sdk.atree \
 	$(sdk_tools_atree_files) \
 	$(HOST_OUT_EXECUTABLES)/atree \
-	$(ALL_HOST_INSTALLED_FILES) \
 	$(HOST_OUT_EXECUTABLES)/line_endings
 
 INTERNAL_SDK_TARGET := $(sdk_dir)/$(sdk_name).zip
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 07ef024..baa8932 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -435,7 +435,6 @@
 cleantarget := clean-$(LOCAL_MODULE)
 $(cleantarget) : PRIVATE_MODULE := $(LOCAL_MODULE)
 $(cleantarget) : PRIVATE_CLEAN_FILES := \
-    $(PRIVATE_CLEAN_FILES) \
     $(LOCAL_BUILT_MODULE) \
     $(LOCAL_INSTALLED_MODULE) \
     $(intermediates)
@@ -516,17 +515,6 @@
 
 $(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
 
 
diff --git a/core/build_id.mk b/core/build_id.mk
index 09f1779..e954794 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -23,7 +23,7 @@
 # (like "TC1-RC5").  It must be a single word, and is
 # capitalized by convention.
 #
-BUILD_ID := JB_MR1.1
+BUILD_ID := OPENMASTER
 
 # DISPLAY_BUILD_NUMBER should only be set for development branches,
 # If set, the BUILD_NUMBER (cl) is appended to the BUILD_ID for
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index 1b662b9..9a30990 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -191,7 +191,9 @@
 	$(PRODUCT_OUT)/system \
 	$(PRODUCT_OUT)/dex_bootjars \
 	$(PRODUCT_OUT)/obj/JAVA_LIBRARIES \
-	$(PRODUCT_OUT)/obj/FAKE
+	$(PRODUCT_OUT)/obj/FAKE \
+	$(PRODUCT_OUT)/obj/ETC/mac_permissions.xml_intermediates \
+	$(PRODUCT_OUT)/obj/ETC/sepolicy_intermediates
 
 # The files/dirs to delete during a dataclean, which removes any files
 # in the staging and emulator data partitions.
diff --git a/core/combo/HOST_darwin-x86.mk b/core/combo/HOST_darwin-x86.mk
index 5b9f8f3..7361ce9 100644
--- a/core/combo/HOST_darwin-x86.mk
+++ b/core/combo/HOST_darwin-x86.mk
@@ -36,52 +36,69 @@
 
 build_mac_version := $(shell sw_vers -productVersion)
 
-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
+mac_sdk_versions_supported :=  10.6 10.7 10.8
+ifneq ($(strip $(MAC_SDK_VERSION)),)
+mac_sdk_version := $(MAC_SDK_VERSION)
+ifeq ($(filter $(mac_sdk_version),$(mac_sdk_versions_supported)),)
+$(warning ****************************************************************)
+$(warning * MAC_SDK_VERSION $(MAC_SDK_VERSION) isn't one of the supported $(mac_sdk_versions_supported))
+$(warning ****************************************************************)
+$(error Stop.)
+endif
 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_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
+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
+# try /Applications/Xcode*.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.?.sdk
+#  or /Volume/Xcode/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
+ifeq ($(wildcard $(mac_sdk_root)),)
+# try legacy /Developer/SDKs/MacOSX10.?.sdk
+mac_sdk_root := /Developer/SDKs/MacOSX$(mac_sdk_version).sdk
 endif
-
 ifeq ($(wildcard $(mac_sdk_root)),)
 $(warning *****************************************************)
-$(warning * Cannot find SDK $(mac_sdk_version) at $(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 * Can not find SDK $(mac_sdk_version) at $(mac_sdk_root))
 $(warning *****************************************************)
 $(error Stop.)
 endif
 
+ifeq ($(mac_sdk_version),10.6)
+  gcc_darwin_version := 10
+else
+  gcc_darwin_version := 11
+endif
+
+HOST_TOOLCHAIN_ROOT := prebuilts/gcc/darwin-x86/host/i686-apple-darwin-4.2.1
+HOST_TOOLCHAIN_PREFIX := $(HOST_TOOLCHAIN_ROOT)/bin/i686-apple-darwin$(gcc_darwin_version)
+# Don't do anything if the toolchain is not there
+ifneq (,$(strip $(wildcard $(HOST_TOOLCHAIN_PREFIX)-gcc)))
+HOST_CC  := $(HOST_TOOLCHAIN_PREFIX)-gcc
+HOST_CXX := $(HOST_TOOLCHAIN_PREFIX)-g++
+ifeq ($(mac_sdk_version),10.8)
+# Mac SDK 10.8 no longer has stdarg.h, etc
+host_toolchain_header := $(HOST_TOOLCHAIN_ROOT)/lib/gcc/i686-apple-darwin$(gcc_darwin_version)/4.2.1/include
+HOST_GLOBAL_CFLAGS += -isystem $(host_toolchain_header)
+endif
+else
+HOST_CC := gcc
+HOST_CXX := g++
+endif # $(HOST_TOOLCHAIN_PREFIX)-gcc exists
+HOST_AR := $(AR)
+HOST_STRIP := $(STRIP)
+HOST_STRIP_COMMAND = $(HOST_STRIP) --strip-debug $< -o $@
+
 HOST_GLOBAL_CFLAGS += -isysroot $(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version) -DMACOSX_DEPLOYMENT_TARGET=$(mac_sdk_version)
 HOST_GLOBAL_LDFLAGS += -isysroot $(mac_sdk_root) -Wl,-syslibroot,$(mac_sdk_root) -mmacosx-version-min=$(mac_sdk_version)
 
 HOST_GLOBAL_CFLAGS += -fPIC -funwind-tables
 HOST_NO_UNDEFINED_LDFLAGS := -Wl,-undefined,error
 
-HOST_CC := gcc
-HOST_CXX := g++
-HOST_AR := $(AR)
-HOST_STRIP := $(STRIP)
-HOST_STRIP_COMMAND = $(HOST_STRIP) --strip-debug $< -o $@
-
 HOST_SHLIB_SUFFIX := .dylib
 HOST_JNILIB_SUFFIX := .jnilib
 
diff --git a/core/combo/HOST_linux-x86.mk b/core/combo/HOST_linux-x86.mk
index 28c8f8c..2d586a3 100644
--- a/core/combo/HOST_linux-x86.mk
+++ b/core/combo/HOST_linux-x86.mk
@@ -22,23 +22,15 @@
 stat --format "%s" "$(1)" | tr -d '\n'
 endef
 
-# Special case for the Linux SDK: We need to use a special cross-toolchain
-# that generates machine code that will run properly on Ubuntu 8.04 (Hardy)
-# By default, the code generated by the Lucid host toolchain will not run
-# on previous versions of the platform, due to GLibc ABI mistmatches
-# (Lucid is 2.11, Hardy is 2.7)
-#
-# Note that components that need to be built as 64-bit (e.g. clearsilver
-# which is loaded by the 64-bit JVM through JNI), will have to use
-# LOCAL_CC and LOCAL_CXX to override this.
-#
-HOST_SDK_TOOLCHAIN_PREFIX := prebuilts/tools/gcc-sdk
+# Previously the prebiult host toolchain is used only for the sdk build,
+# that's why we have "sdk" in the path name.
+HOST_TOOLCHAIN_PREFIX := prebuilts/tools/gcc-sdk
 # Don't do anything if the toolchain is not there
-ifneq (,$(strip $(wildcard $(HOST_SDK_TOOLCHAIN_PREFIX)/gcc)))
-HOST_CC  := $(HOST_SDK_TOOLCHAIN_PREFIX)/gcc
-HOST_CXX := $(HOST_SDK_TOOLCHAIN_PREFIX)/g++
-HOST_AR  := $(HOST_SDK_TOOLCHAIN_PREFIX)/ar
-endif # $(HOST_SDK_TOOLCHAIN_PREFIX)/gcc exists
+ifneq (,$(strip $(wildcard $(HOST_TOOLCHAIN_PREFIX)/gcc)))
+HOST_CC  := $(HOST_TOOLCHAIN_PREFIX)/gcc
+HOST_CXX := $(HOST_TOOLCHAIN_PREFIX)/g++
+HOST_AR  := $(HOST_TOOLCHAIN_PREFIX)/ar
+endif # $(HOST_TOOLCHAIN_PREFIX)/gcc exists
 
 ifneq ($(strip $(BUILD_HOST_64bit)),)
 # By default we build everything in 32-bit, because it gives us
@@ -48,7 +40,8 @@
 HOST_GLOBAL_CFLAGS += -m64
 HOST_GLOBAL_LDFLAGS += -m64
 else
-HOST_GLOBAL_CFLAGS += -m32
+# We expect SSE3 floating point math.
+HOST_GLOBAL_CFLAGS += -mstackrealign -msse3 -mfpmath=sse -m32
 HOST_GLOBAL_LDFLAGS += -m32
 endif # BUILD_HOST_64bit
 
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 854037d..ca14651 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -34,6 +34,12 @@
 TARGET_ARCH_VARIANT := armv5te
 endif
 
+ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
+TARGET_GCC_VERSION := 4.7
+else
+TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
+endif
+
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
 $(error Unknown ARM architecture version: $(TARGET_ARCH_VARIANT))
@@ -43,7 +49,7 @@
 
 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
 ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
-TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-4.6
+TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-$(TARGET_GCC_VERSION)
 TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/arm-linux-androideabi-
 endif
 
@@ -71,18 +77,11 @@
                         -fstrict-aliasing    \
                         -funswitch-loops
 
-# Modules can choose to compile some source as thumb. As
-# non-thumb enabled targets are supported, this is treated
-# as a 'hint'. If thumb is not enabled, these files are just
-# compiled as ARM.
-ifeq ($(ARCH_ARM_HAVE_THUMB_SUPPORT),true)
+# Modules can choose to compile some source as thumb.
 TARGET_thumb_CFLAGS :=  -mthumb \
                         -Os \
                         -fomit-frame-pointer \
                         -fno-strict-aliasing
-else
-TARGET_thumb_CFLAGS := $(TARGET_arm_CFLAGS)
-endif
 
 # Set FORCE_ARM_DEBUGGING to "true" in your buildspec.mk
 # or in your environment to force a full arm build, even for
@@ -114,11 +113,11 @@
 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.
+# This warning causes dalvik not to build with gcc 4.6+ and -Werror.
 # 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 4.6.%, $(shell $(TARGET_CC) --version)),)
+ifneq ($(filter 4.6 4.6.% 4.7 4.7.%, $(shell $(TARGET_CC) --version)),)
 TARGET_GLOBAL_CFLAGS += -Wno-unused-but-set-variable -fno-builtin-sin \
 			-fno-strict-volatile-bitfields
 endif
@@ -141,15 +140,7 @@
 			-Wl,--icf=safe \
 			$(arch_variant_ldflags)
 
-# We only need thumb interworking in cases where thumb support
-# is available in the architecture, and just to be sure, (and
-# 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
-else
-TARGET_GLOBAL_CFLAGS += -mno-thumb-interwork
-endif
 
 TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
 
@@ -242,11 +233,6 @@
 
 TARGET_CUSTOM_LD_COMMAND := true
 
-# Enable the Dalvik JIT compiler if not already specified.
-ifeq ($(strip $(WITH_JIT)),)
-    WITH_JIT := true
-endif
-
 define transform-o-to-shared-lib-inner
 $(hide) $(PRIVATE_CXX) \
 	-nostdlib -Wl,-soname,$(notdir $@) \
@@ -261,6 +247,7 @@
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
+	$(PRIVATE_TARGET_LIBGCC) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
@@ -275,10 +262,8 @@
 	-Wl,-dynamic-linker,/system/bin/linker \
 	-Wl,--gc-sections \
 	-Wl,-z,nocopyreloc \
-	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
 	-Wl,-rpath-link=$(TARGET_OUT_INTERMEDIATE_LIBRARIES) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O)) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
@@ -287,6 +272,9 @@
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
+	$(PRIVATE_TARGET_LIBGCC) \
+	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_TARGET_FDO_LIB) \
diff --git a/core/combo/TARGET_linux-mips.mk b/core/combo/TARGET_linux-mips.mk
index 7c7a9ef..41928f8 100644
--- a/core/combo/TARGET_linux-mips.mk
+++ b/core/combo/TARGET_linux-mips.mk
@@ -34,6 +34,12 @@
 TARGET_ARCH_VARIANT := mips32r2-fp
 endif
 
+ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
+TARGET_GCC_VERSION := 4.7
+else
+TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
+endif
+
 TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk
 ifeq ($(strip $(wildcard $(TARGET_ARCH_SPECIFIC_MAKEFILE))),)
 $(error Unknown MIPS architecture variant: $(TARGET_ARCH_VARIANT))
@@ -43,7 +49,7 @@
 
 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
 ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
-TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mipsel-linux-android-4.6
+TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mipsel-linux-android-$(TARGET_GCC_VERSION)
 TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/mipsel-linux-android-
 endif
 
@@ -81,21 +87,23 @@
 TARGET_GLOBAL_CFLAGS += \
 			$(TARGET_mips_CFLAGS) \
 			-Ulinux -U__unix -U__unix__ -Umips \
-			-fpic \
+			-fpic -fPIE\
 			-ffunction-sections \
 			-fdata-sections \
 			-funwind-tables \
+			-Wa,--noexecstack \
 			-Werror=format-security \
+			-D_FORTIFY_SOURCE=1 \
 			$(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.
+# This warning causes dalvik not to build with gcc 4.6+ and -Werror.
 # We cannot turn it off blindly since the option is not available
 # in gcc-4.4.x.
-ifneq ($(filter 4.6 4.6.%, $(shell $(TARGET_CC) --version)),)
+ifneq ($(filter 4.6 4.6.% 4.7 4.7.%, $(shell $(TARGET_CC) --version)),)
 TARGET_GLOBAL_CFLAGS += -Wno-unused-but-set-variable \
                         -fno-strict-volatile-bitfields
 endif
@@ -115,10 +123,13 @@
 endif
 
 TARGET_GLOBAL_LDFLAGS += \
+			-Wl,-z,noexecstack \
+			-Wl,-z,relro \
+			-Wl,-z,now \
+			-Wl,--warn-shared-textrel \
 			$(arch_variant_ldflags)
 
-TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden \
-				-fno-use-cxa-atexit
+TARGET_GLOBAL_CPPFLAGS += -fvisibility-inlines-hidden
 
 # More flags/options can be added here
 TARGET_RELEASE_CFLAGS := \
@@ -154,7 +165,7 @@
 TARGET_FDO_LIB:=
 
 target_libgcov := $(shell $(TARGET_CC) $(TARGET_GLOBAL_CFLAGS) \
-        --print-file-name=libgcov.a)
+        -print-file-name=libgcov.a)
 ifneq ($(strip $(BUILD_FDO_INSTRUMENT)),)
   # Set BUILD_FDO_INSTRUMENT=true to turn on FDO instrumentation.
   # The profile will be generated on /data/local/tmp/profile on the device.
@@ -214,16 +225,11 @@
 
 TARGET_CUSTOM_LD_COMMAND := true
 
-# Enable the Dalvik JIT compiler if not already specified.
-ifeq ($(strip $(WITH_JIT)),)
-    WITH_JIT := true
-endif
-
 define transform-o-to-shared-lib-inner
 $(hide) $(PRIVATE_CXX) \
 	-nostdlib -Wl,-soname,$(notdir $@) \
 	-Wl,--gc-sections \
-	-shared -Bsymbolic \
+	-Wl,-shared,-Bsymbolic \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
 	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_SO_O)) \
 	$(PRIVATE_ALL_OBJECTS) \
@@ -233,6 +239,7 @@
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
+	$(PRIVATE_TARGET_LIBGCC) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
@@ -243,19 +250,23 @@
 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 \
-	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
 	-Wl,-rpath-link=$(TARGET_OUT_INTERMEDIATE_LIBRARIES) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O)) \
 	$(PRIVATE_ALL_OBJECTS) \
+	-Wl,--whole-archive \
+	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+	-Wl,--no-whole-archive \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
+	$(PRIVATE_TARGET_LIBGCC) \
+	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_TARGET_FDO_LIB) \
@@ -272,6 +283,9 @@
 	$(PRIVATE_TARGET_GLOBAL_LDFLAGS) \
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_ALL_OBJECTS) \
+	-Wl,--whole-archive \
+	$(call normalize-target-libraries,$(PRIVATE_ALL_WHOLE_STATIC_LIBRARIES)) \
+	-Wl,--no-whole-archive \
 	$(call normalize-target-libraries,$(filter-out %libc_nomalloc.a,$(filter-out %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES)))) \
 	-Wl,--start-group \
 	$(call normalize-target-libraries,$(filter %libc.a,$(PRIVATE_ALL_STATIC_LIBRARIES))) \
diff --git a/core/combo/TARGET_linux-x86.mk b/core/combo/TARGET_linux-x86.mk
index 0e7c17d..04531b2 100644
--- a/core/combo/TARGET_linux-x86.mk
+++ b/core/combo/TARGET_linux-x86.mk
@@ -22,6 +22,12 @@
 TARGET_ARCH_VARIANT := x86
 endif
 
+ifeq ($(strip $(TARGET_GCC_VERSION_EXP)),)
+TARGET_GCC_VERSION := 4.7
+else
+TARGET_GCC_VERSION := $(TARGET_GCC_VERSION_EXP)
+endif
+
 # Include the arch-variant-specific configuration file.
 # Its role is to define various ARCH_X86_HAVE_XXX feature macros,
 # plus initial values for TARGET_GLOBAL_CFLAGS
@@ -36,7 +42,7 @@
 
 # You can set TARGET_TOOLS_PREFIX to get gcc from somewhere else
 ifeq ($(strip $(TARGET_TOOLS_PREFIX)),)
-TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/i686-linux-android-4.6
+TARGET_TOOLCHAIN_ROOT := prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/i686-linux-android-$(TARGET_GCC_VERSION)
 TARGET_TOOLS_PREFIX := $(TARGET_TOOLCHAIN_ROOT)/bin/i686-linux-android-
 endif
 
@@ -84,6 +90,7 @@
 			-Ulinux \
 			-Wa,--noexecstack \
 			-Werror=format-security \
+			-D_FORTIFY_SOURCE=1 \
 			-Wstrict-aliasing=2 \
 			-fPIC -fPIE \
 			-ffunction-sections \
@@ -144,6 +151,7 @@
 
 TARGET_GLOBAL_LDFLAGS += -Wl,-z,noexecstack
 TARGET_GLOBAL_LDFLAGS += -Wl,-z,relro -Wl,-z,now
+TARGET_GLOBAL_LDFLAGS += -Wl,--warn-shared-textrel
 TARGET_GLOBAL_LDFLAGS += -Wl,--gc-sections
 
 TARGET_C_INCLUDES := \
@@ -182,6 +190,7 @@
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
+	$(PRIVATE_TARGET_LIBGCC) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	-o $@ \
 	$(PRIVATE_LDFLAGS) \
@@ -196,10 +205,8 @@
 	-Wl,-dynamic-linker,/system/bin/linker \
 	-Wl,-z,nocopyreloc \
 	-fPIE -pie \
-	-o $@ \
 	$(PRIVATE_TARGET_GLOBAL_LD_DIRS) \
 	-Wl,-rpath-link=$(TARGET_OUT_INTERMEDIATE_LIBRARIES) \
-	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
 	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTBEGIN_DYNAMIC_O)) \
 	$(PRIVATE_ALL_OBJECTS) \
 	-Wl,--whole-archive \
@@ -208,6 +215,9 @@
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--start-group) \
 	$(call normalize-target-libraries,$(PRIVATE_ALL_STATIC_LIBRARIES)) \
 	$(if $(PRIVATE_GROUP_STATIC_LIBRARIES),-Wl$(comma)--end-group) \
+	$(PRIVATE_TARGET_LIBGCC) \
+	$(call normalize-target-libraries,$(PRIVATE_ALL_SHARED_LIBRARIES)) \
+	-o $@ \
 	$(PRIVATE_LDFLAGS) \
 	$(PRIVATE_TARGET_LIBGCC) \
 	$(if $(filter true,$(PRIVATE_NO_CRT)),,$(PRIVATE_TARGET_CRTEND_O))
diff --git a/core/combo/arch/arm/armv4t.mk b/core/combo/arch/arm/armv4t.mk
deleted file mode 100644
index abc8fa2..0000000
--- a/core/combo/arch/arm/armv4t.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Configuration for Linux on ARM.
-# Generating binaries for the ARMv4T architecture and higher
-#
-# Supporting armv4 (without thumb) does not make much sense since
-# it's mostly an obsoleted instruction set architecture (only available
-# in StrongArm and arm8). Supporting armv4 will require a lot of conditional
-# code in assembler source since the bx (branch and exchange) instruction is
-# not supported.
-#
-$(warning ARMv4t support is currently a work in progress. It does not work right now!)
-ARCH_ARM_HAVE_THUMB_SUPPORT := false
-ARCH_ARM_HAVE_THUMB_INTERWORKING := false
-ARCH_ARM_HAVE_64BIT_DATA := false
-ARCH_ARM_HAVE_HALFWORD_MULTIPLY := false
-ARCH_ARM_HAVE_CLZ := false
-ARCH_ARM_HAVE_FFS := false
-
-DEFAULT_TARGET_CPU := arm920t
-
-# Note: Hard coding the 'tune' value here is probably not ideal,
-# and a better solution should be found in the future.
-#
-arch_variant_cflags := -march=armv4t -mtune=arm920t -D__ARM_ARCH_4T__
diff --git a/core/combo/arch/arm/armv5te.mk b/core/combo/arch/arm/armv5te.mk
index 29aada6..88e57b7 100644
--- a/core/combo/arch/arm/armv5te.mk
+++ b/core/combo/arch/arm/armv5te.mk
@@ -1,12 +1,6 @@
 # Configuration for Linux on ARM.
 # Generating binaries for the ARMv5TE architecture and higher
 #
-ARCH_ARM_HAVE_THUMB_SUPPORT     := true
-ARCH_ARM_HAVE_FAST_INTERWORKING := true
-ARCH_ARM_HAVE_64BIT_DATA        := true
-ARCH_ARM_HAVE_HALFWORD_MULTIPLY := true
-ARCH_ARM_HAVE_CLZ               := true
-ARCH_ARM_HAVE_FFS               := true
 
 # Note: Hard coding the 'tune' value here is probably not ideal,
 # and a better solution should be found in the future.
diff --git a/core/combo/arch/arm/armv7-a-neon.mk b/core/combo/arch/arm/armv7-a-neon.mk
index 32273ff..7884366 100644
--- a/core/combo/arch/arm/armv7-a-neon.mk
+++ b/core/combo/arch/arm/armv7-a-neon.mk
@@ -1,14 +1,7 @@
 # Configuration for Linux on ARM.
 # Generating binaries for the ARMv7-a architecture and higher with NEON
 #
-ARCH_ARM_HAVE_THUMB_SUPPORT     := true
-ARCH_ARM_HAVE_FAST_INTERWORKING := true
-ARCH_ARM_HAVE_64BIT_DATA        := true
-ARCH_ARM_HAVE_HALFWORD_MULTIPLY := true
-ARCH_ARM_HAVE_CLZ               := true
-ARCH_ARM_HAVE_FFS               := true
 ARCH_ARM_HAVE_ARMV7A            := true
-ARCH_ARM_HAVE_TLS_REGISTER      := true
 ARCH_ARM_HAVE_VFP               := true
 ARCH_ARM_HAVE_VFP_D32           := true
 ARCH_ARM_HAVE_NEON              := true
diff --git a/core/combo/arch/arm/armv7-a.mk b/core/combo/arch/arm/armv7-a.mk
index 220f7ec..4a51977 100644
--- a/core/combo/arch/arm/armv7-a.mk
+++ b/core/combo/arch/arm/armv7-a.mk
@@ -1,14 +1,7 @@
 # Configuration for Linux on ARM.
 # Generating binaries for the ARMv7-a architecture and higher
 #
-ARCH_ARM_HAVE_THUMB_SUPPORT     := true
-ARCH_ARM_HAVE_FAST_INTERWORKING := true
-ARCH_ARM_HAVE_64BIT_DATA        := true
-ARCH_ARM_HAVE_HALFWORD_MULTIPLY := true
-ARCH_ARM_HAVE_CLZ               := true
-ARCH_ARM_HAVE_FFS               := true
 ARCH_ARM_HAVE_ARMV7A            := true
-ARCH_ARM_HAVE_TLS_REGISTER      := true
 ARCH_ARM_HAVE_VFP               := true
 
 # Note: Hard coding the 'tune' value here is probably not ideal,
diff --git a/core/combo/arch/mips/mips32r2-fp.mk b/core/combo/arch/mips/mips32r2-fp.mk
index a407f00..08d91df 100644
--- a/core/combo/arch/mips/mips32r2-fp.mk
+++ b/core/combo/arch/mips/mips32r2-fp.mk
@@ -8,7 +8,8 @@
     -march=mips32r2 \
     -mtune=mips32r2 \
     -mips32r2 \
-    -mhard-float
+    -mhard-float \
+    -msynci
 
 arch_variant_ldflags := \
     -EL
diff --git a/core/combo/arch/mips/mips32r2.mk b/core/combo/arch/mips/mips32r2.mk
index 369d499..16ce76f 100644
--- a/core/combo/arch/mips/mips32r2.mk
+++ b/core/combo/arch/mips/mips32r2.mk
@@ -6,7 +6,8 @@
     -march=mips32r2 \
     -mtune=mips32r2 \
     -mips32r2 \
-    -msoft-float
+    -msoft-float \
+    -msynci
 
 arch_variant_ldflags := \
     -EL
diff --git a/core/combo/arch/mips/mips32r2dsp-fp.mk b/core/combo/arch/mips/mips32r2dsp-fp.mk
index 886872d..fe2b1fe 100644
--- a/core/combo/arch/mips/mips32r2dsp-fp.mk
+++ b/core/combo/arch/mips/mips32r2dsp-fp.mk
@@ -11,7 +11,8 @@
     -mtune=mips32r2 \
     -mips32r2 \
     -mhard-float \
-    -mdsp
+    -mdsp \
+    -msynci
 
 arch_variant_ldflags := \
     -EL
diff --git a/core/combo/arch/mips/mips32r2dsp.mk b/core/combo/arch/mips/mips32r2dsp.mk
index e67adc7..8a8976c 100644
--- a/core/combo/arch/mips/mips32r2dsp.mk
+++ b/core/combo/arch/mips/mips32r2dsp.mk
@@ -10,7 +10,8 @@
     -mtune=mips32r2 \
     -mips32r2 \
     -msoft-float \
-    -mdsp
+    -mdsp \
+    -msynci
 
 arch_variant_ldflags := \
     -EL
diff --git a/core/combo/arch/mips/mips32r2dspr2-fp.mk b/core/combo/arch/mips/mips32r2dspr2-fp.mk
index 27e090d..7e882b3 100644
--- a/core/combo/arch/mips/mips32r2dspr2-fp.mk
+++ b/core/combo/arch/mips/mips32r2dspr2-fp.mk
@@ -11,7 +11,8 @@
     -mtune=mips32r2 \
     -mips32r2 \
     -mhard-float \
-    -mdspr2
+    -mdspr2 \
+    -msynci
 
 arch_variant_ldflags := \
     -EL
diff --git a/core/combo/arch/mips/mips32r2dspr2.mk b/core/combo/arch/mips/mips32r2dspr2.mk
index c493d9a..c311523 100644
--- a/core/combo/arch/mips/mips32r2dspr2.mk
+++ b/core/combo/arch/mips/mips32r2dspr2.mk
@@ -10,7 +10,8 @@
     -mtune=mips32r2 \
     -mips32r2 \
     -msoft-float \
-    -mdspr2
+    -mdspr2 \
+    -msynci
 
 arch_variant_ldflags := \
     -EL
diff --git a/core/combo/include/arch/darwin-x86/AndroidConfig.h b/core/combo/include/arch/darwin-x86/AndroidConfig.h
index 9da01c5..012f014 100644
--- a/core/combo/include/arch/darwin-x86/AndroidConfig.h
+++ b/core/combo/include/arch/darwin-x86/AndroidConfig.h
@@ -171,13 +171,6 @@
 #define HAVE_BACKTRACE 0
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 1
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/combo/include/arch/freebsd-x86/AndroidConfig.h b/core/combo/include/arch/freebsd-x86/AndroidConfig.h
index 4bc5559..6f50918 100644
--- a/core/combo/include/arch/freebsd-x86/AndroidConfig.h
+++ b/core/combo/include/arch/freebsd-x86/AndroidConfig.h
@@ -187,13 +187,6 @@
 #define HAVE_BACKTRACE 0
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 1
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/combo/include/arch/linux-arm/AndroidConfig.h b/core/combo/include/arch/linux-arm/AndroidConfig.h
index 233752b..9257d3e 100644
--- a/core/combo/include/arch/linux-arm/AndroidConfig.h
+++ b/core/combo/include/arch/linux-arm/AndroidConfig.h
@@ -186,13 +186,6 @@
 #define HAVE_BACKTRACE 0
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 1
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/combo/include/arch/linux-mips/AndroidConfig.h b/core/combo/include/arch/linux-mips/AndroidConfig.h
index 2d51dc7..e24f3ea 100644
--- a/core/combo/include/arch/linux-mips/AndroidConfig.h
+++ b/core/combo/include/arch/linux-mips/AndroidConfig.h
@@ -191,13 +191,6 @@
 #define HAVE_BACKTRACE 0
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 1
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/combo/include/arch/linux-ppc/AndroidConfig.h b/core/combo/include/arch/linux-ppc/AndroidConfig.h
index ae2569b..a12ef47 100644
--- a/core/combo/include/arch/linux-ppc/AndroidConfig.h
+++ b/core/combo/include/arch/linux-ppc/AndroidConfig.h
@@ -176,13 +176,6 @@
 #define HAVE_BACKTRACE 1
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 1
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/combo/include/arch/linux-x86/AndroidConfig.h b/core/combo/include/arch/linux-x86/AndroidConfig.h
index 431a54b..2db66a2 100644
--- a/core/combo/include/arch/linux-x86/AndroidConfig.h
+++ b/core/combo/include/arch/linux-x86/AndroidConfig.h
@@ -176,13 +176,6 @@
 #define HAVE_BACKTRACE 1
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 1
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/combo/include/arch/target_linux-x86/AndroidConfig.h b/core/combo/include/arch/target_linux-x86/AndroidConfig.h
index ab53892..aaaf0c9 100644
--- a/core/combo/include/arch/target_linux-x86/AndroidConfig.h
+++ b/core/combo/include/arch/target_linux-x86/AndroidConfig.h
@@ -175,13 +175,6 @@
 #define HAVE_BACKTRACE 0
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 0
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/combo/include/arch/windows/AndroidConfig.h b/core/combo/include/arch/windows/AndroidConfig.h
index 0274da5..83d0a0f 100644
--- a/core/combo/include/arch/windows/AndroidConfig.h
+++ b/core/combo/include/arch/windows/AndroidConfig.h
@@ -189,13 +189,6 @@
 #define HAVE_BACKTRACE 0
 
 /*
- * Defined if we have the dladdr() call for retrieving the symbol associated
- * with a memory address.  If not defined, stack crawls will not have symbolic
- * information.
- */
-#define HAVE_DLADDR 0
-
-/*
  * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
  * not defined, stack crawls will be displayed with raw mangled symbols
  */
diff --git a/core/definitions.mk b/core/definitions.mk
index 067b170..cbff53f 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -55,11 +55,6 @@
 # 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:=
@@ -178,7 +173,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
 
@@ -200,7 +195,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
 
@@ -222,7 +217,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
 
@@ -243,7 +238,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
 
@@ -256,7 +251,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
 
@@ -269,7 +264,7 @@
 define all-renderscript-files-under
 $(patsubst ./%,%, \
   $(shell cd $(LOCAL_PATH) ; \
-          find $(1) \( -name "*.rs" -or -name "*.fs" \) -and -not -name ".*") \
+          find -L $(1) \( -name "*.rs" -or -name "*.fs" \) -and -not -name ".*") \
   )
 endef
 
@@ -282,7 +277,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
 
@@ -301,7 +296,7 @@
 ###########################################################
 
 define find-subdir-files
-$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find $(1)))
+$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find -L $(1)))
 endef
 
 ###########################################################
@@ -314,7 +309,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
 
 ###########################################################
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 03a5011..ce0c46e 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -160,7 +160,7 @@
 
 $(full_target): $(full_src_files) $(droiddoc_templates) $(droiddoc) $(html_dir_files) $(full_java_lib_deps) $(LOCAL_ADDITIONAL_DEPENDENCIES)
 	@echo Docs droiddoc: $(PRIVATE_OUT_DIR)
-	$(hide) mkdir -p $(dir $(full_target))
+	$(hide) mkdir -p $(dir $@)
 	$(call prepare-doc-source-list,$(PRIVATE_SRC_LIST_FILE),$(PRIVATE_JAVA_FILES), \
 			$(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
 	$(hide) ( \
@@ -193,7 +193,7 @@
 ##
 $(full_target): $(full_src_files) $(full_java_lib_deps)
 	@echo Docs javadoc: $(PRIVATE_OUT_DIR)
-	@mkdir -p $(dir $(full_target))
+	@mkdir -p $(dir $@)
 	$(call prepare-doc-source-list,$(PRIVATE_SRC_LIST_FILE),$(PRIVATE_JAVA_FILES), \
 			$(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
 	$(hide) ( \
diff --git a/core/dumpvar.mk b/core/dumpvar.mk
index 5298f35..92bf6af 100644
--- a/core/dumpvar.mk
+++ b/core/dumpvar.mk
@@ -11,23 +11,27 @@
 
 # Add the ARM toolchain bin dir if it actually exists
 ifeq ($(TARGET_ARCH),arm)
-    ifneq ($(wildcard $(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-4.6/bin),)
+    ifneq ($(wildcard $(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-$(TARGET_GCC_VERSION)/bin),)
         # this should be copied to HOST_OUT_EXECUTABLES instead
-        ABP:=$(ABP):$(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-4.6/bin
+        ABP:=$(ABP):$(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-linux-androideabi-$(TARGET_GCC_VERSION)/bin
+    endif
+    ifneq ($(wildcard $(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-eabi-$(TARGET_GCC_VERSION)/bin),)
+        # this should be copied to HOST_OUT_EXECUTABLES instead
+        ABP:=$(ABP):$(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/arm/arm-eabi-$(TARGET_GCC_VERSION)/bin
     endif
 else ifeq ($(TARGET_ARCH),x86)
 
 # Add the x86 toolchain bin dir if it actually exists
-    ifneq ($(wildcard $(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/i686-linux-android-4.6/bin),)
+    ifneq ($(wildcard $(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/i686-linux-android-$(TARGET_GCC_VERSION)/bin),)
         # this should be copied to HOST_OUT_EXECUTABLES instead
-        ABP:=$(ABP):$(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/i686-linux-android-4.6/bin
+        ABP:=$(ABP):$(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/x86/i686-linux-android-$(TARGET_GCC_VERSION)/bin
     endif
 endif
 
 # Add the mips toolchain bin dir if it actually exists
-ifneq ($(wildcard $(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mipsel-linux-android-4.6/bin),)
+ifneq ($(wildcard $(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mipsel-linux-android-$(TARGET_GCC_VERSION)/bin),)
     # this should be copied to HOST_OUT_EXECUTABLES instead
-    ABP:=$(ABP):$(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mipsel-linux-android-4.6/bin
+    ABP:=$(ABP):$(PWD)/prebuilts/gcc/$(HOST_PREBUILT_TAG)/mips/mipsel-linux-android-$(TARGET_GCC_VERSION)/bin
 endif
 
 ANDROID_BUILD_PATHS := $(ABP)
@@ -94,6 +98,7 @@
 $(info   TARGET_BUILD_APPS=$(TARGET_BUILD_APPS))
 $(info   TARGET_ARCH=$(TARGET_ARCH))
 $(info   TARGET_ARCH_VARIANT=$(TARGET_ARCH_VARIANT))
+$(info   TARGET_CPU_VARIANT=$(TARGET_CPU_VARIANT))
 $(info   HOST_ARCH=$(HOST_ARCH))
 $(info   HOST_OS=$(HOST_OS))
 $(info   HOST_OS_EXTRA=$(HOST_OS_EXTRA))
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index 0ca1858..6ede57f 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -128,8 +128,7 @@
 endif # LOCAL_STRIP_MODULE
 
 
-$(cleantarget): PRIVATE_CLEAN_FILES := \
-			$(PRIVATE_CLEAN_FILES) \
-			$(linked_module) \
-			$(symbolic_output) \
-			$(compress_output)
+$(cleantarget): PRIVATE_CLEAN_FILES += \
+    $(linked_module) \
+    $(symbolic_output) \
+    $(compress_output)
diff --git a/core/host_java_library.mk b/core/host_java_library.mk
index c938d57..438e093 100644
--- a/core/host_java_library.mk
+++ b/core/host_java_library.mk
@@ -24,6 +24,10 @@
 LOCAL_BUILT_MODULE_STEM := javalib.jar
 
 ifeq ($(LOCAL_BUILD_HOST_DEX),true)
+ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
+  LOCAL_JAVA_LIBRARIES := $(sort core-hostdex $(LOCAL_JAVA_LIBRARIES))
+endif
+
 intermediates := $(call local-intermediates-dir)
 intermediates.COMMON := $(call local-intermediates-dir,COMMON)
 
@@ -43,6 +47,8 @@
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
+$(full_classes_compiled_jar): PRIVATE_JAVAC_DEBUG_FLAGS := -g
+
 # The layers file allows you to enforce a layering between java packages.
 # Run build/tools/java-layers.py for more details.
 layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE))
diff --git a/core/llvm_config.mk b/core/llvm_config.mk
index 0308b28..7a26842 100644
--- a/core/llvm_config.mk
+++ b/core/llvm_config.mk
@@ -59,7 +59,8 @@
     -march=mips32r2 \
     -mtune=mips32r2 \
     -march=mips32 \
-    -mtune=mips32
+    -mtune=mips32 \
+    -msynci
 endif
 ifeq ($(TARGET_ARCH),x86)
   CLANG_CONFIG_EXTRA_CFLAGS += \
diff --git a/core/main.mk b/core/main.mk
index 9f9fd86..7d6b3b2 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -121,12 +121,20 @@
 $(error Directory names containing spaces not supported)
 endif
 
+# Check for the corrent jdk
+ifneq ($(shell java -version 2>&1 | grep -i openjdk),)
+$(info ************************************************************)
+$(info You are attempting to build with an unsupported JDK.)
+$(info $(space))
+$(info You use OpenJDK but only Sun/Oracle JDK is supported.)
+$(info Please follow the machine setup instructions at)
+$(info $(space)$(space)$(space)$(space)https://source.android.com/source/download.html)
+$(info ************************************************************)
+$(error stop)
+endif
 
 # Check for the correct version of java
 java_version := $(shell java -version 2>&1 | head -n 1 | grep '^java .*[ "]1\.6[\. "$$]')
-ifneq ($(shell java -version 2>&1 | grep -i openjdk),)
-java_version :=
-endif
 ifeq ($(strip $(java_version)),)
 $(info ************************************************************)
 $(info You are attempting to build with the incorrect version)
@@ -158,7 +166,7 @@
 endif
 
 ifeq (darwin,$(HOST_OS))
-GCC_REALPATH = $(realpath $(shell which gcc))
+GCC_REALPATH = $(realpath $(shell which $(HOST_CC)))
 ifneq ($(findstring llvm-gcc,$(GCC_REALPATH)),)
   # Using LLVM GCC results in a non functional emulator due to it
   # not honouring global register variables
@@ -170,23 +178,6 @@
 else
   BUILD_EMULATOR := true
 endif
-# When building on Leopard or above, we need to use the 10.4 SDK
-# or the generated binary will not run on Tiger.
-darwin_version := $(strip $(shell sw_vers -productVersion))
-ifneq ($(filter 10.1 10.2 10.3 10.1.% 10.2.% 10.3.% 10.4 10.4.%,$(darwin_version)),)
-    $(error Building the Android emulator requires OS X 10.5 or above)
-endif
-ifneq ($(filter 10.5 10.5.% 10.6 10.6.%,$(darwin_version)),)
-    # We are on Leopard or Snow Leopard
-    MSDK=10.5
-else
-    # We are on Lion or beyond, and 10.6 SDK is the minimum in Xcode 4.x
-   MSDK=10.6
-endif
-MACOSX_SDK := /Developer/SDKs/MacOSX$(MSDK).sdk
-ifeq ($(strip $(wildcard $(MACOSX_SDK))),)
-  BUILD_EMULATOR := false
-endif
 else   # HOST_OS is not darwin
   BUILD_EMULATOR := true
 endif  # HOST_OS is darwin
@@ -275,11 +266,6 @@
 is_sdk_build := true
 endif
 
-## have selinux ##
-ifeq ($(HAVE_SELINUX),true)
-ADDITIONAL_BUILD_PROPERTIES += ro.build.selinux=1
-endif # HAVE_SELINUX
-
 ## user/userdebug ##
 
 user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
@@ -444,8 +430,8 @@
 endif
 
 ifeq ($(SDK_ONLY),true)
-include $(TOPDIR)sdk/build/sdk_only_whitelist.mk
-include $(TOPDIR)development/build/sdk_only_whitelist.mk
+include $(TOPDIR)sdk/build/windows_sdk_whitelist.mk
+include $(TOPDIR)development/build/windows_sdk_whitelist.mk
 
 # Exclude tools/acp when cross-compiling windows under linux
 ifeq ($(findstring Linux,$(UNAME)),)
@@ -657,7 +643,7 @@
   # 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)),,\
-      $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES has nothing to install!)))
+      $(error $(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)),,\
       $(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_DEBUG has nothing to install!)))
@@ -669,9 +655,6 @@
       $(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
 # contains everything that's built during the current make, but it also further
@@ -717,7 +700,6 @@
 .PHONY: files
 files: prebuilt \
         $(modules_to_install) \
-        $(modules_to_check) \
         $(INSTALLED_ANDROID_INFO_TXT_TARGET)
 
 # -------------------------------------------------------------------
diff --git a/core/package.mk b/core/package.mk
index 358caee..11e557f 100644
--- a/core/package.mk
+++ b/core/package.mk
@@ -410,15 +410,17 @@
 	$(add-java-resources-to-package)
 endif
 	$(sign-package)
-	@# Alignment must happen after all other zip operations.
-	$(align-package)
 ifdef LOCAL_DEX_PREOPT
 	$(hide) rm -f $(patsubst %.apk,%.odex,$@)
 	$(call dexpreopt-one-file,$@,$(patsubst %.apk,%.odex,$@))
 ifneq (nostripping,$(LOCAL_DEX_PREOPT))
 	$(call dexpreopt-remove-classes.dex,$@)
 endif
+endif
+	@# Alignment must happen after all other zip operations.
+	$(align-package)
 
+ifdef LOCAL_DEX_PREOPT
 built_odex := $(basename $(LOCAL_BUILT_MODULE)).odex
 $(built_odex): $(LOCAL_BUILT_MODULE)
 endif
diff --git a/core/product.mk b/core/product.mk
index b934826..bbd0c31 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -209,6 +209,7 @@
 _product_stash_var_list := $(_product_var_list) \
 	TARGET_ARCH \
 	TARGET_ARCH_VARIANT \
+	TARGET_CPU_VARIANT \
 	TARGET_BOARD_PLATFORM \
 	TARGET_BOARD_PLATFORM_GPU \
 	TARGET_BOARD_KERNEL_HEADERS \
diff --git a/core/product_config.mk b/core/product_config.mk
index 75df954..e05907d 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -220,7 +220,7 @@
 else
 # Import just the current product.
 ifndef current_product_makefile
-$(error Cannot locate config makefile for product "$(TARGET_PRODUCT)")
+$(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))
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 108e30b..5b041d6 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -75,6 +75,7 @@
 define generate-core-test-description
 @echo "Generate core-test description ("$(notdir $(1))")"
 $(hide) java -Xmx256M \
+	-Xbootclasspath/a:$(PRIVATE_CLASSPATH) \
 	-classpath $(PRIVATE_CLASSPATH):$(HOST_OUT_JAVA_LIBRARIES)/descGen.jar:$(HOST_JDK_TOOLS_JAR) \
 	$(PRIVATE_PARAMS) CollectAllTests $(1) $(2) $(3) "$(4)" $(5) $(6)
 endef
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index e3ba14f..9330465 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -41,7 +41,7 @@
   # which is the version that we reveal to the end user.
   # Update this value when the platform version changes (rather
   # than overriding it somewhere else).  Can be an arbitrary string.
-  PLATFORM_VERSION := 4.2.2
+  PLATFORM_VERSION := 4.2.2.2.2.2.2.2.2.2
 endif
 
 ifeq "" "$(PLATFORM_SDK_VERSION)"
@@ -59,7 +59,7 @@
 ifeq "" "$(PLATFORM_VERSION_CODENAME)"
   # This is the current development code-name, if the build is not a final
   # release build.  If this is a final release build, it is simply "REL".
-  PLATFORM_VERSION_CODENAME := REL
+  PLATFORM_VERSION_CODENAME := AOSP
 endif
 
 ifeq "" "$(DEFAULT_APP_TARGET_SDK)"
diff --git a/envsetup.sh b/envsetup.sh
index b57a272..274e02e 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -31,7 +31,7 @@
         echo "Couldn't locate the top of the tree.  Try setting TOP." >&2
         return
     fi
-    (cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
+    (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
       make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-abs-$1)
 }
 
@@ -116,15 +116,19 @@
     prebuiltdir=$(getprebuilt)
     gccprebuiltdir=$(get_abs_build_var ANDROID_GCC_PREBUILTS)
 
+    # defined in core/config.mk
+    targetgccversion=$(get_build_var TARGET_GCC_VERSION)
+    export TARGET_GCC_VERSION=$targetgccversion
+
     # The gcc toolchain does not exists for windows/cygwin. In this case, do not reference it.
     export ANDROID_EABI_TOOLCHAIN=
     local ARCH=$(get_build_var TARGET_ARCH)
     case $ARCH in
-        x86) toolchaindir=x86/i686-linux-android-4.6/bin
+        x86) toolchaindir=x86/i686-linux-android-$targetgccversion/bin
             ;;
-        arm) toolchaindir=arm/arm-linux-androideabi-4.6/bin
+        arm) toolchaindir=arm/arm-linux-androideabi-$targetgccversion/bin
             ;;
-        mips) toolchaindir=mips/mipsel-linux-android-4.6/bin
+        mips) toolchaindir=mips/mipsel-linux-android-$targetgccversion/bin
             ;;
         *)
             echo "Can't find toolchain for unknown architecture: $ARCH"
@@ -138,7 +142,7 @@
     unset ARM_EABI_TOOLCHAIN ARM_EABI_TOOLCHAIN_PATH
     case $ARCH in
         arm)
-            toolchaindir=arm/arm-eabi-4.6/bin
+            toolchaindir=arm/arm-eabi-$targetgccversion/bin
             if [ -d "$gccprebuiltdir/$toolchaindir" ]; then
                  export ARM_EABI_TOOLCHAIN="$gccprebuiltdir/$toolchaindir"
                  ARM_EABI_TOOLCHAIN_PATH=":$gccprebuiltdir/$toolchaindir"
@@ -580,16 +584,13 @@
             # faked up with symlink names.
             PWD= /bin/pwd
         else
-            # We redirect cd to /dev/null in case it's aliased to
-            # a command that prints something as a side-effect
-            # (like pushd)
             local HERE=$PWD
             T=
             while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
-                cd .. > /dev/null
+                \cd ..
                 T=`PWD= /bin/pwd`
             done
-            cd $HERE > /dev/null
+            \cd $HERE
             if [ -f "$T/$TOPFILE" ]; then
                 echo $T
             fi
@@ -610,21 +611,18 @@
 function findmakefile()
 {
     TOPFILE=build/core/envsetup.mk
-    # We redirect cd to /dev/null in case it's aliased to
-    # a command that prints something as a side-effect
-    # (like pushd)
     local HERE=$PWD
     T=
     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
         T=`PWD= /bin/pwd`
         if [ -f "$T/Android.mk" ]; then
             echo $T/Android.mk
-            cd $HERE > /dev/null
+            \cd $HERE
             return
         fi
-        cd .. > /dev/null
+        \cd ..
     done
-    cd $HERE > /dev/null
+    \cd $HERE
 }
 
 function mm()
@@ -666,7 +664,7 @@
             fi
             DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'`
             if [ -f $DIR/Android.mk ]; then
-                TO_CHOP=`(cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
+                TO_CHOP=`(\cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
                 TO_CHOP=`expr $TO_CHOP + 1`
                 START=`PWD= /bin/pwd`
                 MFILE=`echo $START | cut -c${TO_CHOP}-`
@@ -701,7 +699,7 @@
 {
     T=$(gettop)
     if [ "$T" ]; then
-        cd $(gettop)
+        \cd $(gettop)
     else
         echo "Couldn't locate the top of the tree.  Try setting TOP."
     fi
@@ -710,20 +708,17 @@
 function cproj()
 {
     TOPFILE=build/core/envsetup.mk
-    # We redirect cd to /dev/null in case it's aliased to
-    # a command that prints something as a side-effect
-    # (like pushd)
     local HERE=$PWD
     T=
     while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
         T=$PWD
         if [ -f "$T/Android.mk" ]; then
-            cd $T
+            \cd $T
             return
         fi
-        cd .. > /dev/null
+        \cd ..
     done
-    cd $HERE > /dev/null
+    \cd $HERE
     echo "can't find Android.mk"
 }
 
@@ -742,7 +737,45 @@
 # to the usual ANR traces file
 function systemstack()
 {
-    adb shell echo '""' '>>' /data/anr/traces.txt && adb shell chmod 776 /data/anr/traces.txt && adb shell kill -3 $(pid system_server)
+    stacks system_server
+}
+
+function stacks()
+{
+    if [[ $1 =~ ^[0-9]+$ ]] ; then
+        local PID="$1"
+    elif [ "$1" ] ; then
+        local PID=$(pid $1)
+    else
+        echo "usage: stacks [pid|process name]"
+    fi
+
+    if [ "$PID" ] ; then
+        local TRACES=/data/anr/traces.txt
+        local ORIG=/data/anr/traces.orig
+        local TMP=/data/anr/traces.tmp
+
+        # Keep original traces to avoid clobbering
+        adb shell mv $TRACES $ORIG
+
+        # Make sure we have a usable file
+        adb shell touch $TRACES
+        adb shell chmod 666 $TRACES
+
+        # Dump stacks and wait for dump to finish
+        adb shell kill -3 $PID
+        adb shell notify $TRACES
+
+        # Restore original stacks, and show current output
+        adb shell mv $TRACES $TMP
+        adb shell mv $ORIG $TRACES
+        adb shell cat $TMP | less -S
+    fi
+}
+
+function gdbwrapper()
+{
+    $ANDROID_TOOLCHAIN/$GDB -x "$@"
 }
 
 function gdbclient()
@@ -801,7 +834,7 @@
        echo >>"$OUT_ROOT/gdbclient.cmds" "target remote $PORT"
        echo >>"$OUT_ROOT/gdbclient.cmds" ""
 
-       $ANDROID_TOOLCHAIN/$GDB -x "$OUT_ROOT/gdbclient.cmds" "$OUT_EXE_SYMBOLS/$EXE"
+       gdbwrapper "$OUT_ROOT/gdbclient.cmds" "$OUT_EXE_SYMBOLS/$EXE"
   else
        echo "Unable to determine build system output dir."
    fi
@@ -844,6 +877,11 @@
     for dir in `find . -name .repo -prune -o -name .git -prune -o -name res -type d`; do find $dir -type f -name '*\.xml' -print0 | xargs -0 grep --color -n "$@"; done;
 }
 
+function mangrep()
+{
+    find . -name .repo -prune -o -name .git -prune -o -path ./out -prune -o -type f -name 'AndroidManifest.xml' -print0 | xargs -0 grep --color -n "$@"
+}
+
 case `uname -s` in
     Darwin)
         function mgrep()
@@ -1063,7 +1101,7 @@
         return
     fi
 
-    (cd "$T" && mmm tests/SmokeTest) &&
+    (\cd "$T" && mmm tests/SmokeTest) &&
       adb uninstall com.android.smoketest > /dev/null &&
       adb uninstall com.android.smoketest.tests > /dev/null &&
       adb install $ANDROID_PRODUCT_OUT/data/app/SmokeTestApp.apk &&
@@ -1090,7 +1128,7 @@
     T=$(gettop)
     if [[ ! -f $T/filelist ]]; then
         echo -n "Creating index..."
-        (cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > filelist)
+        (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > filelist)
         echo " Done"
         echo ""
     fi
@@ -1123,7 +1161,7 @@
     else
         pathname=${lines[0]}
     fi
-    cd $T/$pathname
+    \cd $T/$pathname
 }
 
 # Force JAVA_HOME to point to java 1.6 if it isn't already set
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index 7a25f30..35cbd27 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -20,9 +20,9 @@
 # application code generated with the NDK that uses NEON in the emulator.
 #
 TARGET_ARCH_VARIANT := armv7-a
+TARGET_CPU_VARIANT := generic
 TARGET_CPU_ABI := armeabi-v7a
 TARGET_CPU_ABI2 := armeabi
-ARCH_ARM_HAVE_TLS_REGISTER := true
 
 HAVE_HTC_AUDIO_DRIVER := true
 BOARD_USES_GENERIC_AUDIO := true
diff --git a/target/board/generic_mips/BoardConfig.mk b/target/board/generic_mips/BoardConfig.mk
index 8c2371f..c3881b4 100644
--- a/target/board/generic_mips/BoardConfig.mk
+++ b/target/board/generic_mips/BoardConfig.mk
@@ -34,9 +34,6 @@
 # no hardware camera
 USE_CAMERA_STUB := true
 
-# Set /system/bin/sh to ash, not mksh, to make sure we can switch back.
-TARGET_SHELL := ash
-
 # Enable dex-preoptimization to speed up the first boot sequence
 # of an SDK AVD. Note that this operation only works on Linux for now
 ifeq ($(HOST_OS),linux)
diff --git a/target/product/core.mk b/target/product/core.mk
index ca2101b..bf05584 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -125,13 +125,16 @@
     requestsync \
     screencap \
     sensorservice \
-    lint \
-    uiautomator \
     telephony-common \
-    mms-common \
-    zoneinfo.dat \
-    zoneinfo.idx \
-    zoneinfo.version
+    mms-common
+
+# SELinux packages
+PRODUCT_PACKAGES += \
+    sepolicy \
+    file_contexts \
+    seapp_contexts \
+    property_contexts \
+    mac_permissions.xml
 
 # host-only dependencies
 ifeq ($(WITH_HOST_DALVIK),true)
@@ -146,20 +149,7 @@
         libjavacore \
         libssl \
         libz-host \
-        dalvik \
-        zoneinfo-host.dat \
-        zoneinfo-host.idx \
-        zoneinfo-host.version
-endif
-
-ifeq ($(HAVE_SELINUX),true)
-    PRODUCT_PACKAGES += \
-        sepolicy \
-        file_contexts \
-        seapp_contexts \
-        property_contexts \
-        mac_permissions.xml
+        dalvik
 endif
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)
-
diff --git a/target/product/embedded.mk b/target/product/embedded.mk
index 7f681b1..0830101 100644
--- a/target/product/embedded.mk
+++ b/target/product/embedded.mk
@@ -50,7 +50,6 @@
     libstdc++ \
     libstlport \
     libsurfaceflinger \
-    libsurfaceflinger_client \
     libsurfaceflinger_ddmconnection \
     libsysutils \
     libthread_db \
diff --git a/target/product/emulator.mk b/target/product/emulator.mk
new file mode 100644
index 0000000..b0cc04b
--- /dev/null
+++ b/target/product/emulator.mk
@@ -0,0 +1,53 @@
+#
+# 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.
+
+#
+# This file is included by other product makefiles to add all the
+# emulator-related host modules to PRODUCT_PACKAGES.
+#
+
+PRODUCT_PACKAGES += \
+	emulator \
+	emulator-x86 \
+	emulator-arm \
+	emulator-mips \
+	emulator64-x86 \
+	emulator64-arm \
+	emulator64-mips \
+	libOpenglRender \
+	libGLES_CM_translator \
+	libGLES_V2_translator \
+	libEGL_translator \
+	lib64OpenglRender \
+	lib64GLES_CM_translator \
+	lib64GLES_V2_translator \
+	lib64EGL_translator
+
+PRODUCT_PACKAGES += \
+    egl.cfg \
+    gralloc.goldfish \
+    libGLESv1_CM_emulation \
+    lib_renderControl_enc \
+    libEGL_emulation \
+    libGLESv2_enc \
+    libOpenglSystemCommon \
+    libGLESv2_emulation \
+    libGLESv1_enc \
+    qemu-props \
+    qemud \
+    camera.goldfish \
+    lights.goldfish \
+    gps.goldfish \
+    sensors.goldfish
diff --git a/target/product/full_base.mk b/target/product/full_base.mk
index b2e3189..c28fd1b 100644
--- a/target/product/full_base.mk
+++ b/target/product/full_base.mk
@@ -40,6 +40,8 @@
     VisualizationWallpapers \
     PhotoTable
 
+include $(SRC_TARGET_DIR)/product/emulator.mk
+
 # Additional settings used in all AOSP builds
 PRODUCT_PROPERTY_OVERRIDES := \
     ro.com.android.dateformat=MM-dd-yyyy \
diff --git a/target/product/mini.mk b/target/product/mini.mk
index b69c917..22762ab 100644
--- a/target/product/mini.mk
+++ b/target/product/mini.mk
@@ -140,7 +140,6 @@
     libwebrtc_audio_preprocessing \
     libwilhelm \
     libz \
-    lint \
     mdnsd \
     mms-common \
     network \
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index 6f56bb5..8382ee0 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -53,11 +53,6 @@
 	CubeLiveWallpapers \
 	QuickSearchBox \
 	WidgetPreview \
-	monkeyrunner \
-	guavalib \
-	jsr305lib \
-	jython \
-	jsilver \
 	librs_jni \
 	ConnectivityTest \
 	GpsLocationTest \
@@ -68,6 +63,7 @@
 	rild \
 	LegacyCamera
 
+include $(SRC_TARGET_DIR)/product/emulator.mk
 
 # Define the host tools and libs that are parts of the SDK.
 -include sdk/build/product_sdk.mk
diff --git a/target/product/vbox_x86.mk b/target/product/vbox_x86.mk
index f0d4232..a492774 100644
--- a/target/product/vbox_x86.mk
+++ b/target/product/vbox_x86.mk
@@ -25,6 +25,12 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/full_base.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/board/vbox_x86/device.mk)
 
+PRODUCT_PACKAGES += \
+       camera.vbox_x86 \
+       lights.vbox_x86 \
+       gps.vbox_x86 \
+       sensors.vbox_x86
+
 PRODUCT_NAME := vbox_x86
 PRODUCT_DEVICE := vbox_x86
 PRODUCT_MODEL := Full Android on x86 VirtualBox
diff --git a/tools/adbs b/tools/adbs
index 598af85..37c520c 100755
--- a/tools/adbs
+++ b/tools/adbs
@@ -140,13 +140,15 @@
     uname = "darwin-x86"
   elif uname == "Linux":
     uname = "linux-x86"
-  prefix = "./prebuilts/gcc/" + uname + "/arm/arm-linux-androideabi-4.6/bin/"
+  gcc_version = os.environ["TARGET_GCC_VERSION"]
+  prefix = "./prebuilts/gcc/" + uname + "/arm/arm-linux-androideabi-" + \
+           gcc_version + "/bin/"
   addr2line_cmd = prefix + "arm-linux-androideabi-addr2line"
 
   if (not os.path.exists(addr2line_cmd)):
     try:
       prefix = os.environ['ANDROID_BUILD_TOP'] + "/prebuilts/gcc/" + \
-               uname + "/arm/arm-linux-androideabi-4.6/bin/"
+               uname + "/arm/arm-linux-androideabi-" + gcc_version + "/bin/"
     except:
       prefix = "";
 
diff --git a/tools/fs_config/fs_config.c b/tools/fs_config/fs_config.c
index 5b99b30..f6760cc 100644
--- a/tools/fs_config/fs_config.c
+++ b/tools/fs_config/fs_config.c
@@ -62,7 +62,8 @@
     }
 
     unsigned uid = 0, gid = 0, mode = 0;
-    fs_config(buffer, is_dir, &uid, &gid, &mode);
+    uint64_t capabilities;
+    fs_config(buffer, is_dir, &uid, &gid, &mode, &capabilities);
     printf("%s %d %d %o\n", buffer, uid, gid, mode);
   }
   return 0;
diff --git a/tools/fs_get_stats/fs_get_stats.c b/tools/fs_get_stats/fs_get_stats.c
index 356f6f9..a9814b9 100644
--- a/tools/fs_get_stats/fs_get_stats.c
+++ b/tools/fs_get_stats/fs_get_stats.c
@@ -57,7 +57,8 @@
 	if (!strcmp(argv[2], "1"))
 		is_dir = 1;
 
-	fs_config(argv[3], is_dir, &uid, &gid, &perms);
+	uint64_t capabilities;
+	fs_config(argv[3], is_dir, &uid, &gid, &perms, &capabilities);
 	fprintf(stdout, "%d %d 0%o\n", uid, gid, perms);
 
 	return 0;
diff --git a/tools/signapk/SignApk.java b/tools/signapk/SignApk.java
index 07aefa7..adfe9a3 100644
--- a/tools/signapk/SignApk.java
+++ b/tools/signapk/SignApk.java
@@ -35,6 +35,7 @@
 import org.bouncycastle.util.encoders.Base64;
 
 import java.io.BufferedReader;
+import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.File;
@@ -83,6 +84,8 @@
 class SignApk {
     private static final String CERT_SF_NAME = "META-INF/CERT.SF";
     private static final String CERT_RSA_NAME = "META-INF/CERT.RSA";
+    private static final String CERT_SF_MULTI_NAME = "META-INF/CERT%d.SF";
+    private static final String CERT_RSA_MULTI_NAME = "META-INF/CERT%d.RSA";
 
     private static final String OTACERT_NAME = "META-INF/com/android/otacert";
 
@@ -90,10 +93,11 @@
 
     // Files matching this pattern are not copied to the output.
     private static Pattern stripPattern =
-            Pattern.compile("^META-INF/(.*)[.](SF|RSA|DSA)$");
+        Pattern.compile("^(META-INF/((.*)[.](SF|RSA|DSA)|com/android/otacert))|(" +
+                        Pattern.quote(JarFile.MANIFEST_NAME) + ")$");
 
     private static X509Certificate readPublicKey(File file)
-            throws IOException, GeneralSecurityException {
+        throws IOException, GeneralSecurityException {
         FileInputStream input = new FileInputStream(file);
         try {
             CertificateFactory cf = CertificateFactory.getInstance("X.509");
@@ -130,7 +134,7 @@
      * @param keyFile The file containing the private key
      */
     private static KeySpec decryptPrivateKey(byte[] encryptedPrivateKey, File keyFile)
-            throws GeneralSecurityException {
+        throws GeneralSecurityException {
         EncryptedPrivateKeyInfo epkInfo;
         try {
             epkInfo = new EncryptedPrivateKeyInfo(encryptedPrivateKey);
@@ -157,7 +161,7 @@
 
     /** Read a PKCS 8 format private key. */
     private static PrivateKey readPrivateKey(File file)
-            throws IOException, GeneralSecurityException {
+        throws IOException, GeneralSecurityException {
         DataInputStream input = new DataInputStream(new FileInputStream(file));
         try {
             byte[] bytes = new byte[(int) file.length()];
@@ -180,7 +184,7 @@
 
     /** Add the SHA1 of every file to the manifest, creating it if necessary. */
     private static Manifest addDigestsToManifest(JarFile jar)
-            throws IOException, GeneralSecurityException {
+        throws IOException, GeneralSecurityException {
         Manifest input = jar.getManifest();
         Manifest output = new Manifest();
         Attributes main = output.getMainAttributes();
@@ -208,11 +212,8 @@
 
         for (JarEntry entry: byName.values()) {
             String name = entry.getName();
-            if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) &&
-                !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) &&
-                !name.equals(OTACERT_NAME) &&
-                (stripPattern == null ||
-                 !stripPattern.matcher(name).matches())) {
+            if (!entry.isDirectory() &&
+                (stripPattern == null || !stripPattern.matcher(name).matches())) {
                 InputStream data = jar.getInputStream(entry);
                 while ((num = data.read(buffer)) > 0) {
                     md.update(buffer, 0, num);
@@ -301,8 +302,8 @@
 
         MessageDigest md = MessageDigest.getInstance("SHA1");
         PrintStream print = new PrintStream(
-                new DigestOutputStream(new ByteArrayOutputStream(), md),
-                true, "UTF-8");
+            new DigestOutputStream(new ByteArrayOutputStream(), md),
+            true, "UTF-8");
 
         // Digest of the entire manifest
         manifest.write(print);
@@ -339,31 +340,6 @@
         }
     }
 
-    private static class CMSByteArraySlice implements CMSTypedData {
-        private final ASN1ObjectIdentifier type;
-        private final byte[] data;
-        private final int offset;
-        private final int length;
-        public CMSByteArraySlice(byte[] data, int offset, int length) {
-            this.data = data;
-            this.offset = offset;
-            this.length = length;
-            this.type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
-        }
-
-        public Object getContent() {
-            throw new UnsupportedOperationException();
-        }
-
-        public ASN1ObjectIdentifier getContentType() {
-            return type;
-        }
-
-        public void write(OutputStream out) throws IOException {
-            out.write(data, offset, length);
-        }
-    }
-
     /** Sign data and write the digital signature to 'out'. */
     private static void writeSignatureBlock(
         CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey,
@@ -395,23 +371,170 @@
         dos.writeObject(asn1.readObject());
     }
 
-    private static void signWholeOutputFile(byte[] zipData,
-                                            OutputStream outputStream,
-                                            X509Certificate publicKey,
-                                            PrivateKey privateKey)
-        throws IOException,
-               CertificateEncodingException,
-               OperatorCreationException,
-               CMSException {
-        // For a zip with no archive comment, the
-        // end-of-central-directory record will be 22 bytes long, so
-        // we expect to find the EOCD marker 22 bytes from the end.
-        if (zipData[zipData.length-22] != 0x50 ||
-            zipData[zipData.length-21] != 0x4b ||
-            zipData[zipData.length-20] != 0x05 ||
-            zipData[zipData.length-19] != 0x06) {
-            throw new IllegalArgumentException("zip data already has an archive comment");
+    /**
+     * Copy all the files in a manifest from input to output.  We set
+     * the modification times in the output to a fixed time, so as to
+     * reduce variation in the output file and make incremental OTAs
+     * more efficient.
+     */
+    private static void copyFiles(Manifest manifest,
+                                  JarFile in, JarOutputStream out, long timestamp) throws IOException {
+        byte[] buffer = new byte[4096];
+        int num;
+
+        Map<String, Attributes> entries = manifest.getEntries();
+        ArrayList<String> names = new ArrayList<String>(entries.keySet());
+        Collections.sort(names);
+        for (String name : names) {
+            JarEntry inEntry = in.getJarEntry(name);
+            JarEntry outEntry = null;
+            if (inEntry.getMethod() == JarEntry.STORED) {
+                // Preserve the STORED method of the input entry.
+                outEntry = new JarEntry(inEntry);
+            } else {
+                // Create a new entry so that the compressed len is recomputed.
+                outEntry = new JarEntry(name);
+            }
+            outEntry.setTime(timestamp);
+            out.putNextEntry(outEntry);
+
+            InputStream data = in.getInputStream(inEntry);
+            while ((num = data.read(buffer)) > 0) {
+                out.write(buffer, 0, num);
+            }
+            out.flush();
         }
+    }
+
+    private static class WholeFileSignerOutputStream extends FilterOutputStream {
+        private boolean closing = false;
+        private ByteArrayOutputStream footer = new ByteArrayOutputStream();
+        private OutputStream tee;
+
+        public WholeFileSignerOutputStream(OutputStream out, OutputStream tee) {
+            super(out);
+            this.tee = tee;
+        }
+
+        public void notifyClosing() {
+            closing = true;
+        }
+
+        public void finish() throws IOException {
+            closing = false;
+
+            byte[] data = footer.toByteArray();
+            if (data.length < 2)
+                throw new IOException("Less than two bytes written to footer");
+            write(data, 0, data.length - 2);
+        }
+
+        public byte[] getTail() {
+            return footer.toByteArray();
+        }
+
+        @Override
+        public void write(byte[] b) throws IOException {
+            write(b, 0, b.length);
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            if (closing) {
+                // if the jar is about to close, save the footer that will be written
+                footer.write(b, off, len);
+            }
+            else {
+                // write to both output streams. out is the CMSTypedData signer and tee is the file.
+                out.write(b, off, len);
+                tee.write(b, off, len);
+            }
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+            if (closing) {
+                // if the jar is about to close, save the footer that will be written
+                footer.write(b);
+            }
+            else {
+                // write to both output streams. out is the CMSTypedData signer and tee is the file.
+                out.write(b);
+                tee.write(b);
+            }
+        }
+    }
+
+    private static class CMSSigner implements CMSTypedData {
+        private JarFile inputJar;
+        private File publicKeyFile;
+        private X509Certificate publicKey;
+        private PrivateKey privateKey;
+        private String outputFile;
+        private OutputStream outputStream;
+        private final ASN1ObjectIdentifier type;
+        private WholeFileSignerOutputStream signer;
+
+        public CMSSigner(JarFile inputJar, File publicKeyFile,
+                         X509Certificate publicKey, PrivateKey privateKey,
+                         OutputStream outputStream) {
+            this.inputJar = inputJar;
+            this.publicKeyFile = publicKeyFile;
+            this.publicKey = publicKey;
+            this.privateKey = privateKey;
+            this.outputStream = outputStream;
+            this.type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
+        }
+
+        public Object getContent() {
+            throw new UnsupportedOperationException();
+        }
+
+        public ASN1ObjectIdentifier getContentType() {
+            return type;
+        }
+
+        public void write(OutputStream out) throws IOException {
+            try {
+                signer = new WholeFileSignerOutputStream(out, outputStream);
+                JarOutputStream outputJar = new JarOutputStream(signer);
+
+                Manifest manifest = addDigestsToManifest(inputJar);
+                signFile(manifest, inputJar,
+                         new X509Certificate[]{ publicKey },
+                         new PrivateKey[]{ privateKey },
+                         outputJar);
+                // Assume the certificate is valid for at least an hour.
+                long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
+                addOtacert(outputJar, publicKeyFile, timestamp, manifest);
+
+                signer.notifyClosing();
+                outputJar.close();
+                signer.finish();
+            }
+            catch (Exception e) {
+                throw new IOException(e);
+            }
+        }
+
+        public void writeSignatureBlock(ByteArrayOutputStream temp)
+            throws IOException,
+                   CertificateEncodingException,
+                   OperatorCreationException,
+                   CMSException {
+            SignApk.writeSignatureBlock(this, publicKey, privateKey, temp);
+        }
+
+        public WholeFileSignerOutputStream getSigner() {
+            return signer;
+        }
+    }
+
+    private static void signWholeFile(JarFile inputJar, File publicKeyFile,
+                                      X509Certificate publicKey, PrivateKey privateKey,
+                                      OutputStream outputStream) throws Exception {
+        CMSSigner cmsOut = new CMSSigner(inputJar, publicKeyFile,
+                                         publicKey, privateKey, outputStream);
 
         ByteArrayOutputStream temp = new ByteArrayOutputStream();
 
@@ -423,8 +546,20 @@
         temp.write(message);
         temp.write(0);
 
-        writeSignatureBlock(new CMSByteArraySlice(zipData, 0, zipData.length-2),
-                            publicKey, privateKey, temp);
+        cmsOut.writeSignatureBlock(temp);
+
+        byte[] zipData = cmsOut.getSigner().getTail();
+
+        // For a zip with no archive comment, the
+        // end-of-central-directory record will be 22 bytes long, so
+        // we expect to find the EOCD marker 22 bytes from the end.
+        if (zipData[zipData.length-22] != 0x50 ||
+            zipData[zipData.length-21] != 0x4b ||
+            zipData[zipData.length-20] != 0x05 ||
+            zipData[zipData.length-19] != 0x06) {
+            throw new IllegalArgumentException("zip data already has an archive comment");
+        }
+
         int total_size = temp.size() + 6;
         if (total_size > 0xffff) {
             throw new IllegalArgumentException("signature is too big for ZIP file comment");
@@ -458,54 +593,61 @@
             }
         }
 
-        outputStream.write(zipData, 0, zipData.length-2);
         outputStream.write(total_size & 0xff);
         outputStream.write((total_size >> 8) & 0xff);
         temp.writeTo(outputStream);
     }
 
-    /**
-     * Copy all the files in a manifest from input to output.  We set
-     * the modification times in the output to a fixed time, so as to
-     * reduce variation in the output file and make incremental OTAs
-     * more efficient.
-     */
-    private static void copyFiles(Manifest manifest,
-        JarFile in, JarOutputStream out, long timestamp) throws IOException {
-        byte[] buffer = new byte[4096];
-        int num;
+    private static void signFile(Manifest manifest, JarFile inputJar,
+                                 X509Certificate[] publicKey, PrivateKey[] privateKey,
+                                 JarOutputStream outputJar)
+        throws Exception {
+        // Assume the certificate is valid for at least an hour.
+        long timestamp = publicKey[0].getNotBefore().getTime() + 3600L * 1000;
 
-        Map<String, Attributes> entries = manifest.getEntries();
-        ArrayList<String> names = new ArrayList<String>(entries.keySet());
-        Collections.sort(names);
-        for (String name : names) {
-            JarEntry inEntry = in.getJarEntry(name);
-            JarEntry outEntry = null;
-            if (inEntry.getMethod() == JarEntry.STORED) {
-                // Preserve the STORED method of the input entry.
-                outEntry = new JarEntry(inEntry);
-            } else {
-                // Create a new entry so that the compressed len is recomputed.
-                outEntry = new JarEntry(name);
-            }
-            outEntry.setTime(timestamp);
-            out.putNextEntry(outEntry);
+        JarEntry je;
 
-            InputStream data = in.getInputStream(inEntry);
-            while ((num = data.read(buffer)) > 0) {
-                out.write(buffer, 0, num);
-            }
-            out.flush();
+        // Everything else
+        copyFiles(manifest, inputJar, outputJar, timestamp);
+
+        // MANIFEST.MF
+        je = new JarEntry(JarFile.MANIFEST_NAME);
+        je.setTime(timestamp);
+        outputJar.putNextEntry(je);
+        manifest.write(outputJar);
+
+        int numKeys = publicKey.length;
+        for (int k = 0; k < numKeys; ++k) {
+            // CERT.SF / CERT#.SF
+            je = new JarEntry(numKeys == 1 ? CERT_SF_NAME :
+                              (String.format(CERT_SF_MULTI_NAME, k)));
+            je.setTime(timestamp);
+            outputJar.putNextEntry(je);
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            writeSignatureFile(manifest, baos);
+            byte[] signedData = baos.toByteArray();
+            outputJar.write(signedData);
+
+            // CERT.RSA / CERT#.RSA
+            je = new JarEntry(numKeys == 1 ? CERT_RSA_NAME :
+                              (String.format(CERT_RSA_MULTI_NAME, k)));
+            je.setTime(timestamp);
+            outputJar.putNextEntry(je);
+            writeSignatureBlock(new CMSProcessableByteArray(signedData),
+                                publicKey[k], privateKey[k], outputJar);
         }
     }
 
+    private static void usage() {
+        System.err.println("Usage: signapk [-w] " +
+                           "publickey.x509[.pem] privatekey.pk8 " +
+                           "[publickey2.x509[.pem] privatekey2.pk8 ...] " +
+                           "input.jar output.jar");
+        System.exit(2);
+    }
+
     public static void main(String[] args) {
-        if (args.length != 4 && args.length != 5) {
-            System.err.println("Usage: signapk [-w] " +
-                    "publickey.x509[.pem] privatekey.pk8 " +
-                    "input.jar output.jar");
-            System.exit(2);
-        }
+        if (args.length < 4) usage();
 
         sBouncyCastleProvider = new BouncyCastleProvider();
         Security.addProvider(sBouncyCastleProvider);
@@ -517,80 +659,60 @@
             argstart = 1;
         }
 
+        if ((args.length - argstart) % 2 == 1) usage();
+        int numKeys = ((args.length - argstart) / 2) - 1;
+        if (signWholeFile && numKeys > 1) {
+            System.err.println("Only one key may be used with -w.");
+            System.exit(2);
+        }
+
+        String inputFilename = args[args.length-2];
+        String outputFilename = args[args.length-1];
+
         JarFile inputJar = null;
-        JarOutputStream outputJar = null;
         FileOutputStream outputFile = null;
 
         try {
-            File publicKeyFile = new File(args[argstart+0]);
-            X509Certificate publicKey = readPublicKey(publicKeyFile);
+            File firstPublicKeyFile = new File(args[argstart+0]);
 
-            // Assume the certificate is valid for at least an hour.
-            long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
+            X509Certificate[] publicKey = new X509Certificate[numKeys];
+            for (int i = 0; i < numKeys; ++i) {
+                int argNum = argstart + i*2;
+                publicKey[i] = readPublicKey(new File(args[argNum]));
+            }
 
-            PrivateKey privateKey = readPrivateKey(new File(args[argstart+1]));
-            inputJar = new JarFile(new File(args[argstart+2]), false);  // Don't verify.
+            // Set the ZIP file timestamp to the starting valid time
+            // of the 0th certificate plus one hour (to match what
+            // we've historically done).
+            long timestamp = publicKey[0].getNotBefore().getTime() + 3600L * 1000;
 
-            OutputStream outputStream = null;
+            PrivateKey[] privateKey = new PrivateKey[numKeys];
+            for (int i = 0; i < numKeys; ++i) {
+                int argNum = argstart + i*2 + 1;
+                privateKey[i] = readPrivateKey(new File(args[argNum]));
+            }
+            inputJar = new JarFile(new File(inputFilename), false);  // Don't verify.
+
+            outputFile = new FileOutputStream(outputFilename);
+
+
             if (signWholeFile) {
-                outputStream = new ByteArrayOutputStream();
+                SignApk.signWholeFile(inputJar, firstPublicKeyFile,
+                                      publicKey[0], privateKey[0], outputFile);
             } else {
-                outputStream = outputFile = new FileOutputStream(args[argstart+3]);
-            }
-            outputJar = new JarOutputStream(outputStream);
+                JarOutputStream outputJar = new JarOutputStream(outputFile);
 
-            // For signing .apks, use the maximum compression to make
-            // them as small as possible (since they live forever on
-            // the system partition).  For OTA packages, use the
-            // default compression level, which is much much faster
-            // and produces output that is only a tiny bit larger
-            // (~0.1% on full OTA packages I tested).
-            if (!signWholeFile) {
+                // For signing .apks, use the maximum compression to make
+                // them as small as possible (since they live forever on
+                // the system partition).  For OTA packages, use the
+                // default compression level, which is much much faster
+                // and produces output that is only a tiny bit larger
+                // (~0.1% on full OTA packages I tested).
                 outputJar.setLevel(9);
-            }
 
-            JarEntry je;
-
-            Manifest manifest = addDigestsToManifest(inputJar);
-
-            // Everything else
-            copyFiles(manifest, inputJar, outputJar, timestamp);
-
-            // otacert
-            if (signWholeFile) {
-                addOtacert(outputJar, publicKeyFile, timestamp, manifest);
-            }
-
-            // MANIFEST.MF
-            je = new JarEntry(JarFile.MANIFEST_NAME);
-            je.setTime(timestamp);
-            outputJar.putNextEntry(je);
-            manifest.write(outputJar);
-
-            // CERT.SF
-            je = new JarEntry(CERT_SF_NAME);
-            je.setTime(timestamp);
-            outputJar.putNextEntry(je);
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            writeSignatureFile(manifest, baos);
-            byte[] signedData = baos.toByteArray();
-            outputJar.write(signedData);
-
-            // CERT.RSA
-            je = new JarEntry(CERT_RSA_NAME);
-            je.setTime(timestamp);
-            outputJar.putNextEntry(je);
-            writeSignatureBlock(new CMSProcessableByteArray(signedData),
-                                publicKey, privateKey, outputJar);
-
-            outputJar.close();
-            outputJar = null;
-            outputStream.flush();
-
-            if (signWholeFile) {
-                outputFile = new FileOutputStream(args[argstart+3]);
-                signWholeOutputFile(((ByteArrayOutputStream)outputStream).toByteArray(),
-                                    outputFile, publicKey, privateKey);
+                signFile(addDigestsToManifest(inputJar), inputJar,
+                         publicKey, privateKey, outputJar);
+                outputJar.close();
             }
         } catch (Exception e) {
             e.printStackTrace();