Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9276cf02 authored by Yifan Hong's avatar Yifan Hong
Browse files

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
parent ccb86fe7
Loading
Loading
Loading
Loading
+0 −14
Original line number Diff line number Diff line
@@ -4011,10 +4011,6 @@ $(BUILT_TARGET_FILES_PACKAGE): \
	    $(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 @@ ifdef BUILDING_SYSTEM_OTHER_IMAGE
	$(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
+1 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ python_defaults {
        "target_files_diff.py",
    ],
    libs: [
        "releasetools_check_target_files_vintf",
        "releasetools_common",
        "releasetools_verity_utils",
    ],
+0 −4
Original line number Diff line number Diff line
@@ -117,8 +117,6 @@ DEFAULT_FRAMEWORK_ITEM_LIST = (
    '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 @@ DEFAULT_VENDOR_ITEM_LIST = (
    'META/otakeys.txt',
    'META/releasetools.py',
    'META/vendor_filesystem_config.txt',
    'META/vendor_manifest.xml',
    'META/vendor_matrix.xml',
    'BOOT/*',
    'DATA/*',
    'ODM/*',
+23 −101
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ Common options that apply to both of non-A/B and A/B OTAs
      --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 shlex
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 @@ def HasPartition(target_files_zip, partition):
    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 @@ def WriteFingerprintAssertion(script, target_info, source_info):
        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 @@ def AddCompatibilityArchiveIfTrebleEnabled(target_zip, output_zip, target_info,
  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 @@ else if get_stage("%(bcb_dev)s") == "3/3" then
                             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 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
                                        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 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
    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)