Merge changes from topic "make_deprecation"

* changes:
  Add infrastructure for deprecating module types
  Mark BUILD_* as readonly
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index 931b1b1..bd5772f 100644
--- a/core/android_manifest.mk
+++ b/core/android_manifest.mk
@@ -23,12 +23,6 @@
     $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/manifest/AndroidManifest.xml)
 endif
 
-# With aapt2, we'll link in the built resource from the AAR.
-ifneq ($(LOCAL_USE_AAPT2),true)
-  LOCAL_RESOURCE_DIR += $(foreach lib, $(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
-    $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/aar/res)
-endif
-
 full_android_manifest := $(intermediates.COMMON)/manifest/AndroidManifest.xml
 
 ifneq (,$(strip $(my_full_libs_manifest_files)))
diff --git a/core/build-system.html b/core/build-system.html
index 3a11a47..cc242d9 100644
--- a/core/build-system.html
+++ b/core/build-system.html
@@ -516,8 +516,8 @@
 example the root filesystem instead of in /system, add these lines to your
 Android.mk:</p>
 <pre>
-LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
-LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
 </pre>
 <p>For executables and libraries, you need to specify a
 <code>LOCAL_UNSTRIPPED_PATH</code> location if you specified a
@@ -527,9 +527,6 @@
 <code>LOCAL_MODULE_RELATIVE_PATH</code>.</p>
 <p>Look in <code>core/envsetup.mk</code> for all of the variables defining
 places to build things.</p>
-<p>FYI: If you're installing an executable to /sbin, you probably also want to
-set <code>LOCAL_FORCE_STATIC_EXCUTABLE := true</code> in your Android.mk, which
-will force the linker to only accept static libraries.</p>
 
 
 <h3>Android.mk variables</h3>
@@ -685,8 +682,7 @@
 <h4>LOCAL_FORCE_STATIC_EXECUTABLE</h4>
 <p>If your executable should be linked statically, set 
 <code>LOCAL_FORCE_STATIC_EXECUTABLE:=true</code>.  There is a very short
-list of libraries that we have in static form (currently only libc).  This is
-really only used for executables in /sbin on the root filesystem.</p>
+list of libraries that we have in static form (currently only libc).</p>
 
 <h4>LOCAL_GENERATED_SOURCES</h4>
 <p>Files that you add to <code>LOCAL_GENERATED_SOURCES</code> will be
@@ -812,7 +808,7 @@
 <h4>LOCAL_STATIC_LIBRARIES</h4>
 <p>These are the static libraries that you want to include in your module.
 Mostly, we use shared libraries, but there are a couple of places, like
-executables in sbin and host executables where we use static libraries instead.
+host executables where we use static libraries instead.
 <p><code>LOCAL_STATIC_LIBRARIES := \<br/>
 	&nbsp;&nbsp;&nbsp;&nbsp;libutils \<br/>
 	&nbsp;&nbsp;&nbsp;&nbsp;libtinyxml
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index d67c9f8..fafdce6 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -291,7 +291,7 @@
 LOCAL_UNCOMPRESS_DEX:=
 LOCAL_UNINSTALLABLE_MODULE:=
 LOCAL_UNSTRIPPED_PATH:=
-LOCAL_USE_AAPT2:=$(USE_AAPT2)
+LOCAL_USE_AAPT2:=
 LOCAL_USE_CLANG_LLD:=
 LOCAL_USE_VNDK:=
 LOCAL_USES_LIBRARIES:=
diff --git a/core/config.mk b/core/config.mk
index 57d22ae..16cd376 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -93,6 +93,8 @@
 $(KATI_obsolete_var DIST_DIR dist_goal,Use dist-for-goals instead. See $(CHANGES_URL)#dist)
 $(KATI_obsolete_var TARGET_ANDROID_FILESYSTEM_CONFIG_H,Use TARGET_FS_CONFIG_GEN instead)
 $(KATI_deprecated_var USER,Use BUILD_USERNAME instead. See $(CHANGES_URL)#USER)
+$(KATI_obsolete_var TARGET_ROOT_OUT_SBIN,/sbin has been removed, use /system/bin instead)
+$(KATI_obsolete_var TARGET_ROOT_OUT_SBIN_UNSTRIPPED,/sbin has been removed, use /system/bin instead)
 
 # This is marked as obsolete in envsetup.mk after reading the BoardConfig.mk
 $(KATI_deprecate_export It is a global setting. See $(CHANGES_URL)#export_keyword)
diff --git a/core/definitions.mk b/core/definitions.mk
index 7e44a47..1f5c5ce 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1846,42 +1846,6 @@
 # b/37750224
 AAPT_ASAN_OPTIONS := ASAN_OPTIONS=detect_leaks=0
 
-# TODO: Right now we generate the asset resources twice, first as part
-# of generating the Java classes, then at the end when packaging the final
-# assets.  This should be changed to do one of two things: (1) Don't generate
-# any resource files the first time, only create classes during that stage;
-# or (2) Don't use the -c flag with the second stage, instead taking the
-# resource files from the first stage as additional input.  My original intent
-# was to use approach (2), but this requires a little more work in the tool.
-# Maybe we should just use approach (1).
-
-# This rule creates the R.java and Manifest.java files, both of which
-# are PRODUCT-neutral.  Don't pass PRIVATE_PRODUCT_AAPT_CONFIG to this invocation.
-define create-resource-java-files
-@mkdir -p $(dir $(PRIVATE_RESOURCE_PUBLICS_OUTPUT))
-rm -rf $(PRIVATE_JAVA_GEN_DIR)
-mkdir -p $(PRIVATE_JAVA_GEN_DIR)
-$(hide) $(AAPT_ASAN_OPTIONS) $(AAPT) package $(PRIVATE_AAPT_FLAGS) -m \
-    $(eval # PRIVATE_PRODUCT_AAPT_CONFIG is intentionally missing-- see comment.) \
-    $(addprefix -J , $(PRIVATE_JAVA_GEN_DIR)) \
-    $(addprefix -M , $(PRIVATE_ANDROID_MANIFEST)) \
-    $(addprefix -P , $(PRIVATE_RESOURCE_PUBLICS_OUTPUT)) \
-    $(addprefix -S , $(PRIVATE_RESOURCE_DIR)) \
-    $(addprefix -A , $(PRIVATE_ASSET_DIR)) \
-    $(addprefix -I , $(PRIVATE_AAPT_INCLUDES)) \
-    $(addprefix -G , $(PRIVATE_PROGUARD_OPTIONS_FILE)) \
-    $(addprefix --min-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
-    $(addprefix --target-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
-    $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,--version-code $(PLATFORM_SDK_VERSION)) \
-    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,--version-name $(APPS_DEFAULT_VERSION_NAME)) \
-    $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
-    $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
-    --skip-symbols-without-default-localization
-$(SOONG_ZIP) -o $(PRIVATE_SRCJAR) -C $(PRIVATE_JAVA_GEN_DIR) -D $(PRIVATE_JAVA_GEN_DIR)
-# So that we re-run aapt when the list of input files change
-$(hide) echo $(PRIVATE_RESOURCE_LIST) >/dev/null
-endef
-
 # Search for generated R.java/Manifest.java in $1, copy the found R.java as $2.
 # Also copy them to a central 'R' directory to make it easier to add the files to an IDE.
 define find-generated-R.java
@@ -2246,37 +2210,6 @@
 $(hide) rm -f $(dir $@)d8_input.jar
 endef
 
-#TODO: we kinda want to build different asset packages for
-#      different configurations, then combine them later (or something).
-#      Per-locale, etc.
-#      A list of dynamic and static parameters;  build layers for
-#      dynamic params that lay over the static ones.
-#TODO: update the manifest to point to the package file
-#Note that the version numbers are given to aapt as simple default
-#values; applications can override these by explicitly stating
-#them in their manifest.
-# $(1) the package file
-define create-assets-package
-$(hide) $(AAPT_ASAN_OPTIONS) $(AAPT) package $(PRIVATE_AAPT_FLAGS) \
-    $(addprefix -c , $(PRIVATE_PRODUCT_AAPT_CONFIG)) \
-    $(addprefix --preferred-density , $(PRIVATE_PRODUCT_AAPT_PREF_CONFIG)) \
-    $(addprefix -M , $(PRIVATE_ANDROID_MANIFEST)) \
-    $(addprefix -S , $(PRIVATE_RESOURCE_DIR)) \
-    $(addprefix -A , $(PRIVATE_ASSET_DIR)) \
-    $(addprefix -I , $(PRIVATE_AAPT_INCLUDES)) \
-    $(addprefix --min-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
-    $(addprefix --target-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
-    $(if $(filter --product,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --product , $(PRIVATE_TARGET_AAPT_CHARACTERISTICS))) \
-    $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,--version-code $(PLATFORM_SDK_VERSION)) \
-    $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,--version-name $(APPS_DEFAULT_VERSION_NAME)) \
-    $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
-    $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
-    --skip-symbols-without-default-localization \
-    -F $(1)
-# So that we re-run aapt when the list of input files change
-$(hide) echo $(PRIVATE_RESOURCE_LIST) >/dev/null
-endef
-
 # We need the extra blank line, so that the command will be on a separate line.
 # $(1): the package
 # $(2): the ABI name
@@ -2381,16 +2314,14 @@
 ifeq ($(HOST_OS),linux)
 # Runs appcompat and store logs in $(PRODUCT_OUT)/appcompat
 define extract-package
-$(if $(filter aapt2, $(1)), \
-  $(AAPT2) dump $@ | awk -F ' |=' '/^Package/{print $$3}' >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log &&, \
-  $(AAPT) dump badging $@ | awk -F \' '/^package/{print $$2}' >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log &&)
+$(AAPT2) dump $@ | awk -F ' |=' '/^Package/{print $$3}' >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log &&
 endef
 define appcompat-header
 $(hide) \
   mkdir -p $(PRODUCT_OUT)/appcompat && \
   rm -f $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log && \
   echo -n "Package name: " >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log && \
-  $(call extract-package, $(1)) \
+  $(extract-package) \
   echo "Module name in Android tree: $(PRIVATE_MODULE)" >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log && \
   echo "Local path in Android tree: $(PRIVATE_PATH)" >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log && \
   echo "Install path on $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT): $(PRIVATE_INSTALLED_MODULE)" >> $(PRODUCT_OUT)/appcompat/$(PRIVATE_MODULE).log && \
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
deleted file mode 100644
index ad073c7..0000000
--- a/core/dpi_specific_apk.mk
+++ /dev/null
@@ -1,77 +0,0 @@
-# Set up rules to build dpi-specific apk, with whatever else from the base apk.
-# Input variable: my_dpi, and all other variables set up in package_internal.mk.
-#
-
-dpi_apk_name := $(LOCAL_MODULE)_$(my_dpi)
-dpi_intermediate := $(call intermediates-dir-for,APPS,$(dpi_apk_name))
-built_dpi_apk := $(dpi_intermediate)/package.apk
-additional_certificates := $(foreach c,$(LOCAL_ADDITIONAL_CERTIFICATES), $(c).x509.pem $(c).pk8)
-
-# Set up all the target-specific variables.
-$(built_dpi_apk): PRIVATE_MODULE := $(dpi_apk_name)
-$(built_dpi_apk): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --pseudo-localize $($(LOCAL_PACKAGE_NAME)_aapt_flags_$(my_dpi))
-# Clear PRIVATE_PRODUCT_AAPT_CONFIG to include everything by default.
-$(built_dpi_apk): PRIVATE_PRODUCT_AAPT_CONFIG :=
-$(built_dpi_apk): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := $(my_dpi)
-$(built_dpi_apk): PRIVATE_ANDROID_MANIFEST := $(full_android_manifest)
-$(built_dpi_apk): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
-$(built_dpi_apk): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
-$(built_dpi_apk): PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports)
-$(built_dpi_apk): PRIVATE_RESOURCE_LIST := $(all_res_assets)
-$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(call module-target-sdk-version)
-$(built_dpi_apk): PRIVATE_MANIFEST_PACKAGE_NAME := $(LOCAL_MANIFEST_PACKAGE_NAME)
-$(built_dpi_apk): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_INSTRUMENTATION_FOR)
-$(built_dpi_apk): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)
-$(built_dpi_apk): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abis)
-$(built_dpi_apk): PRIVATE_PRIVATE_KEY := $(private_key)
-$(built_dpi_apk): PRIVATE_CERTIFICATE := $(certificate)
-$(built_dpi_apk): $(additional_certificates)
-$(built_dpi_apk): PRIVATE_ADDITIONAL_CERTIFICATES := $(additional_certificates)
-
-$(built_dpi_apk): PRIVATE_SOURCE_ARCHIVE :=
-ifneq ($(full_classes_jar),)
-$(built_dpi_apk): PRIVATE_DEX_FILE := $(built_dex)
-# Use the jarjar processed arhive as the initial package file.
-$(built_dpi_apk): PRIVATE_SOURCE_ARCHIVE := $(full_classes_pre_proguard_jar)
-$(built_dpi_apk): $(built_dex)
-else
-$(built_dpi_apk): PRIVATE_DEX_FILE :=
-endif # full_classes_jar
-
-# Set up dependenncies and the build recipe.
-$(built_dpi_apk) : $(R_file_stamp)
-$(built_dpi_apk) : $(all_library_res_package_export_deps)
-$(built_dpi_apk) : $(private_key) $(certificate) $(SIGNAPK_JAR)
-$(built_dpi_apk) : $(AAPT)
-$(built_dpi_apk) : $(MERGE_ZIPS) $(SOONG_ZIP) $(ZIP2ZIP)
-$(built_dpi_apk) : $(all_res_assets) $(jni_shared_libraries) $(full_android_manifest)
-	@echo "target Package: $(PRIVATE_MODULE) ($@)"
-	rm -rf $@.parts
-	mkdir -p $@.parts
-	$(call create-assets-package,$@.parts/apk.zip)
-ifneq ($(jni_shared_libraries),)
-	$(call create-jni-shared-libs-package,$@.parts/jni.zip)
-endif
-ifeq ($(full_classes_jar),)
-# We don't build jar, need to add the Java resources here.
-	$(if $(PRIVATE_EXTRA_JAR_ARGS),$(call create-java-resources-jar,$@.parts/res.zip))
-else
-	$(call create-dex-jar,$@.parts/dex.zip,$(PRIVATE_DEX_FILE))
-	$(call extract-resources-jar,$@.parts/res.zip,$(PRIVATE_SOURCE_ARCHIVE))
-endif
-	$(MERGE_ZIPS) $@ $@.parts/*.zip
-	rm -rf $@.parts
-	$(sign-package)
-
-# Set up global variables to register this apk to the higher-level dependency graph.
-ALL_MODULES += $(dpi_apk_name)
-ALL_MODULES.$(dpi_apk_name).CLASS := APPS
-ALL_MODULES.$(dpi_apk_name).BUILT := $(built_dpi_apk)
-ALL_MODULES.$(dpi_apk_name).TARGET_BUILT := $(built_dpi_apk)
-PACKAGES := $(PACKAGES) $(dpi_apk_name)
-PACKAGES.$(dpi_apk_name).PRIVATE_KEY := $(private_key)
-PACKAGES.$(dpi_apk_name).CERTIFICATE := $(certificate)
-
-# Phony targets used by "apps_only".
-.PHONY: $(dpi_apk_name)
-$(dpi_apk_name) : $(built_dpi_apk)
diff --git a/core/envsetup.mk b/core/envsetup.mk
index f4be2c7..7b90334 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -825,7 +825,6 @@
 TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/system/lib
 TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/$(TARGET_COPY_OUT_VENDOR)/lib
 TARGET_ROOT_OUT_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)
-TARGET_ROOT_OUT_SBIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/sbin
 TARGET_ROOT_OUT_BIN_UNSTRIPPED := $(TARGET_OUT_UNSTRIPPED)/bin
 TARGET_OUT_COVERAGE := $(PRODUCT_OUT)/coverage
 .KATI_READONLY := \
@@ -834,7 +833,6 @@
   TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED \
   TARGET_OUT_VENDOR_SHARED_LIBRARIES_UNSTRIPPED \
   TARGET_ROOT_OUT_UNSTRIPPED \
-  TARGET_ROOT_OUT_SBIN_UNSTRIPPED \
   TARGET_ROOT_OUT_BIN_UNSTRIPPED \
   TARGET_OUT_COVERAGE
 
@@ -843,13 +841,11 @@
 
 TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT)
 TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin
-TARGET_ROOT_OUT_SBIN := $(TARGET_ROOT_OUT)/sbin
 TARGET_ROOT_OUT_ETC := $(TARGET_ROOT_OUT)/etc
 TARGET_ROOT_OUT_USR := $(TARGET_ROOT_OUT)/usr
 .KATI_READONLY := \
   TARGET_ROOT_OUT \
   TARGET_ROOT_OUT_BIN \
-  TARGET_ROOT_OUT_SBIN \
   TARGET_ROOT_OUT_ETC \
   TARGET_ROOT_OUT_USR
 
diff --git a/core/force_aapt2.mk b/core/force_aapt2.mk
index db2e60f..816138a 100644
--- a/core/force_aapt2.mk
+++ b/core/force_aapt2.mk
@@ -14,50 +14,40 @@
 # limitations under the License.
 #
 
-# Including this makefile will force AAPT2 on if FORCE_AAPT2==true,
+# Including this makefile will force AAPT2 on,
 # rewriting some properties to convert standard AAPT usage to AAPT2.
 
-ifneq ($(FORCE_AAPT2),false)
-  ifeq ($(LOCAL_USE_AAPT2),)
-    # Force AAPT2 on
-    LOCAL_USE_AAPT2 := true
-    # Filter out support library resources
-    LOCAL_RESOURCE_DIR := $(filter-out \
-      prebuilts/sdk/current/% \
-      frameworks/support/%,\
-        $(LOCAL_RESOURCE_DIR))
-    # Filter out unnecessary aapt flags
-    ifneq (,$(filter --extra-packages,$(LOCAL_AAPT_FLAGS)))
-      LOCAL_AAPT_FLAGS := $(subst --extra-packages=,--extra-packages$(space), \
-        $(filter-out \
-          --extra-packages=android.support.% \
-          --extra-packages=androidx.%, \
-            $(subst --extra-packages$(space),--extra-packages=,$(LOCAL_AAPT_FLAGS))))
-        ifeq (,$(filter --extra-packages,$(LOCAL_AAPT_FLAGS)))
-          LOCAL_AAPT_FLAGS := $(filter-out --auto-add-overlay,$(LOCAL_AAPT_FLAGS))
-        endif
-    endif
-
-    # AAPT2 is pickier about missing resources.  Support library may have references to resources
-    # added in current, so always treat LOCAL_SDK_VERSION as LOCAL_SDK_RES_VERSION := current.
-    ifdef LOCAL_SDK_VERSION
-      LOCAL_SDK_RES_VERSION := current
-    endif
-
-    ifeq (,$(strip $(LOCAL_MANIFEST_FILE)$(LOCAL_FULL_MANIFEST_FILE)))
-      ifeq (,$(wildcard $(LOCAL_PATH)/AndroidManifest.xml))
-        # work around missing manifests by creating a default one
-        LOCAL_FULL_MANIFEST_FILE := $(call local-intermediates-dir,COMMON)/DefaultManifest.xml
-        $(call create-default-manifest-file,$(LOCAL_FULL_MANIFEST_FILE),$(call module-min-sdk-version))
-      endif
-    endif
-  endif
+ifeq ($(LOCAL_USE_AAPT2),false)
+  $(call pretty-error, LOCAL_USE_AAPT2 := false is no longer supported)
 endif
 
-ifneq ($(LOCAL_USE_AAPT2),true)
-  ifneq ($(LOCAL_USE_AAPT2),false)
-    ifneq ($(LOCAL_USE_AAPT2),)
-      $(call pretty-error,Invalid value for LOCAL_USE_AAPT2: "$(LOCAL_USE_AAPT2)")
+# Filter out support library resources
+LOCAL_RESOURCE_DIR := $(filter-out \
+  prebuilts/sdk/current/% \
+  frameworks/support/%,\
+    $(LOCAL_RESOURCE_DIR))
+# Filter out unnecessary aapt flags
+ifneq (,$(filter --extra-packages,$(LOCAL_AAPT_FLAGS)))
+  LOCAL_AAPT_FLAGS := $(subst --extra-packages=,--extra-packages$(space), \
+    $(filter-out \
+      --extra-packages=android.support.% \
+      --extra-packages=androidx.%, \
+        $(subst --extra-packages$(space),--extra-packages=,$(LOCAL_AAPT_FLAGS))))
+    ifeq (,$(filter --extra-packages,$(LOCAL_AAPT_FLAGS)))
+      LOCAL_AAPT_FLAGS := $(filter-out --auto-add-overlay,$(LOCAL_AAPT_FLAGS))
     endif
+endif
+
+# AAPT2 is pickier about missing resources.  Support library may have references to resources
+# added in current, so always treat LOCAL_SDK_VERSION as LOCAL_SDK_RES_VERSION := current.
+ifdef LOCAL_SDK_VERSION
+  LOCAL_SDK_RES_VERSION := current
+endif
+
+ifeq (,$(strip $(LOCAL_MANIFEST_FILE)$(LOCAL_FULL_MANIFEST_FILE)))
+  ifeq (,$(wildcard $(LOCAL_PATH)/AndroidManifest.xml))
+    # work around missing manifests by creating a default one
+    LOCAL_FULL_MANIFEST_FILE := $(call local-intermediates-dir,COMMON)/DefaultManifest.xml
+    $(call create-default-manifest-file,$(LOCAL_FULL_MANIFEST_FILE),$(call module-min-sdk-version))
   endif
 endif
diff --git a/core/java.mk b/core/java.mk
index c3787ae..66431e9 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -422,10 +422,8 @@
 common_proguard_flags += -dontshrink # don't shrink tests by default
 endif # test package
 ifneq ($(LOCAL_PROGUARD_ENABLED),custom)
-  ifeq ($(LOCAL_USE_AAPT2),true)
-    common_proguard_flag_files += $(foreach l,$(LOCAL_STATIC_ANDROID_LIBRARIES),\
-        $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/export_proguard_flags)
-  endif
+  common_proguard_flag_files += $(foreach l,$(LOCAL_STATIC_ANDROID_LIBRARIES),\
+      $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/export_proguard_flags)
 endif
 ifneq ($(common_proguard_flag_files),)
 common_proguard_flags += $(addprefix -include , $(common_proguard_flag_files))
diff --git a/core/java_common.mk b/core/java_common.mk
index f5da120..db5b6c3 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -534,13 +534,6 @@
 my_allowed_types := java:sdk java:system java:platform java:core
 endif
 
-ifdef LOCAL_AAPT2_ONLY
-my_link_type += aapt2_only
-endif
-ifeq ($(LOCAL_USE_AAPT2),true)
-my_allowed_types += aapt2_only
-endif
-
 my_link_deps := $(addprefix JAVA_LIBRARIES:,$(LOCAL_STATIC_JAVA_LIBRARIES) $(LOCAL_JAVA_LIBRARIES))
 my_link_deps += $(addprefix APPS:,$(apk_libraries))
 
diff --git a/core/java_prebuilt_internal.mk b/core/java_prebuilt_internal.mk
index 8a919ff..31aae83 100644
--- a/core/java_prebuilt_internal.mk
+++ b/core/java_prebuilt_internal.mk
@@ -172,11 +172,6 @@
 
 include $(BUILD_SYSTEM)/force_aapt2.mk
 
-ifdef LOCAL_AAPT2_ONLY
-LOCAL_USE_AAPT2 := true
-endif
-
-ifeq ($(LOCAL_USE_AAPT2),true)
 ifneq ($(my_src_aar),)
 
 $(intermediates.COMMON)/export_proguard_flags : $(my_src_proguard_options)
@@ -229,7 +224,7 @@
 # Make sure my_res_package is created when you run mm/mmm.
 $(built_module) : $(my_res_package)
 endif  # $(my_src_aar)
-endif  # LOCAL_USE_AAPT2
+
 # make sure the classes.jar and javalib.jar are built before $(LOCAL_BUILT_MODULE)
 $(built_module) : $(common_javalib_jar)
 
diff --git a/core/package_internal.mk b/core/package_internal.mk
index e27f6ce..493a0f1 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -171,12 +171,7 @@
 need_compile_asset := true
 endif
 
-ifdef LOCAL_AAPT2_ONLY
-LOCAL_USE_AAPT2 := true
-endif
-
 my_res_package :=
-ifeq ($(LOCAL_USE_AAPT2),true)
 # In aapt2 the last takes precedence.
 my_resource_dirs := $(call reverse-list,$(LOCAL_RESOURCE_DIR))
 my_res_dir :=
@@ -210,30 +205,12 @@
 my_res_package := $(intermediates)/package-res.apk
 LOCAL_INTERMEDIATE_TARGETS += $(my_res_package)
 
-ifeq ($(LOCAL_USE_AAPT2),true)
-  my_bundle_module := $(intermediates)/base.zip
-  LOCAL_INTERMEDIATE_TARGETS += $(my_bundle_module)
-endif
+my_bundle_module := $(intermediates)/base.zip
+LOCAL_INTERMEDIATE_TARGETS += $(my_bundle_module)
 
 # Always run aapt2, because we need to at least compile the AndroidManifest.xml.
 need_compile_res := true
 
-else  # LOCAL_USE_AAPT2
-all_resources := $(strip \
-    $(foreach dir, $(LOCAL_RESOURCE_DIR), \
-      $(addprefix $(dir)/, \
-        $(patsubst res/%,%, \
-          $(call find-subdir-assets,$(dir)) \
-         ) \
-       ) \
-     ))
-
-ifdef LOCAL_PACKAGE_SPLITS
-LOCAL_AAPT_FLAGS += $(addprefix --split ,$(LOCAL_PACKAGE_SPLITS))
-endif
-
-endif  # LOCAL_USE_AAPT2
-
 ifneq ($(all_resources),)
   need_compile_res := true
 endif
@@ -369,71 +346,24 @@
 $(R_file_stamp) $(my_res_package): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_MANIFEST_INSTRUMENTATION_FOR)
 
 ###############################
-## AAPT/AAPT2
+## AAPT2
 
-ifeq ($(LOCAL_USE_AAPT2),true)
-  my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res
-  ifneq (,$(filter-out current,$(renderscript_target_api)))
-    ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
-      my_generated_res_zips := $(rs_generated_res_zip)
-    endif  # renderscript_target_api < 21
-  endif  # renderscript_target_api is set
-  my_asset_dirs := $(LOCAL_ASSET_DIR)
-  my_full_asset_paths := $(all_assets)
+my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res
+ifneq (,$(filter-out current,$(renderscript_target_api)))
+  ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
+    my_generated_res_zips := $(rs_generated_res_zip)
+  endif  # renderscript_target_api < 21
+endif  # renderscript_target_api is set
+my_asset_dirs := $(LOCAL_ASSET_DIR)
+my_full_asset_paths := $(all_assets)
 
-  # Add AAPT2 link specific flags.
-  $(my_res_package): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS)
-  ifndef LOCAL_AAPT_NAMESPACES
-    $(my_res_package): PRIVATE_AAPT_FLAGS += --no-static-lib-packages
-  endif
+# Add AAPT2 link specific flags.
+$(my_res_package): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS)
+ifndef LOCAL_AAPT_NAMESPACES
+  $(my_res_package): PRIVATE_AAPT_FLAGS += --no-static-lib-packages
+endif
 
-  include $(BUILD_SYSTEM)/aapt2.mk
-else  # LOCAL_USE_AAPT2
-
-  my_srcjar := $(intermediates.COMMON)/aapt.srcjar
-  LOCAL_SRCJARS += $(my_srcjar)
-  $(R_file_stamp): PRIVATE_SRCJAR := $(my_srcjar)
-  $(R_file_stamp): PRIVATE_JAVA_GEN_DIR := $(intermediates.COMMON)/aapt
-  $(R_file_stamp): .KATI_IMPLICIT_OUTPUTS := $(my_srcjar)
-  # Since we don't know where the real R.java file is going to end up,
-  # we need to use another file to stand in its place.  We'll just
-  # copy the generated file to src/R.stamp, which means it will
-  # have the same contents and timestamp as the actual file.
-  #
-  # At the same time, this will copy the R.java file to a central
-  # 'R' directory to make it easier to add the files to an IDE.
-  #
-
-  $(R_file_stamp): PRIVATE_RESOURCE_PUBLICS_OUTPUT := \
-			$(intermediates.COMMON)/public_resources.xml
-  $(R_file_stamp): PRIVATE_PROGUARD_OPTIONS_FILE := $(proguard_options_file)
-  $(R_file_stamp): PRIVATE_RESOURCE_LIST := $(all_res_assets)
-  $(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(rs_generated_res_zip) $(AAPT) $(SOONG_ZIP) | $(ACP)
-	@echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
-	@rm -rf $@ && mkdir -p $(dir $@)
-	$(create-resource-java-files)
-	$(call find-generated-R.java,$(PRIVATE_JAVA_GEN_DIR),$@)
-
-  $(proguard_options_file): $(R_file_stamp)
-
-  ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
-    # Put this module's resources into a PRODUCT-agnositc package that
-    # other packages can use to build their own PRODUCT-agnostic R.java (etc.)
-    # files.
-    resource_export_package := $(intermediates.COMMON)/package-export.apk
-    $(R_file_stamp): $(resource_export_package)
-
-    # create-assets-package looks at PRODUCT_AAPT_CONFIG, but this target
-    # can't know anything about PRODUCT.  Clear it out just for this target.
-    $(resource_export_package): PRIVATE_PRODUCT_AAPT_CONFIG :=
-    $(resource_export_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
-    $(resource_export_package): PRIVATE_RESOURCE_LIST := $(all_res_assets)
-    $(resource_export_package): $(all_res_assets) $(full_android_manifest) $(rs_generated_res_zip) $(AAPT)
-	@echo "target Export Resources: $(PRIVATE_MODULE) ($@)"
-	$(call create-assets-package,$@)
-  endif
-
-endif  # LOCAL_USE_AAPT2
+include $(BUILD_SYSTEM)/aapt2.mk
 
 endif  # need_compile_res
 
@@ -496,9 +426,7 @@
 $(LOCAL_INTERMEDIATE_TARGETS): \
     PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports)
 
-ifeq ($(LOCAL_USE_AAPT2),true)
 $(my_res_package) : $(all_library_res_package_export_deps)
-endif
 
 # These four are set above for $(R_stamp_file) and $(my_res_package), but
 # $(LOCAL_BUILT_MODULE) is not set before java.mk, so they have to be set again
@@ -595,13 +523,8 @@
 $(LOCAL_BUILT_MODULE): PRIVATE_RESOURCE_INTERMEDIATES_DIR := $(intermediates.COMMON)/resources
 $(LOCAL_BUILT_MODULE) : $(jni_shared_libraries)
 $(LOCAL_BUILT_MODULE) : $(JAR_ARGS) $(SOONG_ZIP) $(MERGE_ZIPS) $(ZIP2ZIP)
-ifeq ($(LOCAL_USE_AAPT2),true)
 $(LOCAL_BUILT_MODULE): PRIVATE_RES_PACKAGE := $(my_res_package)
 $(LOCAL_BUILT_MODULE) : $(my_res_package) $(AAPT2) | $(ACP)
-else
-$(LOCAL_BUILT_MODULE): PRIVATE_RESOURCE_LIST := $(all_res_assets)
-$(LOCAL_BUILT_MODULE) : $(all_res_assets) $(full_android_manifest) $(AAPT) $(ZIPALIGN)
-endif  # LOCAL_USE_AAPT2
 ifdef LOCAL_COMPRESSED_MODULE
 $(LOCAL_BUILT_MODULE) : $(MINIGZIP)
 endif
@@ -622,11 +545,7 @@
 	@echo "target Package: $(PRIVATE_MODULE) ($@)"
 	rm -rf $@.parts
 	mkdir -p $@.parts
-ifeq ($(LOCAL_USE_AAPT2),true)
 	cp -f $(PRIVATE_RES_PACKAGE) $@.parts/apk.zip
-else  # ! LOCAL_USE_AAPT2
-	$(call create-assets-package,$@.parts/apk.zip)
-endif  # LOCAL_USE_AAPT2
 ifneq ($(jni_shared_libraries),)
 	$(call create-jni-shared-libs-package,$@.parts/jni.zip,$(PRIVATE_USE_EMBEDDED_NATIVE_LIBS))
 endif
@@ -645,11 +564,7 @@
 endif
 # Run appcompat before stripping the classes.dex file.
 ifeq ($(module_run_appcompat),true)
-ifeq ($(LOCAL_USE_AAPT2),true)
-	$(call appcompat-header, aapt2)
-else
 	$(appcompat-header)
-endif
 	$(run-appcompat)
 endif  # module_run_appcompat
 ifdef LOCAL_DEX_PREOPT
@@ -665,63 +580,57 @@
 	$(compress-package)
 endif  # LOCAL_COMPRESSED_MODULE
 
-ifeq ($(LOCAL_USE_AAPT2),true)
-  my_package_res_pb := $(intermediates)/package-res.pb.apk
-  $(my_package_res_pb): $(my_res_package) $(AAPT2)
+my_package_res_pb := $(intermediates)/package-res.pb.apk
+$(my_package_res_pb): $(my_res_package) $(AAPT2)
 	$(AAPT2) convert --output-format proto $< -o $@
 
-  $(my_bundle_module): $(my_package_res_pb)
-  $(my_bundle_module): PRIVATE_RES_PACKAGE := $(my_package_res_pb)
+$(my_bundle_module): $(my_package_res_pb)
+$(my_bundle_module): PRIVATE_RES_PACKAGE := $(my_package_res_pb)
 
-  $(my_bundle_module): $(jni_shared_libraries)
-  $(my_bundle_module): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)
-  $(my_bundle_module): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abis)
+$(my_bundle_module): $(jni_shared_libraries)
+$(my_bundle_module): PRIVATE_JNI_SHARED_LIBRARIES := $(jni_shared_libraries_with_abis)
+$(my_bundle_module): PRIVATE_JNI_SHARED_LIBRARIES_ABI := $(jni_shared_libraries_abis)
 
-  ifneq ($(full_classes_jar),)
-    $(my_bundle_module): PRIVATE_DEX_FILE := $(built_dex)
-    # Use the jarjar processed archive as the initial package file.
-    $(my_bundle_module): PRIVATE_SOURCE_ARCHIVE := $(full_classes_pre_proguard_jar)
-    $(my_bundle_module): $(built_dex)
-  else
-    $(my_bundle_module): PRIVATE_DEX_FILE :=
-    $(my_bundle_module): PRIVATE_SOURCE_ARCHIVE :=
-  endif # full_classes_jar
+ifneq ($(full_classes_jar),)
+  $(my_bundle_module): PRIVATE_DEX_FILE := $(built_dex)
+  # Use the jarjar processed archive as the initial package file.
+  $(my_bundle_module): PRIVATE_SOURCE_ARCHIVE := $(full_classes_pre_proguard_jar)
+  $(my_bundle_module): $(built_dex)
+else
+  $(my_bundle_module): PRIVATE_DEX_FILE :=
+  $(my_bundle_module): PRIVATE_SOURCE_ARCHIVE :=
+endif # full_classes_jar
 
-  $(my_bundle_module): $(MERGE_ZIPS) $(SOONG_ZIP) $(ZIP2ZIP)
+$(my_bundle_module): $(MERGE_ZIPS) $(SOONG_ZIP) $(ZIP2ZIP)
 	@echo "target Bundle: $(PRIVATE_MODULE) ($@)"
 	rm -rf $@.parts
 	mkdir -p $@.parts
 	$(ZIP2ZIP) -i $(PRIVATE_RES_PACKAGE) -o $@.parts/apk.zip AndroidManifest.xml:manifest/AndroidManifest.xml resources.pb "res/**/*" "assets/**/*"
-        ifneq ($(jni_shared_libraries),)
+      ifneq ($(jni_shared_libraries),)
 	  $(call create-jni-shared-libs-package,$@.parts/jni.zip)
-        endif
-        ifeq ($(full_classes_jar),)
-        # We don't build jar, need to add the Java resources here.
+      endif
+      ifeq ($(full_classes_jar),)
+      # We don't build jar, need to add the Java resources here.
 	  $(if $(PRIVATE_EXTRA_JAR_ARGS),\
 	    $(call create-java-resources-jar,$@.parts/res.zip) && \
 	    $(ZIP2ZIP) -i $@.parts/res.zip -o $@.parts/res.zip.tmp "**/*:root/" && \
 	    mv -f $@.parts/res.zip.tmp $@.parts/res.zip)
-        else  # full_classes_jar
+      else  # full_classes_jar
 	  $(call create-dex-jar,$@.parts/dex.zip,$(PRIVATE_DEX_FILE))
 	  $(ZIP2ZIP) -i $@.parts/dex.zip -o $@.parts/dex.zip.tmp "classes*.dex:dex/"
 	  mv -f $@.parts/dex.zip.tmp $@.parts/dex.zip
 	  $(call extract-resources-jar,$@.parts/res.zip,$(PRIVATE_SOURCE_ARCHIVE))
 	  $(ZIP2ZIP) -i $@.parts/res.zip -o $@.parts/res.zip.tmp "**/*:root/"
 	  mv -f $@.parts/res.zip.tmp $@.parts/res.zip
-        endif  # full_classes_jar
+      endif  # full_classes_jar
 	$(MERGE_ZIPS) $@ $@.parts/*.zip
 	rm -rf $@.parts
-  ALL_MODULES.$(LOCAL_MODULE).BUNDLE := $(my_bundle_module)
-endif
+ALL_MODULES.$(LOCAL_MODULE).BUNDLE := $(my_bundle_module)
 
-###############################
-## Build dpi-specific apks, if it's apps_only build.
 ifdef TARGET_BUILD_APPS
-ifdef LOCAL_DPI_VARIANTS
-$(foreach d, $(LOCAL_DPI_VARIANTS), \
-  $(eval my_dpi := $(d)) \
-  $(eval include $(BUILD_SYSTEM)/dpi_specific_apk.mk))
-endif
+  ifdef LOCAL_DPI_VARIANTS
+    $(call pretty-error,Building DPI-specific APKs is no longer supported)
+  endif
 endif
 
 ###############################
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index 8d92b20..8153d78 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -60,7 +60,7 @@
   $(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE)
 	@echo "Copy: $@"
 	$(copy-file-to-target)
-	$(call appcompat-header, aapt2)
+	$(appcompat-header)
 	$(run-appcompat)
 else
   $(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_BUILT_MODULE)))
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index ee759b9..cb3281a 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -33,10 +33,6 @@
 
 include $(BUILD_SYSTEM)/force_aapt2.mk
 
-ifdef LOCAL_AAPT2_ONLY
-LOCAL_USE_AAPT2 := true
-endif
-
 # Hack to build static Java library with Android resource
 # See bug 5714516
 all_resources :=
@@ -46,11 +42,9 @@
 need_compile_res := true
 LOCAL_RESOURCE_DIR := $(foreach d,$(LOCAL_RESOURCE_DIR),$(call clean-path,$(d)))
 endif
-ifeq ($(LOCAL_USE_AAPT2),true)
 ifneq ($(strip $(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),)
 need_compile_res := true
 endif
-endif
 
 ifeq ($(need_compile_res),true)
 all_resources := $(strip \
@@ -84,22 +78,20 @@
 R_file_stamp := $(intermediates.COMMON)/src/R.stamp
 LOCAL_INTERMEDIATE_TARGETS += $(R_file_stamp)
 
-ifeq ($(LOCAL_USE_AAPT2),true)
-  ifneq ($(strip $(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),)
-    # If we are using static android libraries, every source file becomes an overlay.
-    # This is to emulate old AAPT behavior which simulated library support.
-    my_res_resources :=
-    my_overlay_resources := $(all_resources)
-  else
-    # Otherwise, for a library we treat all the resource equal with no overlay.
-    my_res_resources := $(all_resources)
-    my_overlay_resources :=
-  endif
-  # For libraries put everything in the COMMON intermediate directory.
-  my_res_package := $(intermediates.COMMON)/package-res.apk
+ifneq ($(strip $(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),)
+  # If we are using static android libraries, every source file becomes an overlay.
+  # This is to emulate old AAPT behavior which simulated library support.
+  my_res_resources :=
+  my_overlay_resources := $(all_resources)
+else
+  # Otherwise, for a library we treat all the resource equal with no overlay.
+  my_res_resources := $(all_resources)
+  my_overlay_resources :=
+endif
+# For libraries put everything in the COMMON intermediate directory.
+my_res_package := $(intermediates.COMMON)/package-res.apk
 
-  LOCAL_INTERMEDIATE_TARGETS += $(my_res_package)
-endif  # LOCAL_USE_AAPT2
+LOCAL_INTERMEDIATE_TARGETS += $(my_res_package)
 
 endif  # need_compile_res
 
@@ -127,7 +119,6 @@
 endif
 endif
 
-ifeq ($(LOCAL_USE_AAPT2),true)
 import_proguard_flag_files := $(strip $(foreach l,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
     $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/export_proguard_flags))
 $(intermediates.COMMON)/export_proguard_flags: $(import_proguard_flag_files) $(addprefix $(LOCAL_PATH)/,$(LOCAL_EXPORT_PROGUARD_FLAG_FILES))
@@ -139,7 +130,6 @@
 		cat $$f >>$@; \
 	done
 import_proguard_flag_files :=
-endif
 
 include $(BUILD_SYSTEM)/aapt_flags.mk
 
@@ -150,7 +140,6 @@
 
 # add --non-constant-id to prevent inlining constants.
 # AAR needs text symbol file R.txt.
-ifeq ($(LOCAL_USE_AAPT2),true)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --static-lib --output-text-symbols $(intermediates.COMMON)/R.txt
 ifndef LOCAL_AAPT_NAMESPACES
   $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS += --no-static-lib-packages
@@ -158,15 +147,6 @@
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_PRODUCT_AAPT_CONFIG :=
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_AAPT_CHARACTERISTICS :=
-else
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --non-constant-id --output-text-symbols $(intermediates.COMMON)
-
-my_srcjar := $(intermediates.COMMON)/aapt.srcjar
-LOCAL_SRCJARS += $(my_srcjar)
-$(R_file_stamp): PRIVATE_SRCJAR := $(my_srcjar)
-$(R_file_stamp): PRIVATE_JAVA_GEN_DIR := $(intermediates.COMMON)/aapt
-$(R_file_stamp): .KATI_IMPLICIT_OUTPUTS := $(my_srcjar)
-endif
 
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ANDROID_MANIFEST := $(full_android_manifest)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_PUBLICS_OUTPUT := $(intermediates.COMMON)/public_resources.xml
@@ -178,26 +158,16 @@
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_PACKAGE_NAME :=
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_INSTRUMENTATION_FOR :=
 
-ifeq ($(LOCAL_USE_AAPT2),true)
-  # One more level with name res so we can zip up the flat resources that can be linked by apps.
-  my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res/res
-  ifneq (,$(filter-out current,$(renderscript_target_api)))
-    ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
-      my_generated_res_zips := $(rs_generated_res_zip)
-    endif  # renderscript_target_api < 21
-  endif  # renderscript_target_api is set
-  include $(BUILD_SYSTEM)/aapt2.mk
-  $(my_res_package) : $(framework_res_package_export)
-  $(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(intermediates.COMMON)/R.txt
-else
-  $(R_file_stamp): .KATI_IMPLICIT_OUTPUTS += $(intermediates.COMMON)/R.txt
-  $(R_file_stamp): PRIVATE_RESOURCE_LIST := $(all_resources)
-  $(R_file_stamp) : $(all_resources) $(full_android_manifest) $(AAPT) $(SOONG_ZIP) \
-    $(framework_res_package_export) $(rs_generated_res_zip)
-	@echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
-	$(create-resource-java-files)
-	$(hide) find $(PRIVATE_JAVA_GEN_DIR) -name R.java | xargs cat > $@
-endif  # LOCAL_USE_AAPT2
+# One more level with name res so we can zip up the flat resources that can be linked by apps.
+my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res/res
+ifneq (,$(filter-out current,$(renderscript_target_api)))
+  ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
+    my_generated_res_zips := $(rs_generated_res_zip)
+  endif  # renderscript_target_api < 21
+endif  # renderscript_target_api is set
+include $(BUILD_SYSTEM)/aapt2.mk
+$(my_res_package) : $(framework_res_package_export)
+$(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(intermediates.COMMON)/R.txt
 
 endif # need_compile_res
 
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index d75809c..66207df 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -18,6 +18,8 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
+# Enable updating of APEXes
+$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
 # Add adb keys to debuggable AOSP builds (if they exist)
 $(call inherit-product-if-exists, vendor/google/security/adb/vendor_key.mk)
 
diff --git a/target/product/updatable_apex.mk b/target/product/updatable_apex.mk
new file mode 100644
index 0000000..4b31578
--- /dev/null
+++ b/target/product/updatable_apex.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2019 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.
+#
+
+# Inherit this when the target needs to support updating APEXes
+
+PRODUCT_PROPERTY_OVERRIDES := ro.apex.updatable=true
+PRODUCT_PACKAGES := com.android.apex.cts.shim.v1_prebuilt
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 3b72551..e306807 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -13,11 +13,11 @@
 # 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 script merges two partial target files packages.
 
-"""
-This script merges two partial target files packages (one of which contains
-system files, and the other contains non-system files) together, producing a
-complete target files package that can be used to generate an OTA package.
+One package contains system files, and the other contains non-system files.
+It produces a complete target files package that can be used to generate an
+OTA package.
 
 Usage: merge_target_files.py [args]
 
@@ -42,7 +42,25 @@
       contents of default_other_item_list if provided.
 
   --output-target-files output-target-files-package
-      The output merged target files package. Also a zip archive.
+      If provided, the output merged target files package. Also a zip archive.
+
+  --output-dir output-directory
+      If provided, the destination directory for saving merged files. Requires
+      the --output-item-list flag.
+      Can be provided alongside --output-target-files, or by itself.
+
+  --output-item-list output-item-list-file.
+      The optional path to a newline-separated config file that specifies the
+      file patterns to copy into the --output-dir. Required if providing
+      the --output-dir flag.
+
+  --output-ota output-ota-package
+      The output ota package. This is a zip archive. Use of this flag may
+      require passing the --path common flag; see common.py.
+
+  --output-super-empty output-super-empty-image
+      If provided, creates a super_empty.img file from the merged target
+      files package and saves it at this path.
 
   --rebuild_recovery
       Rebuild the recovery patch used by non-A/B devices and write it to the
@@ -57,11 +75,14 @@
 import fnmatch
 import logging
 import os
+import shutil
 import sys
 import zipfile
 
-import common
 import add_img_to_target_files
+import build_super_image
+import common
+import ota_from_target_files
 
 logger = logging.getLogger(__name__)
 OPTIONS = common.OPTIONS
@@ -72,6 +93,10 @@
 OPTIONS.other_target_files = None
 OPTIONS.other_item_list = None
 OPTIONS.output_target_files = None
+OPTIONS.output_dir = None
+OPTIONS.output_item_list = None
+OPTIONS.output_ota = None
+OPTIONS.output_super_empty = None
 OPTIONS.rebuild_recovery = False
 OPTIONS.keep_tmp = False
 
@@ -101,8 +126,8 @@
     'META/*',
 ]
 
-# default_system_misc_info_keys is a list of keys to obtain from the system instance of
-# META/misc_info.txt. The remaining keys from the other instance.
+# default_system_misc_info_keys is a list of keys to obtain from the system
+# instance of META/misc_info.txt. The remaining keys from the other instance.
 
 default_system_misc_info_keys = [
     'avb_system_hashtree_enable',
@@ -160,10 +185,8 @@
 
   Args:
     target_files: The target files zip archive from which to extract items.
-
     target_files_temp_dir: The temporary directory where the extracted items
-    will land.
-
+      will land.
     extract_item_list: A list of items to extract.
   """
 
@@ -173,9 +196,7 @@
   # zip file. Otherwise, the extraction step will fail.
 
   with zipfile.ZipFile(
-      target_files,
-      'r',
-      allowZip64=True) as target_files_zipfile:
+      target_files, 'r', allowZip64=True) as target_files_zipfile:
     target_files_namelist = target_files_zipfile.namelist()
 
   filtered_extract_item_list = []
@@ -189,10 +210,32 @@
   # Extract from target_files into target_files_temp_dir the
   # filtered_extract_item_list.
 
-  common.UnzipToDir(
-      target_files,
-      target_files_temp_dir,
-      filtered_extract_item_list)
+  common.UnzipToDir(target_files, target_files_temp_dir,
+                    filtered_extract_item_list)
+
+
+def copy_items(from_dir, to_dir, patterns):
+  """Similar to extract_items() except uses an input dir instead of zip."""
+  file_paths = []
+  for dirpath, _, filenames in os.walk(from_dir):
+    file_paths.extend(
+        os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
+        for filename in filenames)
+
+  filtered_file_paths = set()
+  for pattern in patterns:
+    filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
+
+  for file_path in filtered_file_paths:
+    original_file_path = os.path.join(from_dir, file_path)
+    copied_file_path = os.path.join(to_dir, file_path)
+    copied_file_dir = os.path.dirname(copied_file_path)
+    if not os.path.exists(copied_file_dir):
+      os.makedirs(copied_file_dir)
+    if os.path.islink(original_file_path):
+      os.symlink(os.readlink(original_file_path), copied_file_path)
+    else:
+      shutil.copyfile(original_file_path, copied_file_path)
 
 
 def read_config_list(config_file_path):
@@ -202,26 +245,25 @@
 
   Args:
     config_file_path: The path to the config file to open and read.
+
+  Returns:
+    The list of strings in the config file.
   """
   with open(config_file_path) as config_file:
     return config_file.read().splitlines()
 
 
-def validate_config_lists(
-    system_item_list,
-    system_misc_info_keys,
-    other_item_list):
+def validate_config_lists(system_item_list, system_misc_info_keys,
+                          other_item_list):
   """Performs validations on the merge config lists.
 
   Args:
-    system_item_list: The list of items to extract from the partial
-    system target files package as is.
-
-    system_misc_info_keys: A list of keys to obtain from the system instance
-    of META/misc_info.txt. The remaining keys from the other instance.
-
-    other_item_list: The list of items to extract from the partial
-    other target files package as is.
+    system_item_list: The list of items to extract from the partial system
+      target files package as is.
+    system_misc_info_keys: A list of keys to obtain from the system instance of
+      META/misc_info.txt. The remaining keys from the other instance.
+    other_item_list: The list of items to extract from the partial other target
+      files package as is.
 
   Returns:
     False if a validation fails, otherwise true.
@@ -236,7 +278,7 @@
   # by the default config lists.
   difference = default_combined_item_set.difference(combined_item_set)
   if difference:
-    logger.error('Missing merge config items: %s' % list(difference))
+    logger.error('Missing merge config items: %s', list(difference))
     logger.error('Please ensure missing items are in either the '
                  'system-item-list or other-item-list files provided to '
                  'this script.')
@@ -251,11 +293,10 @@
   return True
 
 
-def process_ab_partitions_txt(
-    system_target_files_temp_dir,
-    other_target_files_temp_dir,
-    output_target_files_temp_dir):
-  """Perform special processing for META/ab_partitions.txt
+def process_ab_partitions_txt(system_target_files_temp_dir,
+                              other_target_files_temp_dir,
+                              output_target_files_temp_dir):
+  """Perform special processing for META/ab_partitions.txt.
 
   This function merges the contents of the META/ab_partitions.txt files from
   the system directory and the other directory, placing the merged result in
@@ -266,22 +307,20 @@
   names.
 
   Args:
-    system_target_files_temp_dir: The name of a directory containing the
-    special items extracted from the system target files package.
-
-    other_target_files_temp_dir: The name of a directory containing the
-    special items extracted from the other target files package.
-
-    output_target_files_temp_dir: The name of a directory that will be used
-    to create the output target files package after all the special cases
-    are processed.
+    system_target_files_temp_dir: The name of a directory containing the special
+      items extracted from the system target files package.
+    other_target_files_temp_dir: The name of a directory containing the special
+      items extracted from the other target files package.
+    output_target_files_temp_dir: The name of a directory that will be used to
+      create the output target files package after all the special cases are
+      processed.
   """
 
-  system_ab_partitions_txt = os.path.join(
-      system_target_files_temp_dir, 'META', 'ab_partitions.txt')
+  system_ab_partitions_txt = os.path.join(system_target_files_temp_dir, 'META',
+                                          'ab_partitions.txt')
 
-  other_ab_partitions_txt = os.path.join(
-      other_target_files_temp_dir, 'META', 'ab_partitions.txt')
+  other_ab_partitions_txt = os.path.join(other_target_files_temp_dir, 'META',
+                                         'ab_partitions.txt')
 
   with open(system_ab_partitions_txt) as f:
     system_ab_partitions = f.read().splitlines()
@@ -291,8 +330,8 @@
 
   output_ab_partitions = set(system_ab_partitions + other_ab_partitions)
 
-  output_ab_partitions_txt = os.path.join(
-      output_target_files_temp_dir, 'META', 'ab_partitions.txt')
+  output_ab_partitions_txt = os.path.join(output_target_files_temp_dir, 'META',
+                                          'ab_partitions.txt')
 
   with open(output_ab_partitions_txt, 'w') as output:
     for partition in sorted(output_ab_partitions):
@@ -300,42 +339,35 @@
 
 
 def append_recovery_to_filesystem_config(output_target_files_temp_dir):
-  """Perform special processing for META/filesystem_config.txt
+  """Perform special processing for META/filesystem_config.txt.
 
   This function appends recovery information to META/filesystem_config.txt
   so that recovery patch regeneration will succeed.
 
   Args:
-    output_target_files_temp_dir: The name of a directory that will be used
-    to create the output target files package after all the special cases
-    are processed. We find filesystem_config.txt here.
+    output_target_files_temp_dir: The name of a directory that will be used to
+      create the output target files package after all the special cases are
+      processed. We find filesystem_config.txt here.
   """
 
-  filesystem_config_txt = os.path.join(
-      output_target_files_temp_dir,
-      'META',
-      'filesystem_config.txt')
+  filesystem_config_txt = os.path.join(output_target_files_temp_dir, 'META',
+                                       'filesystem_config.txt')
 
   with open(filesystem_config_txt, 'a') as f:
     # TODO(bpeckham) this data is hard coded. It should be generated
     # programmatically.
-    f.write(
-        'system/bin/install-recovery.sh 0 0 750 '
-        'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
-    f.write(
-        'system/recovery-from-boot.p 0 0 644 '
-        'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
-    f.write(
-        'system/etc/recovery.img 0 0 440 '
-        'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
+    f.write('system/bin/install-recovery.sh 0 0 750 '
+            'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
+    f.write('system/recovery-from-boot.p 0 0 644 '
+            'selabel=u:object_r:system_file:s0 capabilities=0x0\n')
+    f.write('system/etc/recovery.img 0 0 440 '
+            'selabel=u:object_r:install_recovery_exec:s0 capabilities=0x0\n')
 
 
-def process_misc_info_txt(
-    system_target_files_temp_dir,
-    other_target_files_temp_dir,
-    output_target_files_temp_dir,
-    system_misc_info_keys):
-  """Perform special processing for META/misc_info.txt
+def process_misc_info_txt(system_target_files_temp_dir,
+                          other_target_files_temp_dir,
+                          output_target_files_temp_dir, system_misc_info_keys):
+  """Perform special processing for META/misc_info.txt.
 
   This function merges the contents of the META/misc_info.txt files from the
   system directory and the other directory, placing the merged result in the
@@ -344,18 +376,15 @@
   content.
 
   Args:
-    system_target_files_temp_dir: The name of a directory containing the
-    special items extracted from the system target files package.
-
-    other_target_files_temp_dir: The name of a directory containing the
-    special items extracted from the other target files package.
-
-    output_target_files_temp_dir: The name of a directory that will be used
-    to create the output target files package after all the special cases
-    are processed.
-
-    system_misc_info_keys: A list of keys to obtain from the system instance
-    of META/misc_info.txt. The remaining keys from the other instance.
+    system_target_files_temp_dir: The name of a directory containing the special
+      items extracted from the system target files package.
+    other_target_files_temp_dir: The name of a directory containing the special
+      items extracted from the other target files package.
+    output_target_files_temp_dir: The name of a directory that will be used to
+      create the output target files package after all the special cases are
+      processed.
+    system_misc_info_keys: A list of keys to obtain from the system instance of
+      META/misc_info.txt. The remaining keys from the other instance.
   """
 
   def read_helper(d):
@@ -386,19 +415,18 @@
     # Partition groups and group sizes are defined by the other (non-system)
     # misc info file because these values may vary for each board that uses
     # a shared system image.
-    for partition_group in merged_info_dict['super_partition_groups'].split(' '):
+    for partition_group in merged_info_dict['super_partition_groups'].split(
+        ' '):
       if ('super_%s_group_size' % partition_group) not in merged_info_dict:
-        raise common.ExternalError(
+        raise ValueError(
             'Other META/misc_info.txt does not contain required key '
             'super_%s_group_size.' % partition_group)
       key = 'super_%s_partition_list' % partition_group
-      merged_info_dict[key] = '%s %s' % (
-        system_info_dict.get(key, ''),
-        merged_info_dict.get(key, ''))
+      merged_info_dict[key] = '%s %s' % (system_info_dict.get(
+          key, ''), merged_info_dict.get(key, ''))
 
-  output_misc_info_txt = os.path.join(
-      output_target_files_temp_dir,
-      'META', 'misc_info.txt')
+  output_misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
+                                      'misc_info.txt')
 
   sorted_keys = sorted(merged_info_dict.keys())
 
@@ -416,12 +444,11 @@
 
   Args:
     temp_dir: The name of a scratch directory that this function can use for
-    intermediate files generated during processing.
-
+      intermediate files generated during processing.
     output_target_files_temp_dir: The name of the working directory that must
-    already contain plat_file_contexts and vendor_file_contexts (in the
-    appropriate sub directories), and to which META/file_contexts.bin will be
-    written.
+      already contain plat_file_contexts and vendor_file_contexts (in the
+      appropriate sub directories), and to which META/file_contexts.bin will be
+      written.
   """
 
   # To create a merged file_contexts.bin file, we use the system and vendor
@@ -442,9 +469,8 @@
   for partition in ['SYSTEM', 'VENDOR', 'PRODUCT', 'ODM']:
     prefix = 'plat' if partition == 'SYSTEM' else partition.lower()
 
-    file_contexts = os.path.join(
-        output_target_files_temp_dir,
-        partition, 'etc', 'selinux', prefix + '_file_contexts')
+    file_contexts = os.path.join(output_target_files_temp_dir, partition, 'etc',
+                                 'selinux', prefix + '_file_contexts')
 
     mandatory = partition in ['SYSTEM', 'VENDOR']
 
@@ -470,27 +496,23 @@
 
   # Finally, the compile step creates the final META/file_contexts.bin.
 
-  file_contexts_bin = os.path.join(
-      output_target_files_temp_dir,
-      'META', 'file_contexts.bin')
+  file_contexts_bin = os.path.join(output_target_files_temp_dir, 'META',
+                                   'file_contexts.bin')
 
   command = [
       'sefcontext_compile',
-      '-o', file_contexts_bin,
+      '-o',
+      file_contexts_bin,
       sorted_file_contexts_txt,
   ]
 
   common.RunAndWait(command, verbose=True)
 
 
-def process_special_cases(
-    temp_dir,
-    system_target_files_temp_dir,
-    other_target_files_temp_dir,
-    output_target_files_temp_dir,
-    system_misc_info_keys,
-    rebuild_recovery
-):
+def process_special_cases(temp_dir, system_target_files_temp_dir,
+                          other_target_files_temp_dir,
+                          output_target_files_temp_dir, system_misc_info_keys,
+                          rebuild_recovery):
   """Perform special-case processing for certain target files items.
 
   Certain files in the output target files package require special-case
@@ -498,23 +520,18 @@
 
   Args:
     temp_dir: The name of a scratch directory that this function can use for
-    intermediate files generated during processing.
-
-    system_target_files_temp_dir: The name of a directory containing the
-    special items extracted from the system target files package.
-
-    other_target_files_temp_dir: The name of a directory containing the
-    special items extracted from the other target files package.
-
-    output_target_files_temp_dir: The name of a directory that will be used
-    to create the output target files package after all the special cases
-    are processed.
-
-    system_misc_info_keys: A list of keys to obtain from the system instance
-    of META/misc_info.txt. The remaining keys from the other instance.
-
+      intermediate files generated during processing.
+    system_target_files_temp_dir: The name of a directory containing the special
+      items extracted from the system target files package.
+    other_target_files_temp_dir: The name of a directory containing the special
+      items extracted from the other target files package.
+    output_target_files_temp_dir: The name of a directory that will be used to
+      create the output target files package after all the special cases are
+      processed.
+    system_misc_info_keys: A list of keys to obtain from the system instance of
+      META/misc_info.txt. The remaining keys from the other instance.
     rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
-    devices and write it to the system image.
+      devices and write it to the system image.
   """
 
   if 'ab_update' in system_misc_info_keys:
@@ -538,15 +555,11 @@
       output_target_files_temp_dir=output_target_files_temp_dir)
 
 
-def merge_target_files(
-    temp_dir,
-    system_target_files,
-    system_item_list,
-    system_misc_info_keys,
-    other_target_files,
-    other_item_list,
-    output_target_files,
-    rebuild_recovery):
+def merge_target_files(temp_dir, system_target_files, system_item_list,
+                       system_misc_info_keys, other_target_files,
+                       other_item_list, output_target_files, output_dir,
+                       output_item_list, output_ota, output_super_empty,
+                       rebuild_recovery):
   """Merge two target files packages together.
 
   This function takes system and other target files packages as input, performs
@@ -555,40 +568,35 @@
 
   Args:
     temp_dir: The name of a directory we use when we extract items from the
-    input target files packages, and also a scratch directory that we use for
-    temporary files.
-
+      input target files packages, and also a scratch directory that we use for
+      temporary files.
     system_target_files: The name of the zip archive containing the system
-    partial target files package.
-
+      partial target files package.
     system_item_list: The list of items to extract from the partial system
-    target files package as is, meaning these items will land in the output
-    target files package exactly as they appear in the input partial system
-    target files package.
-
+      target files package as is, meaning these items will land in the output
+      target files package exactly as they appear in the input partial system
+      target files package.
     system_misc_info_keys: The list of keys to obtain from the system instance
-    of META/misc_info.txt. The remaining keys from the other instance.
-
-    other_target_files: The name of the zip archive containing the other
-    partial target files package.
-
-    other_item_list: The list of items to extract from the partial other
-    target files package as is, meaning these items will land in the output
-    target files package exactly as they appear in the input partial other
-    target files package.
-
-    output_target_files: The name of the output zip archive target files
-    package created by merging system and other.
-
+      of META/misc_info.txt. The remaining keys from the other instance.
+    other_target_files: The name of the zip archive containing the other partial
+      target files package.
+    other_item_list: The list of items to extract from the partial other target
+      files package as is, meaning these items will land in the output target
+      files package exactly as they appear in the input partial other target
+      files package.
+    output_target_files: The name of the output zip archive target files package
+      created by merging system and other.
+    output_dir: The destination directory for saving merged files.
+    output_item_list: The list of items to copy into the output_dir.
+    output_ota: The name of the output zip archive ota package.
+    output_super_empty: If provided, creates a super_empty.img file from the
+      merged target files package and saves it at this path.
     rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
-    devices and write it to the system image.
+      devices and write it to the system image.
   """
 
-  logger.info(
-      'starting: merge system %s and other %s into output %s',
-      system_target_files,
-      other_target_files,
-      output_target_files)
+  logger.info('starting: merge system %s and other %s into output %s',
+              system_target_files, other_target_files, output_target_files)
 
   # Create directory names that we'll use when we extract files from system,
   # and other, and for zipping the final output.
@@ -646,6 +654,28 @@
       system_misc_info_keys=system_misc_info_keys,
       rebuild_recovery=rebuild_recovery)
 
+  # Create super_empty.img using the merged misc_info.txt.
+
+  if output_super_empty:
+    misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
+                                 'misc_info.txt')
+
+    def read_helper():
+      with open(misc_info_txt) as f:
+        return list(f.read().splitlines())
+
+    misc_info_dict = common.LoadDictionaryFromLines(read_helper())
+    if misc_info_dict.get('use_dynamic_partitions') != 'true':
+      raise ValueError(
+          'Building super_empty.img requires use_dynamic_partitions=true.')
+
+    build_super_image_args = [
+        '--verbose',
+        misc_info_txt,
+        output_super_empty,
+    ]
+    build_super_image.main(build_super_image_args)
+
   # Regenerate IMAGES in the temporary directory.
 
   add_img_args = ['--verbose']
@@ -655,12 +685,19 @@
 
   add_img_to_target_files.main(add_img_args)
 
-  # Finally, create the output target files zip archive.
+  # Finally, create the output target files zip archive and/or copy the
+  # output items to the output target files directory.
+
+  if output_dir:
+    copy_items(output_target_files_temp_dir, output_dir, output_item_list)
+
+  if not output_target_files:
+    return
 
   output_zip = os.path.abspath(output_target_files)
   output_target_files_list = os.path.join(temp_dir, 'output.list')
-  output_target_files_meta_dir = os.path.join(
-      output_target_files_temp_dir, 'META')
+  output_target_files_meta_dir = os.path.join(output_target_files_temp_dir,
+                                              'META')
 
   command = [
       'find',
@@ -669,13 +706,8 @@
   # TODO(bpeckham): sort this to be more like build.
   meta_content = common.RunAndCheckOutput(command, verbose=False)
   command = [
-      'find',
-      output_target_files_temp_dir,
-      '-path',
-      output_target_files_meta_dir,
-      '-prune',
-      '-o',
-      '-print'
+      'find', output_target_files_temp_dir, '-path',
+      output_target_files_meta_dir, '-prune', '-o', '-print'
   ]
   # TODO(bpeckham): sort this to be more like build.
   other_content = common.RunAndCheckOutput(command, verbose=False)
@@ -687,13 +719,25 @@
   command = [
       'soong_zip',
       '-d',
-      '-o', output_zip,
-      '-C', output_target_files_temp_dir,
-      '-l', output_target_files_list,
+      '-o',
+      output_zip,
+      '-C',
+      output_target_files_temp_dir,
+      '-l',
+      output_target_files_list,
   ]
   logger.info('creating %s', output_target_files)
   common.RunAndWait(command, verbose=True)
 
+  # Create the OTA package from the merged target files package.
+
+  if output_ota:
+    ota_from_target_files_args = [
+        output_zip,
+        output_ota,
+    ]
+    ota_from_target_files.main(ota_from_target_files_args)
+
 
 def call_func_with_temp_dir(func, keep_tmp):
   """Manage the creation and cleanup of the temporary directory.
@@ -702,9 +746,8 @@
   directory. It also cleans up the temporary directory.
 
   Args:
-    func: The function to call. Should accept one parameter, the path to
-    the temporary directory.
-
+    func: The function to call. Should accept one parameter, the path to the
+      temporary directory.
     keep_tmp: Keep the temporary directory after processing is complete.
   """
 
@@ -747,6 +790,14 @@
       OPTIONS.other_item_list = a
     elif o == '--output-target-files':
       OPTIONS.output_target_files = a
+    elif o == '--output-dir':
+      OPTIONS.output_dir = a
+    elif o == '--output-item-list':
+      OPTIONS.output_item_list = a
+    elif o == '--output-ota':
+      OPTIONS.output_ota = a
+    elif o == '--output-super-empty':
+      OPTIONS.output_super_empty = a
     elif o == '--rebuild_recovery':
       OPTIONS.rebuild_recovery = True
     elif o == '--keep-tmp':
@@ -756,7 +807,8 @@
     return True
 
   args = common.ParseOptions(
-      sys.argv[1:], __doc__,
+      sys.argv[1:],
+      __doc__,
       extra_long_opts=[
           'system-target-files=',
           'system-item-list=',
@@ -764,15 +816,19 @@
           'other-target-files=',
           'other-item-list=',
           'output-target-files=',
+          'output-dir=',
+          'output-item-list=',
+          'output-ota=',
+          'output-super-empty=',
           'rebuild_recovery',
           'keep-tmp',
       ],
       extra_option_handler=option_handler)
 
-  if (len(args) != 0 or
-      OPTIONS.system_target_files is None or
+  if (args or OPTIONS.system_target_files is None or
       OPTIONS.other_target_files is None or
-      OPTIONS.output_target_files is None):
+      (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
+      (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None)):
     common.Usage(__doc__)
     sys.exit(1)
 
@@ -791,6 +847,11 @@
   else:
     other_item_list = default_other_item_list
 
+  if OPTIONS.output_item_list:
+    output_item_list = read_config_list(OPTIONS.output_item_list)
+  else:
+    output_item_list = None
+
   if not validate_config_lists(
       system_item_list=system_item_list,
       system_misc_info_keys=system_misc_info_keys,
@@ -806,8 +867,11 @@
           other_target_files=OPTIONS.other_target_files,
           other_item_list=other_item_list,
           output_target_files=OPTIONS.output_target_files,
-          rebuild_recovery=OPTIONS.rebuild_recovery),
-      OPTIONS.keep_tmp)
+          output_dir=OPTIONS.output_dir,
+          output_item_list=output_item_list,
+          output_ota=OPTIONS.output_ota,
+          output_super_empty=OPTIONS.output_super_empty,
+          rebuild_recovery=OPTIONS.rebuild_recovery), OPTIONS.keep_tmp)
 
 
 if __name__ == '__main__':
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
index ec452a8..7e18a34 100644
--- a/tools/releasetools/test_merge_target_files.py
+++ b/tools/releasetools/test_merge_target_files.py
@@ -16,10 +16,12 @@
 
 import os.path
 
+import common
 import test_utils
-from merge_target_files import (
-    read_config_list, validate_config_lists, default_system_item_list,
-    default_other_item_list, default_system_misc_info_keys)
+from merge_target_files import (read_config_list, validate_config_lists,
+                                default_system_item_list,
+                                default_other_item_list,
+                                default_system_misc_info_keys, copy_items)
 
 
 class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
@@ -27,6 +29,58 @@
   def setUp(self):
     self.testdata_dir = test_utils.get_testdata_dir()
 
+  def test_copy_items_CopiesItemsMatchingPatterns(self):
+
+    def createEmptyFile(path):
+      if not os.path.exists(os.path.dirname(path)):
+        os.makedirs(os.path.dirname(path))
+      open(path, 'a').close()
+      return path
+
+    def createSymLink(source, dest):
+      os.symlink(source, dest)
+      return dest
+
+    def getRelPaths(start, filepaths):
+      return set(
+          os.path.relpath(path=filepath, start=start) for filepath in filepaths)
+
+    input_dir = common.MakeTempDir()
+    output_dir = common.MakeTempDir()
+    expected_copied_items = []
+    actual_copied_items = []
+    patterns = ['*.cpp', 'subdir/*.txt']
+
+    # Create various files that we expect to get copied because they
+    # match one of the patterns.
+    expected_copied_items.extend([
+        createEmptyFile(os.path.join(input_dir, 'a.cpp')),
+        createEmptyFile(os.path.join(input_dir, 'b.cpp')),
+        createEmptyFile(os.path.join(input_dir, 'subdir', 'c.txt')),
+        createEmptyFile(os.path.join(input_dir, 'subdir', 'd.txt')),
+        createEmptyFile(
+            os.path.join(input_dir, 'subdir', 'subsubdir', 'e.txt')),
+        createSymLink('a.cpp', os.path.join(input_dir, 'a_link.cpp')),
+    ])
+    # Create some more files that we expect to not get copied.
+    createEmptyFile(os.path.join(input_dir, 'a.h'))
+    createEmptyFile(os.path.join(input_dir, 'b.h'))
+    createEmptyFile(os.path.join(input_dir, 'subdir', 'subsubdir', 'f.gif'))
+    createSymLink('a.h', os.path.join(input_dir, 'a_link.h'))
+
+    # Copy items.
+    copy_items(input_dir, output_dir, patterns)
+
+    # Assert the actual copied items match the ones we expected.
+    for dirpath, _, filenames in os.walk(output_dir):
+      actual_copied_items.extend(
+          os.path.join(dirpath, filename) for filename in filenames)
+    self.assertEqual(
+        getRelPaths(output_dir, actual_copied_items),
+        getRelPaths(input_dir, expected_copied_items))
+    self.assertEqual(
+        os.readlink(os.path.join(output_dir, 'a_link.cpp')), 'a.cpp')
+
   def test_read_config_list(self):
     system_item_list_file = os.path.join(self.testdata_dir,
                                          'merge_config_system_item_list')