Merge "Remove deprecated BOARD_BUILD_SYSTEM_ROOT_IMAGE"
diff --git a/core/Makefile b/core/Makefile
index 5afdfa7..f18dcd4 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4552,6 +4552,26 @@
 intermediates := $(call intermediates-dir-for,PACKAGING,check_vintf_all)
 check_vintf_all_deps :=
 
+APEX_OUT := $(PRODUCT_OUT)/apex
+# -----------------------------------------------------------------
+# Create apex-info-file.xsd
+
+APEX_DIRS := \
+  $(TARGET_OUT)/apex/% \
+  $(TARGET_OUT_SYSTEM_EXT)/apex/% \
+  $(TARGET_OUT_VENDOR)/apex/% \
+  $(TARGET_OUT_ODM)/apex/% \
+  $(TARGET_OUT_PRODUCT)/apex/% \
+
+apex_vintf_files := $(sort $(filter $(APEX_DIRS), $(INTERNAL_ALLIMAGES_FILES)))
+APEX_INFO_FILE   := $(APEX_OUT)/apex-info-list.xml
+
+$(APEX_INFO_FILE): $(HOST_OUT_EXECUTABLES)/dump_apex_info $(apex_vintf_files)
+	@echo "Creating apex-info-file in $(PRODUCT_OUT) "
+	$< --root_dir $(PRODUCT_OUT) --out_file $@
+
+apex_vintf_files :=
+
 # The build system only writes VINTF metadata to */etc/vintf paths. Legacy paths aren't needed here
 # because they are only used for prebuilt images.
 check_vintf_common_srcs_patterns := \
@@ -4562,6 +4582,7 @@
   $(TARGET_OUT_SYSTEM_EXT)/etc/vintf/% \
 
 check_vintf_common_srcs := $(sort $(filter $(check_vintf_common_srcs_patterns),$(INTERNAL_ALLIMAGES_FILES)))
+check_vintf_common_srcs += $(APEX_INFO_FILE)
 check_vintf_common_srcs_patterns :=
 
 check_vintf_has_system :=
@@ -4741,10 +4762,12 @@
   --dirmap /odm:$(TARGET_OUT_ODM) \
   --dirmap /product:$(TARGET_OUT_PRODUCT) \
   --dirmap /system_ext:$(TARGET_OUT_SYSTEM_EXT) \
+  --dirmap /apex:$(APEX_OUT) \
 
 ifdef PRODUCT_SHIPPING_API_LEVEL
 check_vintf_compatible_args += --property ro.product.first_api_level=$(PRODUCT_SHIPPING_API_LEVEL)
 endif # PRODUCT_SHIPPING_API_LEVEL
+check_vintf_compatible_args += --apex-info-file $(APEX_INFO_FILE)
 
 $(check_vintf_compatible_log): PRIVATE_CHECK_VINTF_ARGS := $(check_vintf_compatible_args)
 $(check_vintf_compatible_log): PRIVATE_CHECK_VINTF_DEPS := $(check_vintf_compatible_deps)
@@ -4989,6 +5012,7 @@
   apex_compression_tool \
   deapexer \
   debugfs_static \
+  dump_apex_info \
   merge_zips \
   resize2fs \
   soong_zip \
@@ -6912,10 +6936,15 @@
 $(call dist-for-goals,haiku,$(SOONG_FUZZ_PACKAGING_ARCH_MODULES))
 $(call dist-for-goals,haiku,$(PRODUCT_OUT)/module-info.json)
 
-.PHONY: haiku-java
-haiku-java: $(SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_JAVA_FUZZ_TARGETS)
-$(call dist-for-goals,haiku-java,$(SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES))
-$(call dist-for-goals,haiku-java,$(PRODUCT_OUT)/module-info.json)
+.PHONY: haiku-java-device
+haiku-java-device: $(SOONG_JAVA_FUZZ_DEVICE_PACKAGING_ARCH_MODULES) $(ALL_JAVA_FUZZ_DEVICE_TARGETS)
+$(call dist-for-goals,haiku-java-device,$(SOONG_JAVA_FUZZ_DEVICE_PACKAGING_ARCH_MODULES))
+$(call dist-for-goals,haiku-java-device,$(PRODUCT_OUT)/module-info.json)
+
+.PHONY: haiku-java-host
+haiku-java-host: $(SOONG_JAVA_FUZZ_HOST_PACKAGING_ARCH_MODULES) $(ALL_JAVA_FUZZ_HOST_TARGETS)
+$(call dist-for-goals,haiku-java-host,$(SOONG_JAVA_FUZZ_HOST_PACKAGING_ARCH_MODULES))
+$(call dist-for-goals,haiku-java-host,$(PRODUCT_OUT)/module-info.json)
 
 .PHONY: haiku-rust
 haiku-rust: $(SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_RUST_FUZZ_TARGETS)
diff --git a/core/definitions.mk b/core/definitions.mk
index 0385315..98fdd6c 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -641,6 +641,7 @@
 $(2): PRIVATE_IS_CONTAINER := $(ALL_MODULES.$(1).IS_CONTAINER)
 $(2): PRIVATE_PACKAGE_NAME := $(strip $(ALL_MODULES.$(1).LICENSE_PACKAGE_NAME))
 $(2): PRIVATE_INSTALL_MAP := $(_map)
+$(2): PRIVATE_MODULE_NAME := $(1)
 $(2): PRIVATE_MODULE_TYPE := $(ALL_MODULES.$(1).MODULE_TYPE)
 $(2): PRIVATE_MODULE_CLASS := $(ALL_MODULES.$(1).MODULE_CLASS)
 $(2): PRIVATE_INSTALL_MAP := $(_map)
@@ -651,6 +652,7 @@
 	mkdir -p $$(dir $$@)
 	mkdir -p $$(dir $$(PRIVATE_ARGUMENT_FILE))
 	$$(call dump-words-to-file,\
+	    $$(addprefix -mn ,$$(PRIVATE_MODULE_NAME))\
 	    $$(addprefix -mt ,$$(PRIVATE_MODULE_TYPE))\
 	    $$(addprefix -mc ,$$(PRIVATE_MODULE_CLASS))\
 	    $$(addprefix -k ,$$(PRIVATE_KINDS))\
diff --git a/core/product_config.mk b/core/product_config.mk
index 198dde4..e03ae2b 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -473,6 +473,9 @@
   ifneq (,$(call math_gt_or_eq,29,$(PRODUCT_SHIPPING_API_LEVEL)))
     PRODUCT_PACKAGES += $(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_29)
   endif
+  ifneq (,$(call math_gt_or_eq,33,$(PRODUCT_SHIPPING_API_LEVEL)))
+    PRODUCT_PACKAGES += $(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_33)
+  endif
 endif
 
 # If build command defines OVERRIDE_PRODUCT_EXTRA_VNDK_VERSIONS,
diff --git a/core/proguard_basic_keeps.flags b/core/proguard_basic_keeps.flags
index f9d2d30..7e7b270 100644
--- a/core/proguard_basic_keeps.flags
+++ b/core/proguard_basic_keeps.flags
@@ -2,6 +2,9 @@
 # that isn't explicitly part of the API
 -dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers
 
+# Preserve line number information for debugging stack traces.
+-keepattributes SourceFile,LineNumberTable
+
 # Annotations are implemented as attributes, so we have to explicitly keep them.
 # Keep all runtime-visible annotations like RuntimeVisibleParameterAnnotations
 # and RuntimeVisibleTypeAnnotations, as well as associated defaults.
diff --git a/core/robolectric_test_config_template.xml b/core/robolectric_test_config_template.xml
index 8c03582..56d2312 100644
--- a/core/robolectric_test_config_template.xml
+++ b/core/robolectric_test_config_template.xml
@@ -26,5 +26,12 @@
 
     <test class="com.android.tradefed.testtype.IsolatedHostTest" >
         <option name="jar" value="{MODULE}.jar" />
+        <option name="java-flags" value="--add-modules=jdk.compiler"/>
+        <option name="java-flags" value="--add-opens=java.base/java.lang=ALL-UNNAMED"/>
+        <option name="java-flags" value="--add-opens=java.base/java.lang.reflect=ALL-UNNAMED"/>
+        <!-- b/238100560 -->
+        <option name="java-flags" value="--add-opens=java.base/jdk.internal.util.random=ALL-UNNAMED"/>
+        <!-- b/251387255 -->
+        <option name="java-flags" value="--add-opens=java.base/java.io=ALL-UNNAMED"/>
     </test>
 </configuration>
diff --git a/envsetup.sh b/envsetup.sh
index eee7dbc..bc206c4 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -427,7 +427,7 @@
     # message, instead of FileNotFound.
     local T=$(multitree_gettop)
     if [ -n "$T" ]; then
-      "$T/orchestrator/build/orchestrator/core/orchestrator.py" "$@"
+      "$T/orchestrator/build/orchestrator/core/lunch.py" "$@"
     else
       _multitree_lunch_error
       return 1
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 01897b7..ffc37a9 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -43,6 +43,9 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
 
+# pKVM
+$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
+
 #
 # All components inherited here go to product image
 #
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index b3cfae4..d55866f 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -45,6 +45,9 @@
 $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system_ext.mk)
 $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
 
+# pKVM
+$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
+
 #
 # All components inherited here go to product image
 #
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 8d257bf..7fb785c 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -74,8 +74,9 @@
     shell_and_utilities_vendor \
 
 # OMX not supported for 64bit_only builds
+# Only supported when SHIPPING_API_LEVEL is less than or equal to 33
 ifneq ($(TARGET_SUPPORTS_OMX_SERVICE),false)
-    PRODUCT_PACKAGES += \
+    PRODUCT_PACKAGES_SHIPPING_API_LEVEL_33 += \
         android.hardware.media.omx@1.0-service \
 
 endif
diff --git a/tools/java-event-log-tags.py b/tools/java-event-log-tags.py
index 4bd6d2b..bbd65fa 100755
--- a/tools/java-event-log-tags.py
+++ b/tools/java-event-log-tags.py
@@ -100,7 +100,8 @@
              " * Source file: %s\n"
              " */\n\n" % (fn,))
 
-buffer.write("package %s;\n\n" % (tagfile.options["java_package"][0],))
+# .rstrip(";") to avoid an empty top-level statement errorprone error
+buffer.write("package %s;\n\n" % (tagfile.options["java_package"][0].rstrip(";"),))
 
 basename, _ = os.path.splitext(os.path.basename(fn))
 
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 4fdc707..aefce81 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -99,6 +99,8 @@
     ],
     required: [
         "checkvintf",
+        "deapexer",
+        "dump_apex_info",
     ],
 }
 
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index 63a6cf7..fa2eaeb 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -22,6 +22,7 @@
 target_files can be a ZIP file or an extracted target files directory.
 """
 
+import json
 import logging
 import subprocess
 import sys
@@ -123,7 +124,12 @@
     logger.warning('PRODUCT_ENFORCE_VINTF_MANIFEST is not set, skipping checks')
     return True
 
+
   dirmap = GetDirmap(input_tmp)
+
+  apex_root, apex_info_file = PrepareApexDirectory(input_tmp)
+  dirmap['/apex'] = apex_root
+
   args_for_skus = GetArgsForSkus(info_dict)
   shipping_api_level_args = GetArgsForShippingApiLevel(info_dict)
   kernel_args = GetArgsForKernel(input_tmp)
@@ -132,6 +138,8 @@
       'checkvintf',
       '--check-compat',
   ]
+  common_command += ['--apex-info-file', apex_info_file]
+
   for device_path, real_path in sorted(dirmap.items()):
     common_command += ['--dirmap', '{}:{}'.format(device_path, real_path)]
   common_command += kernel_args
@@ -186,6 +194,102 @@
   paths = sum((PathToPatterns(path) for path in paths if path), [])
   return paths
 
+def GetVintfApexUnzipPatterns():
+  """ Build unzip pattern for APEXes. """
+  patterns = []
+  for target_files_rel_paths in DIR_SEARCH_PATHS.values():
+    for target_files_rel_path in target_files_rel_paths:
+      patterns.append(os.path.join(target_files_rel_path,"apex/*"))
+
+  return patterns
+
+def PrepareApexDirectory(inp):
+  """ Prepare the APEX data.
+
+  Apex binaries do not support dirmaps, in order to use these binaries we
+  need to move the APEXes from the extracted target file archives to the
+  expected device locations.
+
+  The APEXes will also be extracted under the APEX/ directory
+  matching what would be on the target.
+
+  Create the following structure under the input inp directory:
+       APEX/apex             # Extracted APEXes
+       APEX/system/apex/     # System APEXes
+       APEX/vendor/apex/     # Vendor APEXes
+       ...
+
+  Args:
+    inp: path to the directory that contains the extracted target files archive.
+
+  Returns:
+    extracted apex directory
+    apex-info-list.xml file
+  """
+
+  def ExtractApexes(path, outp):
+    # Extract all APEXes found in input path.
+    debugfs_path = 'debugfs'
+    deapexer = 'deapexer'
+    if OPTIONS.search_path:
+      debugfs_path = os.path.join(OPTIONS.search_path, 'bin', 'debugfs_static')
+      deapexer_path = os.path.join(OPTIONS.search_path, 'bin', 'deapexer')
+      if os.path.isfile(deapexer_path):
+        deapexer = deapexer_path
+
+    logger.info('Extracting APEXs in %s', path)
+    for f in os.listdir(path):
+      logger.info('  adding APEX %s', os.path.basename(f))
+      apex = os.path.join(path, f)
+      if os.path.isdir(apex):
+        # TODO(b/242314000) Handle "flattened" apex
+        pass
+      else:
+        cmd = [deapexer,
+               '--debugfs_path', debugfs_path,
+               'info',
+               apex]
+        info = json.loads(common.RunAndCheckOutput(cmd))
+
+        cmd = [deapexer,
+               '--debugfs_path', debugfs_path,
+               'extract',
+               apex,
+               os.path.join(outp, info['name'])]
+        common.RunAndCheckOutput(cmd)
+
+  root_dir_name = 'APEX'
+  root_dir = os.path.join(inp, root_dir_name)
+  extracted_root = os.path.join(root_dir, 'apex')
+  apex_info_file = os.path.join(extracted_root, 'apex-info-list.xml')
+
+  # Always create APEX directory for dirmap
+  os.makedirs(extracted_root)
+
+  create_info_file = False
+
+  # Loop through search path looking for and processing apex/ directories.
+  for device_path, target_files_rel_paths in DIR_SEARCH_PATHS.items():
+    for target_files_rel_path in target_files_rel_paths:
+      inp_partition = os.path.join(inp, target_files_rel_path,"apex")
+      if os.path.exists(inp_partition):
+        apex_dir = root_dir + os.path.join(device_path + "/apex");
+        os.makedirs(apex_dir)
+        os.rename(inp_partition, apex_dir)
+        ExtractApexes(apex_dir, extracted_root)
+        create_info_file = True
+
+  if create_info_file:
+    ### Create apex-info-list.xml
+    dump_cmd = ['dump_apex_info',
+                '--root_dir', root_dir,
+                '--out_file', apex_info_file]
+    common.RunAndCheckOutput(dump_cmd)
+    if not os.path.exists(apex_info_file):
+      raise RuntimeError('Failed to create apex info file %s', apex_info_file)
+    logger.info('Created %s', apex_info_file)
+
+  return extracted_root, apex_info_file
 
 def CheckVintfFromTargetFiles(inp, info_dict=None):
   """
@@ -199,7 +303,7 @@
     True if VINTF check is skipped or compatible, False if incompatible. Raise
     a RuntimeError if any error occurs.
   """
-  input_tmp = common.UnzipTemp(inp, GetVintfFileList() + UNZIP_PATTERN)
+  input_tmp = common.UnzipTemp(inp, GetVintfFileList() + GetVintfApexUnzipPatterns() + UNZIP_PATTERN)
   return CheckVintfFromExtractedTargetFiles(input_tmp, info_dict)
 
 
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index bbdff6e..e7fd204 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -2868,30 +2868,32 @@
 def ZipDelete(zip_filename, entries, force=False):
   """Deletes entries from a ZIP file.
 
-  Since deleting entries from a ZIP file is not supported, it shells out to
-  'zip -d'.
-
   Args:
     zip_filename: The name of the ZIP file.
     entries: The name of the entry, or the list of names to be deleted.
-
-  Raises:
-    AssertionError: In case of non-zero return from 'zip'.
   """
   if isinstance(entries, str):
     entries = [entries]
   # If list is empty, nothing to do
   if not entries:
     return
-  if force:
-    cmd = ["zip", "-q", "-d", zip_filename] + entries
-  else:
-    cmd = ["zip", "-d", zip_filename] + entries
-  if force:
-    p = Run(cmd)
-    p.wait()
-  else:
-    RunAndCheckOutput(cmd)
+
+  with zipfile.ZipFile(zip_filename, 'r') as zin:
+    if not force and len(set(zin.namelist()).intersection(entries)) == 0:
+      raise ExternalError(
+          "Failed to delete zip entries, name not matched: %s" % entries)
+
+    fd, new_zipfile = tempfile.mkstemp(dir=os.path.dirname(zip_filename))
+    os.close(fd)
+
+    with zipfile.ZipFile(new_zipfile, 'w') as zout:
+      for item in zin.infolist():
+        if item.filename in entries:
+          continue
+        buffer = zin.read(item.filename)
+        zout.writestr(item, buffer)
+
+  os.replace(new_zipfile, zip_filename)
 
 
 def ZipClose(zip_file):
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 06349a2..9f41874 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -84,17 +84,14 @@
 
   def ComputeAllPropertyFiles(input_file, needed_property_files):
     # Write the current metadata entry with placeholders.
-    with zipfile.ZipFile(input_file, allowZip64=True) as input_zip:
+    with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
       for property_files in needed_property_files:
         metadata.property_files[property_files.name] = property_files.Compute(
             input_zip)
-      namelist = input_zip.namelist()
 
-    if METADATA_NAME in namelist or METADATA_PROTO_NAME in namelist:
-      ZipDelete(input_file, [METADATA_NAME, METADATA_PROTO_NAME])
-    output_zip = zipfile.ZipFile(input_file, 'a', allowZip64=True)
-    WriteMetadata(metadata, output_zip)
-    ZipClose(output_zip)
+    ZipDelete(input_file, [METADATA_NAME, METADATA_PROTO_NAME], True)
+    with zipfile.ZipFile(input_file, 'a', allowZip64=True) as output_zip:
+      WriteMetadata(metadata, output_zip)
 
     if no_signing:
       return input_file
@@ -104,7 +101,7 @@
     return prelim_signing
 
   def FinalizeAllPropertyFiles(prelim_signing, needed_property_files):
-    with zipfile.ZipFile(prelim_signing, allowZip64=True) as prelim_signing_zip:
+    with zipfile.ZipFile(prelim_signing, 'r', allowZip64=True) as prelim_signing_zip:
       for property_files in needed_property_files:
         metadata.property_files[property_files.name] = property_files.Finalize(
             prelim_signing_zip,
@@ -130,9 +127,8 @@
 
   # Replace the METADATA entry.
   ZipDelete(prelim_signing, [METADATA_NAME, METADATA_PROTO_NAME])
-  output_zip = zipfile.ZipFile(prelim_signing, 'a', allowZip64=True)
-  WriteMetadata(metadata, output_zip)
-  ZipClose(output_zip)
+  with zipfile.ZipFile(prelim_signing, 'a', allowZip64=True) as output_zip:
+    WriteMetadata(metadata, output_zip)
 
   # Re-sign the package after updating the metadata entry.
   if no_signing:
@@ -591,7 +587,7 @@
     else:
       tokens.append(ComputeEntryOffsetSize(METADATA_NAME))
       if METADATA_PROTO_NAME in zip_file.namelist():
-          tokens.append(ComputeEntryOffsetSize(METADATA_PROTO_NAME))
+        tokens.append(ComputeEntryOffsetSize(METADATA_PROTO_NAME))
 
     return ','.join(tokens)