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

Commit 50a00289 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Performs basic APEX validation in the merged target files package."

parents f3162034 e9af70ad
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ import common
import verity_utils
import ota_metadata_pb2

from apex_utils import GetSystemApexInfoFromTargetFiles
from apex_utils import GetApexInfoFromTargetFiles
from common import AddCareMapForAbOta

if sys.hexversion < 0x02070000:
@@ -686,7 +686,7 @@ def HasPartition(partition_name):
                           "{}.img".format(partition_name))))

def AddApexInfo(output_zip):
  apex_infos = GetSystemApexInfoFromTargetFiles(OPTIONS.input_tmp)
  apex_infos = GetApexInfoFromTargetFiles(OPTIONS.input_tmp, 'system')
  apex_metadata_proto = ota_metadata_pb2.ApexMetadata()
  apex_metadata_proto.apex_info.extend(apex_infos)
  apex_info_bytes = apex_metadata_proto.SerializeToString()
+6 −3
Original line number Diff line number Diff line
@@ -516,7 +516,7 @@ def SignApex(avbtool, apex_data, payload_key, container_key, container_pw,
    raise ApexInfoError(
        'Failed to get type for {}:\n{}'.format(apex_file, e))

def GetSystemApexInfoFromTargetFiles(input_file):
def GetApexInfoFromTargetFiles(input_file, partition, compressed_only=True):
  """
  Get information about system APEX stored in the input_file zip

@@ -532,15 +532,17 @@ def GetSystemApexInfoFromTargetFiles(input_file):
  if not isinstance(input_file, str):
    raise RuntimeError("must pass filepath to target-files zip or directory")

  apex_subdir = os.path.join(partition.upper(), 'apex')
  if os.path.isdir(input_file):
    tmp_dir = input_file
  else:
    tmp_dir = UnzipTemp(input_file, ["SYSTEM/apex/*"])
  target_dir = os.path.join(tmp_dir, "SYSTEM/apex/")
    tmp_dir = UnzipTemp(input_file, [os.path.join(apex_subdir, '*')])
  target_dir = os.path.join(tmp_dir, apex_subdir)

  # Partial target-files packages for vendor-only builds may not contain
  # a system apex directory.
  if not os.path.exists(target_dir):
    logger.info('No APEX directory at path: %s', target_dir)
    return []

  apex_infos = []
@@ -585,6 +587,7 @@ def GetSystemApexInfoFromTargetFiles(input_file):
                         '--output', decompressed_file_path])
      apex_info.decompressed_size = os.path.getsize(decompressed_file_path)

    if not compressed_only or apex_info.is_compressed:
      apex_infos.append(apex_info)

  return apex_infos
+33 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ import zipfile
from xml.etree import ElementTree

import add_img_to_target_files
import apex_utils
import build_image
import build_super_image
import check_target_files_vintf
@@ -739,6 +740,35 @@ def compile_split_sepolicy(product_out, partition_map, output_policy):
  return cmd


def validate_merged_apex_info(output_target_files_dir, partitions):
  """Validates the APEX files in the merged target files directory.

  Checks the APEX files in all possible preinstalled APEX directories.
  Depends on the <partition>/apex/* APEX files within partitions.

  Args:
    output_target_files_dir: Output directory containing merged partition directories.
    partitions: A list of all the partitions in the output directory.

  Raises:
    RuntimeError: if apex_utils fails to parse any APEX file.
    ExternalError: if the same APEX package is provided by multiple partitions.
  """
  apex_packages = set()

  apex_partitions = ('system', 'system_ext', 'product', 'vendor')
  for partition in filter(lambda p: p in apex_partitions, partitions):
    apex_info = apex_utils.GetApexInfoFromTargetFiles(
        output_target_files_dir, partition, compressed_only=False)
    partition_apex_packages = set([info.package_name for info in apex_info])
    duplicates = apex_packages.intersection(partition_apex_packages)
    if duplicates:
      raise ExternalError(
          'Duplicate APEX packages found in multiple partitions: %s' %
          ' '.join(duplicates))
    apex_packages.update(partition_apex_packages)


def generate_care_map(partitions, output_target_files_dir):
  """Generates a merged META/care_map.pb file in the output target files dir.

@@ -1116,6 +1146,9 @@ def merge_target_files(temp_dir, framework_target_files, framework_item_list,
  common.RunAndCheckOutput(split_sepolicy_cmd)
  # TODO(b/178864050): Run tests on the combined.policy file.

  # Run validation checks on the pre-installed APEX files.
  validate_merged_apex_info(output_target_files_temp_dir, partition_map.keys())

  generate_images(output_target_files_temp_dir, rebuild_recovery)

  generate_super_empty_image(output_target_files_temp_dir, output_super_empty)
+35 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#

import os.path
import shutil

import common
import test_utils
@@ -22,7 +23,7 @@ from merge_target_files import (
    validate_config_lists, DEFAULT_FRAMEWORK_ITEM_LIST,
    DEFAULT_VENDOR_ITEM_LIST, DEFAULT_FRAMEWORK_MISC_INFO_KEYS, copy_items,
    item_list_to_partition_set, process_apex_keys_apk_certs_common,
    compile_split_sepolicy)
    compile_split_sepolicy, validate_merged_apex_info)


class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
@@ -274,3 +275,36 @@ class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
                      '{OTP}/vendor/etc/selinux/plat_pub_versioned.cil '
                      '{OTP}/product/etc/selinux/mapping/30.0.cil').format(
                          OTP=product_out_dir))

  def _copy_apex(self, source, output_dir, partition):
    shutil.copy(
        source,
        os.path.join(output_dir, partition, 'apex', os.path.basename(source)))

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_validate_merged_apex_info(self):
    output_dir = common.MakeTempDir()
    os.makedirs(os.path.join(output_dir, 'SYSTEM/apex'))
    os.makedirs(os.path.join(output_dir, 'VENDOR/apex'))

    self._copy_apex(
        os.path.join(self.testdata_dir, 'has_apk.apex'), output_dir, 'SYSTEM')
    self._copy_apex(
        os.path.join(test_utils.get_current_dir(),
                     'com.android.apex.compressed.v1.capex'), output_dir,
        'VENDOR')
    validate_merged_apex_info(output_dir, ('system', 'vendor'))

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_validate_merged_apex_info_RaisesOnPackageInMultiplePartitions(self):
    output_dir = common.MakeTempDir()
    os.makedirs(os.path.join(output_dir, 'SYSTEM/apex'))
    os.makedirs(os.path.join(output_dir, 'VENDOR/apex'))

    same_apex_package = os.path.join(self.testdata_dir, 'has_apk.apex')
    self._copy_apex(same_apex_package, output_dir, 'SYSTEM')
    self._copy_apex(same_apex_package, output_dir, 'VENDOR')
    self.assertRaisesRegexp(
        common.ExternalError,
        'Duplicate APEX packages found in multiple partitions: com.android.wifi',
        validate_merged_apex_info, output_dir, ('system', 'vendor'))
+3 −3
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ from ota_from_target_files import (
    GetTargetFilesZipWithoutPostinstallConfig,
    Payload, PayloadSigner, POSTINSTALL_CONFIG,
    StreamingPropertyFiles, AB_PARTITIONS)
from apex_utils import GetSystemApexInfoFromTargetFiles
from apex_utils import GetApexInfoFromTargetFiles
from test_utils import PropertyFilesTestCase


@@ -281,9 +281,9 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
        metadata)

  @test_utils.SkipIfExternalToolsUnavailable()
  def test_GetSystemApexInfoFromTargetFiles(self):
  def test_GetApexInfoFromTargetFiles(self):
    target_files = construct_target_files(compressedApex=True)
    apex_infos = GetSystemApexInfoFromTargetFiles(target_files)
    apex_infos = GetApexInfoFromTargetFiles(target_files, 'system')
    self.assertEqual(len(apex_infos), 1)
    self.assertEqual(apex_infos[0].package_name, "com.android.apex.compressed")
    self.assertEqual(apex_infos[0].version, 1)