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

Commit cbb65267 authored by Tianjie Xu's avatar Tianjie Xu Committed by Automerger Merge Worker
Browse files

Merge "Add an option to input the boot variables for OTA package generation"...

Merge "Add an option to input the boot variables for OTA package generation" am: 1ca7b104 am: 0dbde58c am: 77900694

Change-Id: I641ac60ad190d7bbcf90c07f2b0d9533d68dd273
parents 6bc014d4 77900694
Loading
Loading
Loading
Loading
+43 −19
Original line number Diff line number Diff line
@@ -189,6 +189,13 @@ A/B OTA specific options
  --payload_signer_key_size <key_size>
      Deprecated. Use the '--payload_signer_maximum_signature_size' instead.

  --boot_variable_file <path>
      A file that contains the possible values of ro.boot.* properties. It's
      used to calculate the possible runtime fingerprints when some
      ro.product.* properties are overridden by the 'import' statement.
      The file expects one property per line, and each line has the following
      format: 'prop_name=value1,value2'. e.g. 'ro.boot.product.sku=std,pro'

  --skip_postinstall
      Skip the postinstall hooks when generating an A/B OTA package (default:
      False). Note that this discards ALL the hooks, including non-optional
@@ -257,8 +264,8 @@ OPTIONS.retrofit_dynamic_partitions = False
OPTIONS.skip_compatibility_check = False
OPTIONS.output_metadata_path = None
OPTIONS.disable_fec_computation = False
OPTIONS.boot_variable_values = None
OPTIONS.force_non_ab = False
OPTIONS.boot_variable_file = None


METADATA_NAME = 'META-INF/com/android/metadata'
@@ -931,8 +938,18 @@ def GetPackageMetadata(target_info, source_info=None):
  assert isinstance(target_info, common.BuildInfo)
  assert source_info is None or isinstance(source_info, common.BuildInfo)

  separator = '|'

  boot_variable_values = {}
  if OPTIONS.boot_variable_file:
    d = common.LoadDictionaryFromFile(OPTIONS.boot_variable_file)
    for key, values in d.items():
      boot_variable_values[key] = [val.strip() for val in values.split(',')]

  post_build_devices, post_build_fingerprints = \
      CalculateRuntimeDevicesAndFingerprints(target_info, boot_variable_values)
  metadata = {
      'post-build' : target_info.fingerprint,
      'post-build': separator.join(sorted(post_build_fingerprints)),
      'post-build-incremental': target_info.GetBuildProp(
          'ro.build.version.incremental'),
      'post-sdk-level': target_info.GetBuildProp(
@@ -955,12 +972,15 @@ def GetPackageMetadata(target_info, source_info=None):

  is_incremental = source_info is not None
  if is_incremental:
    metadata['pre-build'] = source_info.fingerprint
    pre_build_devices, pre_build_fingerprints = \
        CalculateRuntimeDevicesAndFingerprints(source_info,
                                               boot_variable_values)
    metadata['pre-build'] = separator.join(sorted(pre_build_fingerprints))
    metadata['pre-build-incremental'] = source_info.GetBuildProp(
        'ro.build.version.incremental')
    metadata['pre-device'] = source_info.device
    metadata['pre-device'] = separator.join(sorted(pre_build_devices))
  else:
    metadata['pre-device'] = target_info.device
    metadata['pre-device'] = separator.join(sorted(post_build_devices))

  # Use the actual post-timestamp, even for a downgrade case.
  metadata['post-timestamp'] = target_info.GetBuildProp('ro.build.date.utc')
@@ -1972,24 +1992,24 @@ def GenerateNonAbOtaPackage(target_file, output_file, source_file=None):
          output_file)


def CalculateRuntimeFingerprints():
  """Returns a set of runtime fingerprints based on the boot variables."""
def CalculateRuntimeDevicesAndFingerprints(build_info, boot_variable_values):
  """Returns a tuple of sets for runtime devices and fingerprints"""

  build_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
  device_names = {build_info.device}
  fingerprints = {build_info.fingerprint}

  if not OPTIONS.boot_variable_values:
    return fingerprints
  if not boot_variable_values:
    return device_names, fingerprints

  # Calculate all possible combinations of the values for the boot variables.
  keys = OPTIONS.boot_variable_values.keys()
  value_list = OPTIONS.boot_variable_values.values()
  keys = boot_variable_values.keys()
  value_list = boot_variable_values.values()
  combinations = [dict(zip(keys, values))
                  for values in itertools.product(*value_list)]
  for placeholder_values in combinations:
    # Reload the info_dict as some build properties may change their values
    # based on the value of ro.boot* properties.
    info_dict = copy.deepcopy(OPTIONS.info_dict)
    info_dict = copy.deepcopy(build_info.info_dict)
    for partition in common.PARTITIONS_WITH_CARE_MAP:
      partition_prop_key = "{}.build.prop".format(partition)
      old_props = info_dict[partition_prop_key]
@@ -1997,9 +2017,10 @@ def CalculateRuntimeFingerprints():
          old_props.input_file, partition, placeholder_values)
    info_dict["build.prop"] = info_dict["system.build.prop"]

    build_info = common.BuildInfo(info_dict, OPTIONS.oem_dicts)
    fingerprints.add(build_info.fingerprint)
  return fingerprints
    new_build_info = common.BuildInfo(info_dict, build_info.oem_dicts)
    device_names.add(new_build_info.device)
    fingerprints.add(new_build_info.fingerprint)
  return device_names, fingerprints


def main(argv):
@@ -2077,6 +2098,8 @@ def main(argv):
      OPTIONS.disable_fec_computation = True
    elif o == "--force_non_ab":
      OPTIONS.force_non_ab = True
    elif o == "--boot_variable_file":
      OPTIONS.boot_variable_file = a
    else:
      return False
    return True
@@ -2114,6 +2137,7 @@ def main(argv):
                                 "output_metadata_path=",
                                 "disable_fec_computation",
                                 "force_non_ab",
                                 "boot_variable_file=",
                             ], extra_option_handler=option_handler)

  if len(args) != 2:
+136 −22
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ from ota_from_target_files import (
    GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
    Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
    StreamingPropertyFiles, WriteFingerprintAssertion,
    CalculateRuntimeFingerprints)
    CalculateRuntimeDevicesAndFingerprints)


def construct_target_files(secondary=False):
@@ -1334,6 +1334,9 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
      'ro.build.version.incremental=version-incremental',
      'ro.build.type=build-type',
      'ro.build.tags=build-tags',
      'ro.build.version.sdk=30',
      'ro.build.version.security_patch=2020',
      'ro.build.date.utc=12345678'
  ]

  VENDOR_BUILD_PROP = [
@@ -1345,11 +1348,12 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
  def setUp(self):
    common.OPTIONS.oem_dicts = None
    self.test_dir = common.MakeTempDir()
    self.writeFiles({'META/misc_info.txt': '\n'.join(self.MISC_INFO)})
    self.writeFiles({'META/misc_info.txt': '\n'.join(self.MISC_INFO)},
                    self.test_dir)

  def writeFiles(self, contents_dict):
  def writeFiles(self, contents_dict, out_dir):
    for path, content in contents_dict.items():
      abs_path = os.path.join(self.test_dir, path)
      abs_path = os.path.join(out_dir, path)
      dir_name = os.path.dirname(abs_path)
      if not os.path.exists(dir_name):
        os.makedirs(dir_name)
@@ -1371,12 +1375,14 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
    self.writeFiles({
        'SYSTEM/build.prop': '\n'.join(build_prop),
        'VENDOR/build.prop': '\n'.join(self.VENDOR_BUILD_PROP),
    })
    common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
    }, self.test_dir)

    self.assertEqual({
        self.constructFingerprint('product-brand/product-name/product-device')
    }, CalculateRuntimeFingerprints())
    build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
    expected = ({'product-device'},
                {self.constructFingerprint(
                    'product-brand/product-name/product-device')})
    self.assertEqual(expected,
                     CalculateRuntimeDevicesAndFingerprints(build_info, {}))

  def test_CalculatePossibleFingerprints_single_override(self):
    vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
@@ -1390,20 +1396,22 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
        'ro.product.vendor.name=vendor-product-std',
        'VENDOR/etc/build_pro.prop':
        'ro.product.vendor.name=vendor-product-pro',
    })
    common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
    common.OPTIONS.boot_variable_values = {
        'ro.boot.sku_name': ['std', 'pro']
    }
    }, self.test_dir)

    build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
    boot_variable_values = {'ro.boot.sku_name': ['std', 'pro']}

    self.assertEqual({
    expected = ({'vendor-product-device'}, {
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-name/vendor-product-device'),
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-std/vendor-product-device'),
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-pro/vendor-product-device'),
    }, CalculateRuntimeFingerprints())
    })
    self.assertEqual(
        expected, CalculateRuntimeDevicesAndFingerprints(
            build_info, boot_variable_values))

  def test_CalculatePossibleFingerprints_multiple_overrides(self):
    vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
@@ -1422,14 +1430,17 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
        'ro.product.vendor.name=vendor-product-pro',
        'VENDOR/etc/build_product2.prop':
        'ro.product.vendor.device=vendor-device-product2',
    })
    common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
    common.OPTIONS.boot_variable_values = {
    }, self.test_dir)

    build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
    boot_variable_values = {
        'ro.boot.sku_name': ['std', 'pro'],
        'ro.boot.device_name': ['product1', 'product2'],
    }

    self.assertEqual({
    expected_devices = {'vendor-product-device', 'vendor-device-product1',
                        'vendor-device-product2'}
    expected_fingerprints = {
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-name/vendor-product-device'),
        self.constructFingerprint(
@@ -1439,5 +1450,108 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-std/vendor-device-product2'),
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-pro/vendor-device-product2'),
    }, CalculateRuntimeFingerprints())
            'vendor-product-brand/vendor-product-pro/vendor-device-product2')
    }
    self.assertEqual((expected_devices, expected_fingerprints),
                     CalculateRuntimeDevicesAndFingerprints(
                         build_info, boot_variable_values))

  def test_GetPackageMetadata_full_package(self):
    vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
    vendor_build_prop.extend([
        'import /vendor/etc/build_${ro.boot.sku_name}.prop',
    ])
    self.writeFiles({
        'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
        'VENDOR/build.prop': '\n'.join(vendor_build_prop),
        'VENDOR/etc/build_std.prop':
        'ro.product.vendor.name=vendor-product-std',
        'VENDOR/etc/build_pro.prop':
        'ro.product.vendor.name=vendor-product-pro',
    }, self.test_dir)

    common.OPTIONS.boot_variable_file = common.MakeTempFile()
    with open(common.OPTIONS.boot_variable_file, 'w') as f:
      f.write('ro.boot.sku_name=std,pro')

    build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
    metadata = GetPackageMetadata(build_info)
    self.assertEqual('vendor-product-device', metadata['pre-device'])
    fingerprints = [
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-name/vendor-product-device'),
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-pro/vendor-product-device'),
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-std/vendor-product-device'),
    ]
    self.assertEqual('|'.join(fingerprints), metadata['post-build'])

  def test_GetPackageMetadata_incremental_package(self):
    vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
    vendor_build_prop.extend([
        'import /vendor/etc/build_${ro.boot.sku_name}.prop',
    ])
    self.writeFiles({
        'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
        'VENDOR/build.prop': '\n'.join(vendor_build_prop),
        'VENDOR/etc/build_std.prop':
        'ro.product.vendor.device=vendor-device-std',
        'VENDOR/etc/build_pro.prop':
        'ro.product.vendor.device=vendor-device-pro',
    }, self.test_dir)

    common.OPTIONS.boot_variable_file = common.MakeTempFile()
    with open(common.OPTIONS.boot_variable_file, 'w') as f:
      f.write('ro.boot.sku_name=std,pro')

    source_dir = common.MakeTempDir()
    source_build_prop = [
        'ro.build.version.release=source-version-release',
        'ro.build.id=source-build-id',
        'ro.build.version.incremental=source-version-incremental',
        'ro.build.type=build-type',
        'ro.build.tags=build-tags',
        'ro.build.version.sdk=29',
        'ro.build.version.security_patch=2020',
        'ro.build.date.utc=12340000'
    ]
    self.writeFiles({
        'META/misc_info.txt': '\n'.join(self.MISC_INFO),
        'SYSTEM/build.prop': '\n'.join(source_build_prop),
        'VENDOR/build.prop': '\n'.join(vendor_build_prop),
        'VENDOR/etc/build_std.prop':
        'ro.product.vendor.device=vendor-device-std',
        'VENDOR/etc/build_pro.prop':
        'ro.product.vendor.device=vendor-device-pro',
    }, source_dir)
    common.OPTIONS.incremental_source = source_dir

    target_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
    source_info = common.BuildInfo(common.LoadInfoDict(source_dir))

    metadata = GetPackageMetadata(target_info, source_info)
    self.assertEqual(
        'vendor-device-pro|vendor-device-std|vendor-product-device',
        metadata['pre-device'])
    suffix = ':source-version-release/source-build-id/' \
             'source-version-incremental:build-type/build-tags'
    pre_fingerprints = [
        'vendor-product-brand/vendor-product-name/vendor-device-pro'
        '{}'.format(suffix),
        'vendor-product-brand/vendor-product-name/vendor-device-std'
        '{}'.format(suffix),
        'vendor-product-brand/vendor-product-name/vendor-product-device'
        '{}'.format(suffix),
    ]
    self.assertEqual('|'.join(pre_fingerprints), metadata['pre-build'])

    post_fingerprints = [
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-name/vendor-device-pro'),
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-name/vendor-device-std'),
        self.constructFingerprint(
            'vendor-product-brand/vendor-product-name/vendor-product-device'),
    ]
    self.assertEqual('|'.join(post_fingerprints), metadata['post-build'])