Merge "Remove workaround for libclang_rt.ubsan* vndk libs"
diff --git a/core/Makefile b/core/Makefile
index a248f5e..9c26b8b 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -2570,14 +2570,6 @@
 
 .PHONY: check_android_partition_sizes
 
-# BOARD_SUPER_PARTITION_PARTITION_LIST: a list of the following tokens
-valid_super_partition_list := system vendor product productservices
-ifneq (,$(filter-out $(valid_super_partition_list),$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
-$(error BOARD_SUPER_PARTITION_PARTITION_LIST contains invalid partition name. \
-        Valid names are $(valid_super_partition_list).)
-endif
-valid_super_partition_list :=
-
 # Add image dependencies so that generated_*_image_info.txt are written before checking.
 ifneq (,$(filter system,$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
 check_android_partition_sizes: $(BUILT_SYSTEMIMAGE)
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index 517379a..13da10c 100644
--- a/core/android_manifest.mk
+++ b/core/android_manifest.mk
@@ -38,28 +38,36 @@
   $(full_android_manifest): PRIVATE_MIN_SDK_VERSION := $(DEFAULT_APP_TARGET_SDK)
 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)))
+  # Set up rules to merge library manifest files
+  fixed_android_manifest := $(intermediates.COMMON)/manifest/AndroidManifest.xml.fixed
 
-$(full_android_manifest): PRIVATE_LIBS_MANIFESTS := $(my_full_libs_manifest_files)
-$(full_android_manifest): $(ANDROID_MANIFEST_MERGER_DEPS)
-$(full_android_manifest) : $(main_android_manifest) $(my_full_libs_manifest_files)
+  $(full_android_manifest): PRIVATE_LIBS_MANIFESTS := $(my_full_libs_manifest_files)
+  $(full_android_manifest): $(ANDROID_MANIFEST_MERGER_DEPS)
+  $(full_android_manifest) : $(fixed_android_manifest) $(my_full_libs_manifest_files)
 	@echo "Merge android manifest files: $@ <-- $< $(PRIVATE_LIBS_MANIFESTS)"
 	@mkdir -p $(dir $@)
-	$(call fix-manifest,$<,$@.tmp,$(PRIVATE_MIN_SDK_VERSION),$(PRIVATE_EXPORTED_SDK_LIBS_FILE))
-	$(hide) $(ANDROID_MANIFEST_MERGER) --main $@.tmp \
+	$(hide) $(ANDROID_MANIFEST_MERGER) --main $< \
 	    --libs $(call normalize-path-list,$(PRIVATE_LIBS_MANIFESTS)) \
 	    --out $@
-	rm $@.tmp
-
 else
-$(full_android_manifest): $(main_android_manifest)
-	@echo "Fix manifest: $@"
-	$(call fix-manifest,$<,$@,$(PRIVATE_MIN_SDK_VERSION),$(PRIVATE_EXPORTED_SDK_LIBS_FILE))
-
+  fixed_android_manifest := $(full_android_manifest)
 endif
+
+my_exported_sdk_libs_file := $(call local-intermediates-dir,COMMON)/exported-sdk-libs
+$(fixed_android_manifest): PRIVATE_EXPORTED_SDK_LIBS_FILE := $(my_exported_sdk_libs_file)
+$(fixed_android_manifest): $(my_exported_sdk_libs_file)
+
+$(fixed_android_manifest): PRIVATE_MANIFEST_FIXER_FLAGS :=
+ifneq ($(LOCAL_MODULE_CLASS),APPS)
+$(fixed_android_manifest): PRIVATE_MANIFEST_FIXER_FLAGS := --library
+endif
+$(fixed_android_manifest): $(MANIFEST_FIXER)
+$(fixed_android_manifest): $(main_android_manifest)
+	@echo "Fix manifest: $@"
+	$(MANIFEST_FIXER) \
+	  --minSdkVersion $(PRIVATE_MIN_SDK_VERSION) \
+	  $(PRIVATE_MANIFEST_FIXER_FLAGS) \
+	  $(if (PRIVATE_EXPORTED_SDK_LIBS_FILE),\
+	    $$(cat $(PRIVATE_EXPORTED_SDK_LIBS_FILE) | sort -u | sed -e 's/^/\ --uses-library\ /' | tr '\n' ' ')) \
+	  $< $@
diff --git a/core/autogen_test_config.mk b/core/autogen_test_config.mk
index 5feec2b..bf87c9d 100644
--- a/core/autogen_test_config.mk
+++ b/core/autogen_test_config.mk
@@ -29,9 +29,10 @@
 autogen_test_config_template := $(NATIVE_TEST_CONFIG_TEMPLATE)
 endif
 # Auto generating test config file for native test
+$(autogen_test_config_file): PRIVATE_MODULE_NAME := $(LOCAL_MODULE)
 $(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_NAME)&g' $< > $@
 my_auto_generate_config := true
 else
 # Auto generating test config file for instrumentation test
@@ -52,6 +53,7 @@
   LOCAL_INTERMEDIATE_TARGETS += $(autogen_test_config_file)
   $(LOCAL_BUILT_MODULE): $(autogen_test_config_file)
   ALL_MODULES.$(my_register_name).auto_test_config := true
+  $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_autogen := true
 else
   autogen_test_config_file :=
 endif
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 744740f..770a16c 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -566,69 +566,74 @@
     $(LOCAL_BUILT_MODULE):$(dir)/$(my_installed_module_stem))) \
   $(eval my_compat_dist_config_$(suite) := ))
 
+
 # Make sure we only add the files once for multilib modules.
-ifndef $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files
-$(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files := true
-
-# LOCAL_COMPATIBILITY_SUPPORT_FILES is a list of <src>[:<dest>].
-$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
-  $(eval my_compat_dist_$(suite) += $(foreach f, $(LOCAL_COMPATIBILITY_SUPPORT_FILES), \
-    $(eval p := $(subst :,$(space),$(f))) \
-    $(eval s := $(word 1,$(p))) \
-    $(eval n := $(or $(word 2,$(p)),$(notdir $(word 1, $(p))))) \
-    $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
-      $(s):$(dir)/$(n)))))
-
-test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
-ifeq (,$(test_config))
-  ifneq (true,$(is_native))
-    is_instrumentation_test := true
-    ifeq (true, $(LOCAL_IS_HOST_MODULE))
-      is_instrumentation_test := false
-    endif
-    # If LOCAL_MODULE_CLASS is not APPS, it's certainly not an instrumentation
-    # test. However, some packages for test data also have LOCAL_MODULE_CLASS
-    # set to APPS. These will require flag LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG
-    # to disable auto-generating test config file.
-    ifneq (APPS, $(LOCAL_MODULE_CLASS))
-      is_instrumentation_test := false
-    endif
+ifdef $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files
+  # Sync the auto_test_config value for multilib modules.
+  ifdef $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_autogen
+    ALL_MODULES.$(my_register_name).auto_test_config := true
   endif
-  # CTS modules can be used for test data, so test config files must be
-  # explicitly created using AndroidTest.xml
-  ifeq (,$(filter cts, $(LOCAL_COMPATIBILITY_SUITE)))
-    ifneq (true, $(LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG))
-      ifeq (true, $(filter true,$(is_native) $(is_instrumentation_test)))
-        include $(BUILD_SYSTEM)/autogen_test_config.mk
-        test_config := $(autogen_test_config_file)
-        autogen_test_config_file :=
+else
+  $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files := true
+  # LOCAL_COMPATIBILITY_SUPPORT_FILES is a list of <src>[:<dest>].
+  $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+    $(eval my_compat_dist_$(suite) += $(foreach f, $(LOCAL_COMPATIBILITY_SUPPORT_FILES), \
+      $(eval p := $(subst :,$(space),$(f))) \
+      $(eval s := $(word 1,$(p))) \
+      $(eval n := $(or $(word 2,$(p)),$(notdir $(word 1, $(p))))) \
+      $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
+        $(s):$(dir)/$(n)))))
+
+  test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
+  ifeq (,$(test_config))
+    ifneq (true,$(is_native))
+      is_instrumentation_test := true
+      ifeq (true, $(LOCAL_IS_HOST_MODULE))
+        is_instrumentation_test := false
+      endif
+      # If LOCAL_MODULE_CLASS is not APPS, it's certainly not an instrumentation
+      # test. However, some packages for test data also have LOCAL_MODULE_CLASS
+      # set to APPS. These will require flag LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG
+      # to disable auto-generating test config file.
+      ifneq (APPS, $(LOCAL_MODULE_CLASS))
+        is_instrumentation_test := false
+      endif
+    endif
+    # CTS modules can be used for test data, so test config files must be
+    # explicitly created using AndroidTest.xml
+    ifeq (,$(filter cts, $(LOCAL_COMPATIBILITY_SUITE)))
+      ifneq (true, $(LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG))
+        ifeq (true, $(filter true,$(is_native) $(is_instrumentation_test)))
+          include $(BUILD_SYSTEM)/autogen_test_config.mk
+          test_config := $(autogen_test_config_file)
+          autogen_test_config_file :=
+        endif
       endif
     endif
   endif
-endif
 
-is_instrumentation_test :=
+  is_instrumentation_test :=
 
-ifneq (,$(test_config))
-$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
-  $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
-    $(test_config):$(dir)/$(LOCAL_MODULE).config)))
-endif
+  ifneq (,$(test_config))
+    $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+      $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
+        $(test_config):$(dir)/$(LOCAL_MODULE).config)))
+  endif
 
-test_config :=
+  test_config :=
 
-ifneq (,$(wildcard $(LOCAL_PATH)/DynamicConfig.xml))
-$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
-  $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
-    $(LOCAL_PATH)/DynamicConfig.xml:$(dir)/$(LOCAL_MODULE).dynamic)))
-endif
+  ifneq (,$(wildcard $(LOCAL_PATH)/DynamicConfig.xml))
+    $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+      $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
+        $(LOCAL_PATH)/DynamicConfig.xml:$(dir)/$(LOCAL_MODULE).dynamic)))
+  endif
 
-ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_MODULE)_*.config))
-$(foreach extra_config, $(wildcard $(LOCAL_PATH)/$(LOCAL_MODULE)_*.config), \
-  $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
-    $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
-      $(extra_config):$(dir)/$(notdir $(extra_config))))))
-endif
+  ifneq (,$(wildcard $(LOCAL_PATH)/$(LOCAL_MODULE)_*.config))
+  $(foreach extra_config, $(wildcard $(LOCAL_PATH)/$(LOCAL_MODULE)_*.config), \
+    $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+      $(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
+        $(extra_config):$(dir)/$(notdir $(extra_config))))))
+  endif
 endif # $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files
 
 ifneq ($(my_test_data_file_pairs),)
diff --git a/core/config.mk b/core/config.mk
index 5ebbd9c..d49d7d5 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -719,6 +719,7 @@
 DEXDUMP := $(HOST_OUT_EXECUTABLES)/dexdump2$(BUILD_EXECUTABLE_SUFFIX)
 PROFMAN := $(HOST_OUT_EXECUTABLES)/profman
 HIDDENAPI := $(HOST_OUT_EXECUTABLES)/hiddenapi
+CLASS2GREYLIST := $(HOST_OUT_EXECUTABLES)/class2greylist
 
 FINDBUGS_DIR := external/owasp/sanitizer/tools/findbugs/bin
 FINDBUGS := $(FINDBUGS_DIR)/findbugs
@@ -945,6 +946,16 @@
 endif
 endif
 
+ifdef BOARD_SUPER_PARTITION_PARTITION_LIST
+# BOARD_SUPER_PARTITION_PARTITION_LIST: a list of the following tokens
+valid_super_partition_list := system vendor product productservices
+ifneq (,$(filter-out $(valid_super_partition_list),$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
+$(error BOARD_SUPER_PARTITION_PARTITION_LIST contains invalid partition name. \
+        Valid names are $(valid_super_partition_list).)
+endif
+valid_super_partition_list :=
+endif # BOARD_SUPER_PARTITION_PARTITION_LIST
+
 endif # USE_LOGICAL_PARTITIONS
 
 # ###############################################################
diff --git a/core/definitions.mk b/core/definitions.mk
index 7108e09..1550206 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -742,18 +742,6 @@
 $(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.
@@ -2866,6 +2854,16 @@
     PRIVATE_DEX_INPUTS := $$(PRIVATE_DEX_INPUTS) $(1)
 endef
 
+# Generate a greylist.txt from a classes.jar
+define hiddenapi-generate-greylist-txt
+$(2): $(1) $(CLASS2GREYLIST)
+	$(CLASS2GREYLIST) $(1) > $(2)
+
+$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): $(2)
+$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST): \
+    PRIVATE_GREYLIST_INPUTS := $$(PRIVATE_GREYLIST_INPUTS) $(2)
+endef
+
 # File names for intermediate dex files of `hiddenapi-copy-soong-jar`.
 hiddenapi-soong-input-dex = $(dir $(1))/hiddenapi/dex-input/classes.dex
 hiddenapi-soong-output-dex = $(dir $(1))/hiddenapi/dex-output/classes.dex
diff --git a/core/dex_preopt_libart_boot.mk b/core/dex_preopt_libart_boot.mk
index 977f852..5a68738 100644
--- a/core/dex_preopt_libart_boot.mk
+++ b/core/dex_preopt_libart_boot.mk
@@ -100,7 +100,9 @@
 		$(PRIVATE_BOOT_IMAGE_FLAGS) \
 		$(addprefix --dex-file=,$(LIBART_TARGET_BOOT_DEX_FILES)) \
 		$(addprefix --dex-location=,$(LIBART_TARGET_BOOT_DEX_LOCATIONS)) \
+		--generate-debug-info --generate-build-id \
 		--oat-symbols=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED) \
+		--strip \
 		--oat-file=$(patsubst %.art,%.oat,$@) \
 		--oat-location=$(patsubst %.art,%.oat,$($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_BOOT_IMAGE_FILENAME)) \
 		--image=$@ --base=$(LIBART_IMG_TARGET_BASE_ADDRESS) \
@@ -109,7 +111,6 @@
 		--instruction-set-features=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) \
 		--android-root=$(PRODUCT_OUT)/system \
 		--runtime-arg -Xnorelocate --compile-pic \
-		--no-generate-debug-info --generate-build-id \
 		--multi-image --no-inline-from=core-oj.jar \
 		--abort-on-hard-verifier-error \
 		--abort-on-soft-verifier-error \
diff --git a/core/java.mk b/core/java.mk
index f7edd55..0d898e7 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -79,6 +79,7 @@
 built_dex_hiddenapi := $(intermediates.COMMON)/dex-hiddenapi/classes.dex
 full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar
 java_source_list_file := $(intermediates.COMMON)/java-source-list
+greylist_txt := $(intermediates.COMMON)/greylist.txt
 
 
 ifeq ($(LOCAL_MODULE_CLASS)$(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),APPS)
@@ -458,14 +459,15 @@
     -applymapping $(link_instr_intermediates_dir.COMMON)/proguard_dictionary \
     -verbose \
     $(legacy_proguard_flags)
+legacy_proguard_lib_deps += \
+  $(link_instr_classes_jar) \
+  $(link_instr_intermediates_dir.COMMON)/proguard_options \
+  $(link_instr_intermediates_dir.COMMON)/proguard_dictionary \
 
 # Sometimes (test + main app) uses different keep rules from the main app -
 # apply the main app's dictionary anyway.
 legacy_proguard_flags += -ignorewarnings
 
-# Make sure we run Proguard on the main app first
-$(full_classes_proguard_jar) : $(link_instr_intermediates_dir.COMMON)/proguard.classes.jar
-
 endif # no obfuscation
 endif # LOCAL_INSTRUMENTATION_FOR
 
@@ -545,6 +547,13 @@
 endif
 
 ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),) # is_boot_jar
+  # Derive API greylist from the classes jar.
+  # We use full_classes_proguard_jar here, as that is what is converted to dex
+  # later on. The difference is academic currently, as we don't proguard any
+  # bootclasspath code at the moment. If we were to do that, we should add keep
+  # rules for all members with the @UnsupportedAppUsage annotation.
+  $(eval $(call hiddenapi-generate-greylist-txt,$(full_classes_proguard_jar),$(greylist_txt)))
+  LOCAL_INTERMEDIATE_TARGETS += $(greylist_txt)
   $(eval $(call hiddenapi-copy-dex-files,$(built_dex_intermediate),$(built_dex_hiddenapi)))
   built_dex_copy_from := $(built_dex_hiddenapi)
 else # !is_boot_jar
diff --git a/core/main.mk b/core/main.mk
index dfbe12f..a991d88 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -977,6 +977,39 @@
 
 ifdef FULL_BUILD
   product_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
+
+  # Verify the artifact path requirements made by included products.
+  all_offending_files :=
+  $(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
+    $(eval requirements := $(PRODUCTS.$(makefile).ARTIFACT_PATH_REQUIREMENTS)) \
+    $(eval ### Verify that the product only produces files inside its path requirements.) \
+    $(eval whitelist := $(PRODUCTS.$(makefile).ARTIFACT_PATH_WHITELIST)) \
+    $(eval path_patterns := $(call resolve-product-relative-paths,$(requirements),%)) \
+    $(eval whitelist_patterns := $(call resolve-product-relative-paths,$(whitelist))) \
+    $(eval files := $(call product-installed-files, $(makefile))) \
+    $(eval files := $(filter-out $(TARGET_OUT_FAKE)/% $(HOST_OUT)/%,$(files))) \
+    $(eval # RROs become REQUIRED by the source module, but are always placed on the vendor partition.) \
+    $(eval files := $(filter-out %__auto_generated_rro.apk,$(files))) \
+    $(eval offending_files := $(filter-out $(path_patterns) $(whitelist_patterns),$(files))) \
+    $(call maybe-print-list-and-error,$(offending_files),$(makefile) produces files outside its artifact path requirement.) \
+    $(eval unused_whitelist := $(filter-out $(files),$(whitelist_patterns))) \
+    $(call maybe-print-list-and-error,$(unused_whitelist),$(makefile) includes redundant whitelist entries in its artifact path requirement.) \
+    $(eval ### Optionally verify that nothing else produces files inside this artifact path requirement.) \
+    $(eval extra_files := $(filter-out $(files) $(HOST_OUT)/%,$(product_FILES))) \
+    $(eval files_in_requirement := $(filter $(path_patterns),$(extra_files))) \
+    $(eval all_offending_files += $(files_in_requirement)) \
+    $(eval whitelist := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST)) \
+    $(eval whitelist_patterns := $(call resolve-product-relative-paths,$(whitelist))) \
+    $(eval offending_files := $(filter-out $(whitelist_patterns),$(files_in_requirement))) \
+    $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS),\
+      $(call maybe-print-list-and-error,$(offending_files),$(INTERNAL_PRODUCT) produces files inside $(makefile)s artifact path requirement.) \
+      $(eval unused_whitelist := $(filter-out $(extra_files),$(whitelist_patterns))) \
+      $(call maybe-print-list-and-error,$(unused_whitelist),$(INTERNAL_PRODUCT) includes redundant artifact path requirement whitelist entries.) \
+    ) \
+  )
+$(PRODUCT_OUT)/offending_artifacts.txt:
+	rm -f $@
+	$(foreach f,$(sort $(all_offending_files)),echo $(f) >> $@;)
 else
   # We're not doing a full build, and are probably only including
   # a subset of the module makefiles.  Don't try to build any modules
@@ -985,38 +1018,6 @@
   product_FILES :=
 endif
 
-# Verify the artifact path requirements made by included products.
-$(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
-  $(eval requirements := $(PRODUCTS.$(makefile).ARTIFACT_PATH_REQUIREMENTS)) \
-  $(eval ### Verify that the product only produces files inside its path requirements.) \
-  $(eval whitelist := $(PRODUCTS.$(makefile).ARTIFACT_PATH_WHITELIST)) \
-  $(eval path_patterns := $(call resolve-product-relative-paths,$(requirements),%)) \
-  $(eval whitelist_patterns := $(call resolve-product-relative-paths,$(whitelist))) \
-  $(eval files := $(call product-installed-files, $(makefile))) \
-  $(eval files := $(filter-out $(TARGET_OUT_FAKE)/% $(HOST_OUT)/%,$(files))) \
-  $(eval # RROs become REQUIRED by the source module, but are always placed on the vendor partition.) \
-  $(eval files := $(filter-out %__auto_generated_rro.apk,$(files))) \
-  $(eval offending_files := $(filter-out $(path_patterns) $(whitelist_patterns),$(files))) \
-  $(call maybe-print-list-and-error,$(offending_files),$(makefile) produces files outside its artifact path requirement.) \
-  $(eval unused_whitelist := $(filter-out $(files),$(whitelist_patterns))) \
-  $(call maybe-print-list-and-error,$(unused_whitelist),$(makefile) includes redundant whitelist entries in its artifact path requirement.) \
-  $(eval ### Optionally verify that nothing else produces files inside this artifact path requirement.) \
-  $(eval extra_files := $(filter-out $(files) $(HOST_OUT)/%,$(product_FILES))) \
-  $(eval files_in_requirement := $(filter $(path_patterns),$(extra_files))) \
-  $(eval all_offending_files += $(files_in_requirement)) \
-  $(eval whitelist := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST)) \
-  $(eval whitelist_patterns := $(call resolve-product-relative-paths,$(whitelist))) \
-  $(eval offending_files := $(filter-out $(whitelist_patterns),$(files_in_requirement))) \
-  $(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS),\
-    $(call maybe-print-list-and-error,$(offending_files),$(INTERNAL_PRODUCT) produces files inside $(makefile)s artifact path requirement.) \
-    $(eval unused_whitelist := $(filter-out $(extra_files),$(whitelist_patterns))) \
-    $(call maybe-print-list-and-error,$(unused_whitelist),$(INTERNAL_PRODUCT) includes redundant artifact path requirement whitelist entries.) \
-  ) \
-)
-$(PRODUCT_OUT)/offending_artifacts.txt:
-	rm -f $@
-	$(foreach f,$(sort $(all_offending_files)),echo $(f) >> $@;)
-
 ifeq (0,1)
   $(info product_FILES for $(TARGET_DEVICE) ($(INTERNAL_PRODUCT)):)
   $(foreach p,$(product_FILES),$(info :   $(p)))
diff --git a/core/native_test_config_template.xml b/core/native_test_config_template.xml
index a960529..a88d57c 100644
--- a/core/native_test_config_template.xml
+++ b/core/native_test_config_template.xml
@@ -15,6 +15,8 @@
 -->
 <!-- This test config file is auto-generated. -->
 <configuration description="Runs {MODULE}.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index aad4b31..44b4f5c 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -19,6 +19,7 @@
 full_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
 full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
 common_javalib.jar := $(intermediates.COMMON)/javalib.jar
+greylist_txt := $(intermediates.COMMON)/greylist.txt
 
 $(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(full_classes_jar)))
 $(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(full_classes_pre_proguard_jar)))
@@ -86,6 +87,11 @@
   ifneq ($(LOCAL_UNINSTALLABLE_MODULE),true)
     ifndef LOCAL_IS_HOST_MODULE
       ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),)  # is_boot_jar
+        # Derive greylist from classes.jar.
+        # We use full_classes_jar here, which is the post-proguard jar (on the basis that we also
+        # have a full_classes_pre_proguard_jar). This is consistent with the equivalent code in
+        # java.mk.
+        $(eval $(call hiddenapi-generate-greylist-txt,$(full_classes_jar),$(greylist_txt)))
         $(eval $(call hiddenapi-copy-soong-jar,$(LOCAL_SOONG_DEX_JAR),$(common_javalib.jar)))
       else # !is_boot_jar
         $(eval $(call copy-one-file,$(LOCAL_SOONG_DEX_JAR),$(common_javalib.jar)))
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index 6117414..34ac1d0 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -48,6 +48,7 @@
 $(compatibility_zip): $(test_artifacts) $(test_tools) $(test_suite_prebuilt_tools) $(test_suite_dynamic_config) $(SOONG_ZIP) | $(ADB) $(ACP)
 # Make dir structure
 	$(hide) mkdir -p $(PRIVATE_OUT_DIR)/tools $(PRIVATE_OUT_DIR)/testcases
+	$(hide) echo $(BUILD_NUMBER_FROM_FILE) > $(PRIVATE_OUT_DIR)/tools/version.txt
 # Copy tools
 	$(hide) $(ACP) -fp $(PRIVATE_TOOLS) $(PRIVATE_OUT_DIR)/tools
 	$(if $(PRIVATE_DYNAMIC_CONFIG),$(hide) $(ACP) -fp $(PRIVATE_DYNAMIC_CONFIG) $(PRIVATE_OUT_DIR)/testcases/$(PRIVATE_SUITE_NAME).dynamic)
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index fc3eb2c..b7e114d 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -425,6 +425,52 @@
   return base_fs_file if exit_code == 0 else None
 
 
+def SetUpInDirAndFsConfig(origin_in, prop_dict):
+  """Returns the in_dir and fs_config that should be used for image building.
+
+  If the target uses system_root_image and it's building system.img, it creates
+  and returns a staged dir that combines the contents of /system (i.e. in the
+  given in_dir) and root.
+
+  Args:
+    origin_in: Path to the input directory.
+    prop_dict: A property dict that contains info like partition size. Values
+        may be updated.
+
+  Returns:
+    A tuple of in_dir and fs_config that should be used to build the image.
+  """
+  fs_config = prop_dict.get("fs_config")
+  if (prop_dict.get("system_root_image") != "true" or
+      prop_dict["mount_point"] != "system"):
+    return origin_in, fs_config
+
+  # Construct a staging directory of the root file system.
+  in_dir = common.MakeTempDir()
+  root_dir = prop_dict.get("root_dir")
+  if root_dir:
+    shutil.rmtree(in_dir)
+    shutil.copytree(root_dir, in_dir, symlinks=True)
+  in_dir_system = os.path.join(in_dir, "system")
+  shutil.rmtree(in_dir_system, ignore_errors=True)
+  shutil.copytree(origin_in, in_dir_system, symlinks=True)
+
+  # Change the mount point to "/".
+  prop_dict["mount_point"] = "/"
+  if fs_config:
+    # We need to merge the fs_config files of system and root.
+    merged_fs_config = common.MakeTempFile(
+        prefix="merged_fs_config", suffix=".txt")
+    with open(merged_fs_config, "w") as fw:
+      if "root_fs_config" in prop_dict:
+        with open(prop_dict["root_fs_config"]) as fr:
+          fw.writelines(fr.readlines())
+      with open(fs_config) as fr:
+        fw.writelines(fr.readlines())
+    fs_config = merged_fs_config
+  return in_dir, fs_config
+
+
 def CheckHeadroom(ext4fs_output, prop_dict):
   """Checks if there's enough headroom space available.
 
@@ -468,40 +514,25 @@
 
 
 def BuildImage(in_dir, prop_dict, out_file, target_out=None):
-  """Build an image to out_file from in_dir with property prop_dict.
-  After the function call, values in prop_dict is updated with
-  computed values.
+  """Builds an image for the files under in_dir and writes it to out_file.
+
+  When using system_root_image, it will additionally look for the files under
+  root (specified by 'root_dir') and builds an image that contains both sources.
 
   Args:
-    in_dir: path of input directory.
-    prop_dict: property dictionary.
-    out_file: path of the output image file.
-    target_out: path of the product out directory to read device specific FS
-        config files.
+    in_dir: Path to input directory.
+    prop_dict: A property dict that contains info like partition size. Values
+        will be updated with computed values.
+    out_file: The output image file.
+    target_out: Path to the TARGET_OUT directory as in Makefile. It actually
+        points to the /system directory under PRODUCT_OUT. fs_config (the one
+        under system/core/libcutils) reads device specific FS config files from
+        there.
 
   Returns:
     True iff the image is built successfully.
   """
-  # system_root_image=true: build a system.img that combines the contents of
-  # /system and root, which should be mounted at the root of the file system.
-  origin_in = in_dir
-  fs_config = prop_dict.get("fs_config")
-  if (prop_dict.get("system_root_image") == "true" and
-      prop_dict["mount_point"] == "system"):
-    in_dir = common.MakeTempDir()
-    # Change the mount point to "/".
-    prop_dict["mount_point"] = "/"
-    if fs_config:
-      # We need to merge the fs_config files of system and root.
-      merged_fs_config = common.MakeTempFile(prefix="merged_fs_config",
-                                             suffix=".txt")
-      with open(merged_fs_config, "w") as fw:
-        if "root_fs_config" in prop_dict:
-          with open(prop_dict["root_fs_config"]) as fr:
-            fw.writelines(fr.readlines())
-        with open(fs_config) as fr:
-          fw.writelines(fr.readlines())
-      fs_config = merged_fs_config
+  in_dir, fs_config = SetUpInDirAndFsConfig(in_dir, prop_dict)
 
   build_command = []
   fs_type = prop_dict.get("fs_type", "")
@@ -518,11 +549,11 @@
   if (prop_dict.get("use_logical_partitions") == "true" and
       "partition_size" not in prop_dict):
     # if partition_size is not defined, use output of `du' + reserved_size
-    success, size = GetDiskUsage(origin_in)
+    success, size = GetDiskUsage(in_dir)
     if not success:
       return False
     if OPTIONS.verbose:
-      print("The tree size of %s is %d MB." % (origin_in, size // BYTES_IN_MB))
+      print("The tree size of %s is %d MB." % (in_dir, size // BYTES_IN_MB))
     size += int(prop_dict.get("partition_reserved_size", 0))
     # Round this up to a multiple of 4K so that avbtool works
     size = common.RoundUpTo4K(size)
@@ -643,31 +674,31 @@
     print("Error: unknown filesystem type '%s'" % (fs_type))
     return False
 
-  if in_dir != origin_in:
-    # Construct a staging directory of the root file system.
-    root_dir = prop_dict.get("root_dir")
-    if root_dir:
-      shutil.rmtree(in_dir)
-      shutil.copytree(root_dir, in_dir, symlinks=True)
-    staging_system = os.path.join(in_dir, "system")
-    shutil.rmtree(staging_system, ignore_errors=True)
-    shutil.copytree(origin_in, staging_system, symlinks=True)
-
   (mkfs_output, exit_code) = RunCommand(build_command)
   if exit_code != 0:
     print("Error: '%s' failed with exit code %d:\n%s" % (
         build_command, exit_code, mkfs_output))
-    success, du = GetDiskUsage(origin_in)
+    success, du = GetDiskUsage(in_dir)
     du_str = ("%d bytes (%d MB)" % (du, du // BYTES_IN_MB)
              ) if success else "unknown"
-    print("Out of space? The tree size of %s is %s." % (
-        origin_in, du_str))
-    print("The max is %d bytes (%d MB)." % (
-        int(prop_dict["partition_size"]),
-        int(prop_dict["partition_size"]) // BYTES_IN_MB))
-    print("Reserved space is %d bytes (%d MB)." % (
-        int(prop_dict.get("partition_reserved_size", 0)),
-        int(prop_dict.get("partition_reserved_size", 0)) // BYTES_IN_MB))
+    print(
+        "Out of space? The tree size of {} is {}, with reserved space of {} "
+        "bytes ({} MB).".format(
+            in_dir, du_str,
+            int(prop_dict.get("partition_reserved_size", 0)),
+            int(prop_dict.get("partition_reserved_size", 0)) // BYTES_IN_MB))
+    if "original_partition_size" in prop_dict:
+      print(
+          "The max size for filsystem files is {} bytes ({} MB), out of a "
+          "total image size of {} bytes ({} MB).".format(
+              int(prop_dict["partition_size"]),
+              int(prop_dict["partition_size"]) // BYTES_IN_MB,
+              int(prop_dict["original_partition_size"]),
+              int(prop_dict["original_partition_size"]) // BYTES_IN_MB))
+    else:
+      print("The max image size is {} bytes ({} MB).".format(
+          int(prop_dict["partition_size"]),
+          int(prop_dict["partition_size"]) // BYTES_IN_MB))
     return False
 
   # Check if there's enough headroom space available for ext4 image.
@@ -931,16 +962,22 @@
       d[dest_p] = image_prop[src_p]
       return True
     return False
+
+  if "original_partition_size" in image_prop:
+    size_property = "original_partition_size"
+  else:
+    size_property = "partition_size"
+
   if mount_point == "system":
-    copy_prop("partition_size", "system_size")
+    copy_prop(size_property, "system_size")
   elif mount_point == "system_other":
-    copy_prop("partition_size", "system_size")
+    copy_prop(size_property, "system_size")
   elif mount_point == "vendor":
-    copy_prop("partition_size", "vendor_size")
+    copy_prop(size_property, "vendor_size")
   elif mount_point == "product":
-    copy_prop("partition_size", "product_size")
+    copy_prop(size_property, "product_size")
   elif mount_point == "product-services":
-    copy_prop("partition_size", "productservices_size")
+    copy_prop(size_property, "productservices_size")
   return d
 
 
diff --git a/tools/releasetools/test_build_image.py b/tools/releasetools/test_build_image.py
index 161faff..19b5e08 100644
--- a/tools/releasetools/test_build_image.py
+++ b/tools/releasetools/test_build_image.py
@@ -14,10 +14,12 @@
 # limitations under the License.
 #
 
+import filecmp
+import os.path
 import unittest
 
 import common
-from build_image import CheckHeadroom, RunCommand
+from build_image import CheckHeadroom, RunCommand, SetUpInDirAndFsConfig
 
 
 class BuildImageTest(unittest.TestCase):
@@ -26,6 +28,9 @@
   EXT4FS_OUTPUT = (
       "Created filesystem with 2777/129024 inodes and 515099/516099 blocks")
 
+  def tearDown(self):
+    common.Cleanup()
+
   def test_CheckHeadroom_SizeUnderLimit(self):
     # Required headroom: 1000 blocks.
     prop_dict = {
@@ -91,4 +96,95 @@
     }
     self.assertFalse(CheckHeadroom(ext4fs_output, prop_dict))
 
-    common.Cleanup()
+  def test_SetUpInDirAndFsConfig_SystemRootImageFalse(self):
+    prop_dict = {
+        'fs_config': 'fs-config',
+        'mount_point': 'system',
+    }
+    in_dir, fs_config = SetUpInDirAndFsConfig('/path/to/in_dir', prop_dict)
+    self.assertEqual('/path/to/in_dir', in_dir)
+    self.assertEqual('fs-config', fs_config)
+    self.assertEqual('system', prop_dict['mount_point'])
+
+  def test_SetUpInDirAndFsConfig_SystemRootImageTrue_NonSystem(self):
+    prop_dict = {
+        'fs_config': 'fs-config',
+        'mount_point': 'vendor',
+        'system_root_image': 'true',
+    }
+    in_dir, fs_config = SetUpInDirAndFsConfig('/path/to/in_dir', prop_dict)
+    self.assertEqual('/path/to/in_dir', in_dir)
+    self.assertEqual('fs-config', fs_config)
+    self.assertEqual('vendor', prop_dict['mount_point'])
+
+  @staticmethod
+  def _gen_fs_config(partition):
+    fs_config = common.MakeTempFile(suffix='.txt')
+    with open(fs_config, 'w') as fs_config_fp:
+      fs_config_fp.write('fs-config-{}\n'.format(partition))
+    return fs_config
+
+  def test_SetUpInDirAndFsConfig_SystemRootImageTrue(self):
+    root_dir = common.MakeTempDir()
+    with open(os.path.join(root_dir, 'init'), 'w') as init_fp:
+      init_fp.write('init')
+
+    origin_in = common.MakeTempDir()
+    with open(os.path.join(origin_in, 'file'), 'w') as in_fp:
+      in_fp.write('system-file')
+    os.symlink('../etc', os.path.join(origin_in, 'symlink'))
+
+    fs_config_system = self._gen_fs_config('system')
+
+    prop_dict = {
+        'fs_config': fs_config_system,
+        'mount_point': 'system',
+        'root_dir': root_dir,
+        'system_root_image': 'true',
+    }
+    in_dir, fs_config = SetUpInDirAndFsConfig(origin_in, prop_dict)
+
+    self.assertTrue(filecmp.cmp(
+        os.path.join(in_dir, 'init'), os.path.join(root_dir, 'init')))
+    self.assertTrue(filecmp.cmp(
+        os.path.join(in_dir, 'system', 'file'),
+        os.path.join(origin_in, 'file')))
+    self.assertTrue(os.path.islink(os.path.join(in_dir, 'system', 'symlink')))
+
+    self.assertTrue(filecmp.cmp(fs_config_system, fs_config))
+    self.assertEqual('/', prop_dict['mount_point'])
+
+  def test_SetUpInDirAndFsConfig_SystemRootImageTrue_WithRootFsConfig(self):
+    root_dir = common.MakeTempDir()
+    with open(os.path.join(root_dir, 'init'), 'w') as init_fp:
+      init_fp.write('init')
+
+    origin_in = common.MakeTempDir()
+    with open(os.path.join(origin_in, 'file'), 'w') as in_fp:
+      in_fp.write('system-file')
+    os.symlink('../etc', os.path.join(origin_in, 'symlink'))
+
+    fs_config_system = self._gen_fs_config('system')
+    fs_config_root = self._gen_fs_config('root')
+
+    prop_dict = {
+        'fs_config': fs_config_system,
+        'mount_point': 'system',
+        'root_dir': root_dir,
+        'root_fs_config': fs_config_root,
+        'system_root_image': 'true',
+    }
+    in_dir, fs_config = SetUpInDirAndFsConfig(origin_in, prop_dict)
+
+    self.assertTrue(filecmp.cmp(
+        os.path.join(in_dir, 'init'), os.path.join(root_dir, 'init')))
+    self.assertTrue(filecmp.cmp(
+        os.path.join(in_dir, 'system', 'file'),
+        os.path.join(origin_in, 'file')))
+    self.assertTrue(os.path.islink(os.path.join(in_dir, 'system', 'symlink')))
+
+    with open(fs_config) as fs_config_fp:
+      fs_config_data = fs_config_fp.readlines()
+    self.assertIn('fs-config-system\n', fs_config_data)
+    self.assertIn('fs-config-root\n', fs_config_data)
+    self.assertEqual('/', prop_dict['mount_point'])