Merge "Merge LOCAL_STATIC_ANDROID_LIBRARIES manifests"
diff --git a/Changes.md b/Changes.md
index b92342e..21a0abe 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,11 +1,57 @@
 # Build System Changes for Android.mk Writers
 
+## Removing '/' from Valid Module Names {#name_slash}
+
+The build system uses module names in path names in many places. Having an
+extra '/' or '../' being inserted can cause problems -- and not just build
+breaks, but stranger invalid behavior.
+
+In every case we've seen, the fix is relatively simple: move the directory into
+`LOCAL_MODULE_RELATIVE_PATH` (or `LOCAL_MODULE_PATH` if you're still using it).
+If this causes multiple modules to be named the same, use unique module names
+and `LOCAL_MODULE_STEM` to change the installed file name:
+
+``` make
+include $(CLEAR_VARS)
+LOCAL_MODULE := ver1/code.bin
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware
+...
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := ver2/code.bin
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware
+...
+include $(BUILD_PREBUILT)
+```
+
+Can be rewritten as:
+
+```
+include $(CLEAR_VARS)
+LOCAL_MODULE := ver1_code.bin
+LOCAL_MODULE_STEM := code.bin
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware/ver1
+...
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := ver2_code.bin
+LOCAL_MODULE_STEM := code.bin
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware/ver2
+...
+include $(BUILD_PREBUILT)
+```
+
+You just need to make sure that any other references (`PRODUCT_PACKAGES`,
+`LOCAL_REQUIRED_MODULES`, etc) are converted to the new names.
+
 ## Valid Module Names {#name}
 
 We've adopted lexical requirements very similar to [Bazel's
 requirements](https://docs.bazel.build/versions/master/build-ref.html#name) for
 target names. Valid characters are `a-z`, `A-Z`, `0-9`, and the special
-characters `_.+-=,@~/`. This currently applies to `LOCAL_PACKAGE_NAME`,
+characters `_.+-=,@~`. This currently applies to `LOCAL_PACKAGE_NAME`,
 `LOCAL_MODULE`, and `LOCAL_MODULE_SUFFIX`, and `LOCAL_MODULE_STEM*`.
 
 Many other characters already caused problems if you used them, so we don't
diff --git a/core/Makefile b/core/Makefile
index 1161e4d..a5109f0 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -2917,7 +2917,7 @@
 # -----------------------------------------------------------------
 # NDK Sysroot Package
 NDK_SYSROOT_TARGET := $(PRODUCT_OUT)/ndk_sysroot.tar.bz2
-$(NDK_SYSROOT_TARGET): ndk
+$(NDK_SYSROOT_TARGET): $(SOONG_OUT_DIR)/ndk.timestamp
 	@echo Package NDK sysroot...
 	$(hide) tar cjf $@ -C $(SOONG_OUT_DIR) ndk
 
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index 4a3e669..3af81ff 100644
--- a/core/android_manifest.mk
+++ b/core/android_manifest.mk
@@ -39,24 +39,27 @@
 endif
 
 # Set up rules to merge library manifest files
+my_exported_sdk_libs_file := $(call local-intermediates-dir,COMMON)/exported-sdk-libs
+$(full_android_manifest): PRIVATE_EXPORTED_SDK_LIBS_FILE := $(my_exported_sdk_libs_file)
+$(full_android_manifest): $(my_exported_sdk_libs_file)
+$(full_android_manifest): $(MANIFEST_FIXER)
+
 ifneq (,$(strip $(my_full_libs_manifest_files)))
 
 $(full_android_manifest): PRIVATE_LIBS_MANIFESTS := $(my_full_libs_manifest_files)
 $(full_android_manifest): $(ANDROID_MANIFEST_MERGER_CLASSPATH)
-$(full_android_manifest): $(MANIFEST_FIXER)
 $(full_android_manifest) : $(main_android_manifest) $(my_full_libs_manifest_files)
 	@echo "Merge android manifest files: $@ <-- $< $(PRIVATE_LIBS_MANIFESTS)"
 	@mkdir -p $(dir $@)
-	$(MANIFEST_FIXER) $< $@.tmp --minSdkVersion $(PRIVATE_MIN_SDK_VERSION)
+	$(call fix-manifest,$<,$@.tmp,$(PRIVATE_MIN_SDK_VERSION),$(PRIVATE_EXPORTED_SDK_LIBS_FILE))
 	$(hide) $(ANDROID_MANIFEST_MERGER) --main $@.tmp \
 	    --libs $(call normalize-path-list,$(PRIVATE_LIBS_MANIFESTS)) \
 	    --out $@
 	rm $@.tmp
 
 else
-$(full_android_manifest): $(MANIFEST_FIXER)
 $(full_android_manifest): $(main_android_manifest)
 	@echo "Fix manifest: $@"
-	$(MANIFEST_FIXER) $< $@ --minSdkVersion $(PRIVATE_MIN_SDK_VERSION)
+	$(call fix-manifest,$<,$@,$(PRIVATE_MIN_SDK_VERSION),$(PRIVATE_EXPORTED_SDK_LIBS_FILE))
 
 endif
diff --git a/core/autogen_test_config.mk b/core/autogen_test_config.mk
index 20c582a..5feec2b 100644
--- a/core/autogen_test_config.mk
+++ b/core/autogen_test_config.mk
@@ -31,7 +31,7 @@
 # Auto generating test config file for native test
 $(autogen_test_config_file) : $(autogen_test_config_template)
 	@echo "Auto generating test config $(notdir $@)"
-	$(hide) sed 's&{MODULE}&$(PRIVATE_MODULE)&g' $^ > $@
+	$(hide) sed 's&{MODULE}&$(PRIVATE_MODULE)&g' $< > $@
 my_auto_generate_config := true
 else
 # Auto generating test config file for instrumentation test
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 41af27b..4f0e39f 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -793,8 +793,10 @@
 $(j_or_n)-$(h_or_t)-tests $(j_or_n)-tests $(h_or_t)-tests : $(my_checked_module)
 endif
 $(LOCAL_MODULE)-$(h_or_hc_or_t) : $(my_all_targets)
+.PHONY: $(LOCAL_MODULE)-$(h_or_hc_or_t)
 ifeq ($(j_or_n),native)
 $(LOCAL_MODULE)-$(h_or_hc_or_t)$(my_32_64_bit_suffix) : $(my_all_targets)
+.PHONY: $(LOCAL_MODULE)-$(h_or_hc_or_t)$(my_32_64_bit_suffix)
 endif
 endif
 
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 8cc7c98..5051ef7 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -84,6 +84,7 @@
 LOCAL_EXPORT_HEADER_LIBRARY_HEADERS:=
 LOCAL_EXPORT_PACKAGE_RESOURCES:=
 LOCAL_EXPORT_PROGUARD_FLAG_FILES:=
+LOCAL_EXPORT_SDK_LIBRARIES:=
 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS:=
 LOCAL_EXPORT_STATIC_LIBRARY_HEADERS:=
 LOCAL_EXTRACT_APK:=
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 1363c8d..aeead06 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -190,6 +190,15 @@
   endif
 endif
 
+# Disable Scudo if ASan or TSan is enabled.
+ifneq ($(filter address thread,$(my_sanitize)),)
+  my_sanitize := $(filter-out scudo,$(my_sanitize))
+endif
+
+ifneq ($(filter scudo,$(my_sanitize)),)
+  my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)SCUDO_RUNTIME_LIBRARY)
+endif
+
 # Undefined symbols can occur if a non-sanitized library links
 # sanitized static libraries. That's OK, because the executable
 # always depends on the ASan runtime library, which defines these
@@ -374,7 +383,7 @@
     notrap_arg := $(subst $(space),$(comma),$(my_sanitize_diag)),
     my_cflags += -fno-sanitize-trap=$(notrap_arg)
     # Diagnostic requires a runtime library, unless ASan or TSan are also enabled.
-    ifeq ($(filter address thread,$(my_sanitize)),)
+    ifeq ($(filter address thread scudo,$(my_sanitize)),)
       # Does not have to be the first DT_NEEDED unlike ASan.
       my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_RUNTIME_LIBRARY)
     endif
diff --git a/core/definitions.mk b/core/definitions.mk
index 07576f9..a8d7b2d 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -731,6 +731,25 @@
 endef
 endif
 
+# Get the exported-sdk-libs files which collectively give you the list of exported java sdk
+# lib names that are (transitively) exported from the given set of java libs
+# $(1): library name list
+define exported-sdk-libs-files
+$(foreach lib,$(1),$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/exported-sdk-libs)
+endef
+
+# Fix manifest
+# $(1): input manifest path
+# $(2): output manifest path
+# $(3): min sdk version
+# $(4): (optional) exported-sdk-libs file
+define fix-manifest
+$(MANIFEST_FIXER) \
+--minSdkVersion $(3) \
+$(if $(4),$$(cat $(4) | sort -u | sed -e 's/^/\ --uses-library\ /' | tr '\n' ' ')) \
+$(1) $(2)
+endef
+
 ###########################################################
 ## Returns true if $(1) and $(2) are equal.  Returns
 ## the empty string if they are not equal.
@@ -3488,24 +3507,26 @@
 ###########################################################
 ## Verify module name meets character requirements:
 ##   a-z A-Z 0-9
-##   _.+-=,@~/
+##   _.+-=,@~
 ##
-## This is equivalent to bazel's target name restrictions:
+## This is a subset of bazel's target name restrictions:
 ##   https://docs.bazel.build/versions/master/build-ref.html#name
 ###########################################################
 define verify-module-name
+$(if $(filter-out $(LOCAL_MODULE),$(subst /,,$(LOCAL_MODULE))), \
+  $(call pretty-warning,Module name contains a /$(comma) use LOCAL_MODULE_STEM and LOCAL_MODULE_RELATIVE_PATH instead)) \
 $(if $(call _invalid-name-chars,$(LOCAL_MODULE)), \
   $(call pretty-error,Invalid characters in module name: $(call _invalid-name-chars,$(LOCAL_MODULE))))
 endef
 define _invalid-name-chars
-$(subst /,,$(subst _,,$(subst .,,$(subst +,,$(subst -,,$(subst =,,$(subst $(comma),,$(subst @,,$(subst ~,,$(subst 0,,$(subst 1,,$(subst 2,,$(subst 3,,$(subst 4,,$(subst 5,,$(subst 6,,$(subst 7,,$(subst 8,,$(subst 9,,$(subst a,,$(subst b,,$(subst c,,$(subst d,,$(subst e,,$(subst f,,$(subst g,,$(subst h,,$(subst i,,$(subst j,,$(subst k,,$(subst l,,$(subst m,,$(subst n,,$(subst o,,$(subst p,,$(subst q,,$(subst r,,$(subst s,,$(subst t,,$(subst u,,$(subst v,,$(subst w,,$(subst x,,$(subst y,,$(subst z,,$(call to-lower,$(1)))))))))))))))))))))))))))))))))))))))))))))))
+$(subst _,,$(subst .,,$(subst +,,$(subst -,,$(subst =,,$(subst $(comma),,$(subst @,,$(subst ~,,$(subst 0,,$(subst 1,,$(subst 2,,$(subst 3,,$(subst 4,,$(subst 5,,$(subst 6,,$(subst 7,,$(subst 8,,$(subst 9,,$(subst a,,$(subst b,,$(subst c,,$(subst d,,$(subst e,,$(subst f,,$(subst g,,$(subst h,,$(subst i,,$(subst j,,$(subst k,,$(subst l,,$(subst m,,$(subst n,,$(subst o,,$(subst p,,$(subst q,,$(subst r,,$(subst s,,$(subst t,,$(subst u,,$(subst v,,$(subst w,,$(subst x,,$(subst y,,$(subst z,,$(call to-lower,$(1))))))))))))))))))))))))))))))))))))))))))))))
 endef
 .KATI_READONLY := verify-module-name _invalid-name-chars
 
 ###########################################################
 ## Verify module stem meets character requirements:
 ##   a-z A-Z 0-9
-##   _.+-=,@~/
+##   _.+-=,@~
 ##
 ## This is a subset of bazel's target name restrictions:
 ##   https://docs.bazel.build/versions/master/build-ref.html#name
@@ -3513,7 +3534,9 @@
 ## $(1): The module stem variable to check
 ###########################################################
 define verify-module-stem
+$(if $(filter-out $($(1)),$(subst /,,$($(1)))), \
+  $(call pretty-warning,Module stem \($(1)\) contains a /$(comma) use LOCAL_MODULE_RELATIVE_PATH instead)) \
 $(if $(call _invalid-name-chars,$($(1))), \
-  $(call pretty-error,Invalid characters in module stem ($(1)): $(call _invalid-name-chars,$($(1)))))
+  $(call pretty-error,Invalid characters in module stem \($(1)\): $(call _invalid-name-chars,$($(1)))))
 endef
 .KATI_READONLY := verify-module-stem
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 64ad200..b64155c 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -100,6 +100,9 @@
 my_use_profile_for_boot_image := true
 endif
 endif
+ifeq (,$(strip $(LIBART_TARGET_BOOT_DEX_FILES)))
+my_use_profile_for_boot_image := false
+endif
 
 ifeq (true,$(my_use_profile_for_boot_image))
 
diff --git a/core/java_common.mk b/core/java_common.mk
index f4696d7..5dfbc5f 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -237,6 +237,8 @@
 full_java_bootclasspath_libs :=
 empty_bootclasspath :=
 my_system_modules :=
+exported_sdk_libs_files :=
+my_exported_sdk_libs_file :=
 
 ifndef LOCAL_IS_HOST_MODULE
   sdk_libs :=
@@ -326,6 +328,14 @@
   full_shared_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES) $(sdk_libs),$(LOCAL_IS_HOST_MODULE))
   full_shared_java_header_libs := $(call java-lib-header-files,$(LOCAL_JAVA_LIBRARIES) $(sdk_libs),$(LOCAL_IS_HOST_MODULE))
   sdk_libs :=
+
+  # Files that contains the names of SDK libraries exported from dependencies. These will be re-exported.
+  # Note: No need to consider LOCAL_*_ANDROID_LIBRARIES and LOCAL_STATIC_JAVA_AAR_LIBRARIES. They are all appended to
+  # LOCAL_*_JAVA_LIBRARIES in java.mk
+  exported_sdk_libs_files := $(call exported-sdk-libs-files,$(LOCAL_JAVA_LIBRARIES) $(LOCAL_STATIC_JAVA_LIBRARIES))
+  # The file that contains the names of all SDK libraries that this module exports and re-exports
+  my_exported_sdk_libs_file := $(call local-intermediates-dir,COMMON)/exported-sdk-libs
+
 else # LOCAL_IS_HOST_MODULE
 
   ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
@@ -362,6 +372,22 @@
   endif # USE_CORE_LIB_BOOTCLASSPATH
 endif # !LOCAL_IS_HOST_MODULE
 
+
+# Export the SDK libs. The sdk library names listed in LOCAL_SDK_LIBRARIES are first exported.
+# Then sdk library names exported from dependencies are all re-exported.
+$(my_exported_sdk_libs_file): PRIVATE_EXPORTED_SDK_LIBS_FILES := $(exported_sdk_libs_files)
+$(my_exported_sdk_libs_file): PRIVATE_SDK_LIBS := $(sort $(LOCAL_SDK_LIBRARIES))
+$(my_exported_sdk_libs_file): $(exported_sdk_libs_files)
+	@echo "Export SDK libs $@"
+	$(hide) mkdir -p $(dir $@) && rm -f $@ $@.temp
+	$(if $(PRIVATE_SDK_LIBS),\
+		echo $(PRIVATE_SDK_LIBS) | tr ' ' '\n' > $@.temp,\
+		touch $@.temp)
+	$(if $(PRIVATE_EXPORTED_SDK_LIBS_FILES),\
+		cat $(PRIVATE_EXPORTED_SDK_LIBS_FILES) >> $@.temp)
+	$(hide) cat $@.temp | sort -u > $@
+	$(hide) rm -f $@.temp
+
 ifdef empty_bootclasspath
   ifdef full_java_bootclasspath_libs
     $(call pretty-error,internal error: empty_bootclasspath and full_java_bootclasspath_libs should not both be set)
diff --git a/core/notice_files.mk b/core/notice_files.mk
index 9dce2b3..08778c5 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -40,6 +40,10 @@
 
 ifdef notice_file
 
+ifdef my_register_name
+ALL_MODULES.$(my_register_name).NOTICES := $(ALL_MODULES.$(my_register_name).NOTICES) $(notice_file)
+endif
+
 # This relies on the name of the directory in PRODUCT_OUT matching where
 # it's installed on the target - i.e. system, data, etc.  This does
 # not work for root and isn't exact, but it's probably good enough for
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index 39f9adb..17dd046 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -678,6 +678,15 @@
 # make sure the classes.jar and javalib.jar are built before $(LOCAL_BUILT_MODULE)
 $(built_module) : $(common_javalib_jar)
 
+my_exported_sdk_libs_file := $(intermediates.COMMON)/exported-sdk-libs
+$(my_exported_sdk_libs_file): PRIVATE_EXPORTED_SDK_LIBS := $(LOCAL_EXPORT_SDK_LIBRARIES)
+$(my_exported_sdk_libs_file):
+	@echo "Export SDK libs $@"
+	$(hide) mkdir -p $(dir $@) && rm -f $@
+	$(if $(PRIATE_EXPORTED_SDK_LIBS),\
+		$(hide) echo $(PRIVATE_EXPORTED_SDK_LIBS) | tr ' ' '\n' > $@,\
+		$(hide) touch $@)
+
 endif # ! prebuilt_module_is_dex_javalib
 endif # LOCAL_IS_HOST_MODULE is not set
 
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index e96394d..0ba2c7a 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -148,3 +148,13 @@
 my_common := COMMON
 include $(BUILD_SYSTEM)/link_type.mk
 endif # !LOCAL_IS_HOST_MODULE
+
+# LOCAL_EXPORT_SDK_LIBRARIES set by soong is written to exported-sdk-libs file
+my_exported_sdk_libs_file := $(intermediates.COMMON)/exported-sdk-libs
+$(my_exported_sdk_libs_file): PRIVATE_EXPORTED_SDK_LIBS := $(LOCAL_EXPORT_SDK_LIBRARIES)
+$(my_exported_sdk_libs_file):
+	@echo "Export SDK libs $@"
+	$(hide) mkdir -p $(dir $@) && rm -f $@
+	$(if $(PRIVATE_EXPORTED_SDK_LIBS),\
+		$(hide) echo $(PRIVATE_EXPORTED_SDK_LIBS) | tr ' ' '\n' > $@,\
+		$(hide) touch $@)
diff --git a/core/tasks/vndk.mk b/core/tasks/vndk.mk
index b9133df..ba48df7 100644
--- a/core/tasks/vndk.mk
+++ b/core/tasks/vndk.mk
@@ -36,38 +36,38 @@
 )
 endef
 
-# Returns list of file paths of the intermediate objs
+# Returns list of src:dest paths of the intermediate objs
 #
 # Args:
 #   $(1): list of module and filename pairs (e.g., ld.config.txt:ld.config.27.txt ...)
-#   $(2): target class (e.g., SHARED_LIBRARIES, STATIC_LIBRARIES, ETC)
-#   $(3): if not empty, evaluates for TARGET_2ND_ARCH
+#   $(2): if not empty, evaluates for TARGET_2ND_ARCH
 define paths-of-intermediates
 $(strip \
   $(foreach pair,$(1), \
-    $(eval split_pair := $(subst :,$(space),$(pair))) \
-    $(eval module := $(word 1,$(split_pair))) \
-    $(eval filename := $(word 2,$(split_pair))) \
-    $(eval dir := $(call intermediates-dir-for,$(2),$(module),,,$(3))) \
-    $(call append-path,$(dir),$(filename)) \
+    $(eval module := $(call word-colon,1,$(pair))$(if $(2),$(TARGET_2ND_ARCH_MODULE_SUFFIX))) \
+    $(eval built := $(ALL_MODULES.$(module).BUILT_INSTALLED)) \
+    $(eval filename := $(call word-colon,2,$(pair))) \
+    $(if $(wordlist 2,100,$(built)), \
+      $(error Unable to handle multiple built files ($(module)): $(built))) \
+    $(if $(built),$(call word-colon,1,$(built)):$(filename)) \
   ) \
 )
 endef
 
-# Returns paths of notice files under $(TARGET_OUT_NOTICE_FILES)
+# Returns src:dest list of notice files
 #
 # Args:
 #   $(1): list of lib names (e.g., libfoo.vendor)
-#   $(2): vndk lib type, one of 'vndk' or 'vndk-sp'
 define paths-of-notice-files
 $(strip \
-  $(eval lib_dir := lib$(if $(TARGET_IS_64BIT),64,)) \
-  $(eval vndk_dir := $(2)-$(PLATFORM_VNDK_VERSION)) \
   $(foreach lib,$(1), \
-    $(eval notice_file_name := $(patsubst %.vendor,%.so.txt,$(lib))) \
-    $(TARGET_OUT_NOTICE_FILES)/src/system/$(lib_dir)/$(vndk_dir)/$(notice_file_name) \
-  ) \
-)
+    $(eval notice := $(sort \
+      $(ALL_MODULES.$(lib).NOTICES) \
+      $(if $(TARGET_2ND_ARCH),
+        $(ALL_MODULES.$(lib)$(TARGET_2ND_ARCH_MODULE_SUFFIX).NOTICES)))) \
+    $(if $(wordlist 2,100,$(notice)), \
+      $(error Unable to handle multiple notice files ($(lib)): $(notice))) \
+    $(if $(notice),$(notice):$(subst .vendor,,$(lib)).so.txt)))
 endef
 
 # If in the future libclang_rt.ubsan* is removed from the VNDK-core list,
@@ -103,34 +103,37 @@
 #######################################
 # vndkcore.libraries.txt
 vndkcore.libraries.txt := $(vndk_snapshot_configs_out)/vndkcore.libraries.txt
-$(vndkcore.libraries.txt): $(vndk_core_libs)
+$(vndkcore.libraries.txt): PRIVATE_LIBS := $(vndk_core_libs)
+$(vndkcore.libraries.txt):
 	@echo 'Generating: $@'
 	@rm -f $@
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
-	$(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
+	$(hide) $(foreach lib,$(PRIVATE_LIBS),echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
 
 
 #######################################
 # vndkprivate.libraries.txt
 vndkprivate.libraries.txt := $(vndk_snapshot_configs_out)/vndkprivate.libraries.txt
-$(vndkprivate.libraries.txt): $(vndk_private_libs)
+$(vndkprivate.libraries.txt): PRIVATE_LIBS := $(vndk_private_libs)
+$(vndkprivate.libraries.txt):
 	@echo 'Generating: $@'
 	@rm -f $@
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
-	$(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
+	$(hide) $(foreach lib,$(PRIVATE_LIBS),echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
 
 
 #######################################
 # module_paths.txt
 module_paths.txt := $(vndk_snapshot_configs_out)/module_paths.txt
-$(module_paths.txt): $(vndk_snapshot_libs)
+$(module_paths.txt): PRIVATE_LIBS := $(vndk_snapshot_libs)
+$(module_paths.txt):
 	@echo 'Generating: $@'
 	@rm -f $@
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
-	$(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so $(ALL_MODULES.$(lib).PATH) >> $@;)
+	$(hide) $(foreach lib,$(PRIVATE_LIBS),echo $(patsubst %.vendor,%,$(lib)).so $(ALL_MODULES.$(lib).PATH) >> $@;)
 
 
 vndk_snapshot_configs := \
@@ -151,70 +154,76 @@
 
 $(vndk_snapshot_zip): PRIVATE_VNDK_SNAPSHOT_OUT := $(vndk_snapshot_out)
 
+deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(subst .vendor,,$(lib)).so))
 $(vndk_snapshot_zip): PRIVATE_VNDK_CORE_OUT := $(vndk_lib_dir)/shared/vndk-core
-$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES := \
-  $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(lib).so),SHARED_LIBRARIES)
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES := $(deps)
+$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
+deps :=
 
+deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(subst .vendor,,$(lib)).so))
 $(vndk_snapshot_zip): PRIVATE_VNDK_SP_OUT := $(vndk_lib_dir)/shared/vndk-sp
-$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES := \
-  $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(lib).so),SHARED_LIBRARIES)
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES := $(deps)
+$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
+deps :=
 
+deps := $(call paths-of-intermediates,$(foreach txt,$(vndk_prebuilt_txts), \
+          $(txt):$(patsubst %.txt,%.$(PLATFORM_VNDK_VERSION).txt,$(txt)))) \
+        $(foreach config,$(vndk_snapshot_configs),$(config):$(notdir $(config)))
 $(vndk_snapshot_zip): PRIVATE_CONFIGS_OUT := $(vndk_snapshot_variant)/configs
-$(vndk_snapshot_zip): PRIVATE_CONFIGS_INTERMEDIATES := \
-  $(call paths-of-intermediates,$(foreach txt,$(vndk_prebuilt_txts), \
-    $(txt):$(patsubst %.txt,%.$(PLATFORM_VNDK_VERSION).txt,$(txt))),ETC) \
-  $(vndk_snapshot_configs)
+$(vndk_snapshot_zip): PRIVATE_CONFIGS_INTERMEDIATES := $(deps)
+$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
+deps :=
 
+notices := $(call paths-of-notice-files,$(vndk_core_libs) $(vndk_sp_libs))
 $(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_OUT := $(vndk_snapshot_variant)/NOTICE_FILES
-$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_INTERMEDIATES := \
-  $(call paths-of-notice-files,$(vndk_core_libs),vndk) \
-  $(call paths-of-notice-files,$(vndk_sp_libs),vndk-sp)
+$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_INTERMEDIATES := $(notices)
+$(vndk_snapshot_zip): $(foreach n,$(notices),$(call word-colon,1,$(n)))
+notices :=
 
 ifdef TARGET_2ND_ARCH
+deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(subst .vendor,,$(lib)).so),true)
 $(vndk_snapshot_zip): PRIVATE_VNDK_CORE_OUT_2ND := $(vndk_lib_dir_2nd)/shared/vndk-core
-$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES_2ND := \
-  $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(lib).so),SHARED_LIBRARIES,true)
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES_2ND := $(deps)
+$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
+deps :=
 
+deps := $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(subst .vendor,,$(lib)).so),true)
 $(vndk_snapshot_zip): PRIVATE_VNDK_SP_OUT_2ND := $(vndk_lib_dir_2nd)/shared/vndk-sp
-$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES_2ND := \
-  $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(lib).so),SHARED_LIBRARIES,true)
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES_2ND := $(deps)
+$(vndk_snapshot_zip): $(foreach d,$(deps),$(call word-colon,1,$(d)))
+deps :=
 endif
 
 # Args
 #   $(1): destination directory
-#   $(2): list of files to copy
-$(vndk_snapshot_zip): private-copy-vndk-intermediates = \
+#   $(2): list of files (src:dest) to copy
+$(vndk_snapshot_zip): private-copy-intermediates = \
   $(if $(2),$(strip \
-    @mkdir -p $(1); \
+    @mkdir -p $(1) && \
     $(foreach file,$(2), \
-      if [ -e $(file) ]; then \
-        cp -p $(file) $(call append-path,$(1),$(subst .vendor,,$(notdir $(file)))); \
-      fi; \
+      cp $(call word-colon,1,$(file)) $(call append-path,$(1),$(call word-colon,2,$(file))) && \
     ) \
+    true \
   ))
 
-vndk_snapshot_dependencies := \
-  $(vndk_snapshot_libs) \
-  $(vndk_prebuilt_txts) \
-  $(vndk_snapshot_configs)
 
-$(vndk_snapshot_zip): $(vndk_snapshot_dependencies) $(SOONG_ZIP)
+$(vndk_snapshot_zip): $(SOONG_ZIP)
 	@echo 'Generating VNDK snapshot: $@'
 	@rm -f $@
 	@rm -rf $(PRIVATE_VNDK_SNAPSHOT_OUT)
 	@mkdir -p $(PRIVATE_VNDK_SNAPSHOT_OUT)
-	$(call private-copy-vndk-intermediates, \
+	$(call private-copy-intermediates, \
 		$(PRIVATE_VNDK_CORE_OUT),$(PRIVATE_VNDK_CORE_INTERMEDIATES))
-	$(call private-copy-vndk-intermediates, \
+	$(call private-copy-intermediates, \
 		$(PRIVATE_VNDK_SP_OUT),$(PRIVATE_VNDK_SP_INTERMEDIATES))
-	$(call private-copy-vndk-intermediates, \
+	$(call private-copy-intermediates, \
 		$(PRIVATE_CONFIGS_OUT),$(PRIVATE_CONFIGS_INTERMEDIATES))
-	$(call private-copy-vndk-intermediates, \
+	$(call private-copy-intermediates, \
 		$(PRIVATE_NOTICE_FILES_OUT),$(PRIVATE_NOTICE_FILES_INTERMEDIATES))
 ifdef TARGET_2ND_ARCH
-	$(call private-copy-vndk-intermediates, \
+	$(call private-copy-intermediates, \
 		$(PRIVATE_VNDK_CORE_OUT_2ND),$(PRIVATE_VNDK_CORE_INTERMEDIATES_2ND))
-	$(call private-copy-vndk-intermediates, \
+	$(call private-copy-intermediates, \
 		$(PRIVATE_VNDK_SP_OUT_2ND),$(PRIVATE_VNDK_SP_INTERMEDIATES_2ND))
 endif
 	$(hide) $(SOONG_ZIP) -o $@ -C $(PRIVATE_VNDK_SNAPSHOT_OUT) -D $(PRIVATE_VNDK_SNAPSHOT_OUT)
@@ -240,7 +249,6 @@
 binder :=
 vndk_lib_dir :=
 vndk_lib_dir_2nd :=
-vndk_snapshot_dependencies :=
 
 else # BOARD_VNDK_RUNTIME_DISABLE is set to 'true'
 error_msg := "CANNOT generate VNDK snapshot. BOARD_VNDK_RUNTIME_DISABLE must not be set to 'true'."
diff --git a/envsetup.sh b/envsetup.sh
index 15373fd..12168e1 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -315,6 +315,17 @@
     export BUILD_ENV_SEQUENCE_NUMBER=13
 }
 
+# Takes a command name, and check if it's in ENVSETUP_NO_COMPLETION or not.
+function should_add_completion() {
+    local cmd="$1"
+    case :"$ENVSETUP_NO_COMPLETION": in
+    *:"$cmd":*)
+        return 1
+        ;;
+    esac
+    return 0
+}
+
 function addcompletions()
 {
     local T dir f
@@ -329,13 +340,19 @@
         return
     fi
 
+    # Completion can be disabled selectively to allow users to use non-standard completion.
+    # e.g.
+    # ENVSETUP_NO_COMPLETION=adb # -> disable adb completion
+    # ENVSETUP_NO_COMPLETION=adb:bit # -> disable adb and bit completion
     for f in system/core/adb/adb.bash system/core/fastboot/fastboot.bash; do
-        if [ -f $f ]; then
+        if [ -f "$f" ] && should_add_completion $(basename "$f" .bash) ; then
             . $f
         fi
     done
 
-    complete -C "bit --tab" bit
+    if should_add_completion bit ; then
+        complete -C "bit --tab" bit
+    fi
 }
 
 function choosetype()
diff --git a/target/board/generic_x86_arm/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
index c66aacc..d1e4884 100644
--- a/target/board/generic_x86_arm/BoardConfig.mk
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -31,6 +31,8 @@
 # Tell the build system this isn't a typical 64bit+32bit multilib configuration.
 TARGET_TRANSLATE_2ND_ARCH := true
 
+BUILD_BROKEN_DUP_RULES := true
+
 # no hardware camera
 USE_CAMERA_STUB := true
 
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 89b66d3..f445a80 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -42,7 +42,6 @@
     $(LOCAL_DIR)/aosp_x86_64.mk
 else
 PRODUCT_MAKEFILES := \
-    $(LOCAL_DIR)/core.mk \
     $(LOCAL_DIR)/generic.mk \
     $(LOCAL_DIR)/generic_x86.mk \
     $(LOCAL_DIR)/aosp_arm.mk \
diff --git a/target/product/base.mk b/target/product/base.mk
index 4664e46..d65f124 100644
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -18,11 +18,18 @@
 PRODUCT_PACKAGES += \
     20-dns.conf \
     95-configured \
+    adb \
+    adbd \
+    adbd.recovery \
     am \
     android.hardware.cas@1.0-service \
+    android.hardware.configstore@1.0-service \
     android.hardware.media.omx@1.0-service \
+    android.hidl.allocator@1.0-service \
     android.hidl.base-V1.0-java \
     android.hidl.manager-V1.0-java \
+    android.hidl.memory@1.0-impl \
+    android.hidl.memory@1.0-impl.vendor \
     android.policy \
     android.test.mock \
     android.test.runner \
@@ -30,39 +37,58 @@
     appops \
     app_process \
     appwidget \
+    atrace \
     audioserver \
     BackupRestoreConfirmation \
     bcc \
     bit \
+    blank_screen \
     blkid \
     bmgr \
+    bootanimation \
+    bootstat \
     bpfloader \
     bu \
     bugreport \
     bugreportz \
     cameraserver \
+    charger \
+    cmd \
     com.android.location.provider \
+    ContactsProvider \
     content \
+    crash_dump \
     CtsShimPrebuilt \
     CtsShimPrivPrebuilt \
+    debuggerd\
     dnsmasq \
+    DefaultContainerService \
     DownloadProvider \
     dpm \
+    dumpstate \
+    dumpsys \
     e2fsck \
     ExtServices \
     ExtShared \
+    fastboot \
     framework \
     framework-res \
     framework-sysconfig.xml \
     fsck_msdos \
     gatekeeperd \
+    gralloc.default \
+    healthd \
     hid \
+    hwservicemanager \
     idmap \
     ime \
     ims-common \
     incident \
     incidentd \
     incident_report \
+    init \
+    init.environ.rc \
+    init.rc \
     input \
     installd \
     ip \
@@ -71,8 +97,8 @@
     ip-up-vpn \
     javax.obex \
     keystore \
-    ld.config.txt \
     ld.config.recovery.txt \
+    ld.config.txt \
     ld.mc \
     libaaudio \
     libandroid \
@@ -82,25 +108,43 @@
     libaudioflinger \
     libaudiopolicymanager \
     libaudiopolicyservice \
+    libbinder \
     libbundlewrapper \
+    libc \
     libcamera2ndk \
     libcamera_client \
     libcameraservice \
     libclearkeycasplugin \
+    libc_malloc_debug \
+    libc_malloc_hooks \
+    libcutils \
+    libdl \
     libdownmix \
     libdrmclearkeyplugin \
     libdrmframework \
     libdrmframework_jni \
     libeffectproxy \
     libeffects \
+    libEGL \
+    libETC1 \
+    libFFTEm \
     libfilterfw \
     libgatekeeper \
+    libGLESv1_CM \
+    libGLESv2 \
+    libGLESv3 \
+    libgui \
+    libhardware \
+    libhardware_legacy \
     libinput \
     libinputflinger \
     libiprouteutil \
     libjnigraphics \
+    libjpeg \
     libkeystore \
     libldnhncr \
+    liblog \
+    libm \
     libmedia \
     libmedia_jni \
     libmediandk \
@@ -113,12 +157,15 @@
     libOpenMAXAL \
     libOpenSLES \
     libpdfium \
+    libpixelflinger \
+    libpower \
     libradio_metadata \
     libreference-ril \
     libreverbwrapper \
     libril \
     librtp_jni \
     libsensorservice \
+    libsigchain \
     libskia \
     libsonic \
     libsonivox \
@@ -133,14 +180,25 @@
     libstagefright_foundation \
     libstagefright_omx \
     libstagefright_yuv \
+    libstdc++ \
+    libsurfaceflinger \
+    libsurfaceflinger_ddmconnection \
+    libsysutils \
+    libui \
     libusbhost \
+    libutils \
     libvisualizer \
     libvorbisidec \
     libvulkan \
     libwifi-service \
     libwilhelm \
+    linker \
+    linker.recovery \
+    lmkd \
     locksettings \
+    logcat \
     logd \
+    lshal \
     mdnsd \
     media \
     media_cmd \
@@ -164,29 +222,42 @@
     pppd \
     privapp-permissions-platform.xml \
     racoon \
+    recovery \
     resize2fs \
     run-as \
     schedtest \
     screencap \
     sdcard \
     secdiscard \
+    selinux_policy \
     sensorservice \
+    service \
+    servicemanager \
     services \
     settings \
     SettingsProvider \
     sgdisk \
     Shell \
+    shell_and_utilities \
     sm \
+    storaged \
+    surfaceflinger \
     svc \
     tc \
     telecom \
     telephony-common \
+    thermalserviced \
+    tombstoned \
     traced \
     traced_probes \
     tune2fs \
+    tzdatacheck \
     uiautomator \
     uncrypt \
+    usbd \
     vdc \
+    vndservice \
+    vndservicemanager \
     voip-common \
     vold \
     WallpaperBackup \
@@ -194,11 +265,39 @@
     wifi-service \
     wm \
 
+
+# VINTF data
+PRODUCT_PACKAGES += \
+    device_compatibility_matrix.xml \
+    device_manifest.xml \
+    framework_manifest.xml \
+    framework_compatibility_matrix.xml \
+
+# AID Generation for
+# <pwd.h> and <grp.h>
+PRODUCT_PACKAGES += \
+    passwd \
+    group \
+    fs_config_files \
+    fs_config_dirs
+
+PRODUCT_COPY_FILES += \
+    system/core/rootdir/init.usb.rc:root/init.usb.rc \
+    system/core/rootdir/init.usb.configfs.rc:root/init.usb.configfs.rc \
+    system/core/rootdir/ueventd.rc:root/ueventd.rc \
+    system/core/rootdir/etc/hosts:system/etc/hosts
+
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote32
 PRODUCT_COPY_FILES += system/core/rootdir/init.zygote32.rc:root/init.zygote32.rc
 
+# Ensure that this property is always defined so that bionic_systrace.cpp
+# can rely on it being initially set by init.
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+    debug.atrace.tags.enableflags=0
+
 # Packages included only for eng or userdebug builds, previously debug tagged
 PRODUCT_PACKAGES_DEBUG := \
+    adb_keys \
     iotop \
     logpersist.start \
     micro_bench \
@@ -223,4 +322,3 @@
     system/core/rootdir/init.zygote32.rc:root/init.zygote32.rc
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/embedded.mk)
diff --git a/target/product/core.mk b/target/product/core.mk
deleted file mode 100644
index 90e15db..0000000
--- a/target/product/core.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# Copyright (C) 2007 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# Base configuration for communication-oriented android devices
-# (phones, tablets, etc.).  If you want a change to apply to ALMOST ALL
-# devices (including non-phones and non-tablets), modify
-# core_minimal.mk instead. If you care about wearables, you need to modify
-# core_tiny.mk in addition to core_minimal.mk.
-
-PRODUCT_PACKAGES += \
-    BasicDreams \
-    BlockedNumberProvider \
-    BookmarkProvider \
-    Browser2 \
-    BuiltInPrintService \
-    Calendar \
-    CalendarProvider \
-    CaptivePortalLogin \
-    CertInstaller \
-    Contacts \
-    DeskClock \
-    DocumentsUI \
-    DownloadProviderUi \
-    Email \
-    ExactCalculator \
-    ExternalStorageProvider \
-    FusedLocation \
-    InputDevices \
-    KeyChain \
-    Keyguard \
-    LatinIME \
-    Launcher2 \
-    ManagedProvisioning \
-    MtpDocumentsProvider \
-    PacProcessor \
-    PrintSpooler \
-    PrintRecommendationService \
-    ProxyHandler \
-    QuickSearchBox \
-    Settings \
-    SharedStorageBackup \
-    StorageManager \
-    Telecom \
-    TeleService \
-    Traceur \
-    VpnDialogs \
-    vr \
-    MmsService
-
-# The set of packages whose code can be loaded by the system server.
-PRODUCT_SYSTEM_SERVER_APPS += \
-    FusedLocation \
-    InputDevices \
-    KeyChain \
-    Telecom \
-
-# The set of packages we want to force 'speed' compilation on.
-PRODUCT_DEXPREOPT_SPEED_APPS += \
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_base.mk)
diff --git a/target/product/core_base.mk b/target/product/core_base.mk
index dd55e60..575bd60 100644
--- a/target/product/core_base.mk
+++ b/target/product/core_base.mk
@@ -13,8 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# Note that components added here will be also shared in PDK. Components
-# that should not be in PDK should be added in lower level like core.mk.
 
 PRODUCT_PROPERTY_OVERRIDES := \
     ro.config.notification_sound=OnTheHunt.ogg \
diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk
index 910d796..baa297c 100644
--- a/target/product/core_minimal.mk
+++ b/target/product/core_minimal.mk
@@ -16,7 +16,7 @@
 
 # Base configuration for most consumer android devices.  Do not put
 # things that are specific to communication devices (phones, tables,
-# etc.) here -- for that, use core.mk.
+# etc.) here -- for that, use generic_no_telephony.mk.
 
 PRODUCT_BRAND := generic
 PRODUCT_DEVICE := generic
@@ -28,8 +28,6 @@
     com.android.media.remotedisplay \
     com.android.media.remotedisplay.xml \
     CompanionDeviceManager \
-    ContactsProvider \
-    DefaultContainerService \
     drmserver \
     ethernet-service \
     fsck.f2fs \
diff --git a/target/product/core_tiny.mk b/target/product/core_tiny.mk
deleted file mode 100644
index 0ec475b..0000000
--- a/target/product/core_tiny.mk
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Copyright (C) 2013 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.
-#
-# Tiny configuration for small devices such as wearables. Includes base and embedded.
-# No telephony
-
-PRODUCT_PACKAGES := \
-    audio.primary.default \
-    Bluetooth \
-    CalendarProvider \
-    CertInstaller \
-    clatd \
-    clatd.conf \
-    ContactsProvider \
-    DefaultContainerService \
-    FusedLocation \
-    InputDevices \
-    local_time.default \
-    logd \
-    nullwebview \
-    power.default \
-    pppd \
-
-
-ifeq ($(TARGET_CORE_JARS),)
-$(error TARGET_CORE_JARS is empty; cannot initialize PRODUCT_BOOT_JARS variable)
-endif
-
-# The order matters
-PRODUCT_BOOT_JARS := \
-    $(TARGET_CORE_JARS) \
-    legacy-test \
-    ext \
-    framework \
-    telephony-common \
-    voip-common \
-    ims-common \
-    nullwebview \
-    org.apache.http.legacy.impl \
-    android.hidl.base-V1.0-java \
-    android.hidl.manager-V1.0-java
-
-# The order of PRODUCT_SYSTEM_SERVER_JARS matters.
-PRODUCT_SYSTEM_SERVER_JARS := \
-    services \
-    wifi-service
-
-# The set of packages whose code can be loaded by the system server.
-PRODUCT_SYSTEM_SERVER_APPS += \
-    FusedLocation \
-    InputDevices \
-    SettingsProvider \
-    WallpaperBackup \
-
-# The set of packages we want to force 'speed' compilation on.
-PRODUCT_DEXPREOPT_SPEED_APPS := \
-
-PRODUCT_PROPERTY_OVERRIDES += \
-    ro.carrier=unknown
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)
-$(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk)
-$(call inherit-product-if-exists, external/roboto-fonts/fonts.mk)
-
-# Overrides
-PRODUCT_BRAND := tiny
-PRODUCT_DEVICE := tiny
-PRODUCT_NAME := core_tiny
diff --git a/target/product/embedded.mk b/target/product/embedded.mk
deleted file mode 100644
index 2a34639..0000000
--- a/target/product/embedded.mk
+++ /dev/null
@@ -1,124 +0,0 @@
-#
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# This is a build configuration for a very minimal build of the
-# Open-Source part of the tree.
-
-PRODUCT_PACKAGES += \
-    adb \
-    adbd \
-    adbd.recovery \
-    usbd \
-    android.hardware.configstore@1.0-service \
-    android.hidl.allocator@1.0-service \
-    android.hidl.memory@1.0-impl \
-    android.hidl.memory@1.0-impl.vendor \
-    atrace \
-    blank_screen \
-    bootanimation \
-    bootstat \
-    charger \
-    cmd \
-    crash_dump \
-    debuggerd\
-    dumpstate \
-    dumpsys \
-    fastboot \
-    gralloc.default \
-    healthd \
-    hwservicemanager \
-    init \
-    init.environ.rc \
-    init.rc \
-    libEGL \
-    libETC1 \
-    libFFTEm \
-    libGLESv1_CM \
-    libGLESv2 \
-    libGLESv3 \
-    libbinder \
-    libc \
-    libc_malloc_debug \
-    libc_malloc_hooks \
-    libcutils \
-    libdl \
-    libgui \
-    libhardware \
-    libhardware_legacy \
-    libjpeg \
-    liblog \
-    libm \
-    libpixelflinger \
-    libpower \
-    libsigchain \
-    libstdc++ \
-    libsurfaceflinger \
-    libsurfaceflinger_ddmconnection \
-    libsysutils \
-    libui \
-    libutils \
-    linker \
-    linker.recovery \
-    lmkd \
-    logcat \
-    lshal \
-    recovery \
-    service \
-    servicemanager \
-    shell_and_utilities \
-    storaged \
-    surfaceflinger \
-    thermalserviced \
-    tombstoned \
-    tzdatacheck \
-    vndservice \
-    vndservicemanager \
-
-# VINTF data
-PRODUCT_PACKAGES += \
-    device_compatibility_matrix.xml \
-    device_manifest.xml \
-    framework_manifest.xml \
-    framework_compatibility_matrix.xml \
-
-# SELinux packages are added as dependencies of the selinux_policy
-# phony package.
-PRODUCT_PACKAGES += \
-    selinux_policy \
-
-# AID Generation for
-# <pwd.h> and <grp.h>
-PRODUCT_PACKAGES += \
-    passwd \
-    group \
-    fs_config_files \
-    fs_config_dirs
-
-# If there are product-specific adb keys defined, install them on debuggable
-# builds.
-PRODUCT_PACKAGES_DEBUG += \
-    adb_keys
-
-# Ensure that this property is always defined so that bionic_systrace.cpp
-# can rely on it being initially set by init.
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
-    debug.atrace.tags.enableflags=0
-
-PRODUCT_COPY_FILES += \
-    system/core/rootdir/init.usb.rc:root/init.usb.rc \
-    system/core/rootdir/init.usb.configfs.rc:root/init.usb.configfs.rc \
-    system/core/rootdir/ueventd.rc:root/ueventd.rc \
-    system/core/rootdir/etc/hosts:system/etc/hosts
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index 9ab6df0..5e6957a 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -18,38 +18,80 @@
 # It includes the base Android platform.
 
 PRODUCT_PACKAGES := \
+    audio.primary.default \
+    BasicDreams \
+    BlockedNumberProvider \
     Bluetooth \
     BluetoothMidiService \
+    BookmarkProvider \
+    Browser2 \
+    BuiltInPrintService \
+    Calendar \
+    CalendarProvider \
     Camera2 \
+    CaptivePortalLogin \
+    CertInstaller \
+    clatd \
+    clatd.conf \
+    Contacts \
+    DeskClock \
+    DocumentsUI \
+    DownloadProviderUi \
+    EasterEgg \
+    Email \
+    ExactCalculator \
+    ExternalStorageProvider \
+    FusedLocation \
     Gallery2 \
+    InputDevices \
+    KeyChain \
+    Keyguard \
+    LatinIME \
+    Launcher3QuickStep \
+    librs_jni \
+    libvideoeditor_core \
+    libvideoeditor_jni \
+    libvideoeditor_osal \
+    libvideoeditorplayer \
+    libvideoeditor_videofilters \
+    local_time.default \
+    ManagedProvisioning \
+    MmsService \
+    MtpDocumentsProvider \
     Music \
     MusicFX \
     NfcNci \
     OneTimeInitializer \
+    PacProcessor \
+    power.default \
+    PrintRecommendationService \
+    PrintSpooler \
     Provision \
+    ProxyHandler \
+    QuickSearchBox \
+    screenrecord \
+    SecureElement \
+    Settings \
+    SettingsIntelligence \
+    SharedStorageBackup \
+    SimAppDialog \
+    StorageManager \
     SystemUI \
     SysuiDarkThemeOverlay \
-    EasterEgg \
-    WallpaperCropper
-
-PRODUCT_PACKAGES += \
-    clatd \
-    clatd.conf \
-    screenrecord
-
-PRODUCT_PACKAGES += \
-    librs_jni \
-    libvideoeditor_jni \
-    libvideoeditor_core \
-    libvideoeditor_osal \
-    libvideoeditor_videofilters \
-    libvideoeditorplayer \
-
-PRODUCT_PACKAGES += \
-    audio.primary.default \
-    local_time.default \
+    Telecom \
+    TeleService \
+    Traceur \
     vibrator.default \
-    power.default
+    VpnDialogs \
+    vr \
+    WallpaperCropper \
+
+
+PRODUCT_SYSTEM_SERVER_APPS += \
+    FusedLocation \
+    InputDevices \
+    KeyChain \
+    Telecom \
 
 PRODUCT_COPY_FILES := \
         frameworks/av/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf
@@ -67,7 +109,7 @@
 $(call inherit-product-if-exists, external/hyphenation-patterns/patterns.mk)
 $(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk)
 $(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_base.mk)
 
 # Overrides
 PRODUCT_BRAND := generic
diff --git a/target/product/sdk_base.mk b/target/product/sdk_base.mk
deleted file mode 100644
index b79b8c6..0000000
--- a/target/product/sdk_base.mk
+++ /dev/null
@@ -1,178 +0,0 @@
-#
-# Copyright (C) 2007 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.
-#
-
-PRODUCT_PROPERTY_OVERRIDES :=
-
-PRODUCT_PACKAGES := \
-	CellBroadcastReceiver \
-	CubeLiveWallpapers \
-	CustomLocale \
-	Development \
-	Dialer \
-	EmulatorSmokeTests \
-	Gallery2 \
-	Launcher3 \
-	Camera2 \
-	librs_jni \
-	libwnndict \
-	libWnnEngDic \
-	libWnnJpnDic \
-	LiveWallpapersPicker \
-	Mms \
-	Music \
-	OpenWnn \
-	Protips \
-	rild \
-	screenrecord \
-	SdkSetup \
-	SoftKeyboard \
-	sqlite3 \
-	SystemUI \
-	SysuiDarkThemeOverlay \
-	EasterEgg \
-	WallpaperPicker \
-	WidgetPreview
-
-# Define the host tools and libs that are parts of the SDK.
--include sdk/build/product_sdk.mk
--include development/build/product_sdk.mk
-
-# audio libraries.
-PRODUCT_PACKAGES += \
-	audio.primary.goldfish \
-	audio.r_submix.default \
-	local_time.default
-
-# CDD mandates following codecs
-PRODUCT_PACKAGES += \
-    libstagefright_soft_aacdec \
-    libstagefright_soft_aacenc \
-    libstagefright_soft_amrdec \
-    libstagefright_soft_amrnbenc \
-    libstagefright_soft_amrwbenc \
-    libstagefright_soft_avcdec \
-    libstagefright_soft_avcenc \
-    libstagefright_soft_flacenc \
-    libstagefright_soft_g711dec \
-    libstagefright_soft_gsmdec \
-    libstagefright_soft_hevcdec \
-    libstagefright_soft_mp3dec \
-    libstagefright_soft_mpeg2dec \
-    libstagefright_soft_mpeg4dec \
-    libstagefright_soft_mpeg4enc \
-    libstagefright_soft_opusdec \
-    libstagefright_soft_rawdec \
-    libstagefright_soft_vorbisdec \
-    libstagefright_soft_vpxdec \
-    libstagefright_soft_vpxenc
-
-PRODUCT_PACKAGE_OVERLAYS := development/sdk_overlay
-
-PRODUCT_COPY_FILES := \
-	device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
-	device/sample/etc/old-apns-conf.xml:system/etc/old-apns-conf.xml \
-	frameworks/base/data/sounds/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
-	frameworks/base/data/sounds/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
-	frameworks/base/data/sounds/effects/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
-	device/generic/goldfish/data/etc/handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml \
-	device/generic/goldfish/camera/media_profiles.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_profiles.xml \
-	frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_audio.xml \
-	frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_telephony.xml \
-	device/generic/goldfish/camera/media_codecs_google_video.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_video.xml \
-	device/generic/goldfish/camera/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \
-	device/generic/goldfish/camera/media_codecs_performance.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_performance.xml \
-	frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
-	frameworks/native/data/etc/android.hardware.camera.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.xml \
-	frameworks/native/data/etc/android.hardware.fingerprint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.fingerprint.xml \
-	frameworks/native/data/etc/android.software.autofill.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.autofill.xml \
-	frameworks/av/media/libeffects/data/audio_effects.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.conf \
-	device/generic/goldfish/audio_policy.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy.conf
-
-include $(SRC_TARGET_DIR)/product/emulator.mk
-
-$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
-$(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk)
-$(call inherit-product-if-exists, external/google-fonts/dancing-script/fonts.mk)
-$(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts.mk)
-$(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk)
-$(call inherit-product-if-exists, external/google-fonts/cutive-mono/fonts.mk)
-$(call inherit-product-if-exists, external/noto-fonts/fonts.mk)
-$(call inherit-product-if-exists, external/roboto-fonts/fonts.mk)
-$(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk)
-$(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
-
-# locale. en_US is both first and in alphabetical order to
-# ensure this is the default locale.
-PRODUCT_LOCALES := \
-	en_US \
-	ar_EG \
-	ar_IL \
-	bg_BG \
-	ca_ES \
-	cs_CZ \
-	da_DK \
-	de_AT \
-	de_CH \
-	de_DE \
-	de_LI \
-	el_GR \
-	en_AU \
-	en_CA \
-	en_GB \
-	en_IE \
-	en_IN \
-	en_NZ \
-	en_SG \
-	en_US \
-	en_ZA \
-	es_ES \
-	es_US \
-	fi_FI \
-	fr_BE \
-	fr_CA \
-	fr_CH \
-	fr_FR \
-	he_IL \
-	hi_IN \
-	hr_HR \
-	hu_HU \
-	id_ID \
-	it_CH \
-	it_IT \
-	ja_JP \
-	ko_KR \
-	lt_LT \
-	lv_LV \
-	nb_NO \
-	nl_BE \
-	nl_NL \
-	pl_PL \
-	pt_BR \
-	pt_PT \
-	ro_RO \
-	ru_RU \
-	sk_SK \
-	sl_SI \
-	sr_RS \
-	sv_SE \
-	th_TH \
-	tl_PH \
-	tr_TR \
-	uk_UA \
-	vi_VN \
-	zh_CN \
-	zh_TW
diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk
index 56eb8c7..96f0bfd 100644
--- a/target/product/sdk_phone_arm64.mk
+++ b/target/product/sdk_phone_arm64.mk
@@ -14,31 +14,15 @@
 # limitations under the License.
 #
 
-PRODUCT_PROPERTY_OVERRIDES += \
-	rild.libpath=/vendor/lib64/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_arm64.mk)
 
-# This is a build configuration for a full-featured build of the
-# Open-Source part of the tree. It's geared toward a US-centric
-# build quite specifically for the emulator, and might not be
-# entirely appropriate to inherit from for on-device configurations.
+# Define the host tools and libs that are parts of the SDK.
+$(call inherit-product, sdk/build/product_sdk.mk)
+$(call inherit-product, development/build/product_sdk.mk)
 
-# Note: the following lines need to stay at the beginning so that it can
-# take priority  and override the rules it inherit from other mk files
-# see copy file rules in core/Makefile
-PRODUCT_COPY_FILES += \
-    development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
-    prebuilts/qemu-kernel/arm64/3.18/kernel-qemu2:kernel-ranchu \
-    device/generic/goldfish/fstab.ranchu.arm:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
+# keep this apk for sdk targets for now
 PRODUCT_PACKAGES += \
-    messaging
+    EmulatorSmokeTests
 
 # Overrides
 PRODUCT_BRAND := Android
diff --git a/target/product/sdk_phone_armv7.mk b/target/product/sdk_phone_armv7.mk
index 73c42c3..04d8d6a 100644
--- a/target/product/sdk_phone_armv7.mk
+++ b/target/product/sdk_phone_armv7.mk
@@ -14,24 +14,16 @@
 # limitations under the License.
 #
 
-PRODUCT_PROPERTY_OVERRIDES += \
-	rild.libpath=/vendor/lib/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_arm.mk)
 
-# Note: the following lines need to stay at the beginning so that it can
-# take priority  and override the rules it inherit from other mk files
-# see copy file rules in core/Makefile
-PRODUCT_COPY_FILES += \
-    development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
-    prebuilts/qemu-kernel/arm64/3.18/kernel-qemu2:kernel-ranchu-64 \
-    device/generic/goldfish/fstab.ranchu.arm:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.ranchu
+# Define the host tools and libs that are parts of the SDK.
+$(call inherit-product, sdk/build/product_sdk.mk)
+$(call inherit-product, development/build/product_sdk.mk)
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
+# keep this apk for sdk targets for now
 PRODUCT_PACKAGES += \
-    messaging
+    EmulatorSmokeTests
+
 
 # Overrides
 PRODUCT_BRAND := Android
diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk
index 32d71eb..abb46ac 100644
--- a/target/product/sdk_phone_x86.mk
+++ b/target/product/sdk_phone_x86.mk
@@ -14,25 +14,15 @@
 # limitations under the License.
 #
 
-PRODUCT_PROPERTY_OVERRIDES += \
-	rild.libpath=/vendor/lib/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86.mk)
 
-# This is a build configuration for a full-featured build of the
-# Open-Source part of the tree. It's geared toward a US-centric
-# build quite specifically for the emulator, and might not be
-# entirely appropriate to inherit from for on-device configurations.
-PRODUCT_COPY_FILES += \
-    development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
-    device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
-    prebuilts/qemu-kernel/x86_64/4.4/kernel-qemu2:kernel-ranchu-64
+# Define the host tools and libs that are parts of the SDK.
+-include sdk/build/product_sdk.mk
+-include development/build/product_sdk.mk
 
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
+# keep this apk for sdk targets for now
 PRODUCT_PACKAGES += \
-    messaging
+    EmulatorSmokeTests
 
 # Overrides
 PRODUCT_BRAND := Android
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
index e40ebb5..828b744 100644
--- a/target/product/sdk_phone_x86_64.mk
+++ b/target/product/sdk_phone_x86_64.mk
@@ -14,27 +14,15 @@
 # limitations under the License.
 #
 
-PRODUCT_PROPERTY_OVERRIDES += \
-	rild.libpath=/vendor/lib64/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86_64.mk)
 
-# This is a build configuration for a full-featured build of the
-# Open-Source part of the tree. It's geared toward a US-centric
-# build quite specifically for the emulator, and might not be
-# entirely appropriate to inherit from for on-device configurations.
+# Define the host tools and libs that are parts of the SDK.
+-include sdk/build/product_sdk.mk
+-include development/build/product_sdk.mk
 
-PRODUCT_COPY_FILES += \
-    development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
-    device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
-    prebuilts/qemu-kernel/x86_64/4.4/kernel-qemu2:kernel-ranchu
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
+# keep this apk for sdk targets for now
 PRODUCT_PACKAGES += \
-    messaging
+    EmulatorSmokeTests
 
 # Overrides
 PRODUCT_BRAND := Android
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index fa62c8f..393c33d 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -27,6 +27,12 @@
       in the apkcerts.txt file.  Option may be repeated to give
       multiple extra packages.
 
+  --skip_apks_with_path_prefix  <prefix>
+      Skip signing an APK if it has the matching prefix in its path. The prefix
+      should be matching the entry name, which has partition names in upper
+      case, e.g. "VENDOR/app/", or "SYSTEM_OTHER/preloads/". Option may be
+      repeated to give multiple prefixes.
+
   -k  (--key_mapping)  <src_key=dest_key>
       Add a mapping from the key name as specified in apkcerts.txt (the
       src_key) to the real key you wish to sign the package with
@@ -118,6 +124,7 @@
 OPTIONS = common.OPTIONS
 
 OPTIONS.extra_apks = {}
+OPTIONS.skip_apks_with_path_prefix = set()
 OPTIONS.key_map = {}
 OPTIONS.rebuild_recovery = False
 OPTIONS.replace_ota_keys = False
@@ -144,28 +151,83 @@
   return certmap
 
 
+def GetApkFileInfo(filename, compressed_extension, skipped_prefixes):
+  """Returns the APK info based on the given filename.
+
+  Checks if the given filename (with path) looks like an APK file, by taking the
+  compressed extension into consideration. If it appears to be an APK file,
+  further checks if the APK file should be skipped when signing, based on the
+  given path prefixes.
+
+  Args:
+    filename: Path to the file.
+    compressed_extension: The extension string of compressed APKs (e.g. ".gz"),
+        or None if there's no compressed APKs.
+    skipped_prefixes: A set/list/tuple of the path prefixes to be skipped.
+
+  Returns:
+    (is_apk, is_compressed, should_be_skipped): is_apk indicates whether the
+    given filename is an APK file. is_compressed indicates whether the APK file
+    is compressed (only meaningful when is_apk is True). should_be_skipped
+    indicates whether the filename matches any of the given prefixes to be
+    skipped.
+
+  Raises:
+    AssertionError: On invalid compressed_extension or skipped_prefixes inputs.
+  """
+  assert compressed_extension is None or compressed_extension.startswith('.'), \
+      "Invalid compressed_extension arg: '{}'".format(compressed_extension)
+
+  # skipped_prefixes should be one of set/list/tuple types. Other types such as
+  # str shouldn't be accepted.
+  assert (isinstance(skipped_prefixes, tuple) or
+          isinstance(skipped_prefixes, set) or
+          isinstance(skipped_prefixes, list)), \
+              "Invalid skipped_prefixes input type: {}".format(
+                  type(skipped_prefixes))
+
+  compressed_apk_extension = (
+      ".apk" + compressed_extension if compressed_extension else None)
+  is_apk = (filename.endswith(".apk") or
+            (compressed_apk_extension and
+             filename.endswith(compressed_apk_extension)))
+  if not is_apk:
+    return (False, False, False)
+
+  is_compressed = (compressed_apk_extension and
+                   filename.endswith(compressed_apk_extension))
+  should_be_skipped = filename.startswith(tuple(skipped_prefixes))
+  return (True, is_compressed, should_be_skipped)
+
+
 def CheckAllApksSigned(input_tf_zip, apk_key_map, compressed_extension):
-  """Check that all the APKs we want to sign have keys specified, and
-  error out if they don't."""
+  """Checks that all the APKs have keys specified, otherwise errors out.
+
+  Args:
+    input_tf_zip: An open target_files zip file.
+    apk_key_map: A dict of known signing keys key'd by APK names.
+    compressed_extension: The extension string of compressed APKs, such as
+        ".gz", or None if there's no compressed APKs.
+
+  Raises:
+    AssertionError: On finding unknown APKs.
+  """
   unknown_apks = []
-  compressed_apk_extension = None
-  if compressed_extension:
-    compressed_apk_extension = ".apk" + compressed_extension
   for info in input_tf_zip.infolist():
-    if (info.filename.endswith(".apk") or
-        (compressed_apk_extension and
-         info.filename.endswith(compressed_apk_extension))):
-      name = os.path.basename(info.filename)
-      if compressed_apk_extension and name.endswith(compressed_apk_extension):
-        name = name[:-len(compressed_extension)]
-      if name not in apk_key_map:
-        unknown_apks.append(name)
-  if unknown_apks:
-    print("ERROR: no key specified for:\n")
-    print("  " + "\n  ".join(unknown_apks))
-    print("\nUse '-e <apkname>=' to specify a key (which may be an empty "
-          "string to not sign this apk).")
-    sys.exit(1)
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        info.filename, compressed_extension, OPTIONS.skip_apks_with_path_prefix)
+    if not is_apk or should_be_skipped:
+      continue
+    name = os.path.basename(info.filename)
+    if is_compressed:
+      name = name[:-len(compressed_extension)]
+    if name not in apk_key_map:
+      unknown_apks.append(name)
+
+  assert not unknown_apks, \
+      ("No key specified for:\n  {}\n"
+       "Use '-e <apkname>=' to specify a key (which may be an empty string to "
+       "not sign this apk).".format("\n  ".join(unknown_apks)))
 
 
 def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map,
@@ -235,32 +297,33 @@
                        apk_key_map, key_passwords, platform_api_level,
                        codename_to_api_level_map,
                        compressed_extension):
-
-  compressed_apk_extension = None
-  if compressed_extension:
-    compressed_apk_extension = ".apk" + compressed_extension
-
+  # maxsize measures the maximum filename length, including the ones to be
+  # skipped.
   maxsize = max(
       [len(os.path.basename(i.filename)) for i in input_tf_zip.infolist()
-       if (i.filename.endswith('.apk') or
-           (compressed_apk_extension and
-            i.filename.endswith(compressed_apk_extension)))])
+       if GetApkFileInfo(i.filename, compressed_extension, [])[0]])
   system_root_image = misc_info.get("system_root_image") == "true"
 
   for info in input_tf_zip.infolist():
-    if info.filename.startswith("IMAGES/"):
+    filename = info.filename
+    if filename.startswith("IMAGES/"):
       continue
 
-    data = input_tf_zip.read(info.filename)
+    data = input_tf_zip.read(filename)
     out_info = copy.copy(info)
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        filename, compressed_extension, OPTIONS.skip_apks_with_path_prefix)
+
+    if is_apk and should_be_skipped:
+      # Copy skipped APKs verbatim.
+      print(
+          "NOT signing: %s\n"
+          "        (skipped due to matching prefix)" % (filename,))
+      common.ZipWriteStr(output_tf_zip, out_info, data)
 
     # Sign APKs.
-    if (info.filename.endswith(".apk") or
-        (compressed_apk_extension and
-         info.filename.endswith(compressed_apk_extension))):
-      is_compressed = (compressed_extension and
-                       info.filename.endswith(compressed_apk_extension))
-      name = os.path.basename(info.filename)
+    elif is_apk:
+      name = os.path.basename(filename)
       if is_compressed:
         name = name[:-len(compressed_extension)]
 
@@ -272,19 +335,21 @@
         common.ZipWriteStr(output_tf_zip, out_info, signed_data)
       else:
         # an APK we're not supposed to sign.
-        print("NOT signing: %s" % (name,))
+        print(
+            "NOT signing: %s\n"
+            "        (skipped due to special cert string)" % (name,))
         common.ZipWriteStr(output_tf_zip, out_info, data)
 
     # System properties.
-    elif info.filename in ("SYSTEM/build.prop",
-                           "VENDOR/build.prop",
-                           "SYSTEM/etc/prop.default",
-                           "BOOT/RAMDISK/prop.default",
-                           "BOOT/RAMDISK/default.prop",  # legacy
-                           "ROOT/default.prop",  # legacy
-                           "RECOVERY/RAMDISK/prop.default",
-                           "RECOVERY/RAMDISK/default.prop"):  # legacy
-      print("Rewriting %s:" % (info.filename,))
+    elif filename in ("SYSTEM/build.prop",
+                      "VENDOR/build.prop",
+                      "SYSTEM/etc/prop.default",
+                      "BOOT/RAMDISK/prop.default",
+                      "BOOT/RAMDISK/default.prop",  # legacy
+                      "ROOT/default.prop",  # legacy
+                      "RECOVERY/RAMDISK/prop.default",
+                      "RECOVERY/RAMDISK/default.prop"):  # legacy
+      print("Rewriting %s:" % (filename,))
       if stat.S_ISLNK(info.external_attr >> 16):
         new_data = data
       else:
@@ -293,20 +358,20 @@
 
     # Replace the certs in *mac_permissions.xml (there could be multiple, such
     # as {system,vendor}/etc/selinux/{plat,nonplat}_mac_permissions.xml).
-    elif info.filename.endswith("mac_permissions.xml"):
-      print("Rewriting %s with new keys." % (info.filename,))
+    elif filename.endswith("mac_permissions.xml"):
+      print("Rewriting %s with new keys." % (filename,))
       new_data = ReplaceCerts(data)
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
 
     # Ask add_img_to_target_files to rebuild the recovery patch if needed.
-    elif info.filename in ("SYSTEM/recovery-from-boot.p",
-                           "SYSTEM/etc/recovery.img",
-                           "SYSTEM/bin/install-recovery.sh"):
+    elif filename in ("SYSTEM/recovery-from-boot.p",
+                      "SYSTEM/etc/recovery.img",
+                      "SYSTEM/bin/install-recovery.sh"):
       OPTIONS.rebuild_recovery = True
 
     # Don't copy OTA keys if we're replacing them.
     elif (OPTIONS.replace_ota_keys and
-          info.filename in (
+          filename in (
               "BOOT/RAMDISK/res/keys",
               "BOOT/RAMDISK/etc/update_engine/update-payload-key.pub.pem",
               "RECOVERY/RAMDISK/res/keys",
@@ -315,22 +380,21 @@
       pass
 
     # Skip META/misc_info.txt since we will write back the new values later.
-    elif info.filename == "META/misc_info.txt":
+    elif filename == "META/misc_info.txt":
       pass
 
     # Skip verity public key if we will replace it.
     elif (OPTIONS.replace_verity_public_key and
-          info.filename in ("BOOT/RAMDISK/verity_key",
-                            "ROOT/verity_key")):
+          filename in ("BOOT/RAMDISK/verity_key",
+                       "ROOT/verity_key")):
       pass
 
     # Skip verity keyid (for system_root_image use) if we will replace it.
-    elif (OPTIONS.replace_verity_keyid and
-          info.filename == "BOOT/cmdline"):
+    elif OPTIONS.replace_verity_keyid and filename == "BOOT/cmdline":
       pass
 
     # Skip the care_map as we will regenerate the system/vendor images.
-    elif info.filename == "META/care_map.txt":
+    elif filename == "META/care_map.txt":
       pass
 
     # A non-APK file; copy it verbatim.
@@ -763,6 +827,12 @@
       names = names.split(",")
       for n in names:
         OPTIONS.extra_apks[n] = key
+    elif o == "--skip_apks_with_path_prefix":
+      # Sanity check the prefix, which must be in all upper case.
+      prefix = a.split('/')[0]
+      if not prefix or prefix != prefix.upper():
+        raise ValueError("Invalid path prefix '%s'" % (a,))
+      OPTIONS.skip_apks_with_path_prefix.add(a)
     elif o in ("-d", "--default_key_mappings"):
       key_mapping_options.append((None, a))
     elif o in ("-k", "--key_mapping"):
@@ -822,6 +892,7 @@
       extra_opts="e:d:k:ot:",
       extra_long_opts=[
           "extra_apks=",
+          "skip_apks_with_path_prefix=",
           "default_key_mappings=",
           "key_mapping=",
           "replace_ota_keys",
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 26f9e10..ac1b567 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -24,7 +24,8 @@
 import common
 import test_utils
 from sign_target_files_apks import (
-    EditTags, ReplaceCerts, ReplaceVerityKeyId, RewriteProps)
+    CheckAllApksSigned, EditTags, GetApkFileInfo, ReplaceCerts,
+    ReplaceVerityKeyId, RewriteProps)
 
 
 class SignTargetFilesApksTest(unittest.TestCase):
@@ -211,3 +212,141 @@
         cert2_path[:-9] : 'non-existent',
     }
     self.assertEqual(output_xml, ReplaceCerts(input_xml))
+
+  def test_CheckAllApksSigned(self):
+    input_file = common.MakeTempFile(suffix='.zip')
+    with zipfile.ZipFile(input_file, 'w') as input_zip:
+      input_zip.writestr('SYSTEM/app/App1.apk', "App1-content")
+      input_zip.writestr('SYSTEM/app/App2.apk.gz', "App2-content")
+
+    apk_key_map = {
+        'App1.apk' : 'key1',
+        'App2.apk' : 'key2',
+        'App3.apk' : 'key3',
+    }
+    with zipfile.ZipFile(input_file) as input_zip:
+      CheckAllApksSigned(input_zip, apk_key_map, None)
+      CheckAllApksSigned(input_zip, apk_key_map, '.gz')
+
+      # 'App2.apk.gz' won't be considered as an APK.
+      CheckAllApksSigned(input_zip, apk_key_map, None)
+      CheckAllApksSigned(input_zip, apk_key_map, '.xz')
+
+      del apk_key_map['App2.apk']
+      self.assertRaises(
+          AssertionError, CheckAllApksSigned, input_zip, apk_key_map, '.gz')
+
+  def test_GetApkFileInfo(self):
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "PRODUCT/apps/Chats.apk", None, [])
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertFalse(should_be_skipped)
+
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "PRODUCT/apps/Chats.apk", None, [])
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertFalse(should_be_skipped)
+
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "PRODUCT/apps/Chats.dat", None, [])
+    self.assertFalse(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertFalse(should_be_skipped)
+
+  def test_GetApkFileInfo_withCompressedApks(self):
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "PRODUCT/apps/Chats.apk.gz", ".gz", [])
+    self.assertTrue(is_apk)
+    self.assertTrue(is_compressed)
+    self.assertFalse(should_be_skipped)
+
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "PRODUCT/apps/Chats.apk.gz", ".xz", [])
+    self.assertFalse(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertFalse(should_be_skipped)
+
+    self.assertRaises(
+        AssertionError, GetApkFileInfo, "PRODUCT/apps/Chats.apk", "", [])
+
+    self.assertRaises(
+        AssertionError, GetApkFileInfo, "PRODUCT/apps/Chats.apk", "apk", [])
+
+  def test_GetApkFileInfo_withSkippedPrefixes(self):
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "PRODUCT/preloads/apps/Chats.apk", None, set())
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertFalse(should_be_skipped)
+
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "PRODUCT/preloads/apps/Chats.apk",
+        None,
+        set(["PRODUCT/preloads/"]))
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertTrue(should_be_skipped)
+
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "SYSTEM_OTHER/preloads/apps/Chats.apk",
+        None,
+        set(["SYSTEM/preloads/", "SYSTEM_OTHER/preloads/"]))
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertTrue(should_be_skipped)
+
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "SYSTEM_OTHER/preloads/apps/Chats.apk.gz",
+        ".gz",
+        set(["PRODUCT/prebuilts/", "SYSTEM_OTHER/preloads/"]))
+    self.assertTrue(is_apk)
+    self.assertTrue(is_compressed)
+    self.assertTrue(should_be_skipped)
+
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "SYSTEM_OTHER/preloads/apps/Chats.dat",
+        None,
+        set(["SYSTEM_OTHER/preloads/"]))
+    self.assertFalse(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertFalse(should_be_skipped)
+
+  def test_GetApkFileInfo_checkSkippedPrefixesInput(self):
+    # set
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "SYSTEM_OTHER/preloads/apps/Chats.apk",
+        None,
+        set(["SYSTEM_OTHER/preloads/"]))
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertTrue(should_be_skipped)
+
+    # tuple
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "SYSTEM_OTHER/preloads/apps/Chats.apk",
+        None,
+        ("SYSTEM_OTHER/preloads/",))
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertTrue(should_be_skipped)
+
+    # list
+    (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
+        "SYSTEM_OTHER/preloads/apps/Chats.apk",
+        None,
+        ["SYSTEM_OTHER/preloads/"])
+    self.assertTrue(is_apk)
+    self.assertFalse(is_compressed)
+    self.assertTrue(should_be_skipped)
+
+    # str is invalid.
+    self.assertRaises(
+        AssertionError, GetApkFileInfo, "SYSTEM_OTHER/preloads/apps/Chats.apk",
+        None, "SYSTEM_OTHER/preloads/")
+
+    # None is invalid.
+    self.assertRaises(
+        AssertionError, GetApkFileInfo, "SYSTEM_OTHER/preloads/apps/Chats.apk",
+        None, None)