auto import from //branches/cupcake/...@130745
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index b2e04a7..0b292bf 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -84,3 +84,111 @@
clean_steps_file :=
INTERNAL_CLEAN_STEPS :=
INTERNAL_CLEAN_BUILD_VERSION :=
+
+
+# Since products and build variants (unfortunately) share the same
+# PRODUCT_OUT staging directory, things can get out of sync if different
+# build configurations are built in the same tree. The following logic
+# will notice when the configuration has changed and remove the files
+# necessary to keep things consistent.
+
+previous_build_config_file := $(PRODUCT_OUT)/previous_build_config.mk
+
+# TODO: this special case for the sdk is only necessary while "sdk"
+# is a valid make target. Eventually, it will just be a product, at
+# which point TARGET_PRODUCT will handle it and we can avoid this check
+# of MAKECMDGOALS. The "addprefix" is just to keep things pretty.
+ifneq ($(TARGET_PRODUCT),sdk)
+ building_sdk := $(addprefix -,$(filter sdk,$(MAKECMDGOALS)))
+else
+ # Don't bother with this extra part when explicitly building the sdk product.
+ building_sdk :=
+endif
+current_build_config := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)$(building_sdk)
+building_sdk :=
+force_installclean := false
+
+# Read the current state from the file, if present.
+# Will set PREVIOUS_BUILD_CONFIG.
+#
+PREVIOUS_BUILD_CONFIG :=
+-include $(previous_build_config_file)
+PREVIOUS_BUILD_CONFIG := $(strip $(PREVIOUS_BUILD_CONFIG))
+ifdef PREVIOUS_BUILD_CONFIG
+ ifneq "$(current_build_config)" "$(PREVIOUS_BUILD_CONFIG)"
+ $(info *** Build configuration changed: "$(PREVIOUS_BUILD_CONFIG)" -> "$(current_build_config)")
+ force_installclean := true
+ endif
+endif # else, this is the first build, so no need to clean.
+PREVIOUS_BUILD_CONFIG :=
+
+# Write the new state to the file.
+#
+$(shell \
+ mkdir -p $(dir $(previous_build_config_file)) && \
+ echo "PREVIOUS_BUILD_CONFIG := $(current_build_config)" > \
+ $(previous_build_config_file) \
+ )
+previous_build_config_file :=
+current_build_config :=
+
+#
+# installclean logic
+#
+
+# The files/dirs to delete during an installclean. This includes the
+# non-common APPS directory, which may contain the wrong resources.
+# Use "./" in front of the paths to avoid accidentally deleting random
+# parts of the filesystem if any of the *_OUT vars resolve to blank.
+#
+# Deletes all of the files that change between different build types,
+# like "make user" vs. "make sdk". This lets you work with different
+# build types without having to do a full clean each time. E.g.:
+#
+# $ make -j8 all
+# $ make installclean
+# $ make -j8 user
+# $ make installclean
+# $ make -j8 sdk
+#
+installclean_files := \
+ ./$(HOST_OUT)/obj/NOTICE_FILES \
+ ./$(HOST_OUT)/sdk \
+ ./$(PRODUCT_OUT)/*.img \
+ ./$(PRODUCT_OUT)/*.txt \
+ ./$(PRODUCT_OUT)/*.xlb \
+ ./$(PRODUCT_OUT)/*.zip \
+ ./$(PRODUCT_OUT)/data \
+ ./$(PRODUCT_OUT)/obj/APPS \
+ ./$(PRODUCT_OUT)/obj/NOTICE_FILES \
+ ./$(PRODUCT_OUT)/obj/PACKAGING \
+ ./$(PRODUCT_OUT)/recovery \
+ ./$(PRODUCT_OUT)/root \
+ ./$(PRODUCT_OUT)/system
+
+# The files/dirs to delete during a dataclean, which removes any files
+# in the staging and emulator data partitions.
+dataclean_files := \
+ ./$(PRODUCT_OUT)/data/* \
+ ./$(PRODUCT_OUT)/data-qemu/* \
+ ./$(PRODUCT_OUT)/userdata-qemu.img
+
+# Define the rules for commandline invocation.
+.PHONY: dataclean
+dataclean: FILES := $(dataclean_files)
+dataclean:
+ $(hide) rm -rf $(FILES)
+ @echo "Deleted emulator userdata images."
+
+.PHONY: installclean
+installclean: FILES := $(installclean_files)
+installclean: dataclean
+ $(hide) rm -rf $(FILES)
+ @echo "Deleted images and staging directories."
+
+ifeq "$(force_installclean)" "true"
+ $(info *** Forcing "make installclean"...)
+ $(shell rm -rf $(dataclean_files) $(installclean_files))
+ $(info *** Done with the cleaning, now starting the real build.)
+endif
+force_installclean :=