Check VINTF compatibility at OTA generation time.

Instead of relying on META/{system,vendor}_{manifest,matrix}.xml
and blindly copy compatibility.zip from target files package to
OTA package, do a static check on the input target files package
before generating the OTA package.

META/{system,vendor}_{manifest,matrix} does not contain ODM manifest
fragments, which is incorrect.

Also, the on-device check of compatibility.zip uses a old libvintf
binary on the device, which may not understand the incoming VINTF
metadata. This change removes the on-device check. Hence, it removes
the requirement of forwards compatibility of libvintf.

This behavior can be skipped with --skip-compatibility-check.

Test: build OTA package
Bug: 139300422
Bug: 131425279
Change-Id: I7fb93be9eb73f578fc05a182c6c9d1f073db2800
diff --git a/core/Makefile b/core/Makefile
index 6f6eee2..f56df1f 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4011,10 +4011,6 @@
 	    $(HOST_OUT_EXECUTABLES)/fs_config \
 	    $(ADD_IMG_TO_TARGET_FILES) \
 	    $(MAKE_RECOVERY_PATCH) \
-	    $(BUILT_ASSEMBLED_FRAMEWORK_MANIFEST) \
-	    $(BUILT_ASSEMBLED_VENDOR_MANIFEST) \
-	    $(BUILT_SYSTEM_MATRIX) \
-	    $(BUILT_VENDOR_MATRIX) \
 	    $(BUILT_KERNEL_CONFIGS_FILE) \
 	    $(BUILT_KERNEL_VERSION_FILE) \
 	    | $(ACP)
@@ -4255,16 +4251,6 @@
 	$(hide) $(call fs_config,$(zip_root)/SYSTEM_OTHER,system/) > $(zip_root)/META/system_other_filesystem_config.txt
 endif
 	@# Metadata for compatibility verification.
-	$(hide) cp $(BUILT_SYSTEM_MATRIX) $(zip_root)/META/system_matrix.xml
-ifdef BUILT_ASSEMBLED_FRAMEWORK_MANIFEST
-	$(hide) cp $(BUILT_ASSEMBLED_FRAMEWORK_MANIFEST) $(zip_root)/META/system_manifest.xml
-endif
-ifdef BUILT_ASSEMBLED_VENDOR_MANIFEST
-	$(hide) cp $(BUILT_ASSEMBLED_VENDOR_MANIFEST) $(zip_root)/META/vendor_manifest.xml
-endif
-ifdef BUILT_VENDOR_MATRIX
-	$(hide) cp $(BUILT_VENDOR_MATRIX) $(zip_root)/META/vendor_matrix.xml
-endif
 ifdef BUILT_KERNEL_CONFIGS_FILE
 	$(hide) cp $(BUILT_KERNEL_CONFIGS_FILE) $(zip_root)/META/kernel_configs.txt
 endif
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index ef76c52..a920ffb 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -96,6 +96,7 @@
         "target_files_diff.py",
     ],
     libs: [
+        "releasetools_check_target_files_vintf",
         "releasetools_common",
         "releasetools_verity_utils",
     ],
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index b7ed645..916c803 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -117,8 +117,6 @@
     'META/apkcerts.txt',
     'META/filesystem_config.txt',
     'META/root_filesystem_config.txt',
-    'META/system_manifest.xml',
-    'META/system_matrix.xml',
     'META/update_engine_config.txt',
     'PRODUCT/*',
     'ROOT/*',
@@ -163,8 +161,6 @@
     'META/otakeys.txt',
     'META/releasetools.py',
     'META/vendor_filesystem_config.txt',
-    'META/vendor_manifest.xml',
-    'META/vendor_matrix.xml',
     'BOOT/*',
     'DATA/*',
     'ODM/*',
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index c6c859c..60b73e7 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -72,7 +72,7 @@
       --skip_postinstall is implied.
 
   --skip_compatibility_check
-      Skip adding the compatibility package to the generated OTA package.
+      Skip checking compatibility of the input target files package.
 
   --output_metadata_path
       Write a copy of the metadata to a separate file. Therefore, users can
@@ -189,9 +189,9 @@
 import shutil
 import struct
 import sys
-import tempfile
 import zipfile
 
+import check_target_files_vintf
 import common
 import edify_generator
 import verity_utils
@@ -723,20 +723,15 @@
     return False
 
 
-def HasVendorPartition(target_files_zip):
-  return HasPartition(target_files_zip, "vendor")
+def HasTrebleEnabled(target_files, target_info):
+  def HasVendorPartition(target_files):
+    if os.path.isdir(target_files):
+      return os.path.isdir(os.path.join(target_files, "VENDOR"))
+    if zipfile.is_zipfile(target_files):
+      return HasPartition(zipfile.ZipFile(target_files), "vendor")
+    raise ValueError("Unknown target_files argument")
 
-
-def HasProductPartition(target_files_zip):
-  return HasPartition(target_files_zip, "product")
-
-
-def HasOdmPartition(target_files_zip):
-  return HasPartition(target_files_zip, "odm")
-
-
-def HasTrebleEnabled(target_files_zip, target_info):
-  return (HasVendorPartition(target_files_zip) and
+  return (HasVendorPartition(target_files) and
           target_info.GetBuildProp("ro.treble.enabled") == "true")
 
 
@@ -761,74 +756,23 @@
         source_info.GetBuildProp("ro.build.thumbprint"))
 
 
-def AddCompatibilityArchiveIfTrebleEnabled(target_zip, output_zip, target_info,
-                                           source_info=None):
-  """Adds compatibility info into the output zip if it's Treble-enabled target.
+def CheckVintfIfTrebleEnabled(target_files, target_info):
+  """Checks compatibility info of the input target files.
 
-  Metadata used for on-device compatibility verification is retrieved from
-  target_zip then added to compatibility.zip which is added to the output_zip
-  archive.
+  Metadata used for compatibility verification is retrieved from target_zip.
 
-  Compatibility archive should only be included for devices that have enabled
+  Compatibility should only be checked for devices that have enabled
   Treble support.
 
   Args:
-    target_zip: Zip file containing the source files to be included for OTA.
-    output_zip: Zip file that will be sent for OTA.
+    target_files: Path to zip file containing the source files to be included
+        for OTA. Can also be the path to extracted directory.
     target_info: The BuildInfo instance that holds the target build info.
-    source_info: The BuildInfo instance that holds the source build info, if
-        generating an incremental OTA; None otherwise.
   """
 
-  def AddCompatibilityArchive(framework_updated, device_updated):
-    """Adds compatibility info based on update status of both sides of Treble
-    boundary.
-
-    Args:
-      framework_updated: If True, the system / product image will be updated
-          and therefore their metadata should be included.
-      device_updated: If True, the vendor / odm image will be updated and
-          therefore their metadata should be included.
-    """
-    # Determine what metadata we need. Files are names relative to META/.
-    compatibility_files = []
-    device_metadata = ("vendor_manifest.xml", "vendor_matrix.xml")
-    framework_metadata = ("system_manifest.xml", "system_matrix.xml")
-    if device_updated:
-      compatibility_files += device_metadata
-    if framework_updated:
-      compatibility_files += framework_metadata
-
-    # Create new archive.
-    compatibility_archive = tempfile.NamedTemporaryFile()
-    compatibility_archive_zip = zipfile.ZipFile(
-        compatibility_archive, "w", compression=zipfile.ZIP_DEFLATED)
-
-    # Add metadata.
-    for file_name in compatibility_files:
-      target_file_name = "META/" + file_name
-
-      if target_file_name in target_zip.namelist():
-        data = target_zip.read(target_file_name)
-        common.ZipWriteStr(compatibility_archive_zip, file_name, data)
-
-    # Ensure files are written before we copy into output_zip.
-    compatibility_archive_zip.close()
-
-    # Only add the archive if we have any compatibility info.
-    if compatibility_archive_zip.namelist():
-      common.ZipWrite(output_zip, compatibility_archive.name,
-                      arcname="compatibility.zip",
-                      compress_type=zipfile.ZIP_STORED)
-
-  def FingerprintChanged(source_fp, target_fp):
-    if source_fp is None or target_fp is None:
-      return True
-    return source_fp != target_fp
-
   # Will only proceed if the target has enabled the Treble support (as well as
   # having a /vendor partition).
-  if not HasTrebleEnabled(target_zip, target_info):
+  if not HasTrebleEnabled(target_files, target_info):
     return
 
   # Skip adding the compatibility package as a workaround for b/114240221. The
@@ -836,28 +780,8 @@
   if OPTIONS.skip_compatibility_check:
     return
 
-  # Full OTA carries the info for system/vendor/product/odm
-  if source_info is None:
-    AddCompatibilityArchive(True, True)
-    return
-
-  source_fp = source_info.fingerprint
-  target_fp = target_info.fingerprint
-  system_updated = source_fp != target_fp
-
-  # other build fingerprints could be possibly blacklisted at build time. For
-  # such a case, we consider those images being changed.
-  vendor_updated = FingerprintChanged(source_info.vendor_fingerprint,
-                                      target_info.vendor_fingerprint)
-  product_updated = HasProductPartition(target_zip) and \
-                    FingerprintChanged(source_info.product_fingerprint,
-                                       target_info.product_fingerprint)
-  odm_updated = HasOdmPartition(target_zip) and \
-                FingerprintChanged(source_info.odm_fingerprint,
-                                   target_info.odm_fingerprint)
-
-  AddCompatibilityArchive(system_updated or product_updated,
-                          vendor_updated or odm_updated)
+  if not check_target_files_vintf.CheckVintf(target_files, target_info):
+    raise RuntimeError("VINTF compatibility check failed")
 
 
 def GetBlockDifferences(target_zip, source_zip, target_info, source_info,
@@ -1068,7 +992,7 @@
                              progress=progress_dict.get(block_diff.partition),
                              write_verify_script=OPTIONS.verify)
 
-  AddCompatibilityArchiveIfTrebleEnabled(input_zip, output_zip, target_info)
+  CheckVintfIfTrebleEnabled(OPTIONS.input_tmp, target_info)
 
   boot_img = common.GetBootableImage(
       "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
@@ -1643,8 +1567,7 @@
                                         source_info=source_info,
                                         device_specific=device_specific)
 
-  AddCompatibilityArchiveIfTrebleEnabled(
-      target_zip, output_zip, target_info, source_info)
+  CheckVintfIfTrebleEnabled(OPTIONS.target_tmp, target_info)
 
   # Assertions (e.g. device properties check).
   target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount)
@@ -2079,11 +2002,10 @@
     else:
       logger.warning("Cannot find care map file in target_file package")
 
-  AddCompatibilityArchiveIfTrebleEnabled(
-      target_zip, output_zip, target_info, source_info)
-
   common.ZipClose(target_zip)
 
+  CheckVintfIfTrebleEnabled(target_file, target_info)
+
   # We haven't written the metadata entry yet, which will be handled in
   # FinalizeMetadata().
   common.ZipClose(output_zip)