Merge "cleanup: remove unnecessary steps in apex_utils"
diff --git a/core/Makefile b/core/Makefile
index b44d1d7..a7df61f 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4621,6 +4621,12 @@
 ifneq ($(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST),)
 	$(hide) echo "partial_ota_update_partitions_list=$(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST)" >> $@
 endif
+ifeq ($(BUILDING_WITH_VSDK),true)
+	$(hide) echo "building_with_vsdk=true" >> $@
+endif
+ifeq ($(TARGET_FLATTEN_APEX),false)
+	$(hide) echo "target_flatten_apex=false" >> $@
+endif
 
 .PHONY: misc_info
 misc_info: $(INSTALLED_MISC_INFO_TARGET)
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 7cd8489..8c702b3 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -54,10 +54,6 @@
 else ifneq (,$(SANITIZE_TARGET)$(SANITIZE_HOST))
   # Prebuilts aren't built with sanitizers either.
   SOONG_CONFIG_art_module_source_build := true
-else ifneq (,$(PRODUCT_FUCHSIA))
-  # Fuchsia picks out ART internal packages that aren't available in the
-  # prebuilt.
-  SOONG_CONFIG_art_module_source_build := true
 else ifeq (,$(filter x86 x86_64,$(HOST_CROSS_ARCH)))
   # We currently only provide prebuilts for x86 on host. This skips prebuilts in
   # cuttlefish builds for ARM servers.
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index e8bcdb8..63b32e7 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -104,7 +104,7 @@
   $(call add_json_bool, DisableGenerateProfile,                  $(filter false,$(WITH_DEX_PREOPT_GENERATE_PROFILE)))
   $(call add_json_str,  ProfileDir,                              $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
   $(call add_json_list, BootJars,                                $(PRODUCT_BOOT_JARS))
-  $(call add_json_list, UpdatableBootJars,                       $(PRODUCT_APEX_BOOT_JARS))
+  $(call add_json_list, ApexBootJars,                            $(PRODUCT_APEX_BOOT_JARS))
   $(call add_json_list, ArtApexJars,                             $(filter $(PRODUCT_BOOT_JARS),$(ART_APEX_JARS)))
   $(call add_json_list, SystemServerJars,                        $(PRODUCT_SYSTEM_SERVER_JARS))
   $(call add_json_list, SystemServerApps,                        $(PRODUCT_SYSTEM_SERVER_APPS))
diff --git a/core/soong_config.mk b/core/soong_config.mk
index fb0b80d..d3f983c 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -142,7 +142,7 @@
 $(call add_json_list, ModulesLoadedByPrivilegedModules,  $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
 
 $(call add_json_list, BootJars,                          $(PRODUCT_BOOT_JARS))
-$(call add_json_list, UpdatableBootJars,                 $(PRODUCT_APEX_BOOT_JARS))
+$(call add_json_list, ApexBootJars,                      $(PRODUCT_APEX_BOOT_JARS))
 
 $(call add_json_bool, VndkUseCoreVariant,                $(TARGET_VNDK_USE_CORE_VARIANT))
 $(call add_json_bool, VndkSnapshotBuildArtifacts,        $(VNDK_SNAPSHOT_BUILD_ARTIFACTS))
diff --git a/target/board/BoardConfigGkiCommon.mk b/target/board/BoardConfigGkiCommon.mk
index 5173012..c0f5db9 100644
--- a/target/board/BoardConfigGkiCommon.mk
+++ b/target/board/BoardConfigGkiCommon.mk
@@ -22,6 +22,9 @@
 # See b/178559811 for more details.
 BOARD_GKI_SIGNING_SIGNATURE_ARGS := --prop foo:bar
 
+# Sets boot SPL.
+BOOT_SECURITY_PATCH = $(PLATFORM_SECURITY_PATCH)
+
 # Boot image with ramdisk and kernel
 BOARD_RAMDISK_USE_LZ4 := true
 BOARD_BOOT_HEADER_VERSION := 4
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index c753e6c..6f4b7f1 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -18,8 +18,11 @@
 LLNDK: libsync.so
 LLNDK: libvndksupport.so
 LLNDK: libvulkan.so
+VNDK-SP: android.hardware.common-V2-ndk.so
 VNDK-SP: android.hardware.common-V2-ndk_platform.so
+VNDK-SP: android.hardware.common.fmq-V1-ndk.so
 VNDK-SP: android.hardware.common.fmq-V1-ndk_platform.so
+VNDK-SP: android.hardware.graphics.common-V2-ndk.so
 VNDK-SP: android.hardware.graphics.common-V2-ndk_platform.so
 VNDK-SP: android.hardware.graphics.common@1.0.so
 VNDK-SP: android.hardware.graphics.common@1.1.so
@@ -57,7 +60,9 @@
 VNDK-SP: libutilscallstack.so
 VNDK-SP: libz.so
 VNDK-core: android.hardware.audio.common@2.0.so
+VNDK-core: android.hardware.authsecret-V1-ndk.so
 VNDK-core: android.hardware.authsecret-V1-ndk_platform.so
+VNDK-core: android.hardware.automotive.occupant_awareness-V1-ndk.so
 VNDK-core: android.hardware.automotive.occupant_awareness-V1-ndk_platform.so
 VNDK-core: android.hardware.configstore-utils.so
 VNDK-core: android.hardware.configstore@1.0.so
@@ -68,29 +73,46 @@
 VNDK-core: android.hardware.graphics.allocator@4.0.so
 VNDK-core: android.hardware.graphics.bufferqueue@1.0.so
 VNDK-core: android.hardware.graphics.bufferqueue@2.0.so
+VNDK-core: android.hardware.health.storage-V1-ndk.so
 VNDK-core: android.hardware.health.storage-V1-ndk_platform.so
+VNDK-core: android.hardware.identity-V2-ndk.so
 VNDK-core: android.hardware.identity-V2-ndk_platform.so
+VNDK-core: android.hardware.keymaster-V2-ndk.so
 VNDK-core: android.hardware.keymaster-V2-ndk_platform.so
+VNDK-core: android.hardware.light-V1-ndk.so
 VNDK-core: android.hardware.light-V1-ndk_platform.so
 VNDK-core: android.hardware.media.bufferpool@2.0.so
 VNDK-core: android.hardware.media.omx@1.0.so
 VNDK-core: android.hardware.media@1.0.so
+VNDK-core: android.hardware.memtrack-V1-ndk.so
 VNDK-core: android.hardware.memtrack-V1-ndk_platform.so
 VNDK-core: android.hardware.memtrack@1.0.so
+VNDK-core: android.hardware.oemlock-V1-ndk.so
 VNDK-core: android.hardware.oemlock-V1-ndk_platform.so
+VNDK-core: android.hardware.power-V1-ndk.so
 VNDK-core: android.hardware.power-V1-ndk_platform.so
+VNDK-core: android.hardware.power.stats-V1-ndk.so
 VNDK-core: android.hardware.power.stats-V1-ndk_platform.so
+VNDK-core: android.hardware.rebootescrow-V1-ndk.so
 VNDK-core: android.hardware.rebootescrow-V1-ndk_platform.so
+VNDK-core: android.hardware.security.keymint-V1-ndk.so
 VNDK-core: android.hardware.security.keymint-V1-ndk_platform.so
+VNDK-core: android.hardware.security.secureclock-V1-ndk.so
 VNDK-core: android.hardware.security.secureclock-V1-ndk_platform.so
+VNDK-core: android.hardware.security.sharedsecret-V1-ndk.so
 VNDK-core: android.hardware.security.sharedsecret-V1-ndk_platform.so
 VNDK-core: android.hardware.soundtrigger@2.0-core.so
 VNDK-core: android.hardware.soundtrigger@2.0.so
+VNDK-core: android.hardware.vibrator-V1-ndk.so
 VNDK-core: android.hardware.vibrator-V1-ndk_platform.so
+VNDK-core: android.hardware.weaver-V1-ndk.so
 VNDK-core: android.hardware.weaver-V1-ndk_platform.so
 VNDK-core: android.hidl.token@1.0-utils.so
 VNDK-core: android.hidl.token@1.0.so
+VNDK-core: android.system.keystore2-V1-ndk.so
 VNDK-core: android.system.keystore2-V1-ndk_platform.so
+VNDK-core: android.system.suspend-V1-ndk.so
+VNDK-core: android.system.suspend-V1-ndk_platform.so
 VNDK-core: android.system.suspend@1.0.so
 VNDK-core: libaudioroute.so
 VNDK-core: libaudioutils.so
diff --git a/tools/releasetools/OWNERS b/tools/releasetools/OWNERS
index d7fc540..9962836 100644
--- a/tools/releasetools/OWNERS
+++ b/tools/releasetools/OWNERS
@@ -1,4 +1,6 @@
 elsk@google.com
 nhdo@google.com
 xunchang@google.com
-zhaojiac@google.com
+
+per-file merge_*.py = danielnorman@google.com
+
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 0711af5..c708154 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -459,6 +459,10 @@
   def oem_props(self):
     return self._oem_props
 
+  @property
+  def avb_enabled(self):
+    return self.get("avb_enable") == "true"
+
   def __getitem__(self, key):
     return self.info_dict[key]
 
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 7086f21..46ffdb7 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -88,11 +88,23 @@
 
   --keep-tmp
       Keep tempoary files for debugging purposes.
+
+  The following only apply when using the VSDK to perform dexopt on vendor apps:
+
+  --framework-dexpreopt-config
+      If provided, the location of framwework's dexpreopt_config.zip.
+
+  --framework-dexpreopt-tools
+      if provided, the location of framework's dexpreopt_tools.zip.
+
+  --vendor-dexpreopt-config
+      If provided, the location of vendor's dexpreopt_config.zip.
 """
 
 from __future__ import print_function
 
 import fnmatch
+import glob
 import json
 import logging
 import os
@@ -140,6 +152,9 @@
 OPTIONS.vendor_otatools = None
 OPTIONS.rebuild_sepolicy = False
 OPTIONS.keep_tmp = False
+OPTIONS.framework_dexpreopt_config = None
+OPTIONS.framework_dexpreopt_tools = None
+OPTIONS.vendor_dexpreopt_config = None
 
 # In an item list (framework or vendor), we may see entries that select whole
 # partitions. Such an entry might look like this 'SYSTEM/*' (e.g., for the
@@ -815,21 +830,23 @@
       PARTITIONS_WITH_CARE_MAP, partition_image_map)
 
 
-def process_special_cases(framework_target_files_temp_dir,
-                          vendor_target_files_temp_dir,
+def process_special_cases(temp_dir, framework_meta, vendor_meta,
                           output_target_files_temp_dir,
                           framework_misc_info_keys, framework_partition_set,
-                          vendor_partition_set):
+                          vendor_partition_set, framework_dexpreopt_tools,
+                          framework_dexpreopt_config, vendor_dexpreopt_config):
   """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.
 
   Args:
-    framework_target_files_temp_dir: The name of a directory containing the
-      special items extracted from the framework target files package.
-    vendor_target_files_temp_dir: The name of a directory containing the special
-      items extracted from the vendor target files package.
+    temp_dir: Location containing an 'output' directory where target files have
+      been extracted, e.g. <temp_dir>/output/SYSTEM, <temp_dir>/output/IMAGES, etc.
+    framework_meta: The name of a directory containing the special items
+      extracted from the framework target files package.
+    vendor_meta: The name of a directory containing the special items
+      extracted from the vendor target files package.
     output_target_files_temp_dir: The name of a directory that will be used to
       create the output target files package after all the special cases are
       processed.
@@ -840,50 +857,361 @@
       partitions. Used to filter apexkeys.txt and apkcerts.txt.
     vendor_partition_set: Partitions that are considered vendor partitions. Used
       to filter apexkeys.txt and apkcerts.txt.
+
+    The following are only used if dexpreopt is applied:
+
+    framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+    framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+    vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
   """
 
   if 'ab_update' in framework_misc_info_keys:
     process_ab_partitions_txt(
-        framework_target_files_temp_dir=framework_target_files_temp_dir,
-        vendor_target_files_temp_dir=vendor_target_files_temp_dir,
+        framework_target_files_temp_dir=framework_meta,
+        vendor_target_files_temp_dir=vendor_meta,
         output_target_files_temp_dir=output_target_files_temp_dir)
 
   copy_file_contexts(
-      framework_target_files_dir=framework_target_files_temp_dir,
-      vendor_target_files_dir=vendor_target_files_temp_dir,
+      framework_target_files_dir=framework_meta,
+      vendor_target_files_dir=vendor_meta,
       output_target_files_dir=output_target_files_temp_dir)
 
   process_misc_info_txt(
-      framework_target_files_temp_dir=framework_target_files_temp_dir,
-      vendor_target_files_temp_dir=vendor_target_files_temp_dir,
+      framework_target_files_temp_dir=framework_meta,
+      vendor_target_files_temp_dir=vendor_meta,
       output_target_files_temp_dir=output_target_files_temp_dir,
       framework_misc_info_keys=framework_misc_info_keys)
 
   process_dynamic_partitions_info_txt(
-      framework_target_files_dir=framework_target_files_temp_dir,
-      vendor_target_files_dir=vendor_target_files_temp_dir,
+      framework_target_files_dir=framework_meta,
+      vendor_target_files_dir=vendor_meta,
       output_target_files_dir=output_target_files_temp_dir)
 
   process_apex_keys_apk_certs_common(
-      framework_target_files_dir=framework_target_files_temp_dir,
-      vendor_target_files_dir=vendor_target_files_temp_dir,
+      framework_target_files_dir=framework_meta,
+      vendor_target_files_dir=vendor_meta,
       output_target_files_dir=output_target_files_temp_dir,
       framework_partition_set=framework_partition_set,
       vendor_partition_set=vendor_partition_set,
       file_name='apkcerts.txt')
 
   process_apex_keys_apk_certs_common(
-      framework_target_files_dir=framework_target_files_temp_dir,
-      vendor_target_files_dir=vendor_target_files_temp_dir,
+      framework_target_files_dir=framework_meta,
+      vendor_target_files_dir=vendor_meta,
       output_target_files_dir=output_target_files_temp_dir,
       framework_partition_set=framework_partition_set,
       vendor_partition_set=vendor_partition_set,
       file_name='apexkeys.txt')
 
+  process_dexopt(
+      temp_dir=temp_dir,
+      framework_meta=framework_meta,
+      vendor_meta=vendor_meta,
+      output_target_files_temp_dir=output_target_files_temp_dir,
+      framework_dexpreopt_tools=framework_dexpreopt_tools,
+      framework_dexpreopt_config=framework_dexpreopt_config,
+      vendor_dexpreopt_config=vendor_dexpreopt_config)
+
+
+def process_dexopt(temp_dir, framework_meta, vendor_meta,
+                   output_target_files_temp_dir,
+                   framework_dexpreopt_tools, framework_dexpreopt_config,
+                   vendor_dexpreopt_config):
+  """If needed, generates dexopt files for vendor apps.
+
+  Args:
+    temp_dir: Location containing an 'output' directory where target files have
+      been extracted, e.g. <temp_dir>/output/SYSTEM, <temp_dir>/output/IMAGES, etc.
+    framework_meta: The name of a directory containing the special items
+      extracted from the framework target files package.
+    vendor_meta: The name of a directory containing the special items extracted
+      from the vendor target files package.
+    output_target_files_temp_dir: The name of a directory that will be used to
+      create the output target files package after all the special cases are
+      processed.
+    framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+    framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+    vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
+  """
+  # Load vendor and framework META/misc_info.txt.
+  misc_info_path = ['META', 'misc_info.txt']
+  vendor_misc_info_dict = common.LoadDictionaryFromFile(
+      os.path.join(vendor_meta, *misc_info_path))
+
+  if (vendor_misc_info_dict.get('building_with_vsdk') != 'true' or
+      framework_dexpreopt_tools is None or
+      framework_dexpreopt_config is None or
+      vendor_dexpreopt_config is None):
+    return
+
+  logger.info('applying dexpreopt')
+
+  # The directory structure to apply dexpreopt is:
+  #
+  # <temp_dir>/
+  #     framework_meta/
+  #         META/
+  #     vendor_meta/
+  #         META/
+  #     output/
+  #         SYSTEM/
+  #         VENDOR/
+  #         IMAGES/
+  #         <other items extracted from system and vendor target files>
+  #     tools/
+  #         <contents of dexpreopt_tools.zip>
+  #     system_config/
+  #         <contents of system dexpreopt_config.zip>
+  #     vendor_config/
+  #         <contents of vendor dexpreopt_config.zip>
+  #     system -> output/SYSTEM
+  #     vendor -> output/VENDOR
+  #     apex -> output/SYSTEM/apex (only for flattened APEX builds)
+  #     apex/ (extracted updatable APEX)
+  #         <apex 1>/
+  #             ...
+  #         <apex 2>/
+  #             ...
+  #         ...
+  #     out/dex2oat_result/vendor/
+  #         <app>
+  #             oat/arm64/
+  #                 package.vdex
+  #                 package.odex
+  #         <priv-app>
+  #             oat/arm64/
+  #                 package.vdex
+  #                 package.odex
+  dexpreopt_tools_files_temp_dir = os.path.join(temp_dir, 'tools')
+  dexpreopt_framework_config_files_temp_dir = os.path.join(temp_dir, 'system_config')
+  dexpreopt_vendor_config_files_temp_dir = os.path.join(temp_dir, 'vendor_config')
+
+  extract_items(
+      target_files=OPTIONS.framework_dexpreopt_tools,
+      target_files_temp_dir=dexpreopt_tools_files_temp_dir,
+      extract_item_list=('*',))
+  extract_items(
+      target_files=OPTIONS.framework_dexpreopt_config,
+      target_files_temp_dir=dexpreopt_framework_config_files_temp_dir,
+      extract_item_list=('*',))
+  extract_items(
+      target_files=OPTIONS.vendor_dexpreopt_config,
+      target_files_temp_dir=dexpreopt_vendor_config_files_temp_dir,
+      extract_item_list=('*',))
+
+  os.symlink(os.path.join(output_target_files_temp_dir, "SYSTEM"),
+             os.path.join(temp_dir, "system"))
+  os.symlink(os.path.join(output_target_files_temp_dir, "VENDOR"),
+             os.path.join(temp_dir, "vendor"))
+
+  # The directory structure for flatteded APEXes is:
+  #
+  # SYSTEM
+  #     apex
+  #         <APEX name, e.g., com.android.wifi>
+  #             apex_manifest.pb
+  #             apex_pubkey
+  #             etc/
+  #             javalib/
+  #             lib/
+  #             lib64/
+  #             priv-app/
+  #
+  # The directory structure for updatable APEXes is:
+  #
+  # SYSTEM
+  #     apex
+  #         com.android.adbd.apex
+  #         com.android.appsearch.apex
+  #         com.android.art.apex
+  #         ...
+  apex_root = os.path.join(output_target_files_temp_dir, "SYSTEM", "apex")
+  framework_misc_info_dict = common.LoadDictionaryFromFile(
+      os.path.join(framework_meta, *misc_info_path))
+
+  # Check for flattended versus updatable APEX.
+  if framework_misc_info_dict.get('target_flatten_apex') == 'false':
+    # Extract APEX.
+    logging.info('extracting APEX')
+
+    apex_extract_root_dir = os.path.join(temp_dir, 'apex')
+    os.makedirs(apex_extract_root_dir)
+
+    for apex in (glob.glob(os.path.join(apex_root, '*.apex')) +
+                 glob.glob(os.path.join(apex_root, '*.capex'))):
+      logging.info('  apex: %s', apex)
+      # deapexer is in the same directory as the merge_target_files binary extracted
+      # from otatools.zip.
+      apex_json_info = subprocess.check_output(['deapexer', 'info', apex])
+      logging.info('    info: %s', apex_json_info)
+      apex_info = json.loads(apex_json_info)
+      apex_name = apex_info['name']
+      logging.info('    name: %s', apex_name)
+
+      apex_extract_dir = os.path.join(apex_extract_root_dir, apex_name)
+      os.makedirs(apex_extract_dir)
+
+      # deapexer uses debugfs_static, which is part of otatools.zip.
+      command = [
+          'deapexer',
+          '--debugfs_path',
+          'debugfs_static',
+          'extract',
+          apex,
+          apex_extract_dir,
+      ]
+      logging.info('    running %s', command)
+      subprocess.check_call(command)
+  else:
+    # Flattened APEXes don't need to be extracted since they have the necessary
+    # directory structure.
+    os.symlink(os.path.join(apex_root), os.path.join(temp_dir, 'apex'))
+
+  # Modify system config to point to the tools that have been extracted.
+  # Absolute or .. paths are not allowed  by the dexpreopt_gen tool in
+  # dexpreopt_soong.config.
+  dexpreopt_framework_soon_config = os.path.join(
+      dexpreopt_framework_config_files_temp_dir, 'dexpreopt_soong.config')
+  with open(dexpreopt_framework_soon_config, 'w') as f:
+    dexpreopt_soong_config = {
+        'Profman': 'tools/profman',
+        'Dex2oat': 'tools/dex2oatd',
+        'Aapt': 'tools/aapt2',
+        'SoongZip': 'tools/soong_zip',
+        'Zip2zip': 'tools/zip2zip',
+        'ManifestCheck': 'tools/manifest_check',
+        'ConstructContext': 'tools/construct_context',
+    }
+    json.dump(dexpreopt_soong_config, f)
+
+  # TODO(b/188179859): Make *dex location configurable to vendor or system_other.
+  use_system_other_odex = False
+
+  if use_system_other_odex:
+    dex_img = 'SYSTEM_OTHER'
+  else:
+    dex_img = 'VENDOR'
+    # Open vendor_filesystem_config to append the items generated by dexopt.
+    vendor_file_system_config = open(
+        os.path.join(temp_dir, 'output', 'META', 'vendor_filesystem_config.txt'),
+        'a')
+
+  # Dexpreopt vendor apps.
+  dexpreopt_config_suffix = '_dexpreopt.config'
+  for config in glob.glob(os.path.join(
+      dexpreopt_vendor_config_files_temp_dir, '*' + dexpreopt_config_suffix)):
+    app = os.path.basename(config)[:-len(dexpreopt_config_suffix)]
+    logging.info('dexpreopt config: %s %s', config, app)
+
+    apk_dir = 'app'
+    apk_path = os.path.join(temp_dir, 'vendor', apk_dir, app, app + '.apk')
+    if not os.path.exists(apk_path):
+      apk_dir = 'priv-app'
+      apk_path = os.path.join(temp_dir, 'vendor', apk_dir, app, app + '.apk')
+      if not os.path.exists(apk_path):
+        logging.warning('skipping dexpreopt for %s, no apk found in vendor/app '
+                        'or vendor/priv-app', app)
+        continue
+
+    # Generate dexpreopting script. Note 'out_dir' is not the output directory
+    # where the script is generated, but the OUT_DIR at build time referenced
+    # in the dexpreot config files, e.g., "out/.../core-oj.jar", so the tool knows
+    # how to adjust the path.
+    command = [
+        os.path.join(dexpreopt_tools_files_temp_dir, 'dexpreopt_gen'),
+        '-global',
+        os.path.join(dexpreopt_framework_config_files_temp_dir, 'dexpreopt.config'),
+        '-global_soong',
+        os.path.join(
+            dexpreopt_framework_config_files_temp_dir, 'dexpreopt_soong.config'),
+        '-module',
+        config,
+        '-dexpreopt_script',
+        'dexpreopt_app.sh',
+        '-out_dir',
+        'out',
+        '-base_path',
+        '.',
+        '--uses_target_files',
+    ]
+
+    # Run the command from temp_dir so all tool paths are its descendants.
+    logging.info("running %s", command)
+    subprocess.check_call(command, cwd = temp_dir)
+
+    # Call the generated script.
+    command = ['sh', 'dexpreopt_app.sh', apk_path]
+    logging.info("running %s", command)
+    subprocess.check_call(command, cwd = temp_dir)
+
+    # Output files are in:
+    #
+    # <temp_dir>/out/dex2oat_result/vendor/priv-app/<app>/oat/arm64/package.vdex
+    # <temp_dir>/out/dex2oat_result/vendor/priv-app/<app>/oat/arm64/package.odex
+    # <temp_dir>/out/dex2oat_result/vendor/app/<app>/oat/arm64/package.vdex
+    # <temp_dir>/out/dex2oat_result/vendor/app/<app>/oat/arm64/package.odex
+    #
+    # Copy the files to their destination. The structure of system_other is:
+    #
+    # system_other/
+    #     system-other-odex-marker
+    #     system/
+    #         app/
+    #             <app>/oat/arm64/
+    #                 <app>.odex
+    #                 <app>.vdex
+    #             ...
+    #         priv-app/
+    #             <app>/oat/arm64/
+    #                 <app>.odex
+    #                 <app>.vdex
+    #             ...
+
+    # TODO(b/188179859): Support for other architectures.
+    arch = 'arm64'
+
+    dex_destination = os.path.join(temp_dir, 'output', dex_img, apk_dir, app, 'oat', arch)
+    os.makedirs(dex_destination)
+    dex2oat_path = os.path.join(
+        temp_dir, 'out', 'dex2oat_result', 'vendor', apk_dir, app, 'oat', arch)
+    shutil.copy(os.path.join(dex2oat_path, 'package.vdex'),
+                os.path.join(dex_destination, app + '.vdex'))
+    shutil.copy(os.path.join(dex2oat_path, 'package.odex'),
+                os.path.join(dex_destination, app + '.odex'))
+
+    # Append entries to vendor_file_system_config.txt, such as:
+    #
+    # vendor/app/<app>/oat 0 2000 755 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+    # vendor/app/<app>/oat/arm64 0 2000 755 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+    # vendor/app/<app>/oat/arm64/<app>.odex 0 0 644 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+    # vendor/app/<app>/oat/arm64/<app>.vdex 0 0 644 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+    if not use_system_other_odex:
+      vendor_app_prefix = 'vendor/' + apk_dir + '/' + app + '/oat'
+      selabel = 'selabel=u:object_r:vendor_app_file:s0 capabilities=0x0'
+      vendor_file_system_config.writelines([
+          vendor_app_prefix + ' 0 2000 755 ' + selabel + '\n',
+          vendor_app_prefix + '/' + arch + ' 0 2000 755 ' + selabel + '\n',
+          vendor_app_prefix + '/' + arch + '/' + app + '.odex 0 0 644 ' + selabel + '\n',
+          vendor_app_prefix + '/' + arch + '/' + app + '.vdex 0 0 644 ' + selabel + '\n',
+      ])
+
+  if not use_system_other_odex:
+    vendor_file_system_config.close()
+    # Delete vendor.img so that it will be regenerated.
+    # TODO(b/188179859): Rebuilding a vendor image in GRF mode (e.g., T(framework)
+    #                    and S(vendor) may require logic similar to that in
+    #                    rebuild_image_with_sepolicy.
+    vendor_img = os.path.join(output_target_files_temp_dir, 'IMAGES', 'vendor.img')
+    if os.path.exists(vendor_img):
+      logging.info('Deleting %s', vendor_img)
+      os.remove(vendor_img)
+
 
 def create_merged_package(temp_dir, framework_target_files, framework_item_list,
                           vendor_target_files, vendor_item_list,
-                          framework_misc_info_keys, rebuild_recovery):
+                          framework_misc_info_keys, rebuild_recovery,
+                          framework_dexpreopt_tools, framework_dexpreopt_config,
+                          vendor_dexpreopt_config):
   """Merges two target files packages into one target files structure.
 
   Args:
@@ -908,6 +1236,12 @@
     rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
       devices and write it to the system image.
 
+    The following are only used if dexpreopt is applied:
+
+    framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+    framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+    vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
+
   Returns:
     Path to merged package under temp directory.
   """
@@ -928,23 +1262,27 @@
   # Perform special case processing on META/* items.
   # After this function completes successfully, all the files we need to create
   # the output target files package are in place.
-  framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
-  vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
+  framework_meta = os.path.join(temp_dir, 'framework_meta')
+  vendor_meta = os.path.join(temp_dir, 'vendor_meta')
   extract_items(
       target_files=framework_target_files,
-      target_files_temp_dir=framework_target_files_temp_dir,
+      target_files_temp_dir=framework_meta,
       extract_item_list=('META/*',))
   extract_items(
       target_files=vendor_target_files,
-      target_files_temp_dir=vendor_target_files_temp_dir,
+      target_files_temp_dir=vendor_meta,
       extract_item_list=('META/*',))
   process_special_cases(
-      framework_target_files_temp_dir=framework_target_files_temp_dir,
-      vendor_target_files_temp_dir=vendor_target_files_temp_dir,
+      temp_dir=temp_dir,
+      framework_meta=framework_meta,
+      vendor_meta=vendor_meta,
       output_target_files_temp_dir=output_target_files_temp_dir,
       framework_misc_info_keys=framework_misc_info_keys,
       framework_partition_set=item_list_to_partition_set(framework_item_list),
-      vendor_partition_set=item_list_to_partition_set(vendor_item_list))
+      vendor_partition_set=item_list_to_partition_set(vendor_item_list),
+      framework_dexpreopt_tools=framework_dexpreopt_tools,
+      framework_dexpreopt_config=framework_dexpreopt_config,
+      vendor_dexpreopt_config=vendor_dexpreopt_config)
 
   return output_target_files_temp_dir
 
@@ -1156,7 +1494,8 @@
                        vendor_item_list, output_target_files, output_dir,
                        output_item_list, output_ota, output_img,
                        output_super_empty, rebuild_recovery, vendor_otatools,
-                       rebuild_sepolicy):
+                       rebuild_sepolicy, framework_dexpreopt_tools,
+                       framework_dexpreopt_config, vendor_dexpreopt_config):
   """Merges two target files packages together.
 
   This function takes framework and vendor target files packages as input,
@@ -1195,6 +1534,12 @@
     vendor_otatools: Path to an otatools zip used for recompiling vendor images.
     rebuild_sepolicy: If true, rebuild odm.img (if target uses ODM) or
       vendor.img using a merged precompiled_sepolicy file.
+
+    The following are only used if dexpreopt is applied:
+
+    framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+    framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+    vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
   """
 
   logger.info('starting: merge framework %s and vendor %s into output %s',
@@ -1203,7 +1548,8 @@
   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)
+      rebuild_recovery, framework_dexpreopt_tools, framework_dexpreopt_config,
+      vendor_dexpreopt_config)
 
   if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
     raise RuntimeError('Incompatible VINTF metadata')
@@ -1377,6 +1723,12 @@
       OPTIONS.rebuild_sepolicy = True
     elif o == '--keep-tmp':
       OPTIONS.keep_tmp = True
+    elif o == '--framework-dexpreopt-config':
+      OPTIONS.framework_dexpreopt_config = a
+    elif o == '--framework-dexpreopt-tools':
+      OPTIONS.framework_dexpreopt_tools = a
+    elif o == '--vendor-dexpreopt-config':
+      OPTIONS.vendor_dexpreopt_config = a
     else:
       return False
     return True
@@ -1401,6 +1753,9 @@
           'output-ota=',
           'output-img=',
           'output-super-empty=',
+          'framework-dexpreopt-config=',
+          'framework-dexpreopt-tools=',
+          'vendor-dexpreopt-config=',
           'rebuild_recovery',
           'allow-duplicate-apkapex-keys',
           'vendor-otatools=',
@@ -1460,7 +1815,10 @@
           output_super_empty=OPTIONS.output_super_empty,
           rebuild_recovery=OPTIONS.rebuild_recovery,
           vendor_otatools=OPTIONS.vendor_otatools,
-          rebuild_sepolicy=OPTIONS.rebuild_sepolicy), OPTIONS.keep_tmp)
+          rebuild_sepolicy=OPTIONS.rebuild_sepolicy,
+          framework_dexpreopt_tools=OPTIONS.framework_dexpreopt_tools,
+          framework_dexpreopt_config=OPTIONS.framework_dexpreopt_config,
+          vendor_dexpreopt_config=OPTIONS.vendor_dexpreopt_config), OPTIONS.keep_tmp)
 
 
 if __name__ == '__main__':
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 8face66..bcc10bd 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -286,6 +286,7 @@
 OPTIONS.disable_vabc = False
 OPTIONS.spl_downgrade = False
 OPTIONS.vabc_downgrade = False
+OPTIONS.enable_vabc_xor = False
 
 POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
 DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt'
@@ -1132,6 +1133,8 @@
 
   if OPTIONS.disable_vabc:
     additional_args += ["--disable_vabc", "true"]
+  if OPTIONS.enable_vabc_xor:
+    additional_args += ["--enable_vabc_xor", "true"]
   additional_args += ["--max_timestamp", max_timestamp]
 
   if SupportsMainlineGkiUpdates(source_file):
@@ -1305,6 +1308,8 @@
       OPTIONS.wipe_user_data = True
     elif o == "--vabc_downgrade":
       OPTIONS.vabc_downgrade = True
+    elif o == "--enable_vabc_xor":
+      OPTIONS.enable_vabc_xor = True
     else:
       return False
     return True
@@ -1349,6 +1354,7 @@
                                  "disable_vabc",
                                  "spl_downgrade",
                                  "vabc_downgrade",
+                                 "enable_vabc_xor",
                              ], extra_option_handler=option_handler)
 
   if len(args) != 2:
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index cfe3139..622e57f 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -251,6 +251,9 @@
 
 def ValidatePartitionFingerprints(input_tmp, info_dict):
   build_info = common.BuildInfo(info_dict)
+  if not build_info.avb_enabled:
+    logging.info("AVB not enabled, skipping partition fingerprint checks")
+    return
   # Expected format:
   #  Prop: com.android.build.vendor.fingerprint -> 'generic/aosp_cf_x86_64_phone/vsoc_x86_64:S/AOSP.MASTER/7335886:userdebug/test-keys'
   #  Prop: com.android.build.vendor_boot.fingerprint -> 'generic/aosp_cf_x86_64_phone/vsoc_x86_64:S/AOSP.MASTER/7335886:userdebug/test-keys'
@@ -258,6 +261,13 @@
       r"Prop: com.android.build.(?P<partition>\w+).fingerprint -> '(?P<fingerprint>[\w\/:\.-]+)'")
   for vbmeta_partition in ["vbmeta", "vbmeta_system"]:
     image = os.path.join(input_tmp, "IMAGES", vbmeta_partition + ".img")
+    if not os.path.exists(image):
+      assert vbmeta_partition != "vbmeta",\
+          "{} is a required partition for AVB.".format(
+              vbmeta_partition)
+      logging.info("vb partition %s not present, skipping", vbmeta_partition)
+      continue
+
     output = common.RunAndCheckOutput(
         [info_dict["avb_avbtool"], "info_image", "--image", image])
     matches = p.findall(output)