Merge "Revise GSI targets to inherit from mainline_system directly"
diff --git a/core/Makefile b/core/Makefile
index 690c9c1..b2da68b 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -592,33 +592,26 @@
 	$(hide) $(POST_PROCESS_PROPS) $@
 
 # -----------------------------------------------------------------
-# product_services build.prop (unless it's merged into /product)
-ifdef MERGE_PRODUCT_SERVICES_INTO_PRODUCT
-  ifneq (,$(PRODUCT_PRODUCT_SERVICES_PROPERTIES))
-    $(error PRODUCT_PRODUCT_SERVICES_PROPERTIES is not supported in this build.)
-  endif
-else
-INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT_SERVICES)/build.prop
-ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET)
+# system_ext build.prop
+INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/build.prop
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET)
 
-FINAL_PRODUCT_SERVICES_PROPERTIES += \
-    $(call collapse-pairs, $(PRODUCT_PRODUCT_SERVICES_PROPERTIES))
-FINAL_PRODUCT_SERVICES_PROPERTIES := $(call uniq-pairs-by-first-component, \
-    $(FINAL_PRODUCT_SERVICES_PROPERTIES),=)
-$(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS)
-	@echo Target product_services buildinfo: $@
+FINAL_SYSTEM_EXT_PROPERTIES += \
+    $(call collapse-pairs, $(PRODUCT_SYSTEM_EXT_PROPERTIES))
+FINAL_SYSTEM_EXT_PROPERTIES := $(call uniq-pairs-by-first-component, \
+    $(FINAL_SYSTEM_EXT_PROPERTIES),=)
+
+$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(POST_PROCESS_PROPS)
+	@echo Target system_ext buildinfo: $@
 	@mkdir -p $(dir $@)
 	$(hide) echo > $@
-ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
-	$(hide) $(call generate-common-build-props,product_services,$@)
-endif  # BOARD_USES_PRODUCT_SERVICESIMAGE
+	$(hide) $(call generate-common-build-props,system_ext,$@)
 	$(hide) echo "#" >> $@; \
-	        echo "# ADDITIONAL PRODUCT_SERVICES PROPERTIES" >> $@; \
+	        echo "# ADDITIONAL SYSTEM_EXT BUILD PROPERTIES" >> $@; \
 	        echo "#" >> $@;
-	$(hide) $(foreach line,$(FINAL_PRODUCT_SERVICES_PROPERTIES), \
+	$(hide) $(foreach line,$(FINAL_SYSTEM_EXT_PROPERTIES), \
 	    echo "$(line)" >> $@;)
 	$(hide) $(POST_PROCESS_PROPS) $@
-endif # MERGE_PRODUCT_SERVICES_INTO_PRODUCT
 
 # ----------------------------------------------------------------
 
@@ -658,45 +651,105 @@
 # $(2): output dir
 # $(3): mount point
 # $(4): staging dir
+# $(5): module load list
+# $(6): module load list filename
 # Returns the a list of src:dest pairs to install the modules using copy-many-files.
 define build-image-kernel-modules
   $(foreach module,$(1),$(module):$(2)/lib/modules/$(notdir $(module))) \
-  $(eval $(call build-image-kernel-modules-depmod,$(1),$(2),$(3),$(4))) \
+  $(eval $(call build-image-kernel-modules-depmod,$(1),$(3),$(4),$(5),$(6))) \
   $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep:$(2)/lib/modules/modules.dep \
-  $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.alias:$(2)/lib/modules/modules.alias
+  $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.alias:$(2)/lib/modules/modules.alias \
+  $(4)/$(DEPMOD_STAGING_SUBDIR)/$(6):$(2)/lib/modules/$(6)
 endef
 
 # $(1): modules list
-# $(2): output dir
-# $(3): mount point
-# $(4): staging dir
+# $(2): mount point
+# $(3): staging dir
+# $(4): module load list
+# $(5): module load list filename
 define build-image-kernel-modules-depmod
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: .KATI_IMPLICIT_OUTPUTS := $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.alias
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(DEPMOD)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULES := $(1)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_OUTPUT_DIR := $(2)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MOUNT_POINT := $(3)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_STAGING_DIR := $(4)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(1)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: .KATI_IMPLICIT_OUTPUTS := $(3)/$(DEPMOD_STAGING_SUBDIR)/modules.alias $(3)/$(DEPMOD_STAGING_SUBDIR)/$(5)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(DEPMOD)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULES := $(1)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MOUNT_POINT := $(2)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULE_DIR := $(3)/$(DEPMOD_STAGING_SUBDIR)/$(2)/lib/modules
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_STAGING_DIR := $(3)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_LOAD_MODULES := $(4)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_LOAD_FILE := $(3)/$(DEPMOD_STAGING_SUBDIR)/$(5)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(1)
 	@echo depmod $$(PRIVATE_STAGING_DIR)
 	rm -rf $$(PRIVATE_STAGING_DIR)
-	mkdir -p $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/$$(PRIVATE_MOUNT_POINT)/lib/modules
-	cp $$(PRIVATE_MODULES) $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/$$(PRIVATE_MOUNT_POINT)/lib/modules
+	mkdir -p $$(PRIVATE_MODULE_DIR)
+	cp $$(PRIVATE_MODULES) $$(PRIVATE_MODULE_DIR)/
 	$(DEPMOD) -b $$(PRIVATE_STAGING_DIR) 0.0
 	# Turn paths in modules.dep into absolute paths
-	sed -i.tmp -e 's|\([^: ]*/lib/modules/[^: ]*\)|/\1|g' $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/modules.dep
+	sed -i.tmp -e 's|\([^: ]*lib/modules/[^: ]*\)|/\1|g' $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/modules.dep
+	touch $$(PRIVATE_LOAD_FILE)
+	(for MODULE in $$(PRIVATE_LOAD_MODULES); do basename $$$$MODULE >> $$(PRIVATE_LOAD_FILE); done)
 endef
 
+# $(1): staging dir
+# $(2): module load list
+# $(3): module load list filename
+# $(4): output dir
+define module-load-list-copy-paths
+  $(eval $(call build-image-module-load-list,$(1),$(2),$(3))) \
+  $(1)/$(DEPMOD_STAGING_SUBDIR)/$(3):$(4)/lib/modules/$(3)
+endef
+
+# $(1): staging dir
+# $(2): module load list
+# $(3): module load list filename
+define build-image-module-load-list
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_STAGING_DIR := $(1)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_LOAD_MODULES := $(2)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_LOAD_FILENAME := $(3)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): $(2)
+	rm -f $$@
+	(for MODULE in $$(PRIVATE_LOAD_MODULES); do basename $$$$MODULE >> $$@; done)
+endef
+
+
+ifeq ($(BOARD_RECOVERY_KERNEL_MODULES_LOAD),)
+  BOARD_RECOVERY_KERNEL_MODULES_LOAD := $(BOARD_RECOVERY_KERNEL_MODULES)
+endif
+ifeq ($(BOARD_RAMDISK_KERNEL_MODULES_LOAD),)
+  BOARD_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_RAMDISK_KERNEL_MODULES)
+endif
+
+ifdef BOARD_RAMDISK_KERNEL_MODULES
+  ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
+    BOARD_RECOVERY_KERNEL_MODULES += $(BOARD_RAMDISK_KERNEL_MODULES)
+  endif
+endif
+
 ifdef BOARD_RECOVERY_KERNEL_MODULES
-  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery)))
+  ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
+    ifdef BOARD_RAMDISK_KERNEL_MODULES_LOAD
+      ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,ramdisk_modules),$(BOARD_RAMDISK_KERNEL_MODULES_LOAD),modules.load,$(TARGET_RECOVERY_ROOT_OUT)))
+    endif
+  endif
+  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery),$(BOARD_RECOVERY_KERNEL_MODULES_LOAD),modules.load.recovery))
+endif
+
+ifneq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
+  ifdef BOARD_RAMDISK_KERNEL_MODULES
+    ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RAMDISK_KERNEL_MODULES),$(TARGET_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_ramdisk),$(BOARD_RAMDISK_KERNEL_MODULES_LOAD),modules.load))
+  endif
 endif
 
 ifdef BOARD_VENDOR_KERNEL_MODULES
-  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor,$(call intermediates-dir-for,PACKAGING,depmod_vendor)))
+  ifeq ($(BOARD_VENDOR_KERNEL_MODULES_LOAD),)
+    BOARD_VENDOR_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_KERNEL_MODULES)
+  endif
+  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor,$(call intermediates-dir-for,PACKAGING,depmod_vendor),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),modules.load))
 endif
 
 ifdef BOARD_ODM_KERNEL_MODULES
-  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_ODM_KERNEL_MODULES),$(TARGET_OUT_ODM),odm,$(call intermediates-dir-for,PACKAGING,depmod_odm)))
+  ifeq ($(BOARD_RECOVERY_KERNEL_MODULES_LOAD),)
+    BOARD_ODM_KERNEL_MODULES_LOAD := $(BOARD_ODM_KERNEL_MODULES)
+  endif
+  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_ODM_KERNEL_MODULES),$(TARGET_OUT_ODM),odm,$(call intermediates-dir-for,PACKAGING,depmod_odm),$(BOARD_ODM_KERNEL_MODULES_LOAD),modules.load))
 endif
 
 # -----------------------------------------------------------------
@@ -1088,6 +1141,7 @@
 # Remove when b/63676296 is resolved.
 $(error Prebuilt bootimage is only supported for AB targets)
 endif
+INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
 $(eval $(call copy-one-file,$(BOARD_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
 else # BOARD_PREBUILT_BOOTIMAGE not defined
 INSTALLED_BOOTIMAGE_TARGET :=
@@ -1134,10 +1188,10 @@
 $(2) : $(3)
 $(3) : $(6) $(BUILD_SYSTEM)/Makefile build/make/tools/generate-notice-files.py
 	build/make/tools/generate-notice-files.py --text-output $(2) \
-	    $(if $(filter $(1),xml_excluded_extra_partitions),-e vendor -e product -e product_services --xml-output, \
+	    $(if $(filter $(1),xml_excluded_extra_partitions),-e vendor -e product -e system_ext --xml-output, \
 	      $(if $(filter $(1),xml_vendor),-i vendor --xml-output, \
 	        $(if $(filter $(1),xml_product),-i product --xml-output, \
-	          $(if $(filter $(1),xml_product_services),-i product_services --xml-output, \
+	          $(if $(filter $(1),xml_system_ext),-i system_ext --xml-output, \
 	            --html-output)))) $(3) \
 	    -t $$(PRIVATE_MESSAGE) -s $$(PRIVATE_DIR)/src
 notice_files: $(2) $(3)
@@ -1186,10 +1240,10 @@
 target_product_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_PRODUCT.xml.gz
 installed_product_notice_xml_gz := $(TARGET_OUT_PRODUCT)/etc/NOTICE.xml.gz
 
-target_product_services_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_PRODUCT_SERVICES.txt
-target_product_services_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_PRODUCT_SERVICES.xml
-target_product_services_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_PRODUCT_SERVICES.xml.gz
-installed_product_services_notice_xml_gz := $(TARGET_OUT_PRODUCT_SERVICES)/etc/NOTICE.xml.gz
+target_system_ext_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_EXT.txt
+target_system_ext_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_EXT.xml
+target_system_ext_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_EXT.xml.gz
+installed_system_ext_notice_xml_gz := $(TARGET_OUT_SYSTEM_EXT)/etc/NOTICE.xml.gz
 
 # Notice files are copied to TARGET_OUT_NOTICE_FILES as a side-effect of their module
 # being built. A notice xml file must depend on all modules that could potentially
@@ -1201,8 +1255,8 @@
 license_modules := $(filter-out $(TARGET_OUT_TESTCASES)/%,$(license_modules))
 license_modules_vendor := $(filter $(TARGET_OUT_VENDOR)/%,$(license_modules))
 license_modules_product := $(filter $(TARGET_OUT_PRODUCT)/%,$(license_modules))
-license_modules_product_services := $(filter $(TARGET_OUT_PRODUCT_SERVICES)/%,$(license_modules))
-license_modules_agg := $(license_modules_vendor) $(license_modules_product) $(license_modules_product_services)
+license_modules_system_ext := $(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(license_modules))
+license_modules_agg := $(license_modules_vendor) $(license_modules_product) $(license_modules_system_ext)
 license_modules_rest := $(filter-out $(license_modules_agg),$(license_modules))
 
 $(eval $(call combine-notice-files, xml_excluded_extra_partitions, \
@@ -1223,12 +1277,12 @@
 	        "Notices for files contained in the product filesystem image in this directory:", \
 	        $(TARGET_OUT_NOTICE_FILES), \
 	        $(license_modules_product)))
-$(eval $(call combine-notice-files, xml_product_services, \
-	        $(target_product_services_notice_file_txt), \
-	        $(target_product_services_notice_file_xml), \
-	        "Notices for files contained in the product_services filesystem image in this directory:", \
+$(eval $(call combine-notice-files, xml_system_ext, \
+	        $(target_system_ext_notice_file_txt), \
+	        $(target_system_ext_notice_file_xml), \
+	        "Notices for files contained in the system_ext filesystem image in this directory:", \
 	        $(TARGET_OUT_NOTICE_FILES), \
-	        $(license_modules_product_services)))
+	        $(license_modules_system_ext)))
 
 $(target_notice_file_xml_gz): $(target_notice_file_xml) | $(MINIGZIP)
 	$(hide) $(MINIGZIP) -9 < $< > $@
@@ -1236,7 +1290,7 @@
 	$(hide) $(MINIGZIP) -9 < $< > $@
 $(target_product_notice_file_xml_gz): $(target_product_notice_file_xml) | $(MINIGZIP)
 	$(hide) $(MINIGZIP) -9 < $< > $@
-$(target_product_services_notice_file_xml_gz): $(target_product_services_notice_file_xml) | $(MINIGZIP)
+$(target_system_ext_notice_file_xml_gz): $(target_system_ext_notice_file_xml) | $(MINIGZIP)
 	$(hide) $(MINIGZIP) -9 < $< > $@
 $(installed_notice_html_or_xml_gz): $(target_notice_file_xml_gz)
 	$(copy-file-to-target)
@@ -1244,20 +1298,15 @@
 	$(copy-file-to-target)
 $(installed_product_notice_xml_gz): $(target_product_notice_file_xml_gz)
 	$(copy-file-to-target)
-
-# No notice file for product_services if its contents are merged into /product.
-# The notices will be part of the /product notice file.
-ifndef MERGE_PRODUCT_SERVICES_INTO_PRODUCT
-$(installed_product_services_notice_xml_gz): $(target_product_services_notice_file_xml_gz)
+$(installed_system_ext_notice_xml_gz): $(target_system_ext_notice_file_xml_gz)
 	$(copy-file-to-target)
-endif
 
 # if we've been run my mm, mmm, etc, don't reinstall this every time
 ifeq ($(ONE_SHOT_MAKEFILE),)
   ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz)
   ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_notice_xml_gz)
   ALL_DEFAULT_INSTALLED_MODULES += $(installed_product_notice_xml_gz)
-  ALL_DEFAULT_INSTALLED_MODULES += $(installed_product_services_notice_xml_gz)
+  ALL_DEFAULT_INSTALLED_MODULES += $(installed_system_ext_notice_xml_gz)
 endif
 endif # PRODUCT_NOTICE_SPLIT
 
@@ -1310,26 +1359,25 @@
 ifneq (true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED))
   INTERNAL_USERIMAGES_SPARSE_EXT_FLAG := -s
 endif
-
-INTERNAL_USERIMAGES_DEPS := $(SIMG2IMG)
-INTERNAL_USERIMAGES_DEPS += $(MKEXTUSERIMG) $(MAKE_EXT4FS) $(E2FSCK) $(TUNE2FS)
-ifeq ($(TARGET_USERIMAGES_USE_F2FS),true)
-INTERNAL_USERIMAGES_DEPS += $(MKF2FSUSERIMG) $(MAKE_F2FS)
-endif
-
-ifeq ($(BOARD_AVB_ENABLE),true)
-INTERNAL_USERIMAGES_DEPS += $(AVBTOOL)
-endif
-
 ifneq (true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED))
   INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG := -s
 endif
-ifneq ($(filter $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE) $(BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE) $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE) $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE) $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),squashfs),)
-INTERNAL_USERIMAGES_DEPS += $(MAKE_SQUASHFS) $(MKSQUASHFSUSERIMG) $(IMG2SIMG)
+
+INTERNAL_USERIMAGES_DEPS := \
+    $(BLK_ALLOC_TO_BASE_FS) \
+    $(E2FSCK) \
+    $(MKE2FS_CONF) \
+    $(MKEXTUSERIMG) \
+    $(SIMG2IMG) \
+    $(TUNE2FS)
+
+ifeq ($(TARGET_USERIMAGES_USE_F2FS),true)
+INTERNAL_USERIMAGES_DEPS += $(MKF2FSUSERIMG)
 endif
 
-# Get a colon-separated list of search paths.
-INTERNAL_USERIMAGES_BINARY_PATHS := $(subst $(space),:,$(sort $(dir $(INTERNAL_USERIMAGES_DEPS))))
+ifneq ($(filter $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE) $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE) $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE) $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE) $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),squashfs),)
+INTERNAL_USERIMAGES_DEPS += $(MKSQUASHFSUSERIMG)
+endif
 
 ifeq (true,$(PRODUCT_SUPPORTS_VERITY))
 INTERNAL_USERIMAGES_DEPS += $(BUILD_VERITY_METADATA) $(BUILD_VERITY_TREE) $(APPEND2SIMG) $(VERITY_SIGNER)
@@ -1338,13 +1386,16 @@
 endif
 endif
 
+ifeq ($(BOARD_AVB_ENABLE),true)
+INTERNAL_USERIMAGES_DEPS += $(AVBTOOL)
+endif
+
+# Get a colon-separated list of search paths.
+INTERNAL_USERIMAGES_BINARY_PATHS := $(subst $(space),:,$(sort $(dir $(INTERNAL_USERIMAGES_DEPS))))
+
 SELINUX_FC := $(call intermediates-dir-for,ETC,file_contexts.bin)/file_contexts.bin
 INTERNAL_USERIMAGES_DEPS += $(SELINUX_FC)
 
-INTERNAL_USERIMAGES_DEPS += $(BLK_ALLOC_TO_BASE_FS)
-
-INTERNAL_USERIMAGES_DEPS += $(MKE2FS_CONF)
-
 ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
 
 ifeq ($(PRODUCT_SUPPORTS_VERITY),true)
@@ -1357,7 +1408,7 @@
 endif # PRODUCT_USE_DYNAMIC_PARTITIONS
 
 # $(1): the path of the output dictionary file
-# $(2): a subset of "system vendor cache userdata product product_services oem odm"
+# $(2): a subset of "system vendor cache userdata product system_ext oem odm"
 # $(3): additional "key=value" pairs to append to the dictionary file.
 define generate-image-prop-dictionary
 $(if $(filter $(2),system),\
@@ -1414,18 +1465,18 @@
     $(if $(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "product_reserved_size=$(BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
     $(hide) echo "product_selinux_fc=$(SELINUX_FC)" >> $(1)
 )
-$(if $(filter $(2),product_services),\
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "product_services_fs_type=$(BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_EXTFS_INODE_COUNT),$(hide) echo "product_services_extfs_inode_count=$(BOARD_PRODUCT_SERVICESIMAGE_EXTFS_INODE_COUNT)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_EXTFS_RSV_PCT),$(hide) echo "product_services_extfs_rsv_pct=$(BOARD_PRODUCT_SERVICESIMAGE_EXTFS_RSV_PCT)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE),$(hide) echo "product_services_size=$(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_JOURNAL_SIZE),$(hide) echo "product_services_journal_size=$(BOARD_PRODUCT_SERVICESIMAGE_JOURNAL_SIZE)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "product_services_squashfs_compressor=$(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "product_services_squashfs_compressor_opt=$(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "product_services_squashfs_block_size=$(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "product_services_squashfs_disable_4k_align=$(BOARD_PRODUCT_SERVICESIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
-    $(if $(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "product_services_reserved_size=$(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
-    $(hide) echo "product_services_selinux_fc=$(SELINUX_FC)" >> $(1)
+$(if $(filter $(2),system_ext),\
+    $(if $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_ext_fs_type=$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_EXTFS_INODE_COUNT),$(hide) echo "system_ext_extfs_inode_count=$(BOARD_SYSTEM_EXTIMAGE_EXTFS_INODE_COUNT)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_EXTFS_RSV_PCT),$(hide) echo "system_ext_extfs_rsv_pct=$(BOARD_SYSTEM_EXTIMAGE_EXTFS_RSV_PCT)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE),$(hide) echo "system_ext_size=$(BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_JOURNAL_SIZE),$(hide) echo "system_ext_journal_size=$(BOARD_SYSTEM_EXTIMAGE_JOURNAL_SIZE)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_ext_squashfs_compressor=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_ext_squashfs_compressor_opt=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_ext_squashfs_block_size=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "system_ext_squashfs_disable_4k_align=$(BOARD_SYSTEM_EXTIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
+    $(if $(BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE),$(hide) echo "system_ext_reserved_size=$(BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE)" >> $(1))
+    $(hide) echo "system_ext_selinux_fc=$(SELINUX_FC)" >> $(1)
 )
 $(if $(filter $(2),odm),\
     $(if $(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "odm_fs_type=$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
@@ -1465,7 +1516,7 @@
 $(if $(PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1))
 $(if $(PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1))
 $(if $(PRODUCT_PRODUCT_VERITY_PARTITION),$(hide) echo "product_verity_block_device=$(PRODUCT_PRODUCT_VERITY_PARTITION)" >> $(1))
-$(if $(PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION),$(hide) echo "product_services_verity_block_device=$(PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION)" >> $(1))
+$(if $(PRODUCT_SYSTEM_EXT_VERITY_PARTITION),$(hide) echo "system_ext_verity_block_device=$(PRODUCT_SYSTEM_EXT_VERITY_PARTITION)" >> $(1))
 $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCT_SUPPORTS_VBOOT)" >> $(1))
 $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCT_VBOOT_SIGNING_KEY)" >> $(1))
 $(if $(PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
@@ -1499,14 +1550,14 @@
         $(hide) echo "avb_product_key_path=$(BOARD_AVB_PRODUCT_KEY_PATH)" >> $(1)
         $(hide) echo "avb_product_algorithm=$(BOARD_AVB_PRODUCT_ALGORITHM)" >> $(1)
         $(hide) echo "avb_product_rollback_index_location=$(BOARD_AVB_PRODUCT_ROLLBACK_INDEX_LOCATION)" >> $(1)))
-$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_product_services_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_system_ext_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),\
-    $(hide) echo "avb_product_services_add_hashtree_footer_args=$(BOARD_AVB_PRODUCT_SERVICES_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
+    $(hide) echo "avb_system_ext_add_hashtree_footer_args=$(BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),\
-    $(if $(BOARD_AVB_PRODUCT_SERVICES_KEY_PATH),\
-        $(hide) echo "avb_product_services_key_path=$(BOARD_AVB_PRODUCT_SERVICES_KEY_PATH)" >> $(1)
-        $(hide) echo "avb_product_services_algorithm=$(BOARD_AVB_PRODUCT_SERVICES_ALGORITHM)" >> $(1)
-        $(hide) echo "avb_product_services_rollback_index_location=$(BOARD_AVB_PRODUCT_SERVICES_ROLLBACK_INDEX_LOCATION)" >> $(1)))
+    $(if $(BOARD_AVB_SYSTEM_EXT_KEY_PATH),\
+        $(hide) echo "avb_system_ext_key_path=$(BOARD_AVB_SYSTEM_EXT_KEY_PATH)" >> $(1)
+        $(hide) echo "avb_system_ext_algorithm=$(BOARD_AVB_SYSTEM_EXT_ALGORITHM)" >> $(1)
+        $(hide) echo "avb_system_ext_rollback_index_location=$(BOARD_AVB_SYSTEM_EXT_ROLLBACK_INDEX_LOCATION)" >> $(1)))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_odm_add_hashtree_footer_args=$(BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
 $(if $(BOARD_AVB_ENABLE),\
@@ -1541,8 +1592,8 @@
 ifdef BUILDING_PRODUCT_IMAGE
   PROP_DICTIONARY_IMAGES += product
 endif
-ifdef BUILDING_PRODUCT_SERVICES_IMAGE
-  PROP_DICTIONARY_IMAGES += product_services
+ifdef BUILDING_SYSTEM_EXT_IMAGE
+  PROP_DICTIONARY_IMAGES += system_ext
 endif
 ifdef BUILDING_ODM_IMAGE
   PROP_DICTIONARY_IMAGES += odm
@@ -1818,7 +1869,7 @@
 	    $(INSTALLED_VENDOR_BUILD_PROP_TARGET) \
 	    $(INSTALLED_ODM_BUILD_PROP_TARGET) \
 	    $(INSTALLED_PRODUCT_BUILD_PROP_TARGET) \
-	    $(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET)
+	    $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET)
 	@echo "Target recovery buildinfo: $@"
 	$(hide) mkdir -p $(dir $@)
 	$(hide) rm -f $@
@@ -1828,7 +1879,7 @@
 	$(hide) cat $(INSTALLED_VENDOR_BUILD_PROP_TARGET) >> $@
 	$(hide) cat $(INSTALLED_ODM_BUILD_PROP_TARGET) >> $@
 	$(hide) cat $(INSTALLED_PRODUCT_BUILD_PROP_TARGET) >> $@
-	$(hide) cat $(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET) >> $@
+	$(hide) cat $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET) >> $@
 	$(call append-recovery-ui-properties,$(PRIVATE_RECOVERY_UI_PROPERTIES),$@)
 
 INTERNAL_RECOVERYIMAGE_ARGS := \
@@ -2212,33 +2263,18 @@
 endef
 endif
 
-# Create symlink /system/product_services to /product_services if necessary.
-ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
-define create-system-product_services-symlink
-$(hide) if [ -d $(TARGET_OUT)/product_services ] && [ ! -h $(TARGET_OUT)/product_services ]; then \
-  echo 'Non-symlink $(TARGET_OUT)/product_services detected!' 1>&2; \
-  echo 'You cannot install files to $(TARGET_OUT)/product_services while building a separate product_services.img!' 1>&2; \
+# Create symlink /system/system_ext to /system_ext if necessary.
+ifdef BOARD_USES_SYSTEM_EXTIMAGE
+define create-system-system_ext-symlink
+$(hide) if [ -d $(TARGET_OUT)/system_ext ] && [ ! -h $(TARGET_OUT)/system_ext ]; then \
+  echo 'Non-symlink $(TARGET_OUT)/system_ext detected!' 1>&2; \
+  echo 'You cannot install files to $(TARGET_OUT)/system_ext while building a separate system_ext.img!' 1>&2; \
   exit 1; \
 fi
-$(hide) ln -sf /product_services $(TARGET_OUT)/product_services
+$(hide) ln -sf /system_ext $(TARGET_OUT)/system_ext
 endef
 else
-define create-system-product_services-symlink
-endef
-endif
-
-# Create symlink /vendor/odm to /odm if necessary.
-ifdef BOARD_USES_ODMIMAGE
-define create-vendor-odm-symlink
-$(hide) if [ -d $(TARGET_OUT_VENDOR)/odm ] && [ ! -h $(TARGET_OUT_VENDOR)/odm ]; then \
-  echo 'Non-symlink $(TARGET_OUT_VENDOR)/odm detected!' 1>&2; \
-  echo 'You cannot install files to $(TARGET_OUT_VENDOR)/odm while building a separate odm.img!' 1>&2; \
-  exit 1; \
-fi
-$(hide) ln -sf /odm $(TARGET_OUT_VENDOR)/odm
-endef
-else
-define create-vendor-odm-symlink
+define create-system-system_ext-symlink
 endef
 endif
 
@@ -2247,7 +2283,7 @@
   @echo "Target system fs image: $(1)"
   $(call create-system-vendor-symlink)
   $(call create-system-product-symlink)
-  $(call create-system-product_services-symlink)
+  $(call create-system-system_ext-symlink)
   $(call check-apex-libs-absence-on-disk)
   @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, \
@@ -2332,7 +2368,7 @@
   $(call pretty,"Target system fs tarball: $(INSTALLED_SYSTEMTARBALL_TARGET)")
   $(call create-system-vendor-symlink)
   $(call create-system-product-symlink)
-  $(call create-system-product_services-symlink)
+  $(call create-system-system_ext-symlink)
   $(MKTARBALL) $(FS_GET_STATS) \
     $(PRODUCT_OUT) system $(PRIVATE_SYSTEM_TAR) \
     $(INSTALLED_SYSTEMTARBALL_TARGET) $(TARGET_OUT)
@@ -2419,8 +2455,8 @@
 ifdef BUILDING_PRODUCT_IMAGE
 	echo "-D $(TARGET_OUT_PRODUCT)" >> $@.lst
 endif
-ifdef BUILDING_PRODUCT_SERVICES_IMAGE
-	echo "-D $(TARGET_OUT_PRODUCT_SERVICES)" >> $@.lst
+ifdef BUILDING_SYSTEM_EXT_IMAGE
+	echo "-D $(TARGET_OUT_SYSTEM_EXT)" >> $@.lst
 endif
 ifdef BUILDING_ODM_IMAGE
 	echo "-D $(TARGET_OUT_ODM)" >> $@.lst
@@ -2806,6 +2842,21 @@
 	$(hide) $(FILESLIST) $(TARGET_OUT_VENDOR) > $(@:.txt=.json)
 	$(hide) $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
 
+# Create symlink /vendor/odm to /odm if necessary.
+ifdef BOARD_USES_ODMIMAGE
+define create-vendor-odm-symlink
+$(hide) if [ -d $(TARGET_OUT_VENDOR)/odm ] && [ ! -h $(TARGET_OUT_VENDOR)/odm ]; then \
+  echo 'Non-symlink $(TARGET_OUT_VENDOR)/odm detected!' 1>&2; \
+  echo 'You cannot install files to $(TARGET_OUT_VENDOR)/odm while building a separate odm.img!' 1>&2; \
+  exit 1; \
+fi
+$(hide) ln -sf /odm $(TARGET_OUT_VENDOR)/odm
+endef
+else
+define create-vendor-odm-symlink
+endef
+endif
+
 vendorimage_intermediates := \
     $(call intermediates-dir-for,PACKAGING,vendor)
 BUILT_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vendor.img
@@ -2939,55 +2990,55 @@
 endif # BUILDING_SYSTEM_IMAGE
 
 # -----------------------------------------------------------------
-# product_services partition image
-ifdef BUILDING_PRODUCT_SERVICES_IMAGE
-INTERNAL_PRODUCT_SERVICESIMAGE_FILES := \
-    $(filter $(TARGET_OUT_PRODUCT_SERVICES)/%,\
+# system_ext partition image
+ifdef BUILDING_SYSTEM_EXT_IMAGE
+INTERNAL_SYSTEM_EXTIMAGE_FILES := \
+    $(filter $(TARGET_OUT_SYSTEM_EXT)/%,\
       $(ALL_DEFAULT_INSTALLED_MODULES)\
       $(ALL_PDK_FUSION_FILES)) \
     $(PDK_FUSION_SYMLINK_STAMP)
 
-# platform.zip depends on $(INTERNAL_PRODUCT_SERVICESIMAGE_FILES).
-$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_PRODUCT_SERVICESIMAGE_FILES)
+# platform.zip depends on $(INTERNAL_SYSTEM_EXTIMAGE_FILES).
+$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_SYSTEM_EXTIMAGE_FILES)
 
-INSTALLED_FILES_FILE_PRODUCT_SERVICES := $(PRODUCT_OUT)/installed-files-product_services.txt
-INSTALLED_FILES_JSON_PRODUCT_SERVICES := $(INSTALLED_FILES_FILE_PRODUCT_SERVICES:.txt=.json)
-$(INSTALLED_FILES_FILE_PRODUCT_SERVICES): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_PRODUCT_SERVICES)
-$(INSTALLED_FILES_FILE_PRODUCT_SERVICES) : $(INTERNAL_PRODUCT_SERVICESIMAGE_FILES) $(FILESLIST) $(FILESLIST_UTIL)
+INSTALLED_FILES_FILE_SYSTEM_EXT := $(PRODUCT_OUT)/installed-files-system_ext.txt
+INSTALLED_FILES_JSON_SYSTEM_EXT := $(INSTALLED_FILES_FILE_SYSTEM_EXT:.txt=.json)
+$(INSTALLED_FILES_FILE_SYSTEM_EXT): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_SYSTEM_EXT)
+$(INSTALLED_FILES_FILE_SYSTEM_EXT) : $(INTERNAL_SYSTEM_EXTIMAGE_FILES) $(FILESLIST) $(FILESLIST_UTIL)
 	@echo Installed file list: $@
 	@mkdir -p $(dir $@)
 	@rm -f $@
-	$(hide) $(FILESLIST) $(TARGET_OUT_PRODUCT_SERVICES) > $(@:.txt=.json)
+	$(hide) $(FILESLIST) $(TARGET_OUT_SYSTEM_EXT) > $(@:.txt=.json)
 	$(hide) $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
 
-product_servicesimage_intermediates := \
-    $(call intermediates-dir-for,PACKAGING,product_services)
-BUILT_PRODUCT_SERVICESIMAGE_TARGET := $(PRODUCT_OUT)/product_services.img
-define build-product_servicesimage-target
-  $(call pretty,"Target product_services fs image: $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET)")
-  @mkdir -p $(TARGET_OUT_PRODUCT_SERVICES)
-  @mkdir -p $(product_servicesimage_intermediates) && rm -rf $(product_servicesimage_intermediates)/product_services_image_info.txt
-  $(call generate-image-prop-dictionary, $(product_servicesimage_intermediates)/product_services_image_info.txt,product_services, skip_fsck=true)
+system_extimage_intermediates := \
+    $(call intermediates-dir-for,PACKAGING,system_ext)
+BUILT_SYSTEM_EXTIMAGE_TARGET := $(PRODUCT_OUT)/system_ext.img
+define build-system_extimage-target
+  $(call pretty,"Target system_ext fs image: $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)")
+  @mkdir -p $(TARGET_OUT_SYSTEM_EXT)
+  @mkdir -p $(system_extimage_intermediates) && rm -rf $(system_extimage_intermediates)/system_ext_image_info.txt
+  $(call generate-image-prop-dictionary, $(system_extimage_intermediates)/system_ext_image_info.txt,system_ext, skip_fsck=true)
   PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
       ./build/tools/releasetools/build_image.py \
-      $(TARGET_OUT_PRODUCT_SERVICES) $(product_servicesimage_intermediates)/product_services_image_info.txt $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) $(TARGET_OUT)
-  $(hide) $(call assert-max-image-size,$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET),$(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE))
+      $(TARGET_OUT_SYSTEM_EXT) $(system_extimage_intermediates)/system_ext_image_info.txt $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) $(TARGET_OUT)
+  $(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEM_EXTIMAGE_TARGET),$(BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE))
 endef
 
 # We just build this directly to the install location.
-INSTALLED_PRODUCT_SERVICESIMAGE_TARGET := $(BUILT_PRODUCT_SERVICESIMAGE_TARGET)
-$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_PRODUCT_SERVICESIMAGE_FILES) $(INSTALLED_FILES_FILE_PRODUCT_SERVICES) $(BUILD_IMAGE_SRCS)
-	$(build-product_servicesimage-target)
+INSTALLED_SYSTEM_EXTIMAGE_TARGET := $(BUILT_SYSTEM_EXTIMAGE_TARGET)
+$(INSTALLED_SYSTEM_EXTIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEM_EXTIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEM_EXT) $(BUILD_IMAGE_SRCS)
+	$(build-system_extimage-target)
 
-.PHONY: productservicesimage-nodeps psnod
-productservicesimage-nodeps psnod: | $(INTERNAL_USERIMAGES_DEPS)
-	$(build-product_servicesimage-target)
+.PHONY: systemextimage-nodeps senod
+systemextimage-nodeps senod: | $(INTERNAL_USERIMAGES_DEPS)
+	$(build-system_extimage-target)
 
-sync: $(INTERNAL_PRODUCT_SERVICESIMAGE_FILES)
+sync: $(INTERNAL_SYSTEM_EXTIMAGE_FILES)
 
-else ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
-INSTALLED_PRODUCT_SERVICESIMAGE_TARGET := $(PRODUCT_OUT)/product_services.img
-$(eval $(call copy-one-file,$(BOARD_PREBUILT_PRODUCT_SERVICESIMAGE),$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET)))
+else ifdef BOARD_PREBUILT_SYSTEM_EXTIMAGE
+INSTALLED_SYSTEM_EXTIMAGE_TARGET := $(PRODUCT_OUT)/system_ext.img
+$(eval $(call copy-one-file,$(BOARD_PREBUILT_SYSTEM_EXTIMAGE),$(INSTALLED_SYSTEM_EXTIMAGE_TARGET)))
 endif
 
 # -----------------------------------------------------------------
@@ -3064,7 +3115,7 @@
 # Returns a list of image targets corresponding to the given list of partitions. For example, it
 # returns "$(INSTALLED_PRODUCTIMAGE_TARGET)" for "product", or "$(INSTALLED_SYSTEMIMAGE_TARGET)
 # $(INSTALLED_VENDORIMAGE_TARGET)" for "system vendor".
-# (1): list of partitions like "system", "vendor" or "system product product_services".
+# (1): list of partitions like "system", "vendor" or "system product system_ext".
 define images-for-partitions
 $(strip $(foreach item,$(1),$(INSTALLED_$(call to-upper,$(item))IMAGE_TARGET)))
 endef
@@ -3126,9 +3177,9 @@
     --prop com.android.build.product.os_version:$(PLATFORM_VERSION) \
     --prop com.android.build.product.security_patch:$(PLATFORM_SECURITY_PATCH)
 
-BOARD_AVB_PRODUCT_SERVICES_ADD_HASHTREE_FOOTER_ARGS += \
-    --prop com.android.build.product_services.os_version:$(PLATFORM_VERSION) \
-    --prop com.android.build.product_services.security_patch:$(PLATFORM_SECURITY_PATCH)
+BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS += \
+    --prop com.android.build.system_ext.os_version:$(PLATFORM_VERSION) \
+    --prop com.android.build.system_ext.security_patch:$(PLATFORM_SECURITY_PATCH)
 
 BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
     --prop com.android.build.boot.os_version:$(PLATFORM_VERSION)
@@ -3161,7 +3212,7 @@
 VENDOR_FOOTER_ARGS := BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS
 RECOVERY_FOOTER_ARGS := BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS
 PRODUCT_FOOTER_ARGS := BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS
-PRODUCT_SERVICES_FOOTER_ARGS := BOARD_AVB_PRODUCT_SERVICES_ADD_HASHTREE_FOOTER_ARGS
+SYSTEM_EXT_FOOTER_ARGS := BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS
 ODM_FOOTER_ARGS := BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS
 
 # Helper function that checks and sets required build variables for an AVB chained partition.
@@ -3224,8 +3275,8 @@
 $(eval $(call check-and-set-avb-args,product))
 endif
 
-ifdef INSTALLED_PRODUCT_SERVICESIMAGE_TARGET
-$(eval $(call check-and-set-avb-args,product_services))
+ifdef INSTALLED_SYSTEM_EXTIMAGE_TARGET
+$(eval $(call check-and-set-avb-args,system_ext))
 endif
 
 ifdef INSTALLED_ODMIMAGE_TARGET
@@ -3298,9 +3349,9 @@
   $(if $(BOARD_AVB_PRODUCT_KEY_PATH),\
     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_PRODUCT_KEY_PATH) \
       --output $(1)/product.avbpubkey)
-  $(if $(BOARD_AVB_PRODUCT_SERVICES_KEY_PATH),\
-    $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_PRODUCT_SERVICES_KEY_PATH) \
-      --output $(1)/product_services.avbpubkey)
+  $(if $(BOARD_AVB_SYSTEM_EXT_KEY_PATH),\
+    $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_EXT_KEY_PATH) \
+      --output $(1)/system_ext.avbpubkey)
   $(if $(BOARD_AVB_ODM_KEY_PATH),\
     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_ODM_KEY_PATH) \
       --output $(1)/odm.avbpubkey)
@@ -3321,8 +3372,8 @@
 # Builds a chained VBMeta image. This VBMeta image will contain the descriptors for the partitions
 # specified in BOARD_AVB_VBMETA_<NAME>. The built VBMeta image will be included into the top-level
 # vbmeta image as a chained partition. For example, if a target defines `BOARD_AVB_VBMETA_SYSTEM
-# := system product_services`, `vbmeta_system.img` will be created that includes the descriptors
-# for `system.img` and `product_services.img`. `vbmeta_system.img` itself will be included into
+# := system system_ext`, `vbmeta_system.img` will be created that includes the descriptors for
+# `system.img` and `system_ext.img`. `vbmeta_system.img` itself will be included into
 # `vbmeta.img` as a chained partition.
 # $(1): VBMeta image name, such as "vbmeta_system", "vbmeta_vendor" etc.
 # $(2): Output filename.
@@ -3378,7 +3429,7 @@
 	    $(INSTALLED_SYSTEMIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
 	    $(INSTALLED_PRODUCTIMAGE_TARGET) \
-	    $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) \
+	    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
 	    $(INSTALLED_ODMIMAGE_TARGET) \
 	    $(INSTALLED_DTBOIMAGE_TARGET) \
 	    $(INSTALLED_RECOVERYIMAGE_TARGET) \
@@ -3403,7 +3454,7 @@
 
 ifeq (true,$(PRODUCT_BUILD_SUPER_PARTITION))
 
-# (1): list of items like "system", "vendor", "product", "product_services"
+# (1): list of items like "system", "vendor", "product", "system_ext"
 # return: map each item into a command ( wrapped in $$() ) that reads the size
 define read-size-of-partitions
 $(foreach image,$(call images-for-partitions,$(1)),$$( \
@@ -3616,6 +3667,7 @@
   imgdiff \
   libconscrypt_openjdk_jni \
   lpmake \
+  lpunpack \
   make_f2fs \
   minigzip \
   mkbootfs \
@@ -3831,7 +3883,7 @@
 	    $(INSTALLED_CACHEIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
 	    $(INSTALLED_PRODUCTIMAGE_TARGET) \
-	    $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) \
+	    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
 	    $(INSTALLED_VBMETAIMAGE_TARGET) \
 	    $(INSTALLED_ODMIMAGE_TARGET) \
 	    $(INSTALLED_DTBOIMAGE_TARGET) \
@@ -3846,7 +3898,7 @@
 	    $(PRODUCT_SYSTEM_BASE_FS_PATH) \
 	    $(PRODUCT_VENDOR_BASE_FS_PATH) \
 	    $(PRODUCT_PRODUCT_BASE_FS_PATH) \
-	    $(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH) \
+	    $(PRODUCT_SYSTEM_EXT_BASE_FS_PATH) \
 	    $(PRODUCT_ODM_BASE_FS_PATH) \
 	    $(LPMAKE) \
 	    $(SELINUX_FC) \
@@ -3866,7 +3918,7 @@
 	@echo "Package target files: $@"
 	$(call create-system-vendor-symlink)
 	$(call create-system-product-symlink)
-	$(call create-system-product_services-symlink)
+	$(call create-system-system_ext-symlink)
 	$(call create-vendor-odm-symlink)
 	$(hide) rm -rf $@ $@.list $(zip_root)
 	$(hide) mkdir -p $(dir $@) $(zip_root)
@@ -3957,10 +4009,10 @@
 	$(hide) $(call package_files-copy-root, \
 	    $(TARGET_OUT_PRODUCT),$(zip_root)/PRODUCT)
 endif
-ifdef BUILDING_PRODUCT_SERVICES_IMAGE
-	@# Contents of the product_services image
+ifdef BUILDING_SYSTEM_EXT_IMAGE
+	@# Contents of the system_ext image
 	$(hide) $(call package_files-copy-root, \
-	    $(TARGET_OUT_PRODUCT_SERVICES),$(zip_root)/PRODUCT_SERVICES)
+	    $(TARGET_OUT_SYSTEM_EXT),$(zip_root)/SYSTEM_EXT)
 endif
 ifdef BUILDING_ODM_IMAGE
 	@# Contents of the odm image
@@ -4048,9 +4100,9 @@
 	$(hide) cp $(PRODUCT_PRODUCT_BASE_FS_PATH) \
 	  $(zip_root)/META/$(notdir $(PRODUCT_PRODUCT_BASE_FS_PATH))
 endif
-ifneq ($(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH),)
-	$(hide) cp $(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH) \
-	  $(zip_root)/META/$(notdir $(PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH))
+ifneq ($(PRODUCT_SYSTEM_EXT_BASE_FS_PATH),)
+	$(hide) cp $(PRODUCT_SYSTEM_EXT_BASE_FS_PATH) \
+	  $(zip_root)/META/$(notdir $(PRODUCT_SYSTEM_EXT_BASE_FS_PATH))
 endif
 ifneq ($(PRODUCT_ODM_BASE_FS_PATH),)
 	$(hide) cp $(PRODUCT_ODM_BASE_FS_PATH) \
@@ -4140,9 +4192,9 @@
 	$(hide) mkdir -p $(zip_root)/IMAGES
 	$(hide) cp $(INSTALLED_PRODUCTIMAGE_TARGET) $(zip_root)/IMAGES/
 endif
-ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
+ifdef BOARD_PREBUILT_SYSTEM_EXTIMAGE
 	$(hide) mkdir -p $(zip_root)/IMAGES
-	$(hide) cp $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) $(zip_root)/IMAGES/
+	$(hide) cp $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) $(zip_root)/IMAGES/
 endif
 ifdef BOARD_PREBUILT_BOOTIMAGE
 	$(hide) mkdir -p $(zip_root)/IMAGES
@@ -4184,8 +4236,8 @@
 ifdef BUILDING_PRODUCT_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/PRODUCT,product/) > $(zip_root)/META/product_filesystem_config.txt
 endif
-ifdef BUILDING_PRODUCT_SERVICES_IMAGE
-	$(hide) $(call fs_config,$(zip_root)/PRODUCT_SERVICES,product_services/) > $(zip_root)/META/product_services_filesystem_config.txt
+ifdef BUILDING_SYSTEM_EXT_IMAGE
+	$(hide) $(call fs_config,$(zip_root)/SYSTEM_EXT,system_ext/) > $(zip_root)/META/system_ext_filesystem_config.txt
 endif
 ifdef BUILDING_ODM_IMAGE
 	$(hide) $(call fs_config,$(zip_root)/ODM,odm/) > $(zip_root)/META/odm_filesystem_config.txt
@@ -4261,14 +4313,14 @@
 # $(1): output file
 # $(2): additional args
 define build-ota-package-target
-PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \
-   build/make/tools/releasetools/ota_from_target_files -v \
-   --block \
-   --extracted_input_target_files $(patsubst %.zip,%,$(BUILT_TARGET_FILES_PACKAGE)) \
-   -p $(HOST_OUT) \
-   $(if $(OEM_OTA_CONFIG), -o $(OEM_OTA_CONFIG)) \
-   $(2) \
-   $(BUILT_TARGET_FILES_PACKAGE) $(1)
+PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH \
+    build/make/tools/releasetools/ota_from_target_files \
+    --verbose \
+    --extracted_input_target_files $(patsubst %.zip,%,$(BUILT_TARGET_FILES_PACKAGE)) \
+    --path $(HOST_OUT) \
+    $(if $(OEM_OTA_CONFIG), --oem_settings $(OEM_OTA_CONFIG)) \
+    $(2) \
+    $(BUILT_TARGET_FILES_PACKAGE) $(1)
 endef
 
 name := $(TARGET_PRODUCT)
@@ -4340,7 +4392,7 @@
 	    $(INSTALLED_USERDATAIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
 	    $(INSTALLED_PRODUCTIMAGE_TARGET) \
-	    $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET)
+	    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
 endif
 $(APPCOMPAT_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,appcompat)/filelist
 $(APPCOMPAT_ZIP): $(SOONG_ZIP)
@@ -4369,7 +4421,7 @@
 	    $(INSTALLED_USERDATAIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
 	    $(INSTALLED_PRODUCTIMAGE_TARGET) \
-	    $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) \
+	    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
 	    $(INSTALLED_ODMIMAGE_TARGET) \
 	    $(updater_dep)
 endif
@@ -4395,7 +4447,7 @@
 	    $(INSTALLED_USERDATAIMAGE_TARGET) \
 	    $(INSTALLED_VENDORIMAGE_TARGET) \
 	    $(INSTALLED_PRODUCTIMAGE_TARGET) \
-	    $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) \
+	    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
 	    $(INSTALLED_ODMIMAGE_TARGET)
 endif
 $(COVERAGE_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,coverage)/filelist
@@ -4472,6 +4524,19 @@
 
 endif # TARGET_BUILD_APPS
 
+
+ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
+
+# Dump variables used by build_super_image.py (for building super.img and super_empty.img).
+# $(1): output file
+define dump-super-image-info
+  $(call dump-dynamic-partitions-info,$(1))
+  $(if $(filter true,$(AB_OTA_UPDATER)), \
+    echo "ab_update=true" >> $(1))
+endef
+
+endif # PRODUCT_USE_DYNAMIC_PARTITIONS
+
 # -----------------------------------------------------------------
 # super partition image (dist)
 
@@ -4480,13 +4545,6 @@
 # BOARD_SUPER_PARTITION_SIZE must be defined to build super image.
 ifneq ($(BOARD_SUPER_PARTITION_SIZE),)
 
-# Dump variables used by build_super_image.py.
-define dump-super-image-info
-  $(call dump-dynamic-partitions-info,$(1))
-  $(if $(filter true,$(AB_OTA_UPDATER)), \
-    echo "ab_update=true" >> $(1))
-endef
-
 ifneq (true,$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS))
 
 # For real devices and for dist builds, build super image from target files to an intermediate directory.
@@ -4567,7 +4625,7 @@
 # -----------------------------------------------------------------
 # super empty image
 
-ifeq (true,$(PRODUCT_BUILD_SUPER_PARTITION))
+ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
 ifneq ($(BOARD_SUPER_PARTITION_SIZE),)
 
 INSTALLED_SUPERIMAGE_EMPTY_TARGET := $(PRODUCT_OUT)/super_empty.img
@@ -4583,7 +4641,7 @@
 $(call dist-for-goals,dist_files,$(INSTALLED_SUPERIMAGE_EMPTY_TARGET))
 
 endif # BOARD_SUPER_PARTITION_SIZE != ""
-endif # PRODUCT_BUILD_SUPER_PARTITION == "true"
+endif # PRODUCT_USE_DYNAMIC_PARTITIONS == "true"
 
 
 # -----------------------------------------------------------------
@@ -4673,14 +4731,14 @@
 productimage: $(INSTALLED_QEMU_PRODUCTIMAGE)
 droidcore: $(INSTALLED_QEMU_PRODUCTIMAGE)
 endif
-ifdef INSTALLED_PRODUCT_SERVICESIMAGE_TARGET
-INSTALLED_QEMU_PRODUCT_SERVICESIMAGE := $(PRODUCT_OUT)/product_services-qemu.img
-$(INSTALLED_QEMU_PRODUCT_SERVICESIMAGE): $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) $(SIMG2IMG)
-	@echo Create product_services-qemu.img
-	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET))
+ifdef INSTALLED_SYSTEM_EXTIMAGE_TARGET
+INSTALLED_QEMU_SYSTEM_EXTIMAGE := $(PRODUCT_OUT)/system_ext-qemu.img
+$(INSTALLED_QEMU_SYSTEM_EXTIMAGE): $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST) $(SIMG2IMG)
+	@echo Create system_ext-qemu.img
+	(export SGDISK=$(SGDISK_HOST) SIMG2IMG=$(SIMG2IMG); $(MK_QEMU_IMAGE_SH) $(INSTALLED_SYSTEM_EXTIMAGE_TARGET))
 
-productservicesimage: $(INSTALLED_QEMU_PRODUCT_SERVICESIMAGE)
-droidcore: $(INSTALLED_QEMU_PRODUCT_SERVICESIMAGE)
+systemextimage: $(INSTALLED_QEMU_SYSTEM_EXTIMAGE)
+droidcore: $(INSTALLED_QEMU_SYSTEM_EXTIMAGE)
 endif
 ifdef INSTALLED_ODMIMAGE_TARGET
 INSTALLED_QEMU_ODMIMAGE := $(PRODUCT_OUT)/odm-qemu.img
diff --git a/core/app_prebuilt_internal.mk b/core/app_prebuilt_internal.mk
index 69f411c..399d173 100644
--- a/core/app_prebuilt_internal.mk
+++ b/core/app_prebuilt_internal.mk
@@ -41,7 +41,7 @@
 include $(BUILD_SYSTEM)/base_rules.mk
 built_module := $(LOCAL_BUILT_MODULE)
 
-# Run veridex on product, product_services and vendor modules.
+# Run veridex on product, system_ext and vendor modules.
 # We skip it for unbundled app builds where we cannot build veridex.
 module_run_appcompat :=
 ifeq (true,$(non_system_module))
diff --git a/core/base_rules.mk b/core/base_rules.mk
index b0e0577..4a0c15b 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -81,11 +81,17 @@
 LOCAL_ODM_MODULE := true
 else ifneq ($(filter $(TARGET_OUT_PRODUCT)/%,$(_path)),)
 LOCAL_PRODUCT_MODULE := true
-else ifneq ($(filter $(TARGET_OUT_PRODUCT_SERVICES)/%,$(_path)),)
-LOCAL_PRODUCT_SERVICES_MODULE := true
+else ifneq ($(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(_path)),)
+LOCAL_SYSTEM_EXT_MODULE := true
 endif
 _path :=
 
+# TODO(b/135957588) Remove following workaround
+# LOCAL_PRODUCT_SERVICES_MODULE to LOCAL_PRODUCT_MODULE for all Android.mk
+ifndef LOCAL_PRODUCT_MODULE
+LOCAL_PRODUCT_MODULE := $(LOCAL_PRODUCT_SERVICES_MODULE)
+endif
+
 ifndef LOCAL_PROPRIETARY_MODULE
   LOCAL_PROPRIETARY_MODULE := $(LOCAL_VENDOR_MODULE)
 endif
@@ -98,7 +104,7 @@
 
 non_system_module := $(filter true, \
    $(LOCAL_PRODUCT_MODULE) \
-   $(LOCAL_PRODUCT_SERVICES_MODULE) \
+   $(LOCAL_SYSTEM_EXT_MODULE) \
    $(LOCAL_VENDOR_MODULE) \
    $(LOCAL_PROPRIETARY_MODULE))
 
@@ -227,8 +233,8 @@
   partition_tag := _ODM
 else ifeq (true,$(strip $(LOCAL_PRODUCT_MODULE)))
   partition_tag := _PRODUCT
-else ifeq (true,$(strip $(LOCAL_PRODUCT_SERVICES_MODULE)))
-  partition_tag := _PRODUCT_SERVICES
+else ifeq (true,$(strip $(LOCAL_SYSTEM_EXT_MODULE)))
+  partition_tag := _SYSTEM_EXT
 else ifeq (NATIVE_TESTS,$(LOCAL_MODULE_CLASS))
   partition_tag := _DATA
 else
@@ -710,18 +716,6 @@
   endif
 endif
 
-
-ifeq ($(use_testcase_folder),true)
-ifneq ($(my_test_data_file_pairs),)
-$(foreach pair, $(my_test_data_file_pairs), \
-  $(eval parts := $(subst :,$(space),$(pair))) \
-  $(eval src_path := $(word 1,$(parts))) \
-  $(eval file := $(word 2,$(parts))) \
-  $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
-    $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
-      $(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data))))))
-endif
-else
 ifneq ($(my_test_data_file_pairs),)
 $(foreach pair, $(my_test_data_file_pairs), \
   $(eval parts := $(subst :,$(space),$(pair))) \
@@ -731,7 +725,6 @@
     $(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
       $(src_path):$(call append-path,$(dir),$(file))))))
 endif
-endif
 
 
 
diff --git a/core/binary.mk b/core/binary.mk
index f63e4cd..e76942c 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -267,6 +267,20 @@
   endif
 endif
 
+ifeq ($(NATIVE_COVERAGE),true)
+  ifndef LOCAL_IS_HOST_MODULE
+    my_ldflags += -Wl,--wrap,getenv
+
+    ifneq ($(LOCAL_MODULE_CLASS),STATIC_LIBRARIES)
+      ifeq ($(LOCAL_SDK_VERSION),)
+        my_whole_static_libraries += libprofile-extras
+      else
+        my_whole_static_libraries += libprofile-extras_ndk
+      endif
+    endif
+  endif
+endif
+
 ifneq ($(LOCAL_USE_VNDK),)
   # Required VNDK version for vendor modules is BOARD_VNDK_VERSION.
   my_vndk_version := $(BOARD_VNDK_VERSION)
diff --git a/core/board_config.mk b/core/board_config.mk
index 9c9e8b1..f7dc557 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -67,8 +67,8 @@
   BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \
   BOARD_PRODUCTIMAGE_PARTITION_SIZE \
   BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE \
-  BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE \
-  BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE \
+  BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE \
+  BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE \
   BOARD_ODMIMAGE_PARTITION_SIZE \
   BOARD_ODMIMAGE_FILE_SYSTEM_TYPE \
 
@@ -78,7 +78,7 @@
   BOARD_VENDORIMAGE_PARTITION_RESERVED_SIZE \
   BOARD_ODMIMAGE_PARTITION_RESERVED_SIZE \
   BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE \
-  BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE \
+  BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE \
   BOARD_SUPER_PARTITION_SIZE \
   BOARD_SUPER_PARTITION_GROUPS \
 
@@ -413,48 +413,48 @@
 .KATI_READONLY := BUILDING_PRODUCT_IMAGE
 
 ###########################################
-# Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT_SERVICES
-MERGE_PRODUCT_SERVICES_INTO_PRODUCT :=
-ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),$(_product_services_path_placeholder))
-  TARGET_COPY_OUT_PRODUCT_SERVICES := $(TARGET_COPY_OUT_PRODUCT)
-  MERGE_PRODUCT_SERVICES_INTO_PRODUCT := true
-else ifeq ($(TARGET_COPY_OUT_PRODUCT),$(TARGET_COPY_OUT_PRODUCT_SERVICES))
-  MERGE_PRODUCT_SERVICES_INTO_PRODUCT := true
-else ifeq ($(filter product_services system/product_services,$(TARGET_COPY_OUT_PRODUCT_SERVICES)),)
-  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be either 'product_services',\
-    '$(TARGET_COPY_OUT_PRODUCT)' or 'system/product_services', seeing '$(TARGET_COPY_OUT_PRODUCT_SERVICES)'.)
-endif
-.KATI_READONLY := MERGE_PRODUCT_SERVICES_INTO_PRODUCT
-PRODUCT_COPY_FILES := $(subst $(_product_services_path_placeholder),$(TARGET_COPY_OUT_PRODUCT_SERVICES),$(PRODUCT_COPY_FILES))
+# TODO(b/135957588) TARGET_COPY_OUT_PRODUCT_SERVICES will be set to
+# TARGET_COPY_OUT_PRODUCT as a workaround.
+TARGET_COPY_OUT_PRODUCT_SERVICES := $(TARGET_COPY_OUT_PRODUCT)
 
-BOARD_USES_PRODUCT_SERVICESIMAGE :=
-ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
-  BOARD_USES_PRODUCT_SERVICESIMAGE := true
+###########################################
+# Now we can substitute with the real value of TARGET_COPY_OUT_SYSTEM_EXT
+ifeq ($(TARGET_COPY_OUT_SYSTEM_EXT),$(_system_ext_path_placeholder))
+TARGET_COPY_OUT_SYSTEM_EXT := system/system_ext
+else ifeq ($(filter system_ext system/system_ext,$(TARGET_COPY_OUT_SYSTEM_EXT)),)
+$(error TARGET_COPY_OUT_SYSTEM_EXT must be either 'system_ext' or 'system/system_ext', seeing '$(TARGET_COPY_OUT_SYSTEM_EXT)'.)
 endif
-ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
-  BOARD_USES_PRODUCT_SERVICESIMAGE := true
-endif
-ifeq ($(TARGET_COPY_OUT_PRODUCT_SERVICES),product_services)
-  BOARD_USES_PRODUCT_SERVICESIMAGE := true
-else ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
-  $(error TARGET_COPY_OUT_PRODUCT_SERVICES must be set to 'product_services' to use a product_services image)
-endif
+PRODUCT_COPY_FILES := $(subst $(_system_ext_path_placeholder),$(TARGET_COPY_OUT_SYSTEM_EXT),$(PRODUCT_COPY_FILES))
 
-BUILDING_PRODUCT_SERVICES_IMAGE :=
-ifeq ($(PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE),)
-  ifdef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
-    BUILDING_PRODUCT_SERVICES_IMAGE := true
+BOARD_USES_SYSTEM_EXTIMAGE :=
+ifdef BOARD_PREBUILT_SYSTEM_EXTIMAGE
+  BOARD_USES_SYSTEM_EXTIMAGE := true
+endif
+ifdef BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE
+  BOARD_USES_SYSTEM_EXTIMAGE := true
+endif
+ifeq ($(TARGET_COPY_OUT_SYSTEM_EXT),system_ext)
+  BOARD_USES_SYSTEM_EXTIMAGE := true
+else ifdef BOARD_USES_SYSTEM_EXTIMAGE
+  $(error TARGET_COPY_OUT_SYSTEM_EXT must be set to 'system_ext' to use a system_ext image)
+endif
+.KATI_READONLY := BOARD_USES_SYSTEM_EXTIMAGE
+
+BUILDING_SYSTEM_EXT_IMAGE :=
+ifeq ($(PRODUCT_BUILD_SYSTEM_EXT_IMAGE),)
+  ifdef BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE
+    BUILDING_SYSTEM_EXT_IMAGE := true
   endif
-else ifeq ($(PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE),true)
-  BUILDING_PRODUCT_SERVICES_IMAGE := true
-  ifndef BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE
-    $(error PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE set to true, but BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE not defined)
+else ifeq ($(PRODUCT_BUILD_SYSTEM_EXT_IMAGE),true)
+  BUILDING_SYSTEM_EXT_IMAGE := true
+  ifndef BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE
+    $(error PRODUCT_BUILD_SYSTEM_EXT_IMAGE set to true, but BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE not defined)
   endif
 endif
-ifdef BOARD_PREBUILT_PRODUCT_SERVICESIMAGE
-  BUILDING_PRODUCT_SERVICES_IMAGE :=
+ifdef BOARD_PREBUILT_SYSTEM_EXTIMAGE
+  BUILDING_SYSTEM_EXT_IMAGE :=
 endif
-.KATI_READONLY := BUILDING_PRODUCT_SERVICES_IMAGE
+.KATI_READONLY := BUILDING_SYSTEM_EXT_IMAGE
 
 ###########################################
 # Now we can substitute with the real value of TARGET_COPY_OUT_ODM
diff --git a/core/build_rro_package.mk b/core/build_rro_package.mk
index a6921d5..e5d7685 100644
--- a/core/build_rro_package.mk
+++ b/core/build_rro_package.mk
@@ -20,8 +20,8 @@
   partition := $(TARGET_OUT_ODM)
 else ifeq ($(strip $(LOCAL_VENDOR_MODULE)),true)
   partition := $(TARGET_OUT_VENDOR)
-else ifeq ($(strip $(LOCAL_PRODUCT_SERVICES_MODULE)),true)
-  partition := $(TARGET_OUT_PRODUCT_SERVICES)
+else ifeq ($(strip $(LOCAL_SYSTEM_EXT_MODULE)),true)
+  partition := $(TARGET_OUT_SYSTEM_EXT)
 else
   partition := $(TARGET_OUT_PRODUCT)
 endif
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 5973e0e..3cc8594 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -216,7 +216,8 @@
 LOCAL_PRIVILEGED_MODULE:=
 # '',full,custom,disabled,obfuscation,optimization
 LOCAL_PRODUCT_MODULE:=
-LOCAL_PRODUCT_SERVICES_MODULE:=
+# TODO(b/135957588) Remove LOCAL_PRODUCT_SERVICES_MODULE
+LOCAL_PRODUCT_SERVICES_MODULE :=
 LOCAL_PROGUARD_ENABLED:=
 LOCAL_PROGUARD_FLAG_FILES:=
 LOCAL_PROGUARD_FLAGS:=
@@ -279,6 +280,7 @@
 LOCAL_STATIC_JAVA_AAR_LIBRARIES:=
 LOCAL_STATIC_JAVA_LIBRARIES:=
 LOCAL_STATIC_LIBRARIES:=
+LOCAL_SYSTEM_EXT_MODULE:=
 LOCAL_STRIP_MODULE:=
 LOCAL_SYSTEM_SHARED_LIBRARIES:=none
 LOCAL_TARGET_REQUIRED_MODULES:=
diff --git a/core/config.mk b/core/config.mk
index 92efd34..d92b891 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -577,16 +577,12 @@
 endif
 APICHECK := $(HOST_OUT_JAVA_LIBRARIES)/metalava$(COMMON_JAVA_PACKAGE_SUFFIX)
 FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
-MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
 MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg_mke2fs
 MKE2FS_CONF := system/extras/ext4_utils/mke2fs.conf
 BLK_ALLOC_TO_BASE_FS := $(HOST_OUT_EXECUTABLES)/blk_alloc_to_base_fs$(HOST_EXECUTABLE_SUFFIX)
-MAKE_SQUASHFS := $(HOST_OUT_EXECUTABLES)/mksquashfs$(HOST_EXECUTABLE_SUFFIX)
 MKSQUASHFSUSERIMG := $(HOST_OUT_EXECUTABLES)/mksquashfsimage.sh
-MAKE_F2FS := $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)
 MKF2FSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh
 SIMG2IMG := $(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX)
-IMG2SIMG := $(HOST_OUT_EXECUTABLES)/img2simg$(HOST_EXECUTABLE_SUFFIX)
 E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)
 MKTARBALL := build/make/tools/mktarball.sh
 TUNE2FS := $(HOST_OUT_EXECUTABLES)/tune2fs$(HOST_EXECUTABLE_SUFFIX)
@@ -875,10 +871,10 @@
 endif
 endif
 
-ifneq ($(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE),)
-ifneq ($(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE),)
-$(error Should not define BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE and \
-    BOARD_PRODUCT_SERVICESIMAGE_PARTITION_RESERVED_SIZE together)
+ifneq ($(BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE),)
+ifneq ($(BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE),)
+$(error Should not define BOARD_SYSTEM_EXTIMAGE_PARTITION_SIZE and \
+    BOARD_SYSTEM_EXTIMAGE_PARTITION_RESERVED_SIZE together)
 endif
 endif
 
@@ -895,19 +891,15 @@
 #     - BOARD_{GROUP}_PARTITION_PARTITION_LIST: the list of partitions that belongs to this group.
 #       If empty, no partitions belong to this group, and the sum of sizes is effectively 0.
 $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
-    $(eval BOARD_$(group)_PARTITION_LIST ?=) \
-    $(eval .KATI_READONLY := BOARD_$(group)_PARTITION_LIST) \
-)
-ifeq ($(PRODUCT_BUILD_SUPER_PARTITION),true)
-$(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
     $(eval BOARD_$(group)_SIZE := $(strip $(BOARD_$(group)_SIZE))) \
     $(if $(BOARD_$(group)_SIZE),,$(error BOARD_$(group)_SIZE must not be empty)) \
     $(eval .KATI_READONLY := BOARD_$(group)_SIZE) \
+    $(eval BOARD_$(group)_PARTITION_LIST ?=) \
+    $(eval .KATI_READONLY := BOARD_$(group)_PARTITION_LIST) \
 )
-endif # PRODUCT_BUILD_SUPER_PARTITION
 
 # BOARD_*_PARTITION_LIST: a list of the following tokens
-valid_super_partition_list := system vendor product product_services odm
+valid_super_partition_list := system vendor product system_ext odm
 $(foreach group,$(call to-upper,$(BOARD_SUPER_PARTITION_GROUPS)), \
     $(if $(filter-out $(valid_super_partition_list),$(BOARD_$(group)_PARTITION_LIST)), \
         $(error BOARD_$(group)_PARTITION_LIST contains invalid partition name \
@@ -1168,7 +1160,7 @@
     bptimage-nodeps \
     vnod vendorimage-nodeps \
     pnod productimage-nodeps \
-    psnod productservicesimage-nodeps \
+    senod systemextimage-nodeps \
     onod odmimage-nodeps \
     systemotherimage-nodeps \
     ramdisk-nodeps \
diff --git a/core/definitions.mk b/core/definitions.mk
index 4017c47..431231d 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1883,20 +1883,20 @@
 ###########################################################
 define aapt2-compile-one-resource-file
 @mkdir -p $(dir $@)
-$(hide) $(AAPT2) compile -o $(dir $@) $(PRIVATE_AAPT2_CFLAGS) --legacy $<
+$(hide) $(AAPT2) compile -o $(dir $@) $(PRIVATE_AAPT2_CFLAGS) $<
 endef
 
 define aapt2-compile-resource-dirs
 @mkdir -p $(dir $@)
 $(hide) $(AAPT2) compile -o $@ $(addprefix --dir ,$(PRIVATE_SOURCE_RES_DIRS)) \
-  $(PRIVATE_AAPT2_CFLAGS) --legacy
+  $(PRIVATE_AAPT2_CFLAGS)
 endef
 
 # TODO(b/74574557): use aapt2 compile --zip if it gets implemented
 define aapt2-compile-resource-zips
 @mkdir -p $(dir $@)
 $(ZIPSYNC) -d $@.contents -l $@.list $(PRIVATE_SOURCE_RES_ZIPS)
-$(hide) $(AAPT2) compile -o $@ --dir $@.contents $(PRIVATE_AAPT2_CFLAGS) --legacy
+$(hide) $(AAPT2) compile -o $@ --dir $@.contents $(PRIVATE_AAPT2_CFLAGS)
 endef
 
 # Set up rule to compile one resource file with aapt2.
@@ -2417,16 +2417,6 @@
 $(if $(filter-out $(2), $(LOCAL_INSTALLED_MODULE)), $(1):$(2))
 endef
 
-# Create copy pair for $(1) $(2)
-# If $(2) is substring of $(3) do nothing.
-# $(1): source path
-# $(2): destination path
-# $(3): filter-out target
-# The format of copy pair is src:dst
-define filter-copy-pair
-$(if $(findstring $(2), $(3)),,$(1):$(2))
-endef
-
 # Copies many files.
 # $(1): The files to copy.  Each entry is a ':' separated src:dst pair
 # $(2): An optional directory to prepend to the destination
@@ -2449,8 +2439,12 @@
 define copy-init-script-file-checked
 # Host init verifier doesn't exist on darwin.
 ifneq ($(HOST_OS),darwin)
-$(2): $(1) $(HOST_INIT_VERIFIER) $(call intermediates-dir-for,ETC,passwd)/passwd
-	$(hide) $(HOST_INIT_VERIFIER) $$< $(call intermediates-dir-for,ETC,passwd)/passwd
+$(2): \
+	$(1) \
+	$(HOST_INIT_VERIFIER) \
+	$(KNOWN_HIDL_INTERFACES) \
+	$(call intermediates-dir-for,ETC,passwd)/passwd
+	$(hide) $(HOST_INIT_VERIFIER) -p $(call intermediates-dir-for,ETC,passwd)/passwd -k $(KNOWN_HIDL_INTERFACES) $$<
 else
 $(2): $(1)
 endif
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 5693147..b856bf4 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -8,8 +8,8 @@
 SYSTEM_OTHER_ODEX_FILTER ?= \
     app/% \
     priv-app/% \
-    product_services/app/% \
-    product_services/priv-app/% \
+    system_ext/app/% \
+    system_ext/priv-app/% \
     product/app/% \
     product/priv-app/% \
 
@@ -138,9 +138,7 @@
   $(call end_json_map)
 
   $(call add_json_str,  DirtyImageObjects,                  $(DIRTY_IMAGE_OBJECTS))
-  $(call add_json_str,  PreloadedClasses,                   $(PRELOADED_CLASSES))
   $(call add_json_list, BootImageProfiles,                  $(PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
-  $(call add_json_bool, UseProfileForBootImage,             $(call invert_bool,$(filter false,$(PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE))))
   $(call add_json_str,  BootFlags,                          $(PRODUCT_DEX_PREOPT_BOOT_FLAGS))
   $(call add_json_str,  Dex2oatImageXmx,                    $(DEX2OAT_IMAGE_XMX))
   $(call add_json_str,  Dex2oatImageXms,                    $(DEX2OAT_IMAGE_XMS))
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 46edc0e..05957cd 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -233,11 +233,14 @@
 # BoardConfig, to be either the partition dir, or a subdir within 'system'.
 _vendor_path_placeholder := ||VENDOR-PATH-PH||
 _product_path_placeholder := ||PRODUCT-PATH-PH||
-_product_services_path_placeholder := ||PRODUCT_SERVICES-PATH-PH||
+_system_ext_path_placeholder := ||SYSTEM_EXT-PATH-PH||
 _odm_path_placeholder := ||ODM-PATH-PH||
 TARGET_COPY_OUT_VENDOR := $(_vendor_path_placeholder)
 TARGET_COPY_OUT_PRODUCT := $(_product_path_placeholder)
-TARGET_COPY_OUT_PRODUCT_SERVICES := $(_product_services_path_placeholder)
+# TODO(b/135957588) TARGET_COPY_OUT_PRODUCT_SERVICES will copy the target to
+# product
+TARGET_COPY_OUT_PRODUCT_SERVICES := $(_product_path_placeholder)
+TARGET_COPY_OUT_SYSTEM_EXT := $(_system_ext_path_placeholder)
 TARGET_COPY_OUT_ODM := $(_odm_path_placeholder)
 
 # Returns the non-sanitized version of the path provided in $1.
@@ -785,38 +788,38 @@
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_APPS \
   $(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_APPS_PRIVILEGED
 
-TARGET_OUT_PRODUCT_SERVICES := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_PRODUCT_SERVICES)
+TARGET_OUT_SYSTEM_EXT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM_EXT)
 ifneq ($(filter address,$(SANITIZE_TARGET)),)
-target_out_product_services_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/$(TARGET_COPY_OUT_PRODUCT_SERVICES)
+target_out_system_ext_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/$(TARGET_COPY_OUT_SYSTEM_EXT)
 ifeq ($(SANITIZE_LITE),true)
 # When using SANITIZE_LITE, APKs must not be packaged with sanitized libraries, as they will not
 # work with unsanitized app_process. For simplicity, generate APKs into /data/asan/.
-target_out_product_services_app_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/$(TARGET_COPY_OUT_PRODUCT_SERVICES)
+target_out_system_ext_app_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/$(TARGET_COPY_OUT_SYSTEM_EXT)
 else
-target_out_product_services_app_base := $(TARGET_OUT_PRODUCT_SERVICES)
+target_out_system_ext_app_base := $(TARGET_OUT_SYSTEM_EXT)
 endif
 else
-target_out_product_services_shared_libraries_base := $(TARGET_OUT_PRODUCT_SERVICES)
-target_out_product_services_app_base := $(TARGET_OUT_PRODUCT_SERVICES)
+target_out_system_ext_shared_libraries_base := $(TARGET_OUT_SYSTEM_EXT)
+target_out_system_ext_app_base := $(TARGET_OUT_SYSTEM_EXT)
 endif
 
 ifeq ($(TARGET_IS_64_BIT),true)
-TARGET_OUT_PRODUCT_SERVICES_SHARED_LIBRARIES := $(target_out_product_services_shared_libraries_base)/lib64
+TARGET_OUT_SYSTEM_EXT_SHARED_LIBRARIES := $(target_out_system_ext_shared_libraries_base)/lib64
 else
-TARGET_OUT_PRODUCT_SERVICES_SHARED_LIBRARIES := $(target_out_product_services_shared_libraries_base)/lib
+TARGET_OUT_SYSTEM_EXT_SHARED_LIBRARIES := $(target_out_system_ext_shared_libraries_base)/lib
 endif
-TARGET_OUT_PRODUCT_SERVICES_JAVA_LIBRARIES:= $(TARGET_OUT_PRODUCT_SERVICES)/framework
-TARGET_OUT_PRODUCT_SERVICES_APPS := $(target_out_product_services_app_base)/app
-TARGET_OUT_PRODUCT_SERVICES_APPS_PRIVILEGED := $(target_out_product_services_app_base)/priv-app
-TARGET_OUT_PRODUCT_SERVICES_ETC := $(TARGET_OUT_PRODUCT_SERVICES)/etc
+TARGET_OUT_SYSTEM_EXT_JAVA_LIBRARIES:= $(TARGET_OUT_SYSTEM_EXT)/framework
+TARGET_OUT_SYSTEM_EXT_APPS := $(target_out_system_ext_app_base)/app
+TARGET_OUT_SYSTEM_EXT_APPS_PRIVILEGED := $(target_out_system_ext_app_base)/priv-app
+TARGET_OUT_SYSTEM_EXT_ETC := $(TARGET_OUT_SYSTEM_EXT)/etc
 
 ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SERVICES_SHARED_LIBRARIES := $(target_out_product_services_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_SHARED_LIBRARIES := $(target_out_system_ext_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
 else
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SERVICES_SHARED_LIBRARIES := $(target_out_product_services_shared_libraries_base)/lib
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_SHARED_LIBRARIES := $(target_out_system_ext_shared_libraries_base)/lib
 endif
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SERVICES_APPS := $(TARGET_OUT_PRODUCT_SERVICES_APPS)
-$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SERVICES_APPS_PRIVILEGED := $(TARGET_OUT_PRODUCT_SERVICES_APPS_PRIVILEGED)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_APPS := $(TARGET_OUT_SYSTEM_EXT_APPS)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_SYSTEM_EXT_APPS_PRIVILEGED := $(TARGET_OUT_SYSTEM_EXT_APPS_PRIVILEGED)
 
 TARGET_OUT_BREAKPAD := $(PRODUCT_OUT)/breakpad
 .KATI_READONLY := TARGET_OUT_BREAKPAD
diff --git a/core/install_jni_libs.mk b/core/install_jni_libs.mk
index 515d34f..0fec9ca 100644
--- a/core/install_jni_libs.mk
+++ b/core/install_jni_libs.mk
@@ -26,7 +26,7 @@
     $(TARGET_OUT_VENDOR)/% \
     $(TARGET_OUT_OEM)/% \
     $(TARGET_OUT_PRODUCT)/% \
-    $(TARGET_OUT_PRODUCT_SERVICES)/% \
+    $(TARGET_OUT_SYSTEM_EXT)/% \
 
 ifeq ($(filter $(supported_partition_patterns),$(my_module_path)),)
   my_embed_jni := true
diff --git a/core/main.mk b/core/main.mk
index 5cb1d34..4552cf2 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -343,6 +343,15 @@
 endif
 endif
 
+## java coverage ##
+# Install additional tools on java coverage builds
+ifeq (true,$(EMMA_INSTRUMENT))
+ifneq (,$(filter debug,$(tags_to_install)))
+  tags_to_install += java_coverage
+endif
+endif
+
+
 ## sdk ##
 
 ifdef is_sdk_build
@@ -832,6 +841,9 @@
 $(call update-host-shared-libs-deps-for-suites)
 ifdef HOST_CROSS_OS
 $(call resolve-shared-libs-depes,HOST_CROSS_,,true)
+ifdef HOST_CROSS_2ND_ARCH
+$(call resolve-shared-libs-depes,HOST_CROSS_,true,true)
+endif
 endif
 
 # Pass the shared libraries dependencies to prebuilt ELF file check.
@@ -1099,7 +1111,7 @@
 define resolve-product-relative-paths
   $(subst $(_vendor_path_placeholder),$(TARGET_COPY_OUT_VENDOR),\
     $(subst $(_product_path_placeholder),$(TARGET_COPY_OUT_PRODUCT),\
-      $(subst $(_product_services_path_placeholder),$(TARGET_COPY_OUT_PRODUCT_SERVICES),\
+      $(subst $(_system_ext_path_placeholder),$(TARGET_COPY_OUT_SYSTEM_EXT),\
         $(subst $(_odm_path_placeholder),$(TARGET_COPY_OUT_ODM),\
           $(foreach p,$(1),$(call append-path,$(PRODUCT_OUT),$(p)$(2)))))))
 endef
@@ -1137,6 +1149,7 @@
     $(if $(filter debug,$(tags_to_install)),$(PRODUCTS.$(_mk).PRODUCT_PACKAGES_DEBUG)) \
     $(if $(filter tests,$(tags_to_install)),$(PRODUCTS.$(_mk).PRODUCT_PACKAGES_TESTS)) \
     $(if $(filter asan,$(tags_to_install)),$(PRODUCTS.$(_mk).PRODUCT_PACKAGES_DEBUG_ASAN)) \
+    $(if $(filter java_coverage,$(tags_to_install)),$(PRODUCTS.$(_mk).PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE)) \
     $(call auto-included-modules) \
   ) \
   $(eval ### Filter out the overridden packages and executables before doing expansion) \
@@ -1588,8 +1601,8 @@
 .PHONY: productimage
 productimage: $(INSTALLED_PRODUCTIMAGE_TARGET)
 
-.PHONY: productservicesimage
-productservicesimage: $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET)
+.PHONY: systemextimage
+systemextimage: $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
 
 .PHONY: odmimage
 odmimage: $(INSTALLED_ODMIMAGE_TARGET)
@@ -1639,8 +1652,8 @@
     $(INSTALLED_FILES_JSON_ODM) \
     $(INSTALLED_FILES_FILE_PRODUCT) \
     $(INSTALLED_FILES_JSON_PRODUCT) \
-    $(INSTALLED_FILES_FILE_PRODUCT_SERVICES) \
-    $(INSTALLED_FILES_JSON_PRODUCT_SERVICES) \
+    $(INSTALLED_FILES_FILE_SYSTEM_EXT) \
+    $(INSTALLED_FILES_JSON_SYSTEM_EXT) \
     $(INSTALLED_FILES_FILE_SYSTEMOTHER) \
     $(INSTALLED_FILES_JSON_SYSTEMOTHER) \
     $(INSTALLED_FILES_FILE_RAMDISK) \
@@ -1732,8 +1745,8 @@
     $(INSTALLED_FILES_JSON_ODM) \
     $(INSTALLED_FILES_FILE_PRODUCT) \
     $(INSTALLED_FILES_JSON_PRODUCT) \
-    $(INSTALLED_FILES_FILE_PRODUCT_SERVICES) \
-    $(INSTALLED_FILES_JSON_PRODUCT_SERVICES) \
+    $(INSTALLED_FILES_FILE_SYSTEM_EXT) \
+    $(INSTALLED_FILES_JSON_SYSTEM_EXT) \
     $(INSTALLED_FILES_FILE_SYSTEMOTHER) \
     $(INSTALLED_FILES_JSON_SYSTEMOTHER) \
     $(INSTALLED_FILES_FILE_RECOVERY) \
diff --git a/core/package_internal.mk b/core/package_internal.mk
index c414295..2130058 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -109,7 +109,7 @@
         $(LOCAL_ODM_MODULE) \
         $(LOCAL_OEM_MODULE) \
         $(LOCAL_PRODUCT_MODULE) \
-        $(LOCAL_PRODUCT_SERVICES_MODULE) \
+        $(LOCAL_SYSTEM_EXT_MODULE) \
         $(LOCAL_PROPRIETARY_MODULE) \
         $(LOCAL_VENDOR_MODULE))
     enforce_rro_enabled := $(if $(non_system_module),,true)
@@ -508,7 +508,7 @@
 endif
 endif
 
-# Run veridex on product, product_services and vendor modules.
+# Run veridex on product, system_ext and vendor modules.
 # We skip it for unbundled app builds where we cannot build veridex.
 module_run_appcompat :=
 ifeq (true,$(non_system_module))
diff --git a/core/product-graph.mk b/core/product-graph.mk
index 9db277c..9fc8e57 100644
--- a/core/product-graph.mk
+++ b/core/product-graph.mk
@@ -117,7 +117,7 @@
 	$(hide) echo 'PRODUCT_DEFAULT_PROPERTY_OVERRIDES=$$(PRODUCTS.$(strip $(1)).PRODUCT_DEFAULT_PROPERTY_OVERRIDES)' >> $$@
 	$(hide) echo 'PRODUCT_SYSTEM_DEFAULT_PROPERTIES=$$(PRODUCTS.$(strip $(1)).PRODUCT_SYSTEM_DEFAULT_PROPERTIES)' >> $$@
 	$(hide) echo 'PRODUCT_PRODUCT_PROPERTIES=$$(PRODUCTS.$(strip $(1)).PRODUCT_PRODUCT_PROPERTIES)' >> $$@
-	$(hide) echo 'PRODUCT_PRODUCT_SERVICES_PROPERTIES=$$(PRODUCTS.$(strip $(1)).PRODUCT_PRODUCT_SERVICES_PROPERTIES)' >> $$@
+	$(hide) echo 'PRODUCT_SYSTEM_EXT_PROPERTIES=$$(PRODUCTS.$(strip $(1)).PRODUCT_SYSTEM_EXT_PROPERTIES)' >> $$@
 	$(hide) echo 'PRODUCT_ODM_PROPERTIES=$$(PRODUCTS.$(strip $(1)).PRODUCT_ODM_PROPERTIES)' >> $$@
 	$(hide) echo 'PRODUCT_CHARACTERISTICS=$$(PRODUCTS.$(strip $(1)).PRODUCT_CHARACTERISTICS)' >> $$@
 	$(hide) echo 'PRODUCT_COPY_FILES=$$(PRODUCTS.$(strip $(1)).PRODUCT_COPY_FILES)' >> $$@
diff --git a/core/product.mk b/core/product.mk
index 838673c..1afd26b 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -126,6 +126,8 @@
 _product_list_vars += PRODUCT_PACKAGES
 _product_list_vars += PRODUCT_PACKAGES_DEBUG
 _product_list_vars += PRODUCT_PACKAGES_DEBUG_ASAN
+# Packages included only for eng/userdebug builds, when building with EMMA_INSTRUMENT=true
+_product_list_vars += PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE
 _product_list_vars += PRODUCT_PACKAGES_ENG
 _product_list_vars += PRODUCT_PACKAGES_TESTS
 
@@ -159,8 +161,8 @@
 
 # A list of property assignments, like "key = value", with zero or more
 # whitespace characters on either side of the '='.
-# used for adding properties to build.prop of product partition
-_product_list_vars += PRODUCT_PRODUCT_SERVICES_PROPERTIES
+# used for adding properties to build.prop of system_ext and odm partitions
+_product_list_vars += PRODUCT_SYSTEM_EXT_PROPERTIES
 _product_list_vars += PRODUCT_ODM_PROPERTIES
 
 # The characteristics of the product, which among other things is passed to aapt
@@ -236,7 +238,7 @@
 _product_single_value_vars += PRODUCT_SYSTEM_VERITY_PARTITION
 _product_single_value_vars += PRODUCT_VENDOR_VERITY_PARTITION
 _product_single_value_vars += PRODUCT_PRODUCT_VERITY_PARTITION
-_product_single_value_vars += PRODUCT_PRODUCT_SERVICES_VERITY_PARTITION
+_product_single_value_vars += PRODUCT_SYSTEM_EXT_VERITY_PARTITION
 _product_single_value_vars += PRODUCT_ODM_VERITY_PARTITION
 _product_single_value_vars += PRODUCT_SYSTEM_SERVER_DEBUG_INFO
 _product_single_value_vars += PRODUCT_OTHER_JAVA_DEBUG_INFO
@@ -263,7 +265,7 @@
 _product_single_value_vars += PRODUCT_SYSTEM_BASE_FS_PATH
 _product_single_value_vars += PRODUCT_VENDOR_BASE_FS_PATH
 _product_single_value_vars += PRODUCT_PRODUCT_BASE_FS_PATH
-_product_single_value_vars += PRODUCT_PRODUCT_SERVICES_BASE_FS_PATH
+_product_single_value_vars += PRODUCT_SYSTEM_EXT_BASE_FS_PATH
 _product_single_value_vars += PRODUCT_ODM_BASE_FS_PATH
 
 # The first API level this product shipped with
@@ -355,7 +357,7 @@
 _product_single_value_vars += PRODUCT_BUILD_SYSTEM_OTHER_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_VENDOR_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_PRODUCT_IMAGE
-_product_single_value_vars += PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE
+_product_single_value_vars += PRODUCT_BUILD_SYSTEM_EXT_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_ODM_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_CACHE_IMAGE
 _product_single_value_vars += PRODUCT_BUILD_RAMDISK_IMAGE
@@ -541,10 +543,15 @@
 endef
 
 #
-# Strip the variables in _product_strip_var_list
+# Strip the variables in _product_var_list and a few build-system
+# internal variables, and assign the ones for the current product
+# to a shorthand that is more convenient to read from elsewhere.
 #
 define strip-product-vars
-$(foreach v,$(_product_var_list), \
+$(foreach v,\
+  $(_product_var_list) \
+    PRODUCT_ENFORCE_PACKAGES_EXIST \
+    PRODUCT_ENFORCE_PACKAGES_EXIST_WHITELIST, \
   $(eval $(v) := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).$(v)))) \
 )
 endef
diff --git a/core/product_config.mk b/core/product_config.mk
index cb58cf4..360c79d 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -418,7 +418,7 @@
     SYSTEM_OTHER \
     VENDOR \
     PRODUCT \
-    PRODUCT_SERVICES \
+    SYSTEM_EXT \
     ODM \
     CACHE \
     RAMDISK \
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index d873cc4..8fc2e4c 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -43,7 +43,7 @@
   endif # TURBINE_ENABLED != false
 endif
 
-# Run veridex on product, product_services and vendor modules.
+# Run veridex on product, system_ext and vendor modules.
 # We skip it for unbundled app builds where we cannot build veridex.
 module_run_appcompat :=
 ifeq (true,$(non_system_module))
diff --git a/core/soong_config.mk b/core/soong_config.mk
index ac3cfb3..c32049d 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -146,7 +146,7 @@
 $(call add_json_str,  VendorPath,                        $(TARGET_COPY_OUT_VENDOR))
 $(call add_json_str,  OdmPath,                           $(TARGET_COPY_OUT_ODM))
 $(call add_json_str,  ProductPath,                       $(TARGET_COPY_OUT_PRODUCT))
-$(call add_json_str,  ProductServicesPath,               $(TARGET_COPY_OUT_PRODUCT_SERVICES))
+$(call add_json_str,  SystemExtPath,                     $(TARGET_COPY_OUT_SYSTEM_EXT))
 $(call add_json_bool, MinimizeJavaDebugInfo,             $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO)))
 
 $(call add_json_bool, UseGoma,                           $(filter-out false,$(USE_GOMA)))
diff --git a/core/tasks/find-shareduid-violation.mk b/core/tasks/find-shareduid-violation.mk
index 45fd937..86052f2 100644
--- a/core/tasks/find-shareduid-violation.mk
+++ b/core/tasks/find-shareduid-violation.mk
@@ -24,7 +24,7 @@
     $(INSTALLED_USERDATAIMAGE_TARGET) \
     $(INSTALLED_VENDORIMAGE_TARGET) \
     $(INSTALLED_PRODUCTIMAGE_TARGET) \
-    $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET)
+    $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
 
 $(shareduid_violation_modules_filename): $(find_shareduid_script)
 $(shareduid_violation_modules_filename): $(AAPT2)
diff --git a/help.sh b/help.sh
index be07344..b02b14c 100755
--- a/help.sh
+++ b/help.sh
@@ -40,8 +40,8 @@
                             Stands for "Vendor, NO Dependencies"
     pnod                    Quickly rebuild the product image from built packages
                             Stands for "Product, NO Dependencies"
-    psnod                   Quickly rebuild the product_services image from built packages
-                            Stands for "ProductServices, NO Dependencies"
+    senod                   Quickly rebuild the system_ext image from built packages
+                            Stands for "SystemExt, NO Dependencies"
     onod                    Quickly rebuild the odm image from built packages
                             Stands for "ODM, NO Dependencies"
 
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index 702ef3c..e4dd032 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -19,8 +19,9 @@
 # Enable dynamic system image size and reserved 64MB in it.
 BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE := 67108864
 
-# GSI forces product packages to /system for now.
+# GSI forces product and system_ext packages to /system for now.
 TARGET_COPY_OUT_PRODUCT := system/product
+TARGET_COPY_OUT_SYSTEM_EXT := system/system_ext
 BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE :=
 
 # Creates metadata partition mount point under root for
diff --git a/target/board/BoardConfigMainlineCommon.mk b/target/board/BoardConfigMainlineCommon.mk
index be014bf..70cfe39 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -8,7 +8,8 @@
 
 TARGET_USERIMAGES_USE_EXT4 := true
 
-# Mainline devices must have /vendor and /product partitions.
+# Mainline devices must have /system_ext, /vendor and /product partitions.
+TARGET_COPY_OUT_SYSTEM_EXT := system_ext
 TARGET_COPY_OUT_VENDOR := vendor
 TARGET_COPY_OUT_PRODUCT := product
 
@@ -39,6 +40,9 @@
 # Enable system property split for Treble
 BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
 
+# Include stats logging code in LMKD
+TARGET_LMKD_STATS_LOG := true
+
 # Generate an APEX image for experiment b/119800099.
 DEXPREOPT_GENERATE_APEX_IMAGE := true
 
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index f09493e..162fbed 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -187,6 +187,7 @@
     libwifi-service \
     libwilhelm \
     linker \
+    linkerconfig \
     lmkd \
     locksettings \
     logcat \
@@ -375,6 +376,9 @@
 # Packages included only for eng/userdebug builds, when building with SANITIZE_TARGET=address
 PRODUCT_PACKAGES_DEBUG_ASAN :=
 
+PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE := \
+    libdumpcoverage
+
 PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,\
     frameworks/base/config/preloaded-classes:system/etc/preloaded-classes)
 
diff --git a/target/product/generic.mk b/target/product/generic.mk
index 6fe4818..68130e3 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -25,4 +25,5 @@
 PRODUCT_DEVICE := generic
 PRODUCT_NAME := generic
 
-$(call enforce-product-packages-exist,)
+whitelist := product_manifest.xml
+$(call enforce-product-packages-exist,$(whitelist))
diff --git a/target/product/gsi/skip_mount.cfg b/target/product/gsi/skip_mount.cfg
index 549767e..3f812cb 100644
--- a/target/product/gsi/skip_mount.cfg
+++ b/target/product/gsi/skip_mount.cfg
@@ -1,2 +1,2 @@
 /product
-/product_services
+/system_ext
diff --git a/target/product/gsi_common.mk b/target/product/gsi_common.mk
index 7578f92..1b5cd55 100644
--- a/target/product/gsi_common.mk
+++ b/target/product/gsi_common.mk
@@ -55,10 +55,10 @@
     system/etc/init/config/skip_mount.cfg \
     system/etc/init/init.gsi.rc \
 
-# Exclude all files under system/product and system/product_services
+# Exclude all files under system/product and system/system_ext
 PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
     system/product/% \
-    system/product_services/%
+    system/system_ext/%
 
 
 # Split selinux policy
diff --git a/target/product/mainline_arm64.mk b/target/product/mainline_arm64.mk
index 6050924..c098c9f 100644
--- a/target/product/mainline_arm64.mk
+++ b/target/product/mainline_arm64.mk
@@ -16,7 +16,8 @@
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/mainline.mk)
-$(call enforce-product-packages-exist,)
+whitelist := product_manifest.xml
+$(call enforce-product-packages-exist,$(whitelist))
 
 PRODUCT_NAME := mainline_arm64
 PRODUCT_DEVICE := mainline_arm64
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index 87393d4..8bcc212 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -97,11 +97,6 @@
 PRODUCT_HOST_PACKAGES += \
     tinyplay
 
-# Enable stats logging in LMKD
-TARGET_LMKD_STATS_LOG := true
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
-    ro.lmk.log_stats=true
-
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
 
diff --git a/target/product/mainline_system_arm64.mk b/target/product/mainline_system_arm64.mk
index f01cc54..b9ac1e3 100644
--- a/target/product/mainline_system_arm64.mk
+++ b/target/product/mainline_system_arm64.mk
@@ -21,7 +21,7 @@
 PRODUCT_BUILD_CACHE_IMAGE := false
 PRODUCT_BUILD_ODM_IMAGE := false
 PRODUCT_BUILD_PRODUCT_IMAGE  := false
-PRODUCT_BUILD_PRODUCT_SERVICES_IMAGE := false
+PRODUCT_BUILD_SYSTEM_EXT_IMAGE := false
 PRODUCT_BUILD_RAMDISK_IMAGE := false
 PRODUCT_BUILD_SYSTEM_IMAGE := true
 PRODUCT_BUILD_SYSTEM_OTHER_IMAGE := false
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
index af0da46..64fabe6 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -27,13 +27,13 @@
 system_android_filesystem_config := system/core/include/private/android_filesystem_config.h
 system_capability_header := bionic/libc/kernel/uapi/linux/capability.h
 
-# List of supported vendor, oem, odm, product and product_services Partitions
+# List of supported vendor, oem, odm, product and system_ext Partitions
 fs_config_generate_extra_partition_list := $(strip \
   $(if $(BOARD_USES_VENDORIMAGE)$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),vendor) \
   $(if $(BOARD_USES_OEMIMAGE)$(BOARD_OEMIMAGE_FILE_SYSTEM_TYPE),oem) \
   $(if $(BOARD_USES_ODMIMAGE)$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),odm) \
   $(if $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),product) \
-  $(if $(BOARD_PRODUCT_SERVICESIMAGE_FILE_SYSTEM_TYPE),product_services) \
+  $(if $(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),system_ext) \
 )
 
 ##################################
@@ -332,17 +332,17 @@
 	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 endif
 
-ifneq ($(filter product_services,$(fs_config_generate_extra_partition_list)),)
+ifneq ($(filter system_ext,$(fs_config_generate_extra_partition_list)),)
 ##################################
-# Generate the product_services/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_product_services to PRODUCT_PACKAGES in
+# Generate the system_ext/etc/fs_config_dirs binary file for the target
+# Add fs_config_dirs or fs_config_dirs_system_ext to PRODUCT_PACKAGES in
 # the device make file to enable
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := fs_config_dirs_product_services
+LOCAL_MODULE := fs_config_dirs_system_ext
 LOCAL_MODULE_CLASS := ETC
 LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES)/etc
+LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
 $(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
 $(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
@@ -352,21 +352,21 @@
 	$< fsconfig \
 	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
 	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
-	   --partition product_services \
+	   --partition system_ext \
 	   --dirs \
 	   --out_file $@ \
 	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
 
 ##################################
-# Generate the product_services/etc/fs_config_files binary file for the target
-# Add fs_config_files of fs_config_files_product_services to PRODUCT_PACKAGES in
+# Generate the system_ext/etc/fs_config_files binary file for the target
+# Add fs_config_files of fs_config_files_system_ext to PRODUCT_PACKAGES in
 # the device make file to enable
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := fs_config_files_product_services
+LOCAL_MODULE := fs_config_files_system_ext
 LOCAL_MODULE_CLASS := ETC
 LOCAL_INSTALLED_MODULE_STEM := fs_config_files
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES)/etc
+LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc
 include $(BUILD_SYSTEM)/base_rules.mk
 $(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
 $(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header)
@@ -376,7 +376,7 @@
 	$< fsconfig \
 	   --aid-header $(PRIVATE_ANDROID_FS_HDR) \
 	   --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
-	   --partition product_services \
+	   --partition system_ext \
 	   --files \
 	   --out_file $@ \
 	   $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
diff --git a/tools/mktarball.sh b/tools/mktarball.sh
index ef0fe86..ced7e17 100755
--- a/tools/mktarball.sh
+++ b/tools/mktarball.sh
@@ -37,7 +37,7 @@
 #    echo "$f: dir: $is_dir curr: $curr_perms uid: $new_uid gid: $new_gid "\
 #         "perms: $new_perms"
     tar --no-recursion --numeric-owner --owner $new_uid \
-        --group $new_gid --mode $new_perms -p -rf ${target_tar} ${f}
+        --group $new_gid --mode $new_perms -rf ${target_tar} ${f}
 done
 
 if [ $? -eq 0 ] ; then
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index b5ae009..8cf3fab 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -44,6 +44,7 @@
         "ota_from_target_files.py",
         "ota_package_parser.py",
         "rangelib.py",
+        "sign_apex.py",
         "sign_target_files_apks.py",
         "sparse_img.py",
         "target_files_diff.py",
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 44719ed..e177828 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -126,7 +126,7 @@
   if not image_size:
     return None
 
-  image_blocks = int(image_size) / 4096 - 1
+  image_blocks = int(image_size) // 4096 - 1
   assert image_blocks > 0, "blocks for {} must be positive".format(which)
 
   # For sparse images, we will only check the blocks that are listed in the care
@@ -154,16 +154,16 @@
     return img.name
 
   def output_sink(fn, data):
-    ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
-    ofile.write(data)
-    ofile.close()
+    output_file = os.path.join(OPTIONS.input_tmp, "SYSTEM", fn)
+    with open(output_file, "wb") as ofile:
+      ofile.write(data)
 
     if output_zip:
       arc_name = "SYSTEM/" + fn
       if arc_name in output_zip.namelist():
         OPTIONS.replace_updated_files_list.append(arc_name)
       else:
-        common.ZipWrite(output_zip, ofile.name, arc_name)
+        common.ZipWrite(output_zip, output_file, arc_name)
 
   if (OPTIONS.rebuild_recovery and recovery_img is not None and
       boot_img is not None):
@@ -222,20 +222,20 @@
   return img.name
 
 
-def AddProductServices(output_zip):
-  """Turn the contents of PRODUCT_SERVICES into a product_services image and
-  store it in output_zip."""
+def AddSystemExt(output_zip):
+  """Turn the contents of SYSTEM_EXT into a system_ext image and store it in
+  output_zip."""
 
   img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES",
-                   "product_services.img")
+                   "system_ext.img")
   if os.path.exists(img.name):
-    logger.info("product_services.img already exists; no need to rebuild...")
+    logger.info("system_ext.img already exists; no need to rebuild...")
     return img.name
 
   block_list = OutputFile(
-      output_zip, OPTIONS.input_tmp, "IMAGES", "product_services.map")
+      output_zip, OPTIONS.input_tmp, "IMAGES", "system_ext.map")
   CreateImage(
-      OPTIONS.input_tmp, OPTIONS.info_dict, "product_services", img,
+      OPTIONS.input_tmp, OPTIONS.info_dict, "system_ext", img,
       block_list=block_list)
   return img.name
 
@@ -290,7 +290,7 @@
 
 
 def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
-  logger.info("creating " + what + ".img...")
+  logger.info("creating %s.img...", what)
 
   image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
   fstab = info_dict["fstab"]
@@ -734,10 +734,10 @@
   has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
   has_boot = OPTIONS.info_dict.get("no_boot") != "true"
 
-  # {vendor,odm,product,product_services}.img are unlike system.img or
+  # {vendor,odm,product,system_ext}.img are unlike system.img or
   # system_other.img. Because it could be built from source, or dropped into
   # target_files.zip as a prebuilt blob. We consider either of them as
-  # {vendor,product,product_services}.img being available, which could be
+  # {vendor,product,system_ext}.img being available, which could be
   # used when generating vbmeta.img for AVB.
   has_vendor = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "VENDOR")) or
                 os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES",
@@ -748,11 +748,11 @@
   has_product = (os.path.isdir(os.path.join(OPTIONS.input_tmp, "PRODUCT")) or
                  os.path.exists(os.path.join(OPTIONS.input_tmp, "IMAGES",
                                              "product.img")))
-  has_product_services = (os.path.isdir(os.path.join(OPTIONS.input_tmp,
-                                                     "PRODUCT_SERVICES")) or
-                          os.path.exists(os.path.join(OPTIONS.input_tmp,
-                                                      "IMAGES",
-                                                      "product_services.img")))
+  has_system_ext = (os.path.isdir(os.path.join(OPTIONS.input_tmp,
+                                               "SYSTEM_EXT")) or
+                    os.path.exists(os.path.join(OPTIONS.input_tmp,
+                                                "IMAGES",
+                                                "system_ext.img")))
   has_system = os.path.isdir(os.path.join(OPTIONS.input_tmp, "SYSTEM"))
   has_system_other = os.path.isdir(os.path.join(OPTIONS.input_tmp,
                                                 "SYSTEM_OTHER"))
@@ -778,7 +778,7 @@
   partitions = dict()
 
   def banner(s):
-    logger.info("\n\n++++ " + s + " ++++\n\n")
+    logger.info("\n\n++++ %s  ++++\n\n", s)
 
   boot_image = None
   if has_boot:
@@ -833,9 +833,9 @@
     banner("product")
     partitions['product'] = AddProduct(output_zip)
 
-  if has_product_services:
-    banner("product_services")
-    partitions['product_services'] = AddProductServices(output_zip)
+  if has_system_ext:
+    banner("system_ext")
+    partitions['system_ext'] = AddSystemExt(output_zip)
 
   if has_odm:
     banner("odm")
@@ -888,10 +888,11 @@
     banner("vbmeta")
     AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
 
-  if OPTIONS.info_dict.get("build_super_partition") == "true":
+  if OPTIONS.info_dict.get("use_dynamic_partitions") == "true":
     banner("super_empty")
     AddSuperEmpty(output_zip)
 
+  if OPTIONS.info_dict.get("build_super_partition") == "true":
     if OPTIONS.info_dict.get(
         "build_retrofit_dynamic_partitions_ota_package") == "true":
       banner("super split images")
@@ -901,7 +902,7 @@
   ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META",
                                    "ab_partitions.txt")
   if os.path.exists(ab_partitions_txt):
-    with open(ab_partitions_txt, 'r') as f:
+    with open(ab_partitions_txt) as f:
       ab_partitions = f.readlines()
 
     # For devices using A/B update, make sure we have all the needed images
@@ -916,7 +917,7 @@
   pack_radioimages_txt = os.path.join(
       OPTIONS.input_tmp, "META", "pack_radioimages.txt")
   if os.path.exists(pack_radioimages_txt):
-    with open(pack_radioimages_txt, 'r') as f:
+    with open(pack_radioimages_txt) as f:
       AddPackRadioImages(output_zip, f.readlines())
 
   if output_zip:
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index fb4ca76..6eaa12f 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -18,7 +18,6 @@
 import os.path
 import re
 import shlex
-import sys
 import zipfile
 
 import common
@@ -42,11 +41,11 @@
     Exception.__init__(self, message)
 
 
-def SignApexPayload(payload_file, payload_key_path, payload_key_name, algorithm,
-                    salt, signing_args=None):
+def SignApexPayload(avbtool, payload_file, payload_key_path, payload_key_name,
+                    algorithm, salt, signing_args=None):
   """Signs a given payload_file with the payload key."""
   # Add the new footer. Old footer, if any, will be replaced by avbtool.
-  cmd = ['avbtool', 'add_hashtree_footer',
+  cmd = [avbtool, 'add_hashtree_footer',
          '--do_not_generate_fec',
          '--algorithm', algorithm,
          '--key', payload_key_path,
@@ -59,31 +58,32 @@
   try:
     common.RunAndCheckOutput(cmd)
   except common.ExternalError as e:
-    raise ApexSigningError, \
+    raise ApexSigningError(
         'Failed to sign APEX payload {} with {}:\n{}'.format(
-            payload_file, payload_key_path, e), sys.exc_info()[2]
+            payload_file, payload_key_path, e))
 
   # Verify the signed payload image with specified public key.
   logger.info('Verifying %s', payload_file)
-  VerifyApexPayload(payload_file, payload_key_path)
+  VerifyApexPayload(avbtool, payload_file, payload_key_path)
 
 
-def VerifyApexPayload(payload_file, payload_key):
+def VerifyApexPayload(avbtool, payload_file, payload_key):
   """Verifies the APEX payload signature with the given key."""
-  cmd = ['avbtool', 'verify_image', '--image', payload_file,
+  cmd = [avbtool, 'verify_image', '--image', payload_file,
          '--key', payload_key]
   try:
     common.RunAndCheckOutput(cmd)
   except common.ExternalError as e:
-    raise ApexSigningError, \
+    raise ApexSigningError(
         'Failed to validate payload signing for {} with {}:\n{}'.format(
-            payload_file, payload_key, e), sys.exc_info()[2]
+            payload_file, payload_key, e))
 
 
-def ParseApexPayloadInfo(payload_path):
+def ParseApexPayloadInfo(avbtool, payload_path):
   """Parses the APEX payload info.
 
   Args:
+    avbtool: The AVB tool to use.
     payload_path: The path to the payload image.
 
   Raises:
@@ -96,13 +96,13 @@
   if not os.path.exists(payload_path):
     raise ApexInfoError('Failed to find image: {}'.format(payload_path))
 
-  cmd = ['avbtool', 'info_image', '--image', payload_path]
+  cmd = [avbtool, 'info_image', '--image', payload_path]
   try:
     output = common.RunAndCheckOutput(cmd)
   except common.ExternalError as e:
-    raise ApexInfoError, \
+    raise ApexInfoError(
         'Failed to get APEX payload info for {}:\n{}'.format(
-            payload_path, e), sys.exc_info()[2]
+            payload_path, e))
 
   # Extract the Algorithm / Salt / Prop info from payload (i.e. an image signed
   # with avbtool). For example,
@@ -150,7 +150,7 @@
   return payload_info
 
 
-def SignApex(apex_data, payload_key, container_key, container_pw,
+def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
              codename_to_api_level_map, signing_args=None):
   """Signs the current APEX with the given payload/container keys.
 
@@ -178,8 +178,9 @@
   with zipfile.ZipFile(apex_file) as apex_fd:
     payload_file = apex_fd.extract(APEX_PAYLOAD_IMAGE, payload_dir)
 
-  payload_info = ParseApexPayloadInfo(payload_file)
+  payload_info = ParseApexPayloadInfo(avbtool, payload_file)
   SignApexPayload(
+      avbtool,
       payload_file,
       payload_key,
       payload_info['apex.key'],
@@ -188,7 +189,7 @@
       signing_args)
 
   # 1b. Update the embedded payload public key.
-  payload_public_key = common.ExtractAvbPublicKey(payload_key)
+  payload_public_key = common.ExtractAvbPublicKey(avbtool, payload_key)
 
   common.ZipDelete(apex_file, APEX_PAYLOAD_IMAGE)
   common.ZipDelete(apex_file, APEX_PUBKEY)
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index ba04651..ee05dd5 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -644,30 +644,30 @@
       d["extfs_rsv_pct"] = "0"
     copy_prop("product_reserved_size", "partition_reserved_size")
     copy_prop("product_selinux_fc", "selinux_fc")
-  elif mount_point == "product_services":
-    copy_prop("avb_product_services_hashtree_enable", "avb_hashtree_enable")
-    copy_prop("avb_product_services_add_hashtree_footer_args",
+  elif mount_point == "system_ext":
+    copy_prop("avb_system_ext_hashtree_enable", "avb_hashtree_enable")
+    copy_prop("avb_system_ext_add_hashtree_footer_args",
               "avb_add_hashtree_footer_args")
-    copy_prop("avb_product_services_key_path", "avb_key_path")
-    copy_prop("avb_product_services_algorithm", "avb_algorithm")
-    copy_prop("product_services_fs_type", "fs_type")
-    copy_prop("product_services_size", "partition_size")
-    if not copy_prop("product_services_journal_size", "journal_size"):
+    copy_prop("avb_system_ext_key_path", "avb_key_path")
+    copy_prop("avb_system_ext_algorithm", "avb_algorithm")
+    copy_prop("system_ext_fs_type", "fs_type")
+    copy_prop("system_ext_size", "partition_size")
+    if not copy_prop("system_ext_journal_size", "journal_size"):
       d["journal_size"] = "0"
-    copy_prop("product_services_verity_block_device", "verity_block_device")
+    copy_prop("system_ext_verity_block_device", "verity_block_device")
     copy_prop("ext4_share_dup_blocks", "ext4_share_dup_blocks")
-    copy_prop("product_services_squashfs_compressor", "squashfs_compressor")
-    copy_prop("product_services_squashfs_compressor_opt",
+    copy_prop("system_ext_squashfs_compressor", "squashfs_compressor")
+    copy_prop("system_ext_squashfs_compressor_opt",
               "squashfs_compressor_opt")
-    copy_prop("product_services_squashfs_block_size", "squashfs_block_size")
-    copy_prop("product_services_squashfs_disable_4k_align",
+    copy_prop("system_ext_squashfs_block_size", "squashfs_block_size")
+    copy_prop("system_ext_squashfs_disable_4k_align",
               "squashfs_disable_4k_align")
-    copy_prop("product_services_base_fs_file", "base_fs_file")
-    copy_prop("product_services_extfs_inode_count", "extfs_inode_count")
-    if not copy_prop("product_services_extfs_rsv_pct", "extfs_rsv_pct"):
+    copy_prop("system_ext_base_fs_file", "base_fs_file")
+    copy_prop("system_ext_extfs_inode_count", "extfs_inode_count")
+    if not copy_prop("system_ext_extfs_rsv_pct", "extfs_rsv_pct"):
       d["extfs_rsv_pct"] = "0"
-    copy_prop("product_services_reserved_size", "partition_reserved_size")
-    copy_prop("product_services_selinux_fc", "selinux_fc")
+    copy_prop("system_ext_reserved_size", "partition_reserved_size")
+    copy_prop("system_ext_selinux_fc", "selinux_fc")
   elif mount_point == "odm":
     copy_prop("avb_odm_hashtree_enable", "avb_hashtree_enable")
     copy_prop("avb_odm_add_hashtree_footer_args",
@@ -736,8 +736,8 @@
     copy_prop("partition_size", "odm_size")
   elif mount_point == "product":
     copy_prop("partition_size", "product_size")
-  elif mount_point == "product_services":
-    copy_prop("partition_size", "product_services_size")
+  elif mount_point == "system_ext":
+    copy_prop("partition_size", "system_ext_size")
   return d
 
 
@@ -777,8 +777,8 @@
       mount_point = "oem"
     elif image_filename == "product.img":
       mount_point = "product"
-    elif image_filename == "product_services.img":
-      mount_point = "product_services"
+    elif image_filename == "system_ext.img":
+      mount_point = "system_ext"
     else:
       logger.error("Unknown image file name %s", image_filename)
       sys.exit(1)
diff --git a/tools/releasetools/check_ota_package_signature.py b/tools/releasetools/check_ota_package_signature.py
index 7d3424b..0d990f1 100755
--- a/tools/releasetools/check_ota_package_signature.py
+++ b/tools/releasetools/check_ota_package_signature.py
@@ -38,8 +38,7 @@
   """Check if the cert uses SHA-256 hashing algorithm."""
 
   cmd = ['openssl', 'x509', '-text', '-noout', '-in', cert]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  cert_dump, _ = p1.communicate()
+  cert_dump = common.RunAndCheckOutput(cmd, stdout=subprocess.PIPE)
 
   algorithm = re.search(r'Signature Algorithm: ([a-zA-Z0-9]+)', cert_dump)
   assert algorithm, "Failed to identify the signature algorithm."
@@ -69,13 +68,13 @@
   print('Certificate: %s' % (cert,))
 
   # Read in the package.
-  with open(package) as package_file:
+  with open(package, 'rb') as package_file:
     package_bytes = package_file.read()
 
   length = len(package_bytes)
   assert length >= 6, "Not big enough to contain footer."
 
-  footer = [ord(x) for x in package_bytes[-6:]]
+  footer = bytearray(package_bytes[-6:])
   assert footer[2] == 0xff and footer[3] == 0xff, "Footer is wrong."
 
   signature_start_from_end = (footer[1] << 8) + footer[0]
@@ -111,31 +110,25 @@
 
   # Parse the signature and get the hash.
   cmd = ['openssl', 'asn1parse', '-inform', 'DER', '-in', sig_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  sig, _ = p1.communicate()
-  assert p1.returncode == 0, "Failed to parse the signature."
+  sig = common.RunAndCheckOutput(cmd, stdout=subprocess.PIPE)
 
-  digest_line = sig.strip().split('\n')[-1]
+  digest_line = sig.rstrip().split('\n')[-1]
   digest_string = digest_line.split(':')[3]
   digest_file = common.MakeTempFile(prefix='digest-')
   with open(digest_file, 'wb') as f:
-    f.write(digest_string.decode('hex'))
+    f.write(bytearray.fromhex(digest_string))
 
   # Verify the digest by outputing the decrypted result in ASN.1 structure.
   decrypted_file = common.MakeTempFile(prefix='decrypted-')
   cmd = ['openssl', 'rsautl', '-verify', '-certin', '-inkey', cert,
          '-in', digest_file, '-out', decrypted_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  p1.communicate()
-  assert p1.returncode == 0, "Failed to run openssl rsautl -verify."
+  common.RunAndCheckOutput(cmd, stdout=subprocess.PIPE)
 
   # Parse the output ASN.1 structure.
   cmd = ['openssl', 'asn1parse', '-inform', 'DER', '-in', decrypted_file]
-  p1 = common.Run(cmd, stdout=subprocess.PIPE)
-  decrypted_output, _ = p1.communicate()
-  assert p1.returncode == 0, "Failed to parse the output."
+  decrypted_output = common.RunAndCheckOutput(cmd, stdout=subprocess.PIPE)
 
-  digest_line = decrypted_output.strip().split('\n')[-1]
+  digest_line = decrypted_output.rstrip().split('\n')[-1]
   digest_string = digest_line.split(':')[3].lower()
 
   # Verify that the two digest strings match.
@@ -156,7 +149,7 @@
 
   # Dump pubkey from the certificate.
   pubkey = common.MakeTempFile(prefix="key-", suffix=".pem")
-  with open(pubkey, 'wb') as pubkey_fp:
+  with open(pubkey, 'w') as pubkey_fp:
     pubkey_fp.write(common.ExtractPublicKey(cert))
 
   package_dir = common.MakeTempDir(prefix='package-')
@@ -166,11 +159,7 @@
   cmd = ['delta_generator',
          '--in_file=' + payload_file,
          '--public_key=' + pubkey]
-  proc = common.Run(cmd)
-  stdoutdata, _ = proc.communicate()
-  assert proc.returncode == 0, \
-      'Failed to verify payload with delta_generator: {}\n{}'.format(
-          package, stdoutdata)
+  common.RunAndCheckOutput(cmd)
   common.ZipClose(package_zip)
 
   # Verified successfully upon reaching here.
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index 4b0d4c7..60200a3 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -39,8 +39,11 @@
 
 """
 
+from __future__ import print_function
+
 import logging
 import os
+import os.path
 import re
 import subprocess
 import sys
@@ -49,7 +52,7 @@
 import common
 
 if sys.hexversion < 0x02070000:
-  print >> sys.stderr, "Python 2.7 or newer is required."
+  print("Python 2.7 or newer is required.", file=sys.stderr)
   sys.exit(1)
 
 
@@ -65,8 +68,10 @@
 class MyZipInfo(zipfile.ZipInfo):
   def _decodeExtra(self):
     pass
+
 zipfile.ZipInfo = MyZipInfo
 
+
 OPTIONS = common.OPTIONS
 
 OPTIONS.text = False
@@ -76,28 +81,34 @@
 PROBLEMS = []
 PROBLEM_PREFIX = []
 
+
 def AddProblem(msg):
   PROBLEMS.append(" ".join(PROBLEM_PREFIX) + " " + msg)
+
+
 def Push(msg):
   PROBLEM_PREFIX.append(msg)
+
+
 def Pop():
   PROBLEM_PREFIX.pop()
 
 
 def Banner(msg):
-  print "-" * 70
-  print "  ", msg
-  print "-" * 70
+  print("-" * 70)
+  print("  ", msg)
+  print("-" * 70)
 
 
 def GetCertSubject(cert):
   p = common.Run(["openssl", "x509", "-inform", "DER", "-text"],
                  stdin=subprocess.PIPE,
-                 stdout=subprocess.PIPE)
+                 stdout=subprocess.PIPE,
+                 universal_newlines=False)
   out, err = p.communicate(cert)
   if err and not err.strip():
     return "(error reading cert subject)"
-  for line in out.split("\n"):
+  for line in out.decode().split("\n"):
     line = line.strip()
     if line.startswith("Subject:"):
       return line[8:].strip()
@@ -105,6 +116,7 @@
 
 
 class CertDB(object):
+
   def __init__(self):
     self.certs = {}
 
@@ -132,13 +144,13 @@
           to_load.extend(certs)
 
     for i in to_load:
-      f = open(i)
-      cert = common.ParseCertificate(f.read())
-      f.close()
+      with open(i) as f:
+        cert = common.ParseCertificate(f.read())
       name, _ = os.path.splitext(i)
       name, _ = os.path.splitext(name)
       self.Add(cert, name)
 
+
 ALL_CERTS = CertDB()
 
 
@@ -152,13 +164,14 @@
                     "-outform", "PEM",
                     "-print_certs"],
                    stdin=subprocess.PIPE,
-                   stdout=subprocess.PIPE)
+                   stdout=subprocess.PIPE,
+                   universal_newlines=False)
     out, err = p.communicate(data)
     if err and not err.strip():
-      AddProblem("error reading cert:\n" + err)
+      AddProblem("error reading cert:\n" + err.decode())
       return None
 
-    cert = common.ParseCertificate(out)
+    cert = common.ParseCertificate(out.decode())
     if not cert:
       AddProblem("error parsing cert output")
       return None
@@ -184,22 +197,20 @@
 
   def RecordCerts(self, full_filename):
     out = set()
-    try:
-      f = open(full_filename)
-      apk = zipfile.ZipFile(f, "r")
+    with zipfile.ZipFile(full_filename) as apk:
       pkcs7 = None
       for info in apk.infolist():
-        if info.filename.startswith("META-INF/") and \
-           (info.filename.endswith(".DSA") or info.filename.endswith(".RSA")):
-          pkcs7 = apk.read(info.filename)
-          cert = CertFromPKCS7(pkcs7, info.filename)
+        filename = info.filename
+        if (filename.startswith("META-INF/") and
+            info.filename.endswith((".DSA", ".RSA"))):
+          pkcs7 = apk.read(filename)
+          cert = CertFromPKCS7(pkcs7, filename)
           out.add(cert)
           ALL_CERTS.Add(cert)
       if not pkcs7:
         AddProblem("no signature")
-    finally:
-      f.close()
-      self.certs = frozenset(out)
+
+    self.certs = frozenset(out)
 
   def ReadManifest(self, full_filename):
     p = common.Run(["aapt", "dump", "xmltree", full_filename,
@@ -247,8 +258,8 @@
     # This is the list of wildcards of files we extract from |filename|.
     apk_extensions = ['*.apk', '*.apex']
 
-    self.certmap, compressed_extension = common.ReadApkCerts(
-        zipfile.ZipFile(filename))
+    with zipfile.ZipFile(filename) as input_zip:
+      self.certmap, compressed_extension = common.ReadApkCerts(input_zip)
     if compressed_extension:
       apk_extensions.append('*.apk' + compressed_extension)
 
@@ -287,7 +298,7 @@
     """Look for any instances where packages signed with different
     certs request the same sharedUserId."""
     apks_by_uid = {}
-    for apk in self.apks.itervalues():
+    for apk in self.apks.values():
       if apk.shared_uid:
         apks_by_uid.setdefault(apk.shared_uid, []).append(apk)
 
@@ -302,15 +313,15 @@
 
       AddProblem("different cert sets for packages with uid %s" % (uid,))
 
-      print "uid %s is shared by packages with different cert sets:" % (uid,)
+      print("uid %s is shared by packages with different cert sets:" % (uid,))
       for apk in apks:
-        print "%-*s  [%s]" % (self.max_pkg_len, apk.package, apk.filename)
+        print("%-*s  [%s]" % (self.max_pkg_len, apk.package, apk.filename))
         for cert in apk.certs:
-          print "   ", ALL_CERTS.Get(cert)
-      print
+          print("   ", ALL_CERTS.Get(cert))
+      print()
 
   def CheckExternalSignatures(self):
-    for apk_filename, certname in self.certmap.iteritems():
+    for apk_filename, certname in self.certmap.items():
       if certname == "EXTERNAL":
         # Apps marked EXTERNAL should be signed with the test key
         # during development, then manually re-signed after
@@ -326,25 +337,25 @@
   def PrintCerts(self):
     """Display a table of packages grouped by cert."""
     by_cert = {}
-    for apk in self.apks.itervalues():
+    for apk in self.apks.values():
       for cert in apk.certs:
         by_cert.setdefault(cert, []).append((apk.package, apk))
 
-    order = [(-len(v), k) for (k, v) in by_cert.iteritems()]
+    order = [(-len(v), k) for (k, v) in by_cert.items()]
     order.sort()
 
     for _, cert in order:
-      print "%s:" % (ALL_CERTS.Get(cert),)
+      print("%s:" % (ALL_CERTS.Get(cert),))
       apks = by_cert[cert]
       apks.sort()
       for _, apk in apks:
         if apk.shared_uid:
-          print "  %-*s  %-*s  [%s]" % (self.max_fn_len, apk.filename,
+          print("  %-*s  %-*s  [%s]" % (self.max_fn_len, apk.filename,
                                         self.max_pkg_len, apk.package,
-                                        apk.shared_uid)
+                                        apk.shared_uid))
         else:
-          print "  %-*s  %s" % (self.max_fn_len, apk.filename, apk.package)
-      print
+          print("  %-*s  %s" % (self.max_fn_len, apk.filename, apk.package))
+      print()
 
   def CompareWith(self, other):
     """Look for instances where a given package that exists in both
@@ -365,12 +376,12 @@
             by_certpair.setdefault((other.apks[i].certs,
                                     self.apks[i].certs), []).append(i)
         else:
-          print "%s [%s]: new APK (not in comparison target_files)" % (
-              i, self.apks[i].filename)
+          print("%s [%s]: new APK (not in comparison target_files)" % (
+              i, self.apks[i].filename))
       else:
         if i in other.apks:
-          print "%s [%s]: removed APK (only in comparison target_files)" % (
-              i, other.apks[i].filename)
+          print("%s [%s]: removed APK (only in comparison target_files)" % (
+              i, other.apks[i].filename))
 
     if by_certpair:
       AddProblem("some APKs changed certs")
@@ -378,23 +389,23 @@
       for (old, new), packages in sorted(by_certpair.items()):
         for i, o in enumerate(old):
           if i == 0:
-            print "was", ALL_CERTS.Get(o)
+            print("was", ALL_CERTS.Get(o))
           else:
-            print "   ", ALL_CERTS.Get(o)
+            print("   ", ALL_CERTS.Get(o))
         for i, n in enumerate(new):
           if i == 0:
-            print "now", ALL_CERTS.Get(n)
+            print("now", ALL_CERTS.Get(n))
           else:
-            print "   ", ALL_CERTS.Get(n)
+            print("   ", ALL_CERTS.Get(n))
         for i in sorted(packages):
           old_fn = other.apks[i].filename
           new_fn = self.apks[i].filename
           if old_fn == new_fn:
-            print "  %-*s  [%s]" % (max_pkg_len, i, old_fn)
+            print("  %-*s  [%s]" % (max_pkg_len, i, old_fn))
           else:
-            print "  %-*s  [was: %s; now: %s]" % (max_pkg_len, i,
-                                                  old_fn, new_fn)
-        print
+            print("  %-*s  [was: %s; now: %s]" % (max_pkg_len, i,
+                                                  old_fn, new_fn))
+        print()
 
 
 def main(argv):
@@ -451,9 +462,9 @@
     target_files.CompareWith(compare_files)
 
   if PROBLEMS:
-    print "%d problem(s) found:\n" % (len(PROBLEMS),)
+    print("%d problem(s) found:\n" % (len(PROBLEMS),))
     for p in PROBLEMS:
-      print p
+      print(p)
     return 1
 
   return 0
@@ -464,9 +475,7 @@
     r = main(sys.argv[1:])
     sys.exit(r)
   except common.ExternalError as e:
-    print
-    print "   ERROR: %s" % (e,)
-    print
+    print("\n   ERROR: %s\n" % (e,))
     sys.exit(1)
   finally:
     common.Cleanup()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 7cff831..9998cd3 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -14,6 +14,7 @@
 
 from __future__ import print_function
 
+import base64
 import collections
 import copy
 import errno
@@ -30,7 +31,6 @@
 import re
 import shlex
 import shutil
-import string
 import subprocess
 import sys
 import tempfile
@@ -54,7 +54,9 @@
       base_search_path = os.path.join(base_out_path,
                                       os.path.basename(os.getcwd()))
 
+    # Python >= 3.3 returns 'linux', whereas Python 2.7 gives 'linux2'.
     platform_search_path = {
+        "linux": os.path.join(base_search_path, "host/linux-x86"),
         "linux2": os.path.join(base_search_path, "host/linux-x86"),
         "darwin": os.path.join(base_search_path, "host/darwin-x86"),
     }
@@ -96,15 +98,14 @@
 # The partitions allowed to be signed by AVB (Android Verified Boot 2.0). Note
 # that system_other is not in the list because we don't want to include its
 # descriptor into vbmeta.img.
-AVB_PARTITIONS = ('boot', 'dtbo', 'odm', 'product', 'product_services',
-                  'recovery', 'system', 'vendor')
+AVB_PARTITIONS = ('boot', 'dtbo', 'odm', 'product', 'recovery', 'system',
+                  'system_ext', 'vendor')
 
 # Chained VBMeta partitions.
 AVB_VBMETA_PARTITIONS = ('vbmeta_system', 'vbmeta_vendor')
 
 # Partitions that should have their care_map added to META/care_map.pb
-PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product', 'product_services',
-                            'odm')
+PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product', 'system_ext', 'odm')
 
 
 class ErrorCode(object):
@@ -190,6 +191,8 @@
     kwargs: Any additional args to be passed to subprocess.Popen(), such as env,
         stdin, etc. stdout and stderr will default to subprocess.PIPE and
         subprocess.STDOUT respectively unless caller specifies any of them.
+        universal_newlines will default to True, as most of the users in
+        releasetools expect string output.
 
   Returns:
     A subprocess.Popen object.
@@ -197,6 +200,8 @@
   if 'stdout' not in kwargs and 'stderr' not in kwargs:
     kwargs['stdout'] = subprocess.PIPE
     kwargs['stderr'] = subprocess.STDOUT
+  if 'universal_newlines' not in kwargs:
+    kwargs['universal_newlines'] = True
   # Don't log any if caller explicitly says so.
   if verbose != False:
     logger.info("  Running: \"%s\"", " ".join(args))
@@ -314,7 +319,7 @@
 
   def read_helper(fn):
     if isinstance(input_file, zipfile.ZipFile):
-      return input_file.read(fn)
+      return input_file.read(fn).decode()
     else:
       path = os.path.join(input_file, *fn.split("/"))
       try:
@@ -455,6 +460,13 @@
   return LoadDictionaryFromLines(data.split("\n"))
 
 
+def LoadDictionaryFromFile(file_path):
+  with open(file_path) as f:
+    lines = list(f.read().splitlines())
+
+  return LoadDictionaryFromLines(lines)
+
+
 def LoadDictionaryFromLines(lines):
   d = {}
   for line in lines:
@@ -526,7 +538,7 @@
   # system. Other areas assume system is always at "/system" so point /system
   # at /.
   if system_root_image:
-    assert not d.has_key("/system") and d.has_key("/")
+    assert '/system' not in d and '/' in d
     d["/system"] = d["/"]
   return d
 
@@ -565,7 +577,7 @@
   """
   if key is None:
     key = info_dict["avb_" + partition + "_key_path"]
-  pubkey_path = ExtractAvbPublicKey(key)
+  pubkey_path = ExtractAvbPublicKey(info_dict["avb_avbtool"], key)
   rollback_index_location = info_dict[
       "avb_" + partition + "_rollback_index_location"]
   return "{}:{}:{}".format(partition, rollback_index_location, pubkey_path)
@@ -953,7 +965,7 @@
     # filename listed in system.map may contain an additional leading slash
     # (i.e. "//system/framework/am.jar"). Using lstrip to get consistent
     # results.
-    arcname = string.replace(entry, which, which.upper(), 1).lstrip('/')
+    arcname = entry.replace(which, which.upper(), 1).lstrip('/')
 
     # Special handling another case, where files not under /system
     # (e.g. "/sbin/charger") are packed under ROOT/ in a target_files.zip.
@@ -1223,7 +1235,7 @@
     if basename:
       installed_files.add(basename)
 
-  for line in tf_zip.read("META/apkcerts.txt").split("\n"):
+  for line in tf_zip.read('META/apkcerts.txt').decode().split('\n'):
     line = line.strip()
     if not line:
       continue
@@ -1433,6 +1445,8 @@
 
       if not first:
         print("key file %s still missing some passwords." % (self.pwfile,))
+        if sys.version_info[0] >= 3:
+          raw_input = input  # pylint: disable=redefined-builtin
         answer = raw_input("try to edit again? [y]> ").strip()
         if answer and answer[0] not in 'yY':
           raise RuntimeError("key passwords unavailable")
@@ -2185,7 +2199,7 @@
   This gives the same result as `openssl x509 -in <filename> -outform DER`.
 
   Returns:
-    The decoded certificate string.
+    The decoded certificate bytes.
   """
   cert_buffer = []
   save = False
@@ -2196,7 +2210,7 @@
       cert_buffer.append(line)
     if "--BEGIN CERTIFICATE--" in line:
       save = True
-  cert = "".join(cert_buffer).decode('base64')
+  cert = base64.b64decode("".join(cert_buffer))
   return cert
 
 
@@ -2224,10 +2238,11 @@
   return pubkey
 
 
-def ExtractAvbPublicKey(key):
+def ExtractAvbPublicKey(avbtool, key):
   """Extracts the AVB public key from the given public or private key.
 
   Args:
+    avbtool: The AVB tool to use.
     key: The input key file, which should be PEM-encoded public or private key.
 
   Returns:
@@ -2235,7 +2250,7 @@
   """
   output = MakeTempFile(prefix='avb-', suffix='.avbpubkey')
   RunAndCheckOutput(
-      ['avbtool', 'extract_public_key', "--key", key, "--output", output])
+      [avbtool, 'extract_public_key', "--key", key, "--output", output])
   return output
 
 
@@ -2338,7 +2353,7 @@
 
   logger.info("putting script in %s", sh_location)
 
-  output_sink(sh_location, sh)
+  output_sink(sh_location, sh.encode())
 
 
 class DynamicPartitionUpdate(object):
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index f0ae217..f73bae1 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -13,7 +13,9 @@
 # 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 package contains framework files, and the other contains vendor files.
 It produces a complete target files package that can be used to generate an
@@ -91,6 +93,7 @@
 import ota_from_target_files
 
 logger = logging.getLogger(__name__)
+
 OPTIONS = common.OPTIONS
 OPTIONS.verbose = True
 OPTIONS.framework_target_files = None
@@ -143,8 +146,8 @@
     'avb_system_rollback_index_location',
     'avb_product_hashtree_enable',
     'avb_product_add_hashtree_footer_args',
-    'avb_product_services_hashtree_enable',
-    'avb_product_services_add_hashtree_footer_args',
+    'avb_system_ext_hashtree_enable',
+    'avb_system_ext_add_hashtree_footer_args',
     'system_root_image',
     'root_dir',
     'ab_update',
@@ -190,7 +193,7 @@
     'DATA/',
     'ODM/',
     'PRODUCT/',
-    'PRODUCT_SERVICES/',
+    'SYSTEM_EXT/',
     'RADIO/',
     'RECOVERY/',
     'ROOT/',
@@ -201,10 +204,10 @@
 
 
 def write_sorted_data(data, path):
-  """Write the sorted contents of either a list or dict to file.
+  """Writes the sorted contents of either a list or dict to file.
 
-  This function sorts the contents of the list or dict and then
-  writes the resulting sorted contents to a file specified by path.
+  This function sorts the contents of the list or dict and then writes the
+  resulting sorted contents to a file specified by path.
 
   Args:
     data: The list or dict to sort and write.
@@ -219,7 +222,7 @@
 
 
 def extract_items(target_files, target_files_temp_dir, extract_item_list):
-  """Extract items from target files to temporary directory.
+  """Extracts items from target files to temporary directory.
 
   This function extracts from the specified target files zip archive into the
   specified temporary directory, the items specified in the extract item list.
@@ -237,7 +240,7 @@
   # zip file. Otherwise, the extraction step will fail.
 
   with zipfile.ZipFile(
-      target_files, 'r', allowZip64=True) as target_files_zipfile:
+      target_files, allowZip64=True) as target_files_zipfile:
     target_files_namelist = target_files_zipfile.namelist()
 
   filtered_extract_item_list = []
@@ -334,9 +337,9 @@
     in_vendor = any(item.startswith(partition) for item in vendor_item_list)
     if in_framework and in_vendor:
       logger.error(
-          'Cannot extract items from {0} for both the framework and vendor builds. '
-          'Please ensure only one merge config item list includes {0}.'.format(
-              partition))
+          'Cannot extract items from %s for both the framework and vendor'
+          ' builds. Please ensure only one merge config item list'
+          ' includes %s.', partition, partition)
       has_error = True
 
   if ('dynamic_partition_list' in framework_misc_info_keys) or (
@@ -351,15 +354,14 @@
 def process_ab_partitions_txt(framework_target_files_temp_dir,
                               vendor_target_files_temp_dir,
                               output_target_files_temp_dir):
-  """Perform special processing for META/ab_partitions.txt.
+  """Performs special processing for META/ab_partitions.txt.
 
-  This function merges the contents of the META/ab_partitions.txt files from
-  the framework directory and the vendor directory, placing the merged result in
-  the output directory. The precondition in that the files are already
-  extracted. The post condition is that the output META/ab_partitions.txt
-  contains the merged content. The format for each ab_partitions.txt a one
-  partition name per line. The output file contains the union of the parition
-  names.
+  This function merges the contents of the META/ab_partitions.txt files from the
+  framework directory and the vendor directory, placing the merged result in the
+  output directory. The precondition in that the files are already extracted.
+  The post condition is that the output META/ab_partitions.txt contains the
+  merged content. The format for each ab_partitions.txt a one partition name per
+  line. The output file contains the union of the parition names.
 
   Args:
     framework_target_files_temp_dir: The name of a directory containing the
@@ -392,10 +394,10 @@
 
 
 def append_recovery_to_filesystem_config(output_target_files_temp_dir):
-  """Perform special processing for META/filesystem_config.txt.
+  """Performs special processing for META/filesystem_config.txt.
 
-  This function appends recovery information to META/filesystem_config.txt
-  so that recovery patch regeneration will succeed.
+  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
@@ -479,7 +481,7 @@
                           vendor_target_files_temp_dir,
                           output_target_files_temp_dir,
                           framework_misc_info_keys):
-  """Perform special processing for META/misc_info.txt.
+  """Performs special processing for META/misc_info.txt.
 
   This function merges the contents of the META/misc_info.txt files from the
   framework directory and the vendor directory, placing the merged result in the
@@ -500,18 +502,14 @@
       instance.
   """
 
-  def read_helper(d):
-    misc_info_txt = os.path.join(d, 'META', 'misc_info.txt')
-    with open(misc_info_txt) as f:
-      return list(f.read().splitlines())
-
-  framework_dict = common.LoadDictionaryFromLines(
-      read_helper(framework_target_files_temp_dir))
+  misc_info_path = ['META', 'misc_info.txt']
+  framework_dict = common.LoadDictionaryFromFile(
+      os.path.join(framework_target_files_temp_dir, *misc_info_path))
 
   # We take most of the misc info from the vendor target files.
 
-  merged_dict = common.LoadDictionaryFromLines(
-      read_helper(vendor_target_files_temp_dir))
+  merged_dict = common.LoadDictionaryFromFile(
+      os.path.join(vendor_target_files_temp_dir, *misc_info_path))
 
   # Replace certain values in merged_dict with values from
   # framework_dict.
@@ -530,9 +528,9 @@
         list_prefix='super_',
         list_suffix='_partition_list')
     merged_dict.update(merged_dynamic_partitions_dict)
-    # Ensure that add_img_to_target_files rebuilds super_empty.img. This flag
-    # may have been set to false in the partial builds to prevent duplicate
-    # building of super.img and super_empty.img.
+    # Ensure that add_img_to_target_files rebuilds super split images for
+    # devices that retrofit dynamic partitions. This flag may have been set to
+    # false in the partial builds to prevent duplicate building of super.img.
     merged_dict['build_super_partition'] = 'true'
 
   # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
@@ -555,7 +553,7 @@
 def process_dynamic_partitions_info_txt(framework_target_files_dir,
                                         vendor_target_files_dir,
                                         output_target_files_dir):
-  """Perform special processing for META/dynamic_partitions_info.txt.
+  """Performs special processing for META/dynamic_partitions_info.txt.
 
   This function merges the contents of the META/dynamic_partitions_info.txt
   files from the framework directory and the vendor directory, placing the
@@ -578,16 +576,12 @@
                    'dynamic_partitions_info.txt')):
     return
 
-  def read_helper(d):
-    dynamic_partitions_info_txt = os.path.join(d, 'META',
-                                               'dynamic_partitions_info.txt')
-    with open(dynamic_partitions_info_txt) as f:
-      return list(f.read().splitlines())
+  dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
 
-  framework_dynamic_partitions_dict = common.LoadDictionaryFromLines(
-      read_helper(framework_target_files_dir))
-  vendor_dynamic_partitions_dict = common.LoadDictionaryFromLines(
-      read_helper(vendor_target_files_dir))
+  framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
+      os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
+  vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
+      os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
 
   merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
       framework_dict=framework_dynamic_partitions_dict,
@@ -607,14 +601,13 @@
 def process_apex_keys_apk_certs_common(framework_target_files_dir,
                                        vendor_target_files_dir,
                                        output_target_files_dir, file_name):
-  """Perform special processing for META/apexkeys.txt or META/apkcerts.txt.
+  """Performs special processing for META/apexkeys.txt or META/apkcerts.txt.
 
   This function merges the contents of the META/apexkeys.txt or
-  META/apkcerts.txt files from the framework directory and the vendor
-  directory, placing the merged result in the output directory. The
-  precondition in that the files are already extracted. The post condition
-  is that the output META/apexkeys.txt or META/apkcerts.txt contains the
-  merged content.
+  META/apkcerts.txt files from the framework directory and the vendor directory,
+  placing the merged result in the output directory. The precondition in that
+  the files are already extracted. The post condition is that the output
+  META/apexkeys.txt or META/apkcerts.txt contains the merged content.
 
   Args:
     framework_target_files_dir: The name of a directory containing the special
@@ -681,7 +674,7 @@
                           vendor_target_files_temp_dir,
                           output_target_files_temp_dir,
                           framework_misc_info_keys, rebuild_recovery):
-  """Perform special-case processing for certain target files items.
+  """Performs special-case processing for certain target files items.
 
   Certain files in the output target files package require special-case
   processing. This function performs all that special-case processing.
@@ -740,16 +733,30 @@
       file_name='apexkeys.txt')
 
 
-def merge_target_files(temp_dir, framework_target_files, framework_item_list,
-                       framework_misc_info_keys, vendor_target_files,
-                       vendor_item_list, output_target_files, output_dir,
-                       output_item_list, output_ota, output_img,
-                       output_super_empty, rebuild_recovery):
-  """Merge two target files packages together.
+def files_from_path(target_path, extra_args=None):
+  """Gets files under given path.
 
-  This function takes framework and vendor target files packages as input,
-  performs various file extractions, special case processing, and finally
-  creates a merged zip archive as output.
+  Get (sub)files from given target path and return sorted list.
+
+  Args:
+    target_path: Target path to get subfiles.
+    extra_args: List of extra argument for find command. Optional.
+
+  Returns:
+    Sorted files and directories list.
+  """
+
+  find_command = ['find', target_path] + (extra_args or [])
+  find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
+  return common.RunAndCheckOutput(['sort'], stdin=find_process.stdout,
+                                  verbose=False)
+
+
+def create_merged_package(temp_dir, framework_target_files, framework_item_list,
+                          vendor_target_files, vendor_item_list,
+                          framework_misc_info_keys,
+                          rebuild_recovery):
+  """Merges two target files packages into one target files structure.
 
   Args:
     temp_dir: The name of a directory we use when we extract items from the
@@ -761,29 +768,21 @@
       target files package as is, meaning these items will land in the output
       target files package exactly as they appear in the input partial framework
       target files package.
-    framework_misc_info_keys: The list of keys to obtain from the framework
-      instance of META/misc_info.txt. The remaining keys from the vendor
-      instance.
     vendor_target_files: The name of the zip archive containing the vendor
       partial target files package.
     vendor_item_list: The list of items to extract from the partial vendor
       target files package as is, meaning these items will land in the output
       target files package exactly as they appear in the input partial vendor
       target files package.
-    output_target_files: The name of the output zip archive target files package
-      created by merging framework and vendor.
-    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_img: The name of the output zip archive img package.
-    output_super_empty: If provided, creates a super_empty.img file from the
-      merged target files package and saves it at this path.
+    framework_misc_info_keys: The list of keys to obtain from the framework
+      instance of META/misc_info.txt. The remaining keys from the vendor
+      instance.
     rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
       devices and write it to the system image.
-  """
 
-  logger.info('starting: merge framework %s and vendor %s into output %s',
-              framework_target_files, vendor_target_files, output_target_files)
+  Returns:
+    Path to merged package under temp directory.
+  """
 
   # Create directory names that we'll use when we extract files from framework,
   # and vendor, and for zipping the final output.
@@ -840,32 +839,53 @@
       framework_misc_info_keys=framework_misc_info_keys,
       rebuild_recovery=rebuild_recovery)
 
-  # Regenerate IMAGES in the temporary directory.
+  return output_target_files_temp_dir
+
+
+def generate_images(target_files_dir, rebuild_recovery):
+  """Generate images from target files.
+
+  This function takes merged output temporary directory and create images
+  from it.
+
+  Args:
+    target_files_dir: Path to merged temp directory.
+    rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
+      devices and write it to the system image.
+  """
+
+  # Regenerate IMAGES in the target directory.
 
   add_img_args = ['--verbose']
   if rebuild_recovery:
     add_img_args.append('--rebuild_recovery')
-  add_img_args.append(output_target_files_temp_dir)
+  add_img_args.append(target_files_dir)
 
   add_img_to_target_files.main(add_img_args)
 
+
+def generate_super_empty_image(target_dir, output_super_empty):
+  """Generates super_empty image from target package.
+
+  Args:
+    target_dir: Path to the target file package which contains misc_info.txt for
+      detailed information for super image.
+    output_super_empty: If provided, copies a super_empty.img file from the
+      target files package to this path.
+  """
   # Create super_empty.img using the merged misc_info.txt.
 
-  misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
+  misc_info_txt = os.path.join(target_dir, 'META',
                                'misc_info.txt')
 
-  def read_helper():
-    with open(misc_info_txt) as f:
-      return list(f.read().splitlines())
-
-  use_dynamic_partitions = common.LoadDictionaryFromLines(
-      read_helper()).get('use_dynamic_partitions')
+  use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
+      'use_dynamic_partitions')
 
   if use_dynamic_partitions != 'true' and output_super_empty:
     raise ValueError(
         'Building super_empty.img requires use_dynamic_partitions=true.')
   elif use_dynamic_partitions == 'true':
-    super_empty_img = os.path.join(output_target_files_temp_dir, 'IMAGES',
+    super_empty_img = os.path.join(target_dir, 'IMAGES',
                                    'super_empty.img')
     build_super_image_args = [
         misc_info_txt,
@@ -877,15 +897,134 @@
     if output_super_empty:
       shutil.copyfile(super_empty_img, output_super_empty)
 
-  # Create the IMG package from the merged target files (before zipping, in
-  # order to avoid an unnecessary unzip and copy).
+
+def create_img_archive(source_path, target_path):
+  """Creates IMG archive in target path from source package.
+
+  Args:
+    source_path: Path of the source package to be packed.
+    target_path: Create IMG package from the source package.
+  """
+
+  img_from_target_files_args = [
+      source_path,
+      target_path,
+  ]
+  img_from_target_files.main(img_from_target_files_args)
+
+
+def create_target_files_archive(output_file, source_dir, temp_dir):
+  """Creates archive from target package.
+
+  Args:
+    output_file: The name of the zip archive target files package.
+    source_dir: The target directory contains package to be archived.
+    temp_dir: Path to temporary directory for any intermediate files.
+  """
+  output_target_files_list = os.path.join(temp_dir, 'output.list')
+  output_zip = os.path.abspath(output_file)
+  output_target_files_meta_dir = os.path.join(source_dir,
+                                              'META')
+
+  meta_content = files_from_path(output_target_files_meta_dir)
+  other_content = files_from_path(source_dir,
+                                  ['-path', output_target_files_meta_dir,
+                                   '-prune', '-o', '-print'])
+
+  with open(output_target_files_list, 'w') as f:
+    f.write(meta_content)
+    f.write(other_content)
+
+  command = [
+      'soong_zip',
+      '-d',
+      '-o',
+      output_zip,
+      '-C',
+      source_dir,
+      '-l',
+      output_target_files_list,
+  ]
+
+  logger.info('creating %s', output_file)
+  common.RunAndWait(command, verbose=True)
+  logger.info('finished creating %s', output_file)
+
+  return output_zip
+
+
+def create_ota_package(zip_package, output_ota):
+  """Creates OTA package from archived package.
+
+  Args:
+    zip_package: The name of the zip archived package.
+    output_ota: The name of the output zip archive ota package.
+  """
+  ota_from_target_files_args = [
+      zip_package,
+      output_ota,
+  ]
+  ota_from_target_files.main(ota_from_target_files_args)
+
+
+def merge_target_files(temp_dir, framework_target_files, framework_item_list,
+                       framework_misc_info_keys, vendor_target_files,
+                       vendor_item_list, output_target_files, output_dir,
+                       output_item_list, output_ota, output_img,
+                       output_super_empty, rebuild_recovery):
+  """Merges two target files packages together.
+
+  This function takes framework and vendor target files packages as input,
+  performs various file extractions, special case processing, and finally
+  creates a merged zip archive as output.
+
+  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.
+    framework_target_files: The name of the zip archive containing the framework
+      partial target files package.
+    framework_item_list: The list of items to extract from the partial framework
+      target files package as is, meaning these items will land in the output
+      target files package exactly as they appear in the input partial framework
+      target files package.
+    framework_misc_info_keys: The list of keys to obtain from the framework
+      instance of META/misc_info.txt. The remaining keys from the vendor
+      instance.
+    vendor_target_files: The name of the zip archive containing the vendor
+      partial target files package.
+    vendor_item_list: The list of items to extract from the partial vendor
+      target files package as is, meaning these items will land in the output
+      target files package exactly as they appear in the input partial vendor
+      target files package.
+    output_target_files: The name of the output zip archive target files package
+      created by merging framework and vendor.
+    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_img: The name of the output zip archive img 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.
+  """
+
+  logger.info('starting: merge framework %s and vendor %s into output %s',
+              framework_target_files, vendor_target_files, output_target_files)
+
+  output_target_files_temp_dir = create_merged_package(
+      temp_dir, framework_target_files, framework_item_list,
+      vendor_target_files, vendor_item_list, framework_misc_info_keys,
+      rebuild_recovery)
+
+  generate_images(output_target_files_temp_dir, rebuild_recovery)
+
+  generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
 
   if output_img:
-    img_from_target_files_args = [
-        output_target_files_temp_dir,
-        output_img,
-    ]
-    img_from_target_files.main(img_from_target_files_args)
+    # Create the IMG package from the merged target files (before zipping, in
+    # order to avoid an unnecessary unzip and copy).
+    create_img_archive(output_target_files_temp_dir, output_img)
 
   # Finally, create the output target files zip archive and/or copy the
   # output items to the output target files directory.
@@ -896,59 +1035,18 @@
   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')
-
-  find_command = [
-      'find',
-      output_target_files_meta_dir,
-  ]
-  find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
-  meta_content = common.RunAndCheckOutput(['sort'],
-                                          stdin=find_process.stdout,
-                                          verbose=False)
-
-  find_command = [
-      'find', output_target_files_temp_dir, '-path',
-      output_target_files_meta_dir, '-prune', '-o', '-print'
-  ]
-  find_process = common.Run(find_command, stdout=subprocess.PIPE, verbose=False)
-  other_content = common.RunAndCheckOutput(['sort'],
-                                           stdin=find_process.stdout,
-                                           verbose=False)
-
-  with open(output_target_files_list, 'wb') as f:
-    f.write(meta_content)
-    f.write(other_content)
-
-  command = [
-      'soong_zip',
-      '-d',
-      '-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)
-  logger.info('finished creating %s', output_target_files)
+  output_zip = create_target_files_archive(output_target_files,
+                                           output_target_files_temp_dir,
+                                           temp_dir)
 
   # 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)
+    create_ota_package(output_zip, output_ota)
 
 
 def call_func_with_temp_dir(func, keep_tmp):
-  """Manage the creation and cleanup of the temporary directory.
+  """Manages the creation and cleanup of the temporary directory.
 
   This function calls the given function after first creating a temporary
   directory. It also cleans up the temporary directory.
@@ -967,8 +1065,6 @@
 
   try:
     func(temp_dir)
-  except:
-    raise
   finally:
     if keep_tmp:
       logger.info('keeping %s', temp_dir)
@@ -1000,7 +1096,8 @@
       OPTIONS.framework_item_list = a
     elif o == '--system-misc-info-keys':
       logger.warning(
-          '--system-misc-info-keys has been renamed to --framework-misc-info-keys'
+          '--system-misc-info-keys has been renamed to '
+          '--framework-misc-info-keys'
       )
       OPTIONS.framework_misc_info_keys = a
     elif o == '--framework-misc-info-keys':
@@ -1061,6 +1158,7 @@
       ],
       extra_option_handler=option_handler)
 
+  # pylint: disable=too-many-boolean-expressions
   if (args or OPTIONS.framework_target_files is None or
       OPTIONS.vendor_target_files is None or
       (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index f686ca0..4598317 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -38,8 +38,8 @@
   -k  (--package_key) <key>
       Key to use to sign the package (default is the value of
       default_system_dev_certificate from the input target-files's
-      META/misc_info.txt, or "build/make/target/product/security/testkey" if that
-      value is not specified).
+      META/misc_info.txt, or "build/make/target/product/security/testkey" if
+      that value is not specified).
 
       For incremental OTAs, the default value is based on the source
       target-file, not the target build.
@@ -276,8 +276,8 @@
   _RO_PRODUCT_RESOLVE_PROPS = ["ro.product.brand", "ro.product.device",
                                "ro.product.manufacturer", "ro.product.model",
                                "ro.product.name"]
-  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "product_services",
-                                            "odm", "vendor", "system"]
+  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "odm", "vendor",
+                                            "system_ext", "system"]
 
   def __init__(self, info_dict, oem_dicts):
     """Initializes a BuildInfo instance with the given dicts.
@@ -371,7 +371,7 @@
       return prop_val
 
     source_order_val = self.info_dict.get("build.prop", {}).get(
-      "ro.product.property_source_order")
+        "ro.product.property_source_order")
     if source_order_val:
       source_order = source_order_val.split(",")
     else:
@@ -381,13 +381,13 @@
     if any([x not in BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
             for x in source_order]):
       raise common.ExternalError(
-        "Invalid ro.product.property_source_order '{}'".format(source_order))
+          "Invalid ro.product.property_source_order '{}'".format(source_order))
 
     for source in source_order:
-      source_prop = prop.replace("ro.product", "ro.product.{}".format(source),
-                                 1)
-      prop_val = self.info_dict.get("{}.build.prop".format(source), {}).get(
-        source_prop)
+      source_prop = prop.replace(
+          "ro.product", "ro.product.{}".format(source), 1)
+      prop_val = self.info_dict.get(
+          "{}.build.prop".format(source), {}).get(source_prop)
       if prop_val:
         return prop_val
 
@@ -412,14 +412,14 @@
         return self.GetBuildProp("ro.build.fingerprint")
       except common.ExternalError:
         return "{}/{}/{}:{}/{}/{}:{}/{}".format(
-          self.GetBuildProp("ro.product.brand"),
-          self.GetBuildProp("ro.product.name"),
-          self.GetBuildProp("ro.product.device"),
-          self.GetBuildProp("ro.build.version.release"),
-          self.GetBuildProp("ro.build.id"),
-          self.GetBuildProp("ro.build.version.incremental"),
-          self.GetBuildProp("ro.build.type"),
-          self.GetBuildProp("ro.build.tags"))
+            self.GetBuildProp("ro.product.brand"),
+            self.GetBuildProp("ro.product.name"),
+            self.GetBuildProp("ro.product.device"),
+            self.GetBuildProp("ro.build.version.release"),
+            self.GetBuildProp("ro.build.id"),
+            self.GetBuildProp("ro.build.version.incremental"),
+            self.GetBuildProp("ro.build.type"),
+            self.GetBuildProp("ro.build.tags"))
     return "%s/%s/%s:%s" % (
         self.GetOemProperty("ro.product.brand"),
         self.GetOemProperty("ro.product.name"),
@@ -508,7 +508,7 @@
     MODULUS_PREFIX = "Modulus="
     assert modulus_string.startswith(MODULUS_PREFIX)
     modulus_string = modulus_string[len(MODULUS_PREFIX):]
-    key_size = len(modulus_string) / 2
+    key_size = len(modulus_string) // 2
     assert key_size == 256 or key_size == 512, \
         "Unsupported key size {}".format(key_size)
     return key_size
@@ -1051,7 +1051,7 @@
     output: A ZipFile object or a string of the output file path.
   """
 
-  value = "".join(["%s=%s\n" % kv for kv in sorted(metadata.iteritems())])
+  value = "".join(["%s=%s\n" % kv for kv in sorted(metadata.items())])
   if isinstance(output, zipfile.ZipFile):
     common.ZipWriteStr(output, METADATA_NAME, value,
                        compress_type=zipfile.ZIP_STORED)
@@ -1067,7 +1067,7 @@
 
   post_timestamp = target_info.GetBuildProp("ro.build.date.utc")
   pre_timestamp = source_info.GetBuildProp("ro.build.date.utc")
-  is_downgrade = long(post_timestamp) < long(pre_timestamp)
+  is_downgrade = int(post_timestamp) < int(pre_timestamp)
 
   if OPTIONS.downgrade:
     if not is_downgrade:
@@ -1392,7 +1392,7 @@
     payload_offset += len(payload_info.extra) + len(payload_info.filename)
     payload_size = payload_info.file_size
 
-    with input_zip.open('payload.bin', 'r') as payload_fp:
+    with input_zip.open('payload.bin') as payload_fp:
       header_bin = payload_fp.read(24)
 
     # network byte order (big-endian)
@@ -1864,7 +1864,6 @@
 
   with zipfile.ZipFile(input_file, 'r') as input_zip:
     infolist = input_zip.infolist()
-    namelist = input_zip.namelist()
 
   input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
   for info in infolist:
@@ -1939,7 +1938,7 @@
   target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
   shutil.copyfile(input_file, target_file)
 
-  with zipfile.ZipFile(input_file, 'r') as input_zip:
+  with zipfile.ZipFile(input_file) as input_zip:
     namelist = input_zip.namelist()
 
   input_tmp = common.UnzipTemp(input_file, RETROFIT_DAP_UNZIP_PATTERN)
@@ -1963,8 +1962,8 @@
     for partition in ab_partitions:
       if (partition in dynamic_partition_list and
           partition not in super_block_devices):
-          logger.info("Dropping %s from ab_partitions.txt", partition)
-          continue
+        logger.info("Dropping %s from ab_partitions.txt", partition)
+        continue
       f.write(partition + "\n")
   to_delete = [AB_PARTITIONS]
 
@@ -1976,7 +1975,7 @@
   to_delete += [DYNAMIC_PARTITION_INFO]
 
   # Remove the existing partition images as well as the map files.
-  to_delete += replace.values()
+  to_delete += list(replace.values())
   to_delete += ['IMAGES/{}.map'.format(dev) for dev in super_block_devices]
 
   common.ZipDelete(target_file, to_delete)
@@ -1986,7 +1985,7 @@
   # Write super_{foo}.img as {foo}.img.
   for src, dst in replace.items():
     assert src in namelist, \
-          'Missing {} in {}; {} cannot be written'.format(src, input_file, dst)
+        'Missing {} in {}; {} cannot be written'.format(src, input_file, dst)
     unzipped_file = os.path.join(input_tmp, *src.split('/'))
     common.ZipWrite(target_zip, unzipped_file, arcname=dst)
 
@@ -2291,7 +2290,8 @@
   OPTIONS.cache_size = cache_size
 
   if OPTIONS.extra_script is not None:
-    OPTIONS.extra_script = open(OPTIONS.extra_script).read()
+    with open(OPTIONS.extra_script) as fp:
+      OPTIONS.extra_script = fp.read()
 
   if OPTIONS.extracted_input is not None:
     OPTIONS.input_tmp = OPTIONS.extracted_input
diff --git a/tools/releasetools/sign_apex.py b/tools/releasetools/sign_apex.py
index 1778615..2516e15 100755
--- a/tools/releasetools/sign_apex.py
+++ b/tools/releasetools/sign_apex.py
@@ -19,6 +19,9 @@
 
 Usage:  sign_apex [flags] input_apex_file output_apex_file
 
+  --avbtool <avbtool>
+      Optional flag that specifies the AVB tool to use. Defaults to `avbtool`.
+
   --container_key <key>
       Mandatory flag that specifies the container signing key.
 
@@ -40,12 +43,30 @@
 logger = logging.getLogger(__name__)
 
 
+def SignApexFile(avbtool, apex_file, payload_key, container_key,
+                 signing_args=None):
+  """Signs the given apex file."""
+  with open(apex_file, 'rb') as input_fp:
+    apex_data = input_fp.read()
+
+  return apex_utils.SignApex(
+      avbtool,
+      apex_data,
+      payload_key=payload_key,
+      container_key=container_key,
+      container_pw=None,
+      codename_to_api_level_map=None,
+      signing_args=signing_args)
+
+
 def main(argv):
 
   options = {}
 
   def option_handler(o, a):
-    if o == '--container_key':
+    if o == '--avbtool':
+      options['avbtool'] = a
+    elif o == '--container_key':
       # Strip the suffix if any, as common.SignFile expects no suffix.
       DEFAULT_CONTAINER_KEY_SUFFIX = '.x509.pem'
       if a.endswith(DEFAULT_CONTAINER_KEY_SUFFIX):
@@ -63,6 +84,7 @@
       argv, __doc__,
       extra_opts='',
       extra_long_opts=[
+          'avbtool=',
           'container_key=',
           'payload_extra_args=',
           'payload_key=',
@@ -76,20 +98,13 @@
 
   common.InitLogging()
 
-  input_zip = args[0]
-  output_zip = args[1]
-  with open(input_zip) as input_fp:
-    apex_data = input_fp.read()
-
-  signed_apex = apex_utils.SignApex(
-      apex_data,
-      payload_key=options['payload_key'],
-      container_key=options['container_key'],
-      container_pw=None,
-      codename_to_api_level_map=None,
-      signing_args=options.get('payload_extra_args'))
-
-  shutil.copyfile(signed_apex, output_zip)
+  signed_apex = SignApexFile(
+      options.get('avbtool', 'avbtool'),
+      args[0],
+      options['payload_key'],
+      options['container_key'],
+      options.get('payload_extra_args'))
+  shutil.copyfile(signed_apex, args[1])
   logger.info("done.")
 
 
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 668ad9b..04b627b 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -154,11 +154,11 @@
 
 def GetApkCerts(certmap):
   # apply the key remapping to the contents of the file
-  for apk, cert in certmap.iteritems():
+  for apk, cert in certmap.items():
     certmap[apk] = OPTIONS.key_map.get(cert, cert)
 
   # apply all the -e options, overriding anything in the file
-  for apk, cert in OPTIONS.extra_apks.iteritems():
+  for apk, cert in OPTIONS.extra_apks.items():
     if not cert:
       cert = "PRESIGNED"
     certmap[apk] = OPTIONS.key_map.get(cert, cert)
@@ -468,6 +468,7 @@
             maxsize, name, payload_key))
 
         signed_apex = apex_utils.SignApex(
+            misc_info['avb_avbtool'],
             data,
             payload_key,
             container_key,
@@ -500,8 +501,8 @@
         "PRODUCT/build.prop",
         "SYSTEM/product/build.prop",
 
-        "PRODUCT_SERVICES/build.prop",
-        "SYSTEM/product_services/build.prop",
+        "SYSTEM_EXT/build.prop",
+        "SYSTEM/system_ext/build.prop",
 
         "SYSTEM/etc/prop.default",
         "BOOT/RAMDISK/prop.default",
@@ -519,14 +520,14 @@
       if stat.S_ISLNK(info.external_attr >> 16):
         new_data = data
       else:
-        new_data = RewriteProps(data)
+        new_data = RewriteProps(data.decode())
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
 
     # Replace the certs in *mac_permissions.xml (there could be multiple, such
     # as {system,vendor}/etc/selinux/{plat,nonplat}_mac_permissions.xml).
     elif filename.endswith("mac_permissions.xml"):
       print("Rewriting %s with new keys." % (filename,))
-      new_data = ReplaceCerts(data)
+      new_data = ReplaceCerts(data.decode())
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
 
     # Ask add_img_to_target_files to rebuild the recovery patch if needed.
@@ -572,7 +573,8 @@
       # 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)
+        public_key = common.ExtractAvbPublicKey(
+            misc_info['avb_avbtool'], signing_key)
         print("    Rewriting AVB public key of system_other in /product")
         common.ZipWrite(output_tf_zip, public_key, filename)
 
@@ -630,17 +632,17 @@
   Raises:
     AssertionError: On finding duplicate entries.
   """
-  for old, new in OPTIONS.key_map.iteritems():
+  for old, new in OPTIONS.key_map.items():
     if OPTIONS.verbose:
       print("    Replacing %s.x509.pem with %s.x509.pem" % (old, new))
 
     try:
       with open(old + ".x509.pem") as old_fp:
         old_cert16 = base64.b16encode(
-            common.ParseCertificate(old_fp.read())).lower()
+            common.ParseCertificate(old_fp.read())).decode().lower()
       with open(new + ".x509.pem") as new_fp:
         new_cert16 = base64.b16encode(
-            common.ParseCertificate(new_fp.read())).lower()
+            common.ParseCertificate(new_fp.read())).decode().lower()
     except IOError as e:
       if OPTIONS.verbose or e.errno != errno.ENOENT:
         print("    Error accessing %s: %s.\nSkip replacing %s.x509.pem with "
@@ -858,7 +860,7 @@
         writable.
     key_path: The path to the PEM encoded X.509 certificate.
   """
-  in_cmdline = input_zip.read("BOOT/cmdline")
+  in_cmdline = input_zip.read("BOOT/cmdline").decode()
   # Copy in_cmdline to output_zip if veritykeyid is not present.
   if "veritykeyid" not in in_cmdline:
     common.ZipWriteStr(output_zip, "BOOT/cmdline", in_cmdline)
@@ -891,7 +893,7 @@
   current in-memory dict contains additional items computed at runtime.
   """
   misc_info_old = common.LoadDictionaryFromLines(
-      input_zip.read('META/misc_info.txt').split('\n'))
+      input_zip.read('META/misc_info.txt').decode().split('\n'))
   items = []
   for key in sorted(misc_info):
     if key in misc_info_old:
@@ -957,7 +959,7 @@
 
 
 def GetApiLevelAndCodename(input_tf_zip):
-  data = input_tf_zip.read("SYSTEM/build.prop")
+  data = input_tf_zip.read("SYSTEM/build.prop").decode()
   api_level = None
   codename = None
   for line in data.split("\n"):
@@ -979,7 +981,7 @@
 
 
 def GetCodenameToApiLevelMap(input_tf_zip):
-  data = input_tf_zip.read("SYSTEM/build.prop")
+  data = input_tf_zip.read("SYSTEM/build.prop").decode()
   api_level = None
   codenames = None
   for line in data.split("\n"):
@@ -997,7 +999,7 @@
   if codenames is None:
     raise ValueError("No ro.build.version.all_codenames in SYSTEM/build.prop")
 
-  result = dict()
+  result = {}
   for codename in codenames:
     codename = codename.strip()
     if codename:
@@ -1021,7 +1023,7 @@
         key.
   """
   keys = {}
-  for line in tf_zip.read("META/apexkeys.txt").split("\n"):
+  for line in tf_zip.read('META/apexkeys.txt').decode().split('\n'):
     line = line.strip()
     if not line:
       continue
diff --git a/tools/releasetools/test_apex_utils.py b/tools/releasetools/test_apex_utils.py
index c7d5807..e9c26f0 100644
--- a/tools/releasetools/test_apex_utils.py
+++ b/tools/releasetools/test_apex_utils.py
@@ -43,8 +43,9 @@
   def test_ParseApexPayloadInfo(self):
     payload_file = self._GetTestPayload()
     apex_utils.SignApexPayload(
-        payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048', self.SALT)
-    payload_info = apex_utils.ParseApexPayloadInfo(payload_file)
+        'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
+        self.SALT)
+    payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
     self.assertEqual('SHA256_RSA2048', payload_info['Algorithm'])
     self.assertEqual(self.SALT, payload_info['Salt'])
     self.assertEqual('testkey', payload_info['apex.key'])
@@ -53,8 +54,9 @@
   def test_SignApexPayload(self):
     payload_file = self._GetTestPayload()
     apex_utils.SignApexPayload(
-        payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048', self.SALT)
-    apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+        'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
+        self.SALT)
+    apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_SignApexPayload_withSignerHelper(self):
@@ -64,17 +66,19 @@
     payload_signer_args = '--signing_helper_with_files {}'.format(
         signing_helper)
     apex_utils.SignApexPayload(
+        'avbtool',
         payload_file,
         self.payload_key,
         'testkey', 'SHA256_RSA2048', self.SALT,
         payload_signer_args)
-    apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+    apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
 
   @test_utils.SkipIfExternalToolsUnavailable()
   def test_SignApexPayload_invalidKey(self):
     self.assertRaises(
         apex_utils.ApexSigningError,
         apex_utils.SignApexPayload,
+        'avbtool',
         self._GetTestPayload(),
         os.path.join(self.testdata_dir, 'testkey.x509.pem'),
         'testkey',
@@ -85,10 +89,12 @@
   def test_VerifyApexPayload_wrongKey(self):
     payload_file = self._GetTestPayload()
     apex_utils.SignApexPayload(
-        payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048', self.SALT)
-    apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+        'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
+        self.SALT)
+    apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
     self.assertRaises(
         apex_utils.ApexSigningError,
         apex_utils.VerifyApexPayload,
+        'avbtool',
         payload_file,
         os.path.join(self.testdata_dir, 'testkey_with_passwd.key'))
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 11ac9f5..50fa86f 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -579,7 +579,7 @@
   def test_ExtractPublicKey(self):
     cert = os.path.join(self.testdata_dir, 'testkey.x509.pem')
     pubkey = os.path.join(self.testdata_dir, 'testkey.pubkey.pem')
-    with open(pubkey, 'rb') as pubkey_fp:
+    with open(pubkey) as pubkey_fp:
       self.assertEqual(pubkey_fp.read(), common.ExtractPublicKey(cert))
 
   def test_ExtractPublicKey_invalidInput(self):
@@ -590,15 +590,18 @@
   def test_ExtractAvbPublicKey(self):
     privkey = os.path.join(self.testdata_dir, 'testkey.key')
     pubkey = os.path.join(self.testdata_dir, 'testkey.pubkey.pem')
-    with open(common.ExtractAvbPublicKey(privkey)) as privkey_fp, \
-        open(common.ExtractAvbPublicKey(pubkey)) as pubkey_fp:
+    extracted_from_privkey = common.ExtractAvbPublicKey('avbtool', privkey)
+    extracted_from_pubkey = common.ExtractAvbPublicKey('avbtool', pubkey)
+    with open(extracted_from_privkey, 'rb') as privkey_fp, \
+        open(extracted_from_pubkey, 'rb') as pubkey_fp:
       self.assertEqual(privkey_fp.read(), pubkey_fp.read())
 
   def test_ParseCertificate(self):
     cert = os.path.join(self.testdata_dir, 'testkey.x509.pem')
 
     cmd = ['openssl', 'x509', '-in', cert, '-outform', 'DER']
-    proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                      universal_newlines=False)
     expected, _ = proc.communicate()
     self.assertEqual(0, proc.returncode)
 
@@ -914,7 +917,7 @@
     target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
     with zipfile.ZipFile(target_files, 'w') as target_files_zip:
       info_values = ''.join(
-          ['{}={}\n'.format(k, v) for k, v in sorted(info_dict.iteritems())])
+          ['{}={}\n'.format(k, v) for k, v in sorted(info_dict.items())])
       common.ZipWriteStr(target_files_zip, 'META/misc_info.txt', info_values)
 
       FSTAB_TEMPLATE = "/dev/block/system {} ext4 ro,barrier=1 defaults"
@@ -1085,7 +1088,7 @@
     loc = os.path.join(self._tempdir, prefix, name)
     if not os.path.exists(os.path.dirname(loc)):
       os.makedirs(os.path.dirname(loc))
-    with open(loc, "w+") as f:
+    with open(loc, "wb") as f:
       f.write(data)
 
   def test_full_recovery(self):
@@ -1110,7 +1113,7 @@
     validate_target_files.ValidateInstallRecoveryScript(self._tempdir,
                                                         self._info)
     # Validate 'recovery-from-boot' with bonus argument.
-    self._out_tmp_sink("etc/recovery-resource.dat", "bonus", "SYSTEM")
+    self._out_tmp_sink("etc/recovery-resource.dat", b"bonus", "SYSTEM")
     common.MakeRecoveryPatch(self._tempdir, self._out_tmp_sink,
                              recovery_image, boot_image, self._info)
     validate_target_files.ValidateInstallRecoveryScript(self._tempdir,
@@ -1118,25 +1121,30 @@
 
 
 class MockScriptWriter(object):
-  """A class that mocks edify_generator.EdifyGenerator.
-  """
+  """A class that mocks edify_generator.EdifyGenerator."""
+
   def __init__(self, enable_comments=False):
     self.lines = []
     self.enable_comments = enable_comments
+
   def Comment(self, comment):
     if self.enable_comments:
-      self.lines.append("# {}".format(comment))
+      self.lines.append('# {}'.format(comment))
+
   def AppendExtra(self, extra):
     self.lines.append(extra)
+
   def __str__(self):
-    return "\n".join(self.lines)
+    return '\n'.join(self.lines)
 
 
 class MockBlockDifference(object):
+
   def __init__(self, partition, tgt, src=None):
     self.partition = partition
     self.tgt = tgt
     self.src = src
+
   def WriteScript(self, script, _, progress=None,
                   write_verify_script=False):
     if progress:
@@ -1144,11 +1152,13 @@
     script.AppendExtra("patch({});".format(self.partition))
     if write_verify_script:
       self.WritePostInstallVerifyScript(script)
+
   def WritePostInstallVerifyScript(self, script):
     script.AppendExtra("verify({});".format(self.partition))
 
 
 class FakeSparseImage(object):
+
   def __init__(self, size):
     self.blocksize = 4096
     self.total_blocks = size // 4096
@@ -1156,12 +1166,13 @@
 
 
 class DynamicPartitionsDifferenceTest(test_utils.ReleaseToolsTestCase):
+
   @staticmethod
   def get_op_list(output_path):
     with zipfile.ZipFile(output_path) as output_zip:
-      with output_zip.open("dynamic_partitions_op_list") as op_list:
-        return [line.strip() for line in op_list.readlines()
-                if not line.startswith("#")]
+      with output_zip.open('dynamic_partitions_op_list') as op_list:
+        return [line.decode().strip() for line in op_list.readlines()
+                if not line.startswith(b'#')]
 
   def setUp(self):
     self.script = MockScriptWriter()
@@ -1243,10 +1254,10 @@
 
   def test_incremental(self):
     source_info = common.LoadDictionaryFromLines("""
-dynamic_partition_list=system vendor product product_services
+dynamic_partition_list=system vendor product system_ext
 super_partition_groups=group_foo
 super_group_foo_group_size={group_foo_size}
-super_group_foo_partition_list=system vendor product product_services
+super_group_foo_partition_list=system vendor product system_ext
 """.format(group_foo_size=4 * GiB).split("\n"))
     target_info = common.LoadDictionaryFromLines("""
 dynamic_partition_list=system vendor product odm
@@ -1263,7 +1274,7 @@
                                        src=FakeSparseImage(1024 * MiB)),
                    MockBlockDifference("product", FakeSparseImage(1024 * MiB),
                                        src=FakeSparseImage(1024 * MiB)),
-                   MockBlockDifference("product_services", None,
+                   MockBlockDifference("system_ext", None,
                                        src=FakeSparseImage(1024 * MiB)),
                    MockBlockDifference("odm", FakeSparseImage(1024 * MiB),
                                        src=None)]
@@ -1286,11 +1297,11 @@
       self.assertLess(patch_idx, verify_idx,
                       "Should verify {} after patching".format(p))
 
-    self.assertNotIn("patch(product_services);", self.script.lines)
+    self.assertNotIn("patch(system_ext);", self.script.lines)
 
     lines = self.get_op_list(self.output_path)
 
-    remove = lines.index("remove product_services")
+    remove = lines.index("remove system_ext")
     move_product_out = lines.index("move product default")
     shrink = lines.index("resize vendor 536870912")
     shrink_group = lines.index("resize_group group_foo 3221225472")
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
index 0a636bb..bca29e5 100644
--- a/tools/releasetools/test_merge_target_files.py
+++ b/tools/releasetools/test_merge_target_files.py
@@ -98,7 +98,8 @@
         'ROOT/*',
         'SYSTEM/*',
     ]
-    self.assertItemsEqual(framework_item_list, expected_framework_item_list)
+    self.assertEqual(sorted(framework_item_list),
+                     sorted(expected_framework_item_list))
 
   def test_validate_config_lists_ReturnsFalseIfMissingDefaultItem(self):
     framework_item_list = list(DEFAULT_FRAMEWORK_ITEM_LIST)
@@ -174,6 +175,38 @@
     }
     self.assertEqual(merged_dict, expected_merged_dict)
 
+  def test_merge_dynamic_partition_info_dicts_IgnoringFrameworkGroupSize(self):
+    framework_dict = {
+        'super_partition_groups': 'group_a',
+        'dynamic_partition_list': 'system',
+        'super_group_a_list': 'system',
+        'super_group_a_size': '5000',
+    }
+    vendor_dict = {
+        'super_partition_groups': 'group_a group_b',
+        'dynamic_partition_list': 'vendor product',
+        'super_group_a_list': 'vendor',
+        'super_group_a_size': '1000',
+        'super_group_b_list': 'product',
+        'super_group_b_size': '2000',
+    }
+    merged_dict = merge_dynamic_partition_info_dicts(
+        framework_dict=framework_dict,
+        vendor_dict=vendor_dict,
+        size_prefix='super_',
+        size_suffix='_size',
+        list_prefix='super_',
+        list_suffix='_list')
+    expected_merged_dict = {
+        'super_partition_groups': 'group_a group_b',
+        'dynamic_partition_list': 'system vendor product',
+        'super_group_a_list': 'system vendor',
+        'super_group_a_size': '1000',
+        'super_group_b_list': 'product',
+        'super_group_b_size': '2000',
+    }
+    self.assertEqual(merged_dict, expected_merged_dict)
+
   def test_process_apex_keys_apk_certs_ReturnsTrueIfNoConflicts(self):
     output_dir = common.MakeTempDir()
     os.makedirs(os.path.join(output_dir, 'META'))
diff --git a/tools/releasetools/test_sign_apex.py b/tools/releasetools/test_sign_apex.py
new file mode 100644
index 0000000..b4ef127
--- /dev/null
+++ b/tools/releasetools/test_sign_apex.py
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+import os.path
+
+import common
+import sign_apex
+import test_utils
+
+
+class SignApexTest(test_utils.ReleaseToolsTestCase):
+
+  def setUp(self):
+    self.testdata_dir = test_utils.get_testdata_dir()
+    self.assertTrue(os.path.exists(self.testdata_dir))
+
+    common.OPTIONS.search_path = test_utils.get_search_path()
+
+  @test_utils.SkipIfExternalToolsUnavailable()
+  def test_SignApexFile(self):
+    foo_apex = os.path.join(self.testdata_dir, 'foo.apex')
+    payload_key = os.path.join(self.testdata_dir, 'testkey_RSA4096.key')
+    container_key = os.path.join(self.testdata_dir, 'testkey')
+    signed_foo_apex = sign_apex.SignApexFile(
+        'avbtool',
+        foo_apex,
+        payload_key,
+        container_key)
+    self.assertTrue(os.path.exists(signed_foo_apex))
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index e142ebb..0100729 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -70,10 +70,10 @@
          'ro.product.build.fingerprint=foo/bar/release-keys'),
         ('ro.product.build.thumbprint=foo/bar/dev-keys',
          'ro.product.build.thumbprint=foo/bar/release-keys'),
-        ('ro.product_services.build.fingerprint=foo/bar/test-keys',
-         'ro.product_services.build.fingerprint=foo/bar/release-keys'),
-        ('ro.product_services.build.thumbprint=foo/bar/test-keys',
-         'ro.product_services.build.thumbprint=foo/bar/release-keys'),
+        ('ro.system_ext.build.fingerprint=foo/bar/test-keys',
+         'ro.system_ext.build.fingerprint=foo/bar/release-keys'),
+        ('ro.system_ext.build.thumbprint=foo/bar/test-keys',
+         'ro.system_ext.build.thumbprint=foo/bar/release-keys'),
         ('# comment line 1', '# comment line 1'),
         ('ro.bootimage.build.fingerprint=foo/bar/dev-keys',
          'ro.bootimage.build.fingerprint=foo/bar/release-keys'),
@@ -91,8 +91,8 @@
          'ro.odm.build.tags=release-keys'),
         ('ro.product.build.tags=dev-keys',
          'ro.product.build.tags=release-keys'),
-        ('ro.product_services.build.tags=dev-keys',
-         'ro.product_services.build.tags=release-keys'),
+        ('ro.system_ext.build.tags=dev-keys',
+         'ro.system_ext.build.tags=release-keys'),
         ('# comment line 2', '# comment line 2'),
         ('ro.build.display.id=OPR6.170623.012 dev-keys',
          'ro.build.display.id=OPR6.170623.012'),
@@ -136,7 +136,7 @@
       ReplaceVerityKeyId(input_zip, output_zip, cert_file)
 
     with zipfile.ZipFile(output_file) as output_zip:
-      self.assertEqual(BOOT_CMDLINE1, output_zip.read('BOOT/cmdline'))
+      self.assertEqual(BOOT_CMDLINE1, output_zip.read('BOOT/cmdline').decode())
 
     # Test with the second certificate.
     cert_file = os.path.join(self.testdata_dir, 'testkey.x509.pem')
@@ -146,7 +146,7 @@
       ReplaceVerityKeyId(input_zip, output_zip, cert_file)
 
     with zipfile.ZipFile(output_file) as output_zip:
-      self.assertEqual(BOOT_CMDLINE2, output_zip.read('BOOT/cmdline'))
+      self.assertEqual(BOOT_CMDLINE2, output_zip.read('BOOT/cmdline').decode())
 
   def test_ReplaceVerityKeyId_no_veritykeyid(self):
     BOOT_CMDLINE = (
@@ -164,7 +164,7 @@
       ReplaceVerityKeyId(input_zip, output_zip, None)
 
     with zipfile.ZipFile(output_file) as output_zip:
-      self.assertEqual(BOOT_CMDLINE, output_zip.read('BOOT/cmdline'))
+      self.assertEqual(BOOT_CMDLINE, output_zip.read('BOOT/cmdline').decode())
 
   def test_ReplaceCerts(self):
     cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index 70e3b49..0f0d773 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -98,7 +98,7 @@
     with open(boot_image, 'r+b') as boot_fp:
       boot_fp.seek(-1, os.SEEK_END)
       last_byte = boot_fp.read(1)
-      last_byte = chr(255 - ord(last_byte))
+      last_byte = bytes([255 - ord(last_byte)])
       boot_fp.seek(-1, os.SEEK_END)
       boot_fp.write(last_byte)
 
diff --git a/tools/releasetools/test_verity_utils.py b/tools/releasetools/test_verity_utils.py
index 1cc539f..d02bc7f 100644
--- a/tools/releasetools/test_verity_utils.py
+++ b/tools/releasetools/test_verity_utils.py
@@ -47,25 +47,22 @@
     }
 
     self.hash_algorithm = "sha256"
-    self.fixed_salt = \
-        "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7"
-    self.expected_root_hash = \
-        "0b7c4565e87b1026e11fbab91c0bc29e185c847a5b44d40e6e86e461e8adf80d"
+    self.fixed_salt = (
+        "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7")
+    self.expected_root_hash = (
+        "0b7c4565e87b1026e11fbab91c0bc29e185c847a5b44d40e6e86e461e8adf80d")
 
-  def _create_simg(self, raw_data):
+  def _CreateSimg(self, raw_data):  # pylint: disable=no-self-use
     output_file = common.MakeTempFile()
     raw_image = common.MakeTempFile()
     with open(raw_image, 'wb') as f:
       f.write(raw_data)
 
     cmd = ["img2simg", raw_image, output_file, '4096']
-    p = common.Run(cmd)
-    p.communicate()
-    self.assertEqual(0, p.returncode)
-
+    common.RunAndCheckOutput(cmd)
     return output_file
 
-  def _generate_image(self):
+  def _GenerateImage(self):
     partition_size = 1024 * 1024
     prop_dict = {
         'partition_size': str(partition_size),
@@ -79,11 +76,11 @@
     self.assertIsNotNone(verity_image_builder)
     adjusted_size = verity_image_builder.CalculateMaxImageSize()
 
-    raw_image = ""
+    raw_image = bytearray(adjusted_size)
     for i in range(adjusted_size):
-      raw_image += str(i % 10)
+      raw_image[i] = ord('0') + i % 10
 
-    output_file = self._create_simg(raw_image)
+    output_file = self._CreateSimg(raw_image)
 
     # Append the verity metadata.
     verity_image_builder.Build(output_file)
@@ -92,7 +89,7 @@
 
   @SkipIfExternalToolsUnavailable()
   def test_CreateHashtreeInfoGenerator(self):
-    image_file = sparse_img.SparseImage(self._generate_image())
+    image_file = sparse_img.SparseImage(self._GenerateImage())
 
     generator = CreateHashtreeInfoGenerator(
         'system', image_file, self.prop_dict)
@@ -103,7 +100,7 @@
 
   @SkipIfExternalToolsUnavailable()
   def test_DecomposeSparseImage(self):
-    image_file = sparse_img.SparseImage(self._generate_image())
+    image_file = sparse_img.SparseImage(self._GenerateImage())
 
     generator = VerifiedBootVersion1HashtreeInfoGenerator(
         self.partition_size, 4096, True)
@@ -114,7 +111,7 @@
 
   @SkipIfExternalToolsUnavailable()
   def test_ParseHashtreeMetadata(self):
-    image_file = sparse_img.SparseImage(self._generate_image())
+    image_file = sparse_img.SparseImage(self._GenerateImage())
     generator = VerifiedBootVersion1HashtreeInfoGenerator(
         self.partition_size, 4096, True)
     generator.DecomposeSparseImage(image_file)
@@ -131,12 +128,12 @@
   def test_ValidateHashtree_smoke(self):
     generator = VerifiedBootVersion1HashtreeInfoGenerator(
         self.partition_size, 4096, True)
-    generator.image = sparse_img.SparseImage(self._generate_image())
+    generator.image = sparse_img.SparseImage(self._GenerateImage())
 
     generator.hashtree_info = info = HashtreeInfo()
-    info.filesystem_range = RangeSet(data=[0, 991232 / 4096])
+    info.filesystem_range = RangeSet(data=[0, 991232 // 4096])
     info.hashtree_range = RangeSet(
-        data=[991232 / 4096, (991232 + 12288) / 4096])
+        data=[991232 // 4096, (991232 + 12288) // 4096])
     info.hash_algorithm = self.hash_algorithm
     info.salt = self.fixed_salt
     info.root_hash = self.expected_root_hash
@@ -147,12 +144,12 @@
   def test_ValidateHashtree_failure(self):
     generator = VerifiedBootVersion1HashtreeInfoGenerator(
         self.partition_size, 4096, True)
-    generator.image = sparse_img.SparseImage(self._generate_image())
+    generator.image = sparse_img.SparseImage(self._GenerateImage())
 
     generator.hashtree_info = info = HashtreeInfo()
-    info.filesystem_range = RangeSet(data=[0, 991232 / 4096])
+    info.filesystem_range = RangeSet(data=[0, 991232 // 4096])
     info.hashtree_range = RangeSet(
-        data=[991232 / 4096, (991232 + 12288) / 4096])
+        data=[991232 // 4096, (991232 + 12288) // 4096])
     info.hash_algorithm = self.hash_algorithm
     info.salt = self.fixed_salt
     info.root_hash = "a" + self.expected_root_hash[1:]
@@ -161,12 +158,12 @@
 
   @SkipIfExternalToolsUnavailable()
   def test_Generate(self):
-    image_file = sparse_img.SparseImage(self._generate_image())
+    image_file = sparse_img.SparseImage(self._GenerateImage())
     generator = CreateHashtreeInfoGenerator('system', 4096, self.prop_dict)
     info = generator.Generate(image_file)
 
-    self.assertEqual(RangeSet(data=[0, 991232 / 4096]), info.filesystem_range)
-    self.assertEqual(RangeSet(data=[991232 / 4096, (991232 + 12288) / 4096]),
+    self.assertEqual(RangeSet(data=[0, 991232 // 4096]), info.filesystem_range)
+    self.assertEqual(RangeSet(data=[991232 // 4096, (991232 + 12288) // 4096]),
                      info.hashtree_range)
     self.assertEqual(self.hash_algorithm, info.hash_algorithm)
     self.assertEqual(self.fixed_salt, info.salt)
diff --git a/tools/releasetools/testdata/foo.apex b/tools/releasetools/testdata/foo.apex
new file mode 100644
index 0000000..42e0adb
--- /dev/null
+++ b/tools/releasetools/testdata/foo.apex
Binary files differ
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index 37d5d27..435e7f2 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -44,7 +44,7 @@
   """Constructs and returns a File object. Rounds up its size if needed."""
 
   assert os.path.exists(unpacked_name)
-  with open(unpacked_name, 'r') as f:
+  with open(unpacked_name, 'rb') as f:
     file_data = f.read()
   file_size = len(file_data)
   if round_up:
@@ -324,7 +324,8 @@
 
     # avbtool verifies all the images that have descriptors listed in vbmeta.
     image = os.path.join(input_tmp, 'IMAGES', 'vbmeta.img')
-    cmd = ['avbtool', 'verify_image', '--image', image, '--key', key]
+    cmd = [info_dict['avb_avbtool'], 'verify_image', '--image', image,
+           '--key', key]
 
     # Append the args for chained partitions if any.
     for partition in common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS:
diff --git a/tools/releasetools/verity_utils.py b/tools/releasetools/verity_utils.py
index 3063800..e7f84f5 100644
--- a/tools/releasetools/verity_utils.py
+++ b/tools/releasetools/verity_utils.py
@@ -131,7 +131,8 @@
     BuildVerityImageError: On error.
   """
   try:
-    with open(target, "a") as out_file, open(file_to_append, "r") as input_file:
+    with open(target, 'ab') as out_file, \
+        open(file_to_append, 'rb') as input_file:
       for line in input_file:
         out_file.write(line)
   except IOError:
@@ -178,6 +179,8 @@
     # key_path and algorithm are only available when chain partition is used.
     key_path = prop_dict.get("avb_key_path")
     algorithm = prop_dict.get("avb_algorithm")
+
+    # Image uses hash footer.
     if prop_dict.get("avb_hash_enable") == "true":
       return VerifiedBootVersion2VerityImageBuilder(
           prop_dict["partition_name"],
@@ -188,16 +191,17 @@
           algorithm,
           prop_dict.get("avb_salt"),
           prop_dict["avb_add_hash_footer_args"])
-    else:
-      return VerifiedBootVersion2VerityImageBuilder(
-          prop_dict["partition_name"],
-          partition_size,
-          VerifiedBootVersion2VerityImageBuilder.AVB_HASHTREE_FOOTER,
-          prop_dict["avb_avbtool"],
-          key_path,
-          algorithm,
-          prop_dict.get("avb_salt"),
-          prop_dict["avb_add_hashtree_footer_args"])
+
+    # Image uses hashtree footer.
+    return VerifiedBootVersion2VerityImageBuilder(
+        prop_dict["partition_name"],
+        partition_size,
+        VerifiedBootVersion2VerityImageBuilder.AVB_HASHTREE_FOOTER,
+        prop_dict["avb_avbtool"],
+        key_path,
+        algorithm,
+        prop_dict.get("avb_salt"),
+        prop_dict["avb_add_hashtree_footer_args"])
 
   return None
 
@@ -605,19 +609,19 @@
     self.metadata_size = metadata_size
 
     self.hashtree_info.filesystem_range = RangeSet(
-        data=[0, adjusted_size / self.block_size])
+        data=[0, adjusted_size // self.block_size])
     self.hashtree_info.hashtree_range = RangeSet(
-        data=[adjusted_size / self.block_size,
-              (adjusted_size + verity_tree_size) / self.block_size])
+        data=[adjusted_size // self.block_size,
+              (adjusted_size + verity_tree_size) // self.block_size])
 
   def _ParseHashtreeMetadata(self):
     """Parses the hash_algorithm, root_hash, salt from the metadata block."""
 
     metadata_start = self.filesystem_size + self.hashtree_size
     metadata_range = RangeSet(
-        data=[metadata_start / self.block_size,
-              (metadata_start + self.metadata_size) / self.block_size])
-    meta_data = ''.join(self.image.ReadRangeSet(metadata_range))
+        data=[metadata_start // self.block_size,
+              (metadata_start + self.metadata_size) // self.block_size])
+    meta_data = b''.join(self.image.ReadRangeSet(metadata_range))
 
     # More info about the metadata structure available in:
     # system/extras/verity/build_verity_metadata.py
@@ -640,9 +644,9 @@
     assert (int(table_entries[5]) * self.block_size == self.filesystem_size and
             int(table_entries[6]) * self.block_size == self.filesystem_size)
 
-    self.hashtree_info.hash_algorithm = table_entries[7]
-    self.hashtree_info.root_hash = table_entries[8]
-    self.hashtree_info.salt = table_entries[9]
+    self.hashtree_info.hash_algorithm = table_entries[7].decode()
+    self.hashtree_info.root_hash = table_entries[8].decode()
+    self.hashtree_info.salt = table_entries[9].decode()
 
   def ValidateHashtree(self):
     """Checks that we can reconstruct the verity hash tree."""
@@ -669,8 +673,8 @@
 
     # Reads the generated hash tree and checks if it has the exact same bytes
     # as the one in the sparse image.
-    with open(generated_verity_tree, "rb") as fd:
-      return fd.read() == ''.join(self.image.ReadRangeSet(
+    with open(generated_verity_tree, 'rb') as fd:
+      return fd.read() == b''.join(self.image.ReadRangeSet(
           self.hashtree_info.hashtree_range))
 
   def Generate(self, image):
diff --git a/tools/warn.py b/tools/warn.py
index c710164..9389b7d 100755
--- a/tools/warn.py
+++ b/tools/warn.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# This file uses the following encoding: utf-8
+# Prefer python3 but work also with python2.
 
 """Grep warnings messages and output HTML tables or warning counts in CSV.
 
@@ -74,9 +74,11 @@
 #   escape_string, strip_escape_string, emit_warning_arrays
 #   emit_js_data():
 
+from __future__ import print_function
 import argparse
 import cgi
 import csv
+import io
 import multiprocessing
 import os
 import re
@@ -540,7 +542,7 @@
     {'category': 'java',
      'severity': Severity.LOW,
      'description':
-         'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.',
+         u'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.',
      'patterns': [r".*: warning: \[LambdaFunctionalInterface\] .+"]},
     {'category': 'java',
      'severity': Severity.LOW,
@@ -1270,7 +1272,7 @@
     {'category': 'java',
      'severity': Severity.MEDIUM,
      'description':
-         'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.',
+         u'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.',
      'patterns': [r".*: warning: \[ShortCircuitBoolean\] .+"]},
     {'category': 'java',
      'severity': Severity.MEDIUM,
@@ -1535,7 +1537,7 @@
     {'category': 'java',
      'severity': Severity.HIGH,
      'description':
-         'Java:  Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.',
+         u'Java:  Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.',
      'patterns': [r".*: warning: \[ComparableType\] .+"]},
     {'category': 'java',
      'severity': Severity.HIGH,
@@ -1790,7 +1792,7 @@
     {'category': 'java',
      'severity': Severity.HIGH,
      'description':
-         'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity',
+         u'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity',
      'patterns': [r".*: warning: \[IterablePathParameter\] .+"]},
     {'category': 'java',
      'severity': Severity.HIGH,
@@ -2922,17 +2924,17 @@
 
 
 def dump_html_prologue(title):
-  print '<html>\n<head>'
-  print '<title>' + title + '</title>'
-  print html_head_scripts
+  print('<html>\n<head>')
+  print('<title>' + title + '</title>')
+  print(html_head_scripts)
   emit_stats_by_project()
-  print '</head>\n<body>'
-  print html_big(title)
-  print '<p>'
+  print('</head>\n<body>')
+  print(html_big(title))
+  print('<p>')
 
 
 def dump_html_epilogue():
-  print '</body>\n</head>\n</html>'
+  print('</body>\n</head>\n</html>')
 
 
 def sort_warnings():
@@ -2943,6 +2945,7 @@
 def emit_stats_by_project():
   """Dump a google chart table of warnings per project and severity."""
   # warnings[p][s] is number of warnings in project p of severity s.
+  # pylint:disable=g-complex-comprehension
   warnings = {p: {s: 0 for s in Severity.range} for p in project_names}
   for i in warn_patterns:
     s = i['severity']
@@ -2988,11 +2991,11 @@
       total_all_severities += total_by_severity[s]
   one_row.append(total_all_projects)
   stats_rows.append(one_row)
-  print '<script>'
+  print('<script>')
   emit_const_string_array('StatsHeader', stats_header)
   emit_const_object_array('StatsRows', stats_rows)
-  print draw_table_javascript
-  print '</script>'
+  print(draw_table_javascript)
+  print('</script>')
 
 
 def dump_stats():
@@ -3008,14 +3011,14 @@
       skipped += len(i['members'])
     else:
       known += len(i['members'])
-  print 'Number of classified warnings: <b>' + str(known) + '</b><br>'
-  print 'Number of skipped warnings: <b>' + str(skipped) + '</b><br>'
-  print 'Number of unclassified warnings: <b>' + str(unknown) + '</b><br>'
+  print('Number of classified warnings: <b>' + str(known) + '</b><br>')
+  print('Number of skipped warnings: <b>' + str(skipped) + '</b><br>')
+  print('Number of unclassified warnings: <b>' + str(unknown) + '</b><br>')
   total = unknown + known + skipped
   extra_msg = ''
   if total < 1000:
     extra_msg = ' (low count may indicate incremental build)'
-  print 'Total number of warnings: <b>' + str(total) + '</b>' + extra_msg
+  print('Total number of warnings: <b>' + str(total) + '</b>' + extra_msg)
 
 
 # New base table of warnings, [severity, warn_id, project, warning_message]
@@ -3029,14 +3032,14 @@
 #     id for each warning pattern
 #     sort by project, severity, warn_id, warning_message
 def emit_buttons():
-  print ('<button class="button" onclick="expandCollapse(1);">'
-         'Expand all warnings</button>\n'
-         '<button class="button" onclick="expandCollapse(0);">'
-         'Collapse all warnings</button>\n'
-         '<button class="button" onclick="groupBySeverity();">'
-         'Group warnings by severity</button>\n'
-         '<button class="button" onclick="groupByProject();">'
-         'Group warnings by project</button><br>')
+  print('<button class="button" onclick="expandCollapse(1);">'
+        'Expand all warnings</button>\n'
+        '<button class="button" onclick="expandCollapse(0);">'
+        'Collapse all warnings</button>\n'
+        '<button class="button" onclick="groupBySeverity();">'
+        'Group warnings by severity</button>\n'
+        '<button class="button" onclick="groupByProject();">'
+        'Group warnings by project</button><br>')
 
 
 def all_patterns(category):
@@ -3051,14 +3054,14 @@
   """Show which warnings no longer occur."""
   anchor = 'fixed_warnings'
   mark = anchor + '_mark'
-  print ('\n<br><p style="background-color:lightblue"><b>'
-         '<button id="' + mark + '" '
-         'class="bt" onclick="expand(\'' + anchor + '\');">'
-         '&#x2295</button> Fixed warnings. '
-         'No more occurrences. Please consider turning these into '
-         'errors if possible, before they are reintroduced in to the build'
-         ':</b></p>')
-  print '<blockquote>'
+  print('\n<br><p style="background-color:lightblue"><b>'
+        '<button id="' + mark + '" '
+        'class="bt" onclick="expand(\'' + anchor + '\');">'
+        '&#x2295</button> Fixed warnings. '
+        'No more occurrences. Please consider turning these into '
+        'errors if possible, before they are reintroduced in to the build'
+        ':</b></p>')
+  print('<blockquote>')
   fixed_patterns = []
   for i in warn_patterns:
     if not i['members']:
@@ -3066,16 +3069,16 @@
                             all_patterns(i) + ')')
     if i['option']:
       fixed_patterns.append(' ' + i['option'])
-  fixed_patterns.sort()
-  print '<div id="' + anchor + '" style="display:none;"><table>'
+  fixed_patterns = sorted(fixed_patterns)
+  print('<div id="' + anchor + '" style="display:none;"><table>')
   cur_row_class = 0
   for text in fixed_patterns:
     cur_row_class = 1 - cur_row_class
     # remove last '\n'
     t = text[:-1] if text[-1] == '\n' else text
-    print '<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>'
-  print '</table></div>'
-  print '</blockquote>'
+    print('<tr><td class="c' + str(cur_row_class) + '">' + t + '</td></tr>')
+  print('</table></div>')
+  print('</blockquote>')
 
 
 def find_project_index(line):
@@ -3187,8 +3190,9 @@
 def normalize_warning_line(line):
   """Normalize file path relative to android_root in a warning line."""
   # replace fancy quotes with plain ol' quotes
-  line = line.replace('‘', "'")
-  line = line.replace('’', "'")
+  line = re.sub(u'[\u2018\u2019]', '\'', line)
+  # replace non-ASCII chars to spaces
+  line = re.sub(u'[^\x00-\x7f]', ' ', line)
   line = line.strip()
   first_column = line.find(':')
   if first_column > 0:
@@ -3246,21 +3250,22 @@
 
 
 def emit_warning_array(name):
-  print 'var warning_{} = ['.format(name)
+  print('var warning_{} = ['.format(name))
   for i in range(len(warn_patterns)):
-    print '{},'.format(warn_patterns[i][name])
-  print '];'
+    print('{},'.format(warn_patterns[i][name]))
+  print('];')
 
 
 def emit_warning_arrays():
   emit_warning_array('severity')
-  print 'var warning_description = ['
+  print('var warning_description = [')
   for i in range(len(warn_patterns)):
     if warn_patterns[i]['members']:
-      print '"{}",'.format(escape_string(warn_patterns[i]['description']))
+      print('"{}",'.format(escape_string(warn_patterns[i]['description'])))
     else:
-      print '"",'  # no such warning
-  print '];'
+      print('"",')  # no such warning
+  print('];')
+
 
 scripts_for_warning_groups = """
   function compareMessages(x1, x2) { // of the same warning type
@@ -3393,39 +3398,42 @@
 
 # Emit a JavaScript const string
 def emit_const_string(name, value):
-  print 'const ' + name + ' = "' + escape_string(value) + '";'
+  print('const ' + name + ' = "' + escape_string(value) + '";')
 
 
 # Emit a JavaScript const integer array.
 def emit_const_int_array(name, array):
-  print 'const ' + name + ' = ['
+  print('const ' + name + ' = [')
   for n in array:
-    print str(n) + ','
-  print '];'
+    print(str(n) + ',')
+  print('];')
 
 
 # Emit a JavaScript const string array.
 def emit_const_string_array(name, array):
-  print 'const ' + name + ' = ['
+  print('const ' + name + ' = [')
   for s in array:
-    print '"' + strip_escape_string(s) + '",'
-  print '];'
+    print('"' + strip_escape_string(s) + '",')
+  print('];')
 
 
 # Emit a JavaScript const string array for HTML.
 def emit_const_html_string_array(name, array):
-  print 'const ' + name + ' = ['
+  print('const ' + name + ' = [')
   for s in array:
-    print '"' + cgi.escape(strip_escape_string(s)) + '",'
-  print '];'
+    # Not using html.escape yet, to work for both python 2 and 3,
+    # until all users switch to python 3.
+    # pylint:disable=deprecated-method
+    print('"' + cgi.escape(strip_escape_string(s)) + '",')
+  print('];')
 
 
 # Emit a JavaScript const object array.
 def emit_const_object_array(name, array):
-  print 'const ' + name + ' = ['
+  print('const ' + name + ' = [')
   for x in array:
-    print str(x) + ','
-  print '];'
+    print(str(x) + ',')
+  print('];')
 
 
 def emit_js_data():
@@ -3471,18 +3479,18 @@
   dump_html_prologue('Warnings for ' + platform_version + ' - ' +
                      target_product + ' - ' + target_variant)
   dump_stats()
-  print '<br><div id="stats_table"></div><br>'
-  print '\n<script>'
+  print('<br><div id="stats_table"></div><br>')
+  print('\n<script>')
   emit_js_data()
-  print scripts_for_warning_groups
-  print '</script>'
+  print(scripts_for_warning_groups)
+  print('</script>')
   emit_buttons()
   # Warning messages are grouped by severities or project names.
-  print '<br><div id="warning_groups"></div>'
+  print('<br><div id="warning_groups"></div>')
   if args.byproject:
-    print '<script>groupByProject();</script>'
+    print('<script>groupByProject();</script>')
   else:
-    print '<script>groupBySeverity();</script>'
+    print('<script>groupBySeverity();</script>')
   dump_fixed()
   dump_html_epilogue()
 
@@ -3506,8 +3514,7 @@
       warning = kind + ': ' + description_for_csv(i)
       writer.writerow([n, '', warning])
       # print number of warnings for each project, ordered by project name.
-      projects = i['projects'].keys()
-      projects.sort()
+      projects = sorted(i['projects'].keys())
       for p in projects:
         writer.writerow([i['projects'][p], p, warning])
   writer.writerow([total, '', kind + ' warnings'])
@@ -3526,7 +3533,9 @@
 
 
 def main():
-  warning_lines = parse_input_file(open(args.buildlog, 'r'))
+  # We must use 'utf-8' codec to parse some non-ASCII code in warnings.
+  warning_lines = parse_input_file(
+      io.open(args.buildlog, mode='r', encoding='utf-8'))
   parallel_classify_warnings(warning_lines)
   # If a user pases a csv path, save the fileoutput to the path
   # If the user also passed gencsv write the output to stdout