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

Commit 763c8a76 authored by Greg Kaiser's avatar Greg Kaiser Committed by Gerrit Code Review
Browse files

Merge changes from topic "revert-1297095-MANSYJSCZY"

* changes:
  Revert "Add a wrapper class PartitionBuildProp"
  Revert "Calculate the runtime fingerprint prefixes from build prop"
parents 8aba9ec7 60225452
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -548,19 +548,17 @@ def AddCareMapForAbOta(output_zip, ab_partitions, image_paths):
      care_map_list += care_map

      # adds fingerprint field to the care_map
      # TODO(xunchang) revisit the fingerprint calculation for care_map.
      partition_props = OPTIONS.info_dict.get(partition + ".build.prop")
      build_props = OPTIONS.info_dict.get(partition + ".build.prop", {})
      prop_name_list = ["ro.{}.build.fingerprint".format(partition),
                        "ro.{}.build.thumbprint".format(partition)]

      present_props = [x for x in prop_name_list if
                       partition_props and partition_props.GetProp(x)]
      present_props = [x for x in prop_name_list if x in build_props]
      if not present_props:
        logger.warning("fingerprint is not present for partition %s", partition)
        property_id, fingerprint = "unknown", "unknown"
      else:
        property_id = present_props[0]
        fingerprint = partition_props.GetProp(property_id)
        fingerprint = build_props[property_id]
      care_map_list += [property_id, fingerprint]

  if not care_map_list:
+3 −3
Original line number Diff line number Diff line
@@ -509,9 +509,9 @@ def ImagePropFromGlobalDict(glob_dict, mount_point):
  d = {}

  if "build.prop" in glob_dict:
    timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
    if timestamp:
      d["timestamp"] = timestamp
    bp = glob_dict["build.prop"]
    if "ro.build.date.utc" in bp:
      d["timestamp"] = bp["ro.build.date.utc"]

  def copy_prop(src_p, dest_p):
    """Copy a property from the global dictionary.
+1 −2
Original line number Diff line number Diff line
@@ -80,9 +80,8 @@ def GetArgsForSkus(info_dict):
           '--property', 'ro.boot.product.vendor.sku=' + vendor_sku]
          for odm_sku in odm_skus for vendor_sku in vendor_skus]


def GetArgsForShippingApiLevel(info_dict):
  shipping_api_level = info_dict['vendor.build.prop'].GetProp(
  shipping_api_level = info_dict['vendor.build.prop'].get(
      'ro.product.first_api_level')
  if not shipping_api_level:
    logger.warning('Cannot determine ro.product.first_api_level')
+46 −154
Original line number Diff line number Diff line
@@ -423,14 +423,6 @@ class BuildInfo(object):
  def items(self):
    return self.info_dict.items()

  def _GetRawBuildProp(self, prop, partition):
    prop_file = '{}.build.prop'.format(
        partition) if partition else 'build.prop'
    partition_props = self.info_dict.get(prop_file)
    if not partition_props:
      return None
    return partition_props.GetProp(prop)

  def GetPartitionBuildProp(self, prop, partition):
    """Returns the inquired build property for the provided partition."""
    # If provided a partition for this property, only look within that
@@ -439,10 +431,9 @@ class BuildInfo(object):
      prop = prop.replace("ro.product", "ro.product.{}".format(partition))
    else:
      prop = prop.replace("ro.", "ro.{}.".format(partition))

    prop_val = self._GetRawBuildProp(prop, partition)
    if prop_val is not None:
      return prop_val
    try:
      return self.info_dict.get("{}.build.prop".format(partition), {})[prop]
    except KeyError:
      raise ExternalError("couldn't find %s in %s.build.prop" %
                          (prop, partition))

@@ -451,21 +442,20 @@ class BuildInfo(object):
    if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS:
      return self._ResolveRoProductBuildProp(prop)

    prop_val = self._GetRawBuildProp(prop, None)
    if prop_val is not None:
      return prop_val

    try:
      return self.info_dict.get("build.prop", {})[prop]
    except KeyError:
      raise ExternalError("couldn't find %s in build.prop" % (prop,))

  def _ResolveRoProductBuildProp(self, prop):
    """Resolves the inquired ro.product.* build property"""
    prop_val = self._GetRawBuildProp(prop, None)
    prop_val = self.info_dict.get("build.prop", {}).get(prop)
    if prop_val:
      return prop_val

    default_source_order = self._GetRoProductPropsDefaultSourceOrder()
    source_order_val = self._GetRawBuildProp(
        "ro.product.property_source_order", None)
    source_order_val = self.info_dict.get("build.prop", {}).get(
        "ro.product.property_source_order")
    if source_order_val:
      source_order = source_order_val.split(",")
    else:
@@ -476,10 +466,11 @@ class BuildInfo(object):
      raise ExternalError(
          "Invalid ro.product.property_source_order '{}'".format(source_order))

    for source_partition in source_order:
    for source in source_order:
      source_prop = prop.replace(
          "ro.product", "ro.product.{}".format(source_partition), 1)
      prop_val = self._GetRawBuildProp(source_prop, source_partition)
          "ro.product", "ro.product.{}".format(source), 1)
      prop_val = self.info_dict.get(
          "{}.build.prop".format(source), {}).get(source_prop)
      if prop_val:
        return prop_val

@@ -488,9 +479,11 @@ class BuildInfo(object):
  def _GetRoProductPropsDefaultSourceOrder(self):
    # NOTE: refer to CDDs and android.os.Build.VERSION for the definition and
    # values of these properties for each Android release.
    android_codename = self._GetRawBuildProp("ro.build.version.codename", None)
    android_codename = self.info_dict.get("build.prop", {}).get(
        "ro.build.version.codename")
    if android_codename == "REL":
      android_version = self._GetRawBuildProp("ro.build.version.release", None)
      android_version = self.info_dict.get("build.prop", {}).get(
          "ro.build.version.release")
      if android_version == "10":
        return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_ANDROID_10
      # NOTE: float() conversion of android_version will have rounding error.
@@ -573,20 +566,6 @@ class BuildInfo(object):
      script.AssertOemProperty(prop, values, oem_no_mount)


def ReadFromInputFile(input_file, fn):
  """Reads the contents of fn from input zipfile or directory."""
  if isinstance(input_file, zipfile.ZipFile):
    return input_file.read(fn).decode()
  else:
    path = os.path.join(input_file, *fn.split("/"))
    try:
      with open(path) as f:
        return f.read()
    except IOError as e:
      if e.errno == errno.ENOENT:
        raise KeyError(fn)


def LoadInfoDict(input_file, repacking=False):
  """Loads the key/value pairs from the given input target_files.

@@ -624,7 +603,16 @@ def LoadInfoDict(input_file, repacking=False):
        "input_file must be a path str when doing repacking"

  def read_helper(fn):
    return ReadFromInputFile(input_file, fn)
    if isinstance(input_file, zipfile.ZipFile):
      return input_file.read(fn).decode()
    else:
      path = os.path.join(input_file, *fn.split("/"))
      try:
        with open(path) as f:
          return f.read()
      except IOError as e:
        if e.errno == errno.ENOENT:
          raise KeyError(fn)

  try:
    d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n"))
@@ -687,8 +675,13 @@ def LoadInfoDict(input_file, repacking=False):
  # system and vendor.
  for partition in PARTITIONS_WITH_CARE_MAP:
    partition_prop = "{}.build.prop".format(partition)
    d[partition_prop] = PartitionBuildProps.FromInputFile(
        input_file, partition)
    d[partition_prop] = LoadBuildProp(
        read_helper, "{}/build.prop".format(partition.upper()))
    # Some partition might use /<partition>/etc/build.prop as the new path.
    # TODO: try new path first when majority of them switch to the new path.
    if not d[partition_prop]:
      d[partition_prop] = LoadBuildProp(
          read_helper, "{}/etc/build.prop".format(partition.upper()))
  d["build.prop"] = d["system.build.prop"]

  # Set up the salt (based on fingerprint) that will be used when adding AVB
@@ -703,6 +696,15 @@ def LoadInfoDict(input_file, repacking=False):
  return d


def LoadBuildProp(read_helper, prop_file):
  try:
    data = read_helper(prop_file)
  except KeyError:
    logger.warning("Failed to read %s", prop_file)
    data = ""
  return LoadDictionaryFromLines(data.split("\n"))


def LoadListFromFile(file_path):
  with open(file_path) as f:
    return f.read().splitlines()
@@ -725,116 +727,6 @@ def LoadDictionaryFromLines(lines):
  return d


class PartitionBuildProps(object):
  """The class holds the build prop of a particular partition.

  This class loads the build.prop and holds the build properties for a given
  partition. It also partially recognizes the 'import' statement in the
  build.prop; and calculates alternative values of some specific build
  properties during runtime.

  Attributes:
    input_file: a zipped target-file or an unzipped target-file directory.
    partition: name of the partition.
    props_allow_override: a list of build properties to search for the
        alternative values during runtime.
    build_props: a dict of build properties for the given partition.
    prop_overrides: a set of props that are overridden by import.
    placeholder_values: A dict of runtime variables' values to replace the
        placeholders in the build.prop file. We expect exactly one value for
        each of the variables.
  """
  def __init__(self, input_file, name, placeholder_values=None):
    self.input_file = input_file
    self.partition = name
    self.props_allow_override = [props.format(name) for props in [
        'ro.product.{}.brand', 'ro.product.{}.name', 'ro.product.{}.device']]
    self.build_props = {}
    self.prop_overrides = set()
    self.placeholder_values = {}
    if placeholder_values:
      self.placeholder_values = copy.deepcopy(placeholder_values)

  @staticmethod
  def FromDictionary(name, build_props):
    """Constructs an instance from a build prop dictionary."""

    props = PartitionBuildProps("unknown", name)
    props.build_props = build_props.copy()
    return props

  @staticmethod
  def FromInputFile(input_file, name, placeholder_values=None):
    """Loads the build.prop file and builds the attributes."""
    data = ''
    for prop_file in ['{}/etc/build.prop'.format(name.upper()),
                      '{}/build.prop'.format(name.upper())]:
      try:
        data = ReadFromInputFile(input_file, prop_file)
        break
      except KeyError:
        logger.warning('Failed to read %s', prop_file)

    props = PartitionBuildProps(input_file, name, placeholder_values)
    props._LoadBuildProp(data)
    return props

  def _LoadBuildProp(self, data):
    for line in data.split('\n'):
      line = line.strip()
      if not line or line.startswith("#"):
        continue
      if line.startswith("import"):
        overrides = self._ImportParser(line)
        duplicates = self.prop_overrides.intersection(overrides.keys())
        if duplicates:
          raise ValueError('prop {} is overridden multiple times'.format(
              ','.join(duplicates)))
        self.prop_overrides = self.prop_overrides.union(overrides.keys())
        self.build_props.update(overrides)
      elif "=" in line:
        name, value = line.split("=", 1)
        if name in self.prop_overrides:
          raise ValueError('prop {} is set again after overridden by import '
                           'statement'.format(name))
        self.build_props[name] = value

  def _ImportParser(self, line):
    """Parses the build prop in a given import statement."""

    tokens = line.split()
    if len(tokens) != 2 or tokens[0] != 'import':
      raise ValueError('Unrecognized import statement {}'.format(line))
    import_path = tokens[1]
    if not re.match(r'^/{}/.*\.prop$'.format(self.partition), import_path):
      raise ValueError('Unrecognized import path {}'.format(line))

    # We only recognize a subset of import statement that the init process
    # supports. And we can loose the restriction based on how the dynamic
    # fingerprint is used in practice. The placeholder format should be
    # ${placeholder}, and its value should be provided by the caller through
    # the placeholder_values.
    for prop, value in self.placeholder_values.items():
      prop_place_holder = '${{{}}}'.format(prop)
      if prop_place_holder in import_path:
        import_path = import_path.replace(prop_place_holder, value)
    if '$' in import_path:
      logger.info('Unresolved place holder in import path %s', import_path)
      return {}

    import_path = import_path.replace('/{}'.format(self.partition),
                                      self.partition.upper())
    logger.info('Parsing build props override from %s', import_path)

    lines = ReadFromInputFile(self.input_file, import_path).split('\n')
    d = LoadDictionaryFromLines(lines)
    return {key: val for key, val in d.items()
            if key in self.props_allow_override}

  def GetProp(self, prop):
    return self.build_props.get(prop)


def LoadRecoveryFSTab(read_helper, fstab_version, recovery_fstab_path,
                      system_root_image=False):
  class Partition(object):
+0 −34
Original line number Diff line number Diff line
@@ -193,8 +193,6 @@ A/B OTA specific options
from __future__ import print_function

import collections
import copy
import itertools
import logging
import multiprocessing
import os.path
@@ -231,7 +229,6 @@ OPTIONS.include_secondary = False
OPTIONS.no_signing = False
OPTIONS.block_based = True
OPTIONS.updater_binary = None
OPTIONS.oem_dicts = None
OPTIONS.oem_source = None
OPTIONS.oem_no_mount = False
OPTIONS.full_radio = False
@@ -250,7 +247,6 @@ 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


METADATA_NAME = 'META-INF/com/android/metadata'
@@ -1963,36 +1959,6 @@ def GenerateNonAbOtaPackage(target_file, output_file, source_file=None):
          output_file)


def CalculateRuntimeFingerprints():
  """Returns a set of runtime fingerprints based on the boot variables."""

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

  if not OPTIONS.boot_variable_values:
    return 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()
  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)
    for partition in common.PARTITIONS_WITH_CARE_MAP:
      partition_prop_key = "{}.build.prop".format(partition)
      old_props = info_dict[partition_prop_key]
      info_dict[partition_prop_key] = common.PartitionBuildProps.FromInputFile(
          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


def main(argv):

  def option_handler(o, a):
Loading