Merge master@5406228 into git_qt-dev-plus-aosp.

Change-Id: I535a555e659ba80e2dc839324b3d4672e8918661
BUG: 129345239
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 51139ed..3d9a1ef 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -610,6 +610,9 @@
 $(call add-clean-step, rm -rf $(TARGET_OUT_DATA)/*)
 $(call add-clean-step, rm -rf $(HOST_OUT)/vts/*)
 $(call add-clean-step, rm -rf $(HOST_OUT)/framework/vts-tradefed.jar)
+
+# Clean up old location of system_other.avbpubkey
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/security/avb/)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index 1b6e453..ff5a0c6 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -734,6 +734,15 @@
 $(call dist-for-goals,droidcore,$(BUILD_SYSTEM_STATS))
 
 # -----------------------------------------------------------------
+# build /product/etc/security/avb/system_other.avbpubkey if needed
+ifdef BUILDING_SYSTEM_OTHER_IMAGE
+ifeq ($(BOARD_AVB_ENABLE),true)
+INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET := $(TARGET_OUT_PRODUCT_ETC)/security/avb/system_other.avbpubkey
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET)
+endif # BOARD_AVB_ENABLE
+endif # BUILDING_SYSTEM_OTHER_IMAGE
+
+# -----------------------------------------------------------------
 # Modules ready to be converted to Soong, ordered by how many
 # modules depend on them.
 SOONG_CONV := $(sort $(SOONG_CONV))
@@ -1467,8 +1476,7 @@
 $(if $(BOARD_AVB_ENABLE),\
     $(if $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH),\
         $(hide) echo "avb_system_other_key_path=$(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_system_extract_system_other_key=true" >> $(1)))
+        $(hide) echo "avb_system_other_algorithm=$(BOARD_AVB_SYSTEM_OTHER_ALGORITHM)" >> $(1)))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_vendor_add_hashtree_footer_args=$(BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),\
@@ -2139,12 +2147,80 @@
 endef
 endif
 
+# Check that libraries that should only be in APEXes don't end up in the system
+# image. For the Runtime APEX this complements the checks in
+# art/build/apex/art_apex_test.py.
+# TODO(b/128708192): Implement this restriction in Soong instead.
+
+# TODO(b/124293228): Fix remaining bugs and add these libraries to the list:
+#   libart-compiler.so
+#   libart-dexlayout.so
+#   libart.so
+#   libartbase.so
+#   libartpalette.so
+#   libdexfile.so
+#   libdexfile_external.so  - aosp_marlin-userdebug gets this in a vndk-sp-Q subdirectory.
+#   libicui18n.so
+#   libicuuc.so
+#   libnativehelper.so  - cf_x86_phone-userdebug builds get this in system/lib/arm
+#   libprofile.so
+#   libsigchain.so
+#   libtombstoned_client.so
+APEX_MODULE_LIBS= \
+  libadbconnection.so \
+  libandroidicu.so \
+  libdt_fd_forward.so \
+  libdt_socket.so \
+  libjavacore.so \
+  libjdwp.so \
+  libnativebridge.so \
+  libnativeloader.so \
+  libnpt.so \
+  libopenjdk.so \
+  libopenjdkjvm.so \
+  libopenjdkjvmti.so \
+  libpac.so \
+
+# If the check below fails, some library has ended up in system/lib or
+# system/lib64 that is intended to only go into some APEX package. The likely
+# cause is that a library or binary in /system has grown a dependency that
+# directly or indirectly pulls in the prohibited library.
+#
+# To resolve this, look for the APEX package that the library belong to - search
+# for it in 'native_shared_lib' properties in 'apex' build modules (see
+# art/build/apex/Android.bp for an example). Then check if there is an exported
+# library in that APEX package that should be used instead, i.e. one listed in
+# its 'native_shared_lib' property for which the corresponding 'cc_library'
+# module has a 'stubs' clause (like libdexfile_external in
+# art/libdexfile/Android.bp).
+#
+# If you cannot find an APEX exported library that fits your needs, or you think
+# that the library you want to depend on should be allowed in /system, then
+# please contact the owners of the APEX package containing the library.
+#
+# If you get this error for a library that is exported in an APEX, then the APEX
+# might be misconfigured or something is wrong in the build system. Please reach
+# out to the APEX package owners and/or soong-team@, or
+# android-building@googlegroups.com externally.
+define check-apex-libs-absence
+$(hide) ( \
+  cd $(TARGET_OUT); \
+  findres=$$(find lib* -type f \( -false $(foreach lib,$(APEX_MODULE_LIBS),-o -name $(lib)) \) -print) || exit 1; \
+  if [ -n "$$findres" ]; then \
+    echo "APEX libraries found in system image (see comment in this makefile for details):" 1>&2; \
+    echo "$$findres" | sort 1>&2; \
+    false; \
+  fi; \
+)
+endef
+
 # $(1): output file
 define build-systemimage-target
   @echo "Target system fs image: $(1)"
   $(call create-system-vendor-symlink)
   $(call create-system-product-symlink)
   $(call create-system-product_services-symlink)
+  $(call check-apex-libs-absence)
   @mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt
   $(call generate-image-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt,system, \
       skip_fsck=true)
@@ -2979,9 +3055,11 @@
 BOARD_AVB_SYSTEM_OTHER_ALGORITHM := $(BOARD_AVB_ALGORITHM)
 endif
 
-# To extract the public key of SYSTEM_OTHER_KEY_PATH will into system.img:
-# /system/etc/security/avb/system_other.avbpubkey.
-FULL_SYSTEMIMAGE_DEPS += $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)
+$(INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET): $(AVBTOOL) $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH)
+	@echo Extracting system_other avb key: $@
+	@rm -f $@
+	@mkdir -p $(dir $@)
+	$(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH) --output $@
 
 ifndef BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX
 BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
@@ -3937,8 +4015,10 @@
 endif
 	$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
 ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
+ifdef BUILDING_SYSTEM_IMAGE
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	    build/make/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
+endif # BUILDING_SYSTEM_IMAGE
 endif
 ifeq ($(AB_OTA_UPDATER),true)
 	@# When using the A/B updater, include the updater config files in the zip.
@@ -4225,7 +4305,7 @@
 	@echo "Package symbols: $@"
 	$(hide) rm -rf $@ $(PRIVATE_LIST_FILE)
 	$(hide) mkdir -p $(dir $@) $(TARGET_OUT_UNSTRIPPED) $(dir $(PRIVATE_LIST_FILE))
-	$(hide) find $(TARGET_OUT_UNSTRIPPED) | sort >$(PRIVATE_LIST_FILE)
+	$(hide) find -L $(TARGET_OUT_UNSTRIPPED) -type f | sort >$(PRIVATE_LIST_FILE)
 	$(hide) $(SOONG_ZIP) -d -o $@ -C $(OUT_DIR)/.. -l $(PRIVATE_LIST_FILE)
 # -----------------------------------------------------------------
 # A zip of the coverage directory.
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 742119f..7e7d6dc 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -776,6 +776,10 @@
     $(ALL_MODULES.$(my_register_name).CHECKED) $(my_checked_module)
 ALL_MODULES.$(my_register_name).BUILT := \
     $(ALL_MODULES.$(my_register_name).BUILT) $(LOCAL_BUILT_MODULE)
+ifndef LOCAL_IS_HOST_MODULE
+ALL_MODULES.$(my_register_name).TARGET_BUILT := \
+    $(ALL_MODULES.$(my_register_name).TARGET_BUILT) $(LOCAL_BUILT_MODULE)
+endif
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 ALL_MODULES.$(my_register_name).INSTALLED := \
     $(strip $(ALL_MODULES.$(my_register_name).INSTALLED) \
diff --git a/core/binary.mk b/core/binary.mk
index e59e32e..43063a8 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -1214,17 +1214,17 @@
         # with vendor_available: false
         my_link_type := native:vendor
         my_warn_types :=
-        my_allowed_types := native:vendor native:vndk
+        my_allowed_types := native:vendor native:vndk native:platform_vndk
     endif
 else ifneq ($(filter $(TARGET_RECOVERY_OUT)/%,$(call get_non_asan_path,$(LOCAL_MODULE_PATH))),)
 my_link_type := native:recovery
 my_warn_types :=
 # TODO(b/113303515) remove native:platform and my_allowed_ndk_types
-my_allowed_types := native:recovery native:platform $(my_allowed_ndk_types)
+my_allowed_types := native:recovery native:platform native:platform_vndk $(my_allowed_ndk_types)
 else
 my_link_type := native:platform
 my_warn_types := $(my_warn_ndk_types)
-my_allowed_types := $(my_allowed_ndk_types) native:platform
+my_allowed_types := $(my_allowed_ndk_types) native:platform native:platform_vndk
 endif
 
 my_link_deps := $(addprefix STATIC_LIBRARIES:,$(my_whole_static_libraries) $(my_static_libraries))
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 1883743..d67c9f8 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -263,7 +263,8 @@
 LOCAL_SOONG_LINK_TYPE :=
 LOCAL_SOONG_PROGUARD_DICT :=
 LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=
-LOCAL_SOONG_RRO_DIRS :=
+LOCAL_SOONG_DEVICE_RRO_DIRS :=
+LOCAL_SOONG_PRODUCT_RRO_DIRS :=
 LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=
 LOCAL_SOONG_SYMBOL_PATH :=
 LOCAL_SOONG_TOC :=
@@ -296,6 +297,7 @@
 LOCAL_USES_LIBRARIES:=
 LOCAL_VENDOR_MODULE:=
 LOCAL_VINTF_FRAGMENTS:=
+LOCAL_VNDK_DEPEND_ON_CORE_VARIANT:=
 LOCAL_VTSC_FLAGS:=
 LOCAL_VTS_INCLUDES:=
 LOCAL_VTS_MODE:=
diff --git a/core/definitions.mk b/core/definitions.mk
index 42fa30d..205a055 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -651,6 +651,18 @@
 
 ###########################################################
 ## Convert a list of short modules names (e.g., "framework", "Browser")
+## into the list of files that are built *for the target* for those modules.
+## NOTE: this won't return reliable results until after all
+## sub-makefiles have been included.
+## $(1): target list
+###########################################################
+
+define module-target-built-files
+$(foreach module,$(1),$(ALL_MODULES.$(module).TARGET_BUILT))
+endef
+
+###########################################################
+## Convert a list of short modules names (e.g., "framework", "Browser")
 ## into the list of files that should be used when linking
 ## against that module as a public API.
 ## TODO: Allow this for more than JAVA_LIBRARIES modules
@@ -3300,10 +3312,12 @@
 #  $(4): Whether LOCAL_EXPORT_PACKAGE_RESOURCES is set or
 #        not for the source module.
 #  $(5): Resource overlay list.
+#  $(6): Target partition
 ###########################################################
 define append_enforce_rro_sources
   $(eval ENFORCE_RRO_SOURCES += \
-      $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||$(call normalize-path-list, $(strip $(5))))
+      $(strip $(1))||$(strip $(2))||$(strip $(3))||$(strip $(4))||$(call normalize-path-list, $(strip $(5)))||$(strip $(6)) \
+  )
 endef
 
 ###########################################################
@@ -3318,6 +3332,7 @@
   $(eval enforce_rro_source_manifest_package_info := $(word 3,$(_o))) \
   $(eval enforce_rro_use_res_lib := $(word 4,$(_o))) \
   $(eval enforce_rro_source_overlays := $(subst :, ,$(word 5,$(_o)))) \
+  $(eval enforce_rro_partition := $(word 6,$(_o))) \
   $(eval include $(BUILD_SYSTEM)/generate_enforce_rro.mk) \
   $(eval ALL_MODULES.$$(enforce_rro_source_module).REQUIRED += $$(LOCAL_PACKAGE_NAME)) \
 )
@@ -3386,3 +3401,19 @@
   initialize-package-file \
   add-jni-shared-libs-to-package,\
   These functions have been removed)
+
+###########################################################
+## Verify the variants of a VNDK library are identical
+##
+## $(1): Path to the core variant shared library file.
+## $(2): Path to the vendor variant shared library file.
+## $(3): TOOLS_PREFIX
+###########################################################
+LIBRARY_IDENTITY_CHECK_SCRIPT := build/make/tools/check_identical_lib.sh
+define verify-vndk-libs-identical
+@echo "Checking VNDK vendor variant: $(2)"
+$(hide) CLANG_BIN="$(LLVM_PREBUILTS_PATH)" \
+	CROSS_COMPILE="$(strip $(3))" \
+	XZ="$(XZ)" \
+	$(LIBRARY_IDENTITY_CHECK_SCRIPT) $(SOONG_STRIP_PATH) $(1) $(2)
+endef
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
index ad734b5..ad073c7 100644
--- a/core/dpi_specific_apk.mk
+++ b/core/dpi_specific_apk.mk
@@ -67,6 +67,7 @@
 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)
diff --git a/core/generate_enforce_rro.mk b/core/generate_enforce_rro.mk
index 6124a4f..f7877f2 100644
--- a/core/generate_enforce_rro.mk
+++ b/core/generate_enforce_rro.mk
@@ -1,6 +1,6 @@
 include $(CLEAR_VARS)
 
-enforce_rro_module := $(enforce_rro_source_module)__auto_generated_rro
+enforce_rro_module := $(enforce_rro_source_module)__auto_generated_rro_$(enforce_rro_partition)
 LOCAL_PACKAGE_NAME := $(enforce_rro_module)
 
 intermediates := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
@@ -14,10 +14,17 @@
 endif
 
 $(rro_android_manifest_file): PRIVATE_PACKAGE_INFO := $(enforce_rro_source_manifest_package_info)
+$(rro_android_manifest_file): PRIVATE_USE_PACKAGE_NAME := $(use_package_name_arg)
+$(rro_android_manifest_file): PRIVATE_PARTITION := $(enforce_rro_partition)
+# There should be no duplicate overrides, but just in case, set the priority of
+# /product overlays to be higher than /vendor, to at least get deterministic results.
+$(rro_android_manifest_file): PRIVATE_PRIORITY := $(if $(filter product,$(enforce_rro_partition)),1,0)
 $(rro_android_manifest_file): build/make/tools/generate-enforce-rro-android-manifest.py
 	$(hide) build/make/tools/generate-enforce-rro-android-manifest.py \
 	    --package-info $(PRIVATE_PACKAGE_INFO) \
-	    $(use_package_name_arg) \
+	    $(PRIVATE_USE_PACKAGE_NAME) \
+	    --partition $(PRIVATE_PARTITION) \
+	    --priority $(PRIVATE_PRIORITY) \
 	    -o $@
 
 LOCAL_PATH:= $(intermediates)
@@ -31,7 +38,14 @@
 
 LOCAL_AAPT_FLAGS += --auto-add-overlay
 LOCAL_RESOURCE_DIR := $(enforce_rro_source_overlays)
-LOCAL_PRODUCT_MODULE := true
+
+ifeq (product,$(enforce_rro_partition))
+  LOCAL_PRODUCT_MODULE := true
+else ifeq (vendor,$(enforce_rro_partition))
+  LOCAL_VENDOR_MODULE := true
+else
+  $(error Unsupported partition. Want: [vendor/product] Got: [$(enforce_rro_partition)])
+endif
 
 ifneq (,$(LOCAL_RES_LIBRARIES))
   # Technically we are linking against the app (if only to grab its resources),
diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk
index e0f1ad4..a79a49a 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -113,12 +113,12 @@
 my_warn_types := native:platform $(my_warn_ndk_types)
 my_allowed_types := $(my_allowed_ndk_types)
     ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
-        my_allowed_types += native:vendor native:vndk
+        my_allowed_types += native:vendor native:vndk native:platform_vndk
     endif
 else
 my_link_type := app:platform
 my_warn_types := $(my_warn_ndk_types)
-my_allowed_types := $(my_allowed_ndk_types) native:platform native:vendor native:vndk native:vndk_private
+my_allowed_types := $(my_allowed_ndk_types) native:platform native:vendor native:vndk native:vndk_private native:platform_vndk
 endif
 
 my_link_deps := $(addprefix SHARED_LIBRARIES:,$(LOCAL_JNI_SHARED_LIBRARIES))
diff --git a/core/local_systemsdk.mk b/core/local_systemsdk.mk
index 0f1271f..6c022f2 100644
--- a/core/local_systemsdk.mk
+++ b/core/local_systemsdk.mk
@@ -25,7 +25,7 @@
   ifneq (,$(filter JAVA_LIBRARIES APPS,$(LOCAL_MODULE_CLASS)))
     ifndef LOCAL_SDK_VERSION
       ifeq ($(_is_vendor_app),true)
-        ifeq (,$(filter %__auto_generated_rro,$(LOCAL_MODULE)))
+        ifeq (,$(filter %__auto_generated_rro_vendor,$(LOCAL_MODULE)))
           # Runtime resource overlays are exempted from building against System SDK.
           # TODO(b/35859726): remove this exception
           LOCAL_SDK_VERSION := system_current
diff --git a/core/main.mk b/core/main.mk
index bbe6b38..62d3719 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -501,6 +501,10 @@
 subdir_makefiles_total := $(words init post finish)
 endif
 
+droid_targets: no_vendor_variant_vndk_check
+.PHONY: no_vendor_variant_vndk_check
+no_vendor_variant_vndk_check:
+
 $(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] finishing build rules ...)
 
 # -------------------------------------------------------------------
@@ -1202,7 +1206,8 @@
   # Fakes don't get installed, host files are irrelevant, and NDK stubs aren't installed to device.
   static_whitelist_patterns := $(TARGET_OUT_FAKE)/% $(HOST_OUT)/% $(SOONG_OUT_DIR)/ndk/%
   # RROs become REQUIRED by the source module, but are always placed on the vendor partition.
-  static_whitelist_patterns += %__auto_generated_rro.apk
+  static_whitelist_patterns += %__auto_generated_rro_product.apk
+  static_whitelist_patterns += %__auto_generated_rro_vendor.apk
   # Auto-included targets are not considered
   static_whitelist_patterns += $(call module-installed-files,$(call auto-included-modules))
   # $(PRODUCT_OUT)/apex is where shared libraries in APEXes get installed.
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 89296e6..f07e4f5 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -132,21 +132,26 @@
   enforce_rro_enabled := true
 endif
 
-all_package_resource_overlays := $(strip \
+product_package_overlays := $(strip \
     $(wildcard $(foreach dir, $(PRODUCT_PACKAGE_OVERLAYS), \
-      $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))) \
+      $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))))
+device_package_overlays := $(strip \
     $(wildcard $(foreach dir, $(DEVICE_PACKAGE_OVERLAYS), \
       $(addprefix $(dir)/, $(LOCAL_RESOURCE_DIR)))))
 
 static_resource_overlays :=
-runtime_resource_overlays :=
+runtime_resource_overlays_product :=
+runtime_resource_overlays_vendor :=
 ifdef enforce_rro_enabled
   ifneq ($(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS),)
-    static_resource_overlays += $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(all_package_resource_overlays))
+    # The PRODUCT_ exclusion variable applies to both inclusion variables..
+    static_resource_overlays += $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(product_package_overlays))
+    static_resource_overlays += $(filter $(addsuffix %,$(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS)),$(device_package_overlays))
   endif
-  runtime_resource_overlays := $(filter-out $(static_resource_overlays),$(all_package_resource_overlays))
+  runtime_resource_overlays_product := $(filter-out $(static_resource_overlays),$(product_package_overlays))
+  runtime_resource_overlays_vendor := $(filter-out $(static_resource_overlays),$(device_package_overlays))
 else
-  static_resource_overlays := $(all_package_resource_overlays)
+  static_resource_overlays := $(product_package_overlays) $(device_package_overlays)
 endif
 
 # Add the static overlays. Auto-RRO is created later, as it depends on
@@ -790,7 +795,7 @@
 # Reset internal variables.
 all_res_assets :=
 
-ifdef runtime_resource_overlays
+ifneq (,$(runtime_resource_overlays_product)$(runtime_resource_overlays_vendor))
   ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
     enforce_rro_use_res_lib := true
   else
@@ -805,11 +810,24 @@
     enforce_rro_manifest_package_info := $(full_android_manifest)
   endif
 
-  $(call append_enforce_rro_sources, \
-      $(my_register_name), \
-      $(enforce_rro_is_manifest_package_name), \
-      $(enforce_rro_manifest_package_info), \
-      $(enforce_rro_use_res_lib), \
-      $(runtime_resource_overlays) \
-  )
+  ifdef runtime_resource_overlays_product
+    $(call append_enforce_rro_sources, \
+        $(my_register_name), \
+        $(enforce_rro_is_manifest_package_name), \
+        $(enforce_rro_manifest_package_info), \
+        $(enforce_rro_use_res_lib), \
+        $(runtime_resource_overlays_product), \
+        product \
+    )
+  endif
+  ifdef runtime_resource_overlays_vendor
+    $(call append_enforce_rro_sources, \
+        $(my_register_name), \
+        $(enforce_rro_is_manifest_package_name), \
+        $(enforce_rro_manifest_package_info), \
+        $(enforce_rro_use_res_lib), \
+        $(runtime_resource_overlays_vendor), \
+        vendor \
+    )
+  endif
 endif
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index a9169eb..8d92b20 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -159,13 +159,26 @@
 include $(BUILD_SYSTEM)/link_type.mk
 endif # !LOCAL_IS_HOST_MODULE
 
-ifdef LOCAL_SOONG_RRO_DIRS
+ifdef LOCAL_SOONG_DEVICE_RRO_DIRS
   $(call append_enforce_rro_sources, \
       $(my_register_name), \
       false, \
       $(LOCAL_FULL_MANIFEST_FILE), \
       $(if $(LOCAL_EXPORT_PACKAGE_RESOURCES),true,false), \
-      $(LOCAL_SOONG_RRO_DIRS))
+      $(LOCAL_SOONG_DEVICE_RRO_DIRS), \
+      vendor \
+  )
+endif
+
+ifdef LOCAL_SOONG_PRODUCT_RRO_DIRS
+  $(call append_enforce_rro_sources, \
+      $(my_register_name), \
+      false, \
+      $(LOCAL_FULL_MANIFEST_FILE), \
+      $(if $(LOCAL_EXPORT_PACKAGE_RESOURCES),true,false), \
+      $(LOCAL_SOONG_PRODUCT_RRO_DIRS), \
+      product \
+  )
 endif
 
 SOONG_ALREADY_CONV := $(SOONG_ALREADY_CONV) $(LOCAL_MODULE)
diff --git a/core/soong_cc_prebuilt.mk b/core/soong_cc_prebuilt.mk
index 8d248af..679d5b8 100644
--- a/core/soong_cc_prebuilt.mk
+++ b/core/soong_cc_prebuilt.mk
@@ -86,11 +86,13 @@
 endif
 
 ifdef LOCAL_USE_VNDK
-  name_without_suffix := $(patsubst %.vendor,%,$(LOCAL_MODULE))
-  ifneq ($(name_without_suffix),$(LOCAL_MODULE)
-    SPLIT_VENDOR.$(LOCAL_MODULE_CLASS).$(name_without_suffix) := 1
+  ifneq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+    name_without_suffix := $(patsubst %.vendor,%,$(LOCAL_MODULE))
+    ifneq ($(name_without_suffix),$(LOCAL_MODULE)
+      SPLIT_VENDOR.$(LOCAL_MODULE_CLASS).$(name_without_suffix) := 1
+    endif
+    name_without_suffix :=
   endif
-  name_without_suffix :=
 endif
 
 # Check prebuilt ELF binaries.
@@ -113,27 +115,52 @@
   endif
 endif
 
+ifeq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+  # Add $(LOCAL_BUILT_MODULE) as a dependency to no_vendor_variant_vndk_check so
+  # that the vendor variant will be built and checked against the core variant.
+  no_vendor_variant_vndk_check: $(LOCAL_BUILT_MODULE)
+
+  my_core_register_name := $(subst .vendor,,$(my_register_name))
+  my_core_variant_files := $(call module-target-built-files,$(my_core_register_name))
+  my_core_shared_lib := $(sort $(filter %.so,$(my_core_variant_files)))
+  $(LOCAL_BUILT_MODULE): PRIVATE_CORE_VARIANT := $(my_core_shared_lib)
+
+  # The built vendor variant library needs to depend on the built core variant
+  # so that we can perform identity check against the core variant.
+  $(LOCAL_BUILT_MODULE): $(my_core_shared_lib)
+endif
+
+ifeq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE) $(LIBRARY_IDENTITY_CHECK_SCRIPT)
+	$(call verify-vndk-libs-identical,\
+		$(PRIVATE_CORE_VARIANT),\
+		$<,\
+		$($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)TOOLS_PREFIX))
+	$(copy-file-to-target)
+else
 $(LOCAL_BUILT_MODULE): $(LOCAL_PREBUILT_MODULE_FILE)
 	$(transform-prebuilt-to-target)
+endif
 ifneq ($(filter EXECUTABLES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
 	$(hide) chmod +x $@
 endif
 
 ifndef LOCAL_IS_HOST_MODULE
   ifdef LOCAL_SOONG_UNSTRIPPED_BINARY
-    my_symbol_path := $(if $(LOCAL_SOONG_SYMBOL_PATH),$(LOCAL_SOONG_SYMBOL_PATH),$(my_module_path))
-    # Store a copy with symbols for symbolic debugging
-    my_unstripped_path := $(TARGET_OUT_UNSTRIPPED)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
-    # drop /root as /root is mounted as /
-    my_unstripped_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/root/%,$(TARGET_OUT_UNSTRIPPED)/%, $(my_unstripped_path))
-    symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
-    $(eval $(call copy-one-file,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
-    $(call add-dependency,$(LOCAL_BUILT_MODULE),$(symbolic_output))
+    ifneq ($(LOCAL_VNDK_DEPEND_ON_CORE_VARIANT),true)
+      my_symbol_path := $(if $(LOCAL_SOONG_SYMBOL_PATH),$(LOCAL_SOONG_SYMBOL_PATH),$(my_module_path))
+      # Store a copy with symbols for symbolic debugging
+      my_unstripped_path := $(TARGET_OUT_UNSTRIPPED)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
+      # drop /root as /root is mounted as /
+      my_unstripped_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/root/%,$(TARGET_OUT_UNSTRIPPED)/%, $(my_unstripped_path))
+      symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
+      $(eval $(call copy-one-file,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
+      $(call add-dependency,$(LOCAL_BUILT_MODULE),$(symbolic_output))
 
-    ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
-      my_breakpad_path := $(TARGET_OUT_BREAKPAD)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
-      breakpad_output := $(my_breakpad_path)/$(my_installed_module_stem).sym
-      $(breakpad_output) : $(LOCAL_SOONG_UNSTRIPPED_BINARY) | $(BREAKPAD_DUMP_SYMS) $(PRIVATE_READELF)
+      ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
+        my_breakpad_path := $(TARGET_OUT_BREAKPAD)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_symbol_path))
+        breakpad_output := $(my_breakpad_path)/$(my_installed_module_stem).sym
+        $(breakpad_output) : $(LOCAL_SOONG_UNSTRIPPED_BINARY) | $(BREAKPAD_DUMP_SYMS) $(PRIVATE_READELF)
 	@echo "target breakpad: $(PRIVATE_MODULE) ($@)"
 	@mkdir -p $(dir $@)
 	$(hide) if $(PRIVATE_READELF) -S $< > /dev/null 2>&1 ; then \
@@ -142,7 +169,8 @@
 	  echo "skipped for non-elf file."; \
 	  touch $@; \
 	fi
-      $(call add-dependency,$(LOCAL_BUILT_MODULE),$(breakpad_output))
+        $(call add-dependency,$(LOCAL_BUILT_MODULE),$(breakpad_output))
+      endif
     endif
   endif
 endif
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 3c82e88..baba31b 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -61,7 +61,8 @@
 $(call add_json_str,  CrossHostArch,                     $(HOST_CROSS_ARCH))
 $(call add_json_str,  CrossHostSecondaryArch,            $(HOST_CROSS_2ND_ARCH))
 
-$(call add_json_list, ResourceOverlays,                  $(PRODUCT_PACKAGE_OVERLAYS) $(DEVICE_PACKAGE_OVERLAYS))
+$(call add_json_list, DeviceResourceOverlays,            $(DEVICE_PACKAGE_OVERLAYS))
+$(call add_json_list, ProductResourceOverlays,           $(PRODUCT_PACKAGE_OVERLAYS))
 $(call add_json_list, EnforceRROTargets,                 $(PRODUCT_ENFORCE_RRO_TARGETS))
 $(call add_json_list, EnforceRROExcludedOverlays,        $(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS))
 
@@ -115,6 +116,8 @@
 
 $(call add_json_list, BootJars,                          $(PRODUCT_BOOT_JARS))
 
+$(call add_json_bool, VndkUseCoreVariant,                $(TARGET_VNDK_USE_CORE_VARIANT))
+
 $(call add_json_bool, Product_is_iot,                    $(filter true,$(PRODUCT_IOT)))
 
 $(call add_json_bool, Treble_linker_namespaces,          $(filter true,$(PRODUCT_TREBLE_LINKER_NAMESPACES)))
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 68d29c8..d53995c 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -6,9 +6,6 @@
 
 include build/make/target/board/BoardConfigMainlineCommon.mk
 
-# Enable system property split for Treble
-BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
-
 # This flag is set by mainline but isn't desired for GSI.
 BOARD_USES_SYSTEM_OTHER_ODEX :=
 
@@ -27,6 +24,7 @@
 
 # GSI forces product packages to /system for now.
 TARGET_COPY_OUT_PRODUCT := system/product
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE :=
 
 # Creates metadata partition mount point under root for
 # the devices with metadata parition
diff --git a/target/board/BoardConfigMainlineCommon.mk b/target/board/BoardConfigMainlineCommon.mk
index e13317f..fc55408 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -10,7 +10,10 @@
 
 # Mainline devices must have /vendor and /product partitions.
 TARGET_COPY_OUT_VENDOR := vendor
+BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
+
 TARGET_COPY_OUT_PRODUCT := product
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
 
 # system-as-root is mandatory from Android P
 TARGET_NO_RECOVERY := true
@@ -39,3 +42,10 @@
 BOARD_AVB_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
 
 BOARD_CHARGER_ENABLE_SUSPEND := true
+
+# Enable A/B update
+AB_OTA_UPDATER := true
+AB_OTA_PARTITIONS := system
+
+# Enable system property split for Treble
+BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 8fcfa79..51dd82a 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -73,7 +73,7 @@
     dpm \
     dumpstate \
     dumpsys \
-    DynamicAndroidInstallationService \
+    DynamicSystemInstallationService \
     e2fsck \
     ExtServices \
     ExtShared \
diff --git a/target/product/gsi/adb_debug.prop b/target/product/gsi/adb_debug.prop
new file mode 100644
index 0000000..37e2f2d
--- /dev/null
+++ b/target/product/gsi/adb_debug.prop
@@ -0,0 +1,12 @@
+# Note: This file will be loaded with highest priority to override
+# other system properties, if a special ramdisk with "/force_debuggable"
+# is used and the device is unlocked.
+
+# Disable adb authentication to allow test automation on user build GSI
+ro.adb.secure=0
+
+# Allow 'adb root' on user build GSI
+ro.debuggable=1
+
+# Introduce this property to indicate that init has loaded adb_debug.prop
+ro.force.debuggable=1
diff --git a/target/product/gsi_common.mk b/target/product/gsi_common.mk
index fb0478d..5e73e63 100644
--- a/target/product/gsi_common.mk
+++ b/target/product/gsi_common.mk
@@ -51,23 +51,19 @@
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     system/etc/init/config/skip_mount.cfg \
     system/etc/init/init.gsi.rc \
+    system/etc/adb_debug.prop \
 
 # Exclude all files under system/product and system/product_services
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     system/product/% \
     system/product_services/%
 
-
 # Split selinux policy
 PRODUCT_FULL_TREBLE_OVERRIDE := true
 
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
 
-# Enable A/B update
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-
 # Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
 PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
 
@@ -97,3 +93,7 @@
 #   Provide a libnfc-nci.conf to GSI product
 PRODUCT_COPY_FILES += \
     device/generic/common/nfc/libnfc-nci.conf:$(TARGET_COPY_OUT_PRODUCT)/etc/libnfc-nci.conf
+
+# Allow 'adb root' on user build GSI
+PRODUCT_COPY_FILES += \
+    build/make/target/product/gsi/adb_debug.prop:$(TARGET_COPY_OUT_SYSTEM)/etc/adb_debug.prop
diff --git a/target/product/mainline_system_arm64.mk b/target/product/mainline_system_arm64.mk
index 0b0929e..f01cc54 100644
--- a/target/product/mainline_system_arm64.mk
+++ b/target/product/mainline_system_arm64.mk
@@ -18,6 +18,16 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/mainline_system.mk)
 $(call enforce-product-packages-exist,)
 
+PRODUCT_BUILD_CACHE_IMAGE := false
+PRODUCT_BUILD_ODM_IMAGE := false
+PRODUCT_BUILD_PRODUCT_IMAGE  := false
+PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE := false
+PRODUCT_BUILD_RAMDISK_IMAGE := false
+PRODUCT_BUILD_SYSTEM_IMAGE := true
+PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false
+PRODUCT_BUILD_USERDATA_IMAGE := false
+PRODUCT_BUILD_VENDOR_IMAGE := false
+
 PRODUCT_NAME := mainline_system_arm64
 PRODUCT_DEVICE := mainline_arm64
 PRODUCT_BRAND := generic
diff --git a/tools/check_elf_file.py b/tools/check_elf_file.py
index 38c1cf4..de855c6 100755
--- a/tools/check_elf_file.py
+++ b/tools/check_elf_file.py
@@ -260,13 +260,20 @@
   _SYMBOL_ENTRY_END_PATTERN = '  }'
 
 
-  @classmethod
-  def _parse_symbol_name(cls, name_with_version):
+  @staticmethod
+  def _parse_symbol_name(name_with_version):
     """Split `name_with_version` into name and version. This function may split
     at last occurrence of `@@` or `@`."""
-    name, version = name_with_version.rsplit('@', 1)
-    if name and name[-1] == '@':
-      name = name[:-1]
+    pos = name_with_version.rfind('@')
+    if pos == -1:
+      name = name_with_version
+      version = ''
+    else:
+      if pos > 0 and name_with_version[pos - 1] == '@':
+        name = name_with_version[0:pos - 1]
+      else:
+        name = name_with_version[0:pos]
+      version = name_with_version[pos + 1:]
     return (name, version)
 
 
diff --git a/tools/check_identical_lib.sh b/tools/check_identical_lib.sh
new file mode 100755
index 0000000..01007c0
--- /dev/null
+++ b/tools/check_identical_lib.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+set -e
+
+STRIP_PATH="${1}"
+CORE="${2}"
+VENDOR="${3}"
+
+stripped_core="${CORE}.vndk_lib_check.stripped"
+stripped_vendor="${VENDOR}.vndk_lib_check.stripped"
+
+function cleanup() {
+  rm -f ${stripped_core} ${stripped_vendor}
+}
+trap cleanup EXIT
+
+function strip_lib() {
+  ${STRIP_PATH} \
+    -i ${1} \
+    -o ${2} \
+    -d /dev/null \
+    --remove-build-id
+}
+
+strip_lib ${CORE} ${stripped_core}
+strip_lib ${VENDOR} ${stripped_vendor}
+if ! cmp -s ${stripped_core} ${stripped_vendor}; then
+  echo "VNDK library not in vndkMustUseVendorVariantList but has different core and vendor variant: $(basename ${CORE})"
+  echo "If the two variants need to have different runtime behavior, consider using libvndksupport."
+  exit 1
+fi
diff --git a/tools/generate-enforce-rro-android-manifest.py b/tools/generate-enforce-rro-android-manifest.py
index 0d7623f..2d9382a 100755
--- a/tools/generate-enforce-rro-android-manifest.py
+++ b/tools/generate-enforce-rro-android-manifest.py
@@ -23,10 +23,10 @@
 import sys
 
 ANDROID_MANIFEST_TEMPLATE="""<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="%s.auto_generated_rro__"
+    package="%s.auto_generated_rro_%s__"
     android:versionCode="1"
     android:versionName="1.0">
-    <overlay android:targetPackage="%s" android:priority="0" android:isStatic="true"/>
+    <overlay android:targetPackage="%s" android:priority="%s" android:isStatic="true"/>
 </manifest>
 """
 
@@ -40,6 +40,12 @@
         '-p', '--package-info', required=True,
         help='Manifest package name or manifest file path of source module.')
     parser.add_argument(
+        '--partition', required=True,
+        help='The partition this RRO package is installed on.')
+    parser.add_argument(
+        '--priority', required=True,
+        help='The priority for the <overlay>.')
+    parser.add_argument(
         '-o', '--output', required=True,
         help='Output manifest file path.')
     return parser.parse_args()
@@ -48,6 +54,8 @@
 def main(argv):
   args = get_args()
 
+  partition = args.partition
+  priority = args.priority
   if args.use_package_name:
     package_name = args.package_info
   else:
@@ -58,7 +66,7 @@
       package_name = dom.documentElement.getAttribute('package')
 
   with open(args.output, 'w+') as f:
-    f.write(ANDROID_MANIFEST_TEMPLATE % (package_name, package_name))
+    f.write(ANDROID_MANIFEST_TEMPLATE % (package_name, partition, package_name, priority))
     f.close()
 
 
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index bcbc921..d2f4e25 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -740,28 +740,6 @@
     f.writelines(["%s=%s" % (key, value) for (key, value) in glob_dict.items()])
 
 
-def ExtractSystemOtherAvbKey(in_dir, glob_dict):
-  if glob_dict.get("avb_system_extract_system_other_key") != "true":
-    return
-
-  extract_to = os.path.join(in_dir, "etc/security/avb/system_other.avbpubkey")
-  extract_to_dir = os.path.dirname(extract_to)
-
-  if os.path.isdir(extract_to_dir):
-    shutil.rmtree(extract_to_dir)
-  elif os.path.isfile(extract_to_dir):
-    os.remove(extract_to_dir)
-  os.mkdir(extract_to_dir);
-
-  # Extracts the public key used to sign system_other.img, into system.img:
-  #   /system/etc/security/avb/system_other.avbpubkey.
-  avbtool = glob_dict.get("avb_avbtool")
-  extract_from = glob_dict.get("avb_system_other_key_path")
-  cmd = [avbtool, "extract_public_key", "--key", extract_from,
-         "--output", extract_to]
-  common.RunAndCheckOutput(cmd, verbose=False)
-
-
 def main(argv):
   if len(argv) < 4 or len(argv) > 5:
     print(__doc__)
@@ -785,7 +763,6 @@
     mount_point = ""
     if image_filename == "system.img":
       mount_point = "system"
-      ExtractSystemOtherAvbKey(in_dir, glob_dict)
     elif image_filename == "system_other.img":
       mount_point = "system_other"
     elif image_filename == "userdata.img":
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index 9b76954..4b0d4c7 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -168,6 +168,7 @@
 
 
 class APK(object):
+
   def __init__(self, full_filename, filename):
     self.filename = filename
     self.certs = None
@@ -244,12 +245,12 @@
     # must decompress them individually before we perform any analysis.
 
     # This is the list of wildcards of files we extract from |filename|.
-    apk_extensions = ['*.apk']
+    apk_extensions = ['*.apk', '*.apex']
 
     self.certmap, compressed_extension = common.ReadApkCerts(
-        zipfile.ZipFile(filename, "r"))
+        zipfile.ZipFile(filename))
     if compressed_extension:
-      apk_extensions.append("*.apk" + compressed_extension)
+      apk_extensions.append('*.apk' + compressed_extension)
 
     d = common.UnzipTemp(filename, apk_extensions)
     self.apks = {}
@@ -272,7 +273,7 @@
           os.remove(os.path.join(dirpath, fn))
           fn = uncompressed_fn
 
-        if fn.endswith(".apk"):
+        if fn.endswith(('.apk', '.apex')):
           fullname = os.path.join(dirpath, fn)
           displayname = fullname[len(d)+1:]
           apk = APK(fullname, displayname)
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 780b9c1..632c1e2 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -17,6 +17,7 @@
 import collections
 import copy
 import errno
+import fnmatch
 import getopt
 import getpass
 import gzip
@@ -771,21 +772,29 @@
     shutil.copyfileobj(in_file, out_file)
 
 
-def UnzipToDir(filename, dirname, pattern=None):
+def UnzipToDir(filename, dirname, patterns=None):
   """Unzips the archive to the given directory.
 
   Args:
     filename: The name of the zip file to unzip.
-
     dirname: Where the unziped files will land.
-
-    pattern: Files to unzip from the archive. If omitted, will unzip the entire
-    archvie.
+    patterns: Files to unzip from the archive. If omitted, will unzip the entire
+        archvie. Non-matching patterns will be filtered out. If there's no match
+        after the filtering, no file will be unzipped.
   """
-
   cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
-  if pattern is not None:
-    cmd.extend(pattern)
+  if patterns is not None:
+    # Filter out non-matching patterns. unzip will complain otherwise.
+    with zipfile.ZipFile(filename) as input_zip:
+      names = input_zip.namelist()
+    filtered = [
+        pattern for pattern in patterns if fnmatch.filter(names, pattern)]
+
+    # There isn't any matching files. Don't unzip anything.
+    if not filtered:
+      return
+    cmd.extend(filtered)
+
   RunAndCheckOutput(cmd)
 
 
@@ -999,7 +1008,8 @@
 
 
 def SignFile(input_name, output_name, key, password, min_api_level=None,
-             codename_to_api_level_map=None, whole_file=False):
+             codename_to_api_level_map=None, whole_file=False,
+             extra_signapk_args=None):
   """Sign the input_name zip/jar/apk, producing output_name.  Use the
   given key and password (the latter may be None if the key does not
   have a password.
@@ -1014,9 +1024,14 @@
 
   codename_to_api_level_map is needed to translate the codename which may be
   encountered as the APK's minSdkVersion.
+
+  Caller may optionally specify extra args to be passed to SignApk, which
+  defaults to OPTIONS.extra_signapk_args if omitted.
   """
   if codename_to_api_level_map is None:
     codename_to_api_level_map = {}
+  if extra_signapk_args is None:
+    extra_signapk_args = OPTIONS.extra_signapk_args
 
   java_library_path = os.path.join(
       OPTIONS.search_path, OPTIONS.signapk_shared_library_path)
@@ -1024,7 +1039,7 @@
   cmd = ([OPTIONS.java_path] + OPTIONS.java_args +
          ["-Djava.library.path=" + java_library_path,
           "-jar", os.path.join(OPTIONS.search_path, OPTIONS.signapk_path)] +
-         OPTIONS.extra_signapk_args)
+         extra_signapk_args)
   if whole_file:
     cmd.append("-w")
 
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 1d62e3b..3c6bfbf 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -204,13 +204,19 @@
     return config_file.read().splitlines()
 
 
-def validate_config_lists(system_item_list, 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.
 
@@ -233,6 +239,12 @@
                  'this script.')
     return False
 
+  if ('dynamic_partition_list' in system_misc_info_keys) or (
+      'super_partition_groups' in system_misc_info_keys):
+    logger.error('Dynamic partition misc info keys should come from '
+                 'the other instance of META/misc_info.txt.')
+    return False
+
   return True
 
 
@@ -331,6 +343,25 @@
   for key in system_misc_info_keys:
     merged_info_dict[key] = system_info_dict[key]
 
+  # Merge misc info keys used for Dynamic Partitions.
+  if (merged_info_dict.get('use_dynamic_partitions') == 'true') and (
+      system_info_dict.get('use_dynamic_partitions') == 'true'):
+    merged_info_dict['dynamic_partition_list'] = '%s %s' % (
+        system_info_dict.get('dynamic_partition_list', ''),
+        merged_info_dict.get('dynamic_partition_list', ''))
+    # 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(' '):
+      if ('super_%s_group_size' % partition_group) not in merged_info_dict:
+        raise common.ExternalError(
+            '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, ''))
+
   output_misc_info_txt = os.path.join(
       output_target_files_temp_dir,
       'META', 'misc_info.txt')
@@ -717,6 +748,7 @@
 
   if not validate_config_lists(
       system_item_list=system_item_list,
+      system_misc_info_keys=system_misc_info_keys,
       other_item_list=other_item_list):
     sys.exit(1)
 
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index fe40936..37f4e38 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -236,7 +236,7 @@
 POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
 DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt'
 AB_PARTITIONS = 'META/ab_partitions.txt'
-UNZIP_PATTERN = ['IMAGES/*', 'META/*']
+UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'RADIO/*']
 RETROFIT_DAP_UNZIP_PATTERN = ['OTA/super_*.img', AB_PARTITIONS]
 
 
@@ -1802,12 +1802,7 @@
     infolist = input_zip.infolist()
     namelist = input_zip.namelist()
 
-  # Additionally unzip 'RADIO/*' if exists.
-  unzip_pattern = UNZIP_PATTERN[:]
-  if any([entry.startswith('RADIO/') for entry in namelist]):
-    unzip_pattern.append('RADIO/*')
-  input_tmp = common.UnzipTemp(input_file, unzip_pattern)
-
+  input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
   for info in infolist:
     unzipped_file = os.path.join(input_tmp, *info.filename.split('/'))
     if info.filename == 'IMAGES/system_other.img':
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 71598e3..16c1840 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -91,12 +91,12 @@
       Replace the veritykeyid in BOOT/cmdline of input_target_file_zip
       with keyid of the cert pointed by <path_to_X509_PEM_cert_file>.
 
-  --avb_{boot,system,vendor,dtbo,vbmeta}_algorithm <algorithm>
-  --avb_{boot,system,vendor,dtbo,vbmeta}_key <key>
+  --avb_{boot,system,system_other,vendor,dtbo,vbmeta}_algorithm <algorithm>
+  --avb_{boot,system,system_other,vendor,dtbo,vbmeta}_key <key>
       Use the specified algorithm (e.g. SHA256_RSA4096) and the key to AVB-sign
       the specified image. Otherwise it uses the existing values in info dict.
 
-  --avb_{apex,boot,system,vendor,dtbo,vbmeta}_extra_args <args>
+  --avb_{apex,boot,system,system_other,vendor,dtbo,vbmeta}_extra_args <args>
       Specify any additional args that are needed to AVB-sign the image
       (e.g. "--signing_helper /path/to/helper"). The args will be appended to
       the existing ones in info dict.
@@ -400,7 +400,6 @@
 
   APEX_PAYLOAD_IMAGE = 'apex_payload.img'
 
-  # Signing an APEX is a two step process.
   # 1. Extract and sign the APEX_PAYLOAD_IMAGE entry with the given payload_key.
   payload_dir = common.MakeTempDir(prefix='apex-payload-')
   with zipfile.ZipFile(apex_file) as apex_fd:
@@ -420,21 +419,28 @@
   common.ZipWrite(apex_zip, payload_file, arcname=APEX_PAYLOAD_IMAGE)
   common.ZipClose(apex_zip)
 
-  # 2. Sign the overall APEX container with container_key.
+  # 2. Align the files at page boundary (same as in apexer).
+  aligned_apex = common.MakeTempFile(
+      prefix='apex-container-', suffix='.apex')
+  common.RunAndCheckOutput(
+      ['zipalign', '-f', '4096', apex_file, aligned_apex])
+
+  # 3. Sign the APEX container with container_key.
   signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
+
+  # Specify the 4K alignment when calling SignApk.
+  extra_signapk_args = OPTIONS.extra_signapk_args[:]
+  extra_signapk_args.extend(['-a', '4096'])
+
   common.SignFile(
-      apex_file,
+      aligned_apex,
       signed_apex,
       container_key,
       container_pw,
-      codename_to_api_level_map=codename_to_api_level_map)
+      codename_to_api_level_map=codename_to_api_level_map,
+      extra_signapk_args=extra_signapk_args)
 
-  signed_and_aligned_apex = common.MakeTempFile(
-      prefix='apex-container-', suffix='.apex')
-  common.RunAndCheckOutput(
-      ['zipalign', '-f', '4096', signed_apex, signed_and_aligned_apex])
-
-  return (signed_and_aligned_apex, payload_info['apex.key'])
+  return (signed_apex, payload_info['apex.key'])
 
 
 def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
@@ -584,11 +590,23 @@
     elif filename == "META/care_map.pb" or filename == "META/care_map.txt":
       pass
 
+    # Updates system_other.avbpubkey in /product/etc/.
+    elif filename in (
+        "PRODUCT/etc/security/avb/system_other.avbpubkey",
+        "SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
+      # Only update system_other's public key, if the corresponding signing
+      # key is specified via --avb_system_other_key.
+      signing_key = OPTIONS.avb_keys.get("system_other")
+      if signing_key:
+        public_key = common.ExtractAvbPublicKey(signing_key)
+        print("    Rewriting AVB public key of system_other in /product")
+        common.ZipWrite(output_tf_zip, public_key, filename)
+
     # A non-APK file; copy it verbatim.
     else:
       common.ZipWriteStr(output_tf_zip, out_info, data)
 
-  # Update APEX payload public keys.
+  # Copy or update APEX payload public keys.
   for info in input_tf_zip.infolist():
     filename = info.filename
     if (os.path.dirname(filename) != 'SYSTEM/etc/security/apex' or
@@ -597,8 +615,10 @@
 
     name = os.path.basename(filename)
 
-    # Skip PRESIGNED APEXes.
+    # Copy the keys for PRESIGNED APEXes.
     if name not in updated_apex_payload_keys:
+      data = input_tf_zip.read(filename)
+      common.ZipWriteStr(output_tf_zip, info, data)
       continue
 
     key_path = updated_apex_payload_keys[name]
@@ -934,6 +954,7 @@
       'dtbo' : 'avb_dtbo_add_hash_footer_args',
       'recovery' : 'avb_recovery_add_hash_footer_args',
       'system' : 'avb_system_add_hashtree_footer_args',
+      'system_other' : 'avb_system_other_add_hashtree_footer_args',
       'vendor' : 'avb_vendor_add_hashtree_footer_args',
       'vbmeta' : 'avb_vbmeta_args',
   }
@@ -1153,6 +1174,12 @@
       OPTIONS.avb_algorithms['system'] = a
     elif o == "--avb_system_extra_args":
       OPTIONS.avb_extra_args['system'] = a
+    elif o == "--avb_system_other_key":
+      OPTIONS.avb_keys['system_other'] = a
+    elif o == "--avb_system_other_algorithm":
+      OPTIONS.avb_algorithms['system_other'] = a
+    elif o == "--avb_system_other_extra_args":
+      OPTIONS.avb_extra_args['system_other'] = a
     elif o == "--avb_vendor_key":
       OPTIONS.avb_keys['vendor'] = a
     elif o == "--avb_vendor_algorithm":
@@ -1192,6 +1219,9 @@
           "avb_system_algorithm=",
           "avb_system_key=",
           "avb_system_extra_args=",
+          "avb_system_other_algorithm=",
+          "avb_system_other_key=",
+          "avb_system_other_extra_args=",
           "avb_vendor_algorithm=",
           "avb_vendor_key=",
           "avb_vendor_extra_args=",
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 8709124..d4fa5f3 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -359,6 +359,90 @@
     finally:
       os.remove(zip_file.name)
 
+  @staticmethod
+  def _test_UnzipTemp_createZipFile():
+    zip_file = common.MakeTempFile(suffix='.zip')
+    output_zip = zipfile.ZipFile(
+        zip_file, 'w', compression=zipfile.ZIP_DEFLATED)
+    contents = os.urandom(1024)
+    with tempfile.NamedTemporaryFile() as entry_file:
+      entry_file.write(contents)
+      common.ZipWrite(output_zip, entry_file.name, arcname='Test1')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Test2')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Foo3')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Bar4')
+      common.ZipWrite(output_zip, entry_file.name, arcname='Dir5/Baz5')
+      common.ZipClose(output_zip)
+    common.ZipClose(output_zip)
+    return zip_file
+
+  def test_UnzipTemp(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file)
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test1'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test1', 'Foo3'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test*', 'Foo3*'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+    unzipped_dir = common.UnzipTemp(zip_file, ['*Test1', '*Baz*'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withEmptyPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file, [])
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withPartiallyMatchingPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file, ['Test*', 'Nonexistent*'])
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
+  def test_UnzipTemp_withNoMatchingPatterns(self):
+    zip_file = self._test_UnzipTemp_createZipFile()
+    unzipped_dir = common.UnzipTemp(zip_file, ['Foo4', 'Nonexistent*'])
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test1')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Test2')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Foo3')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
+    self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+
 
 class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
   """Tests the APK utils related functions."""