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

Commit dd33d75d authored by Steven Laver's avatar Steven Laver
Browse files

releasetools: correct allowed property sources for incremental OTAs

When loading build info from a previous version of Android, the set of
allowed property sources should match those available in that version.
In this particular case, the product_services partition was a valid
property source in Android 10.

Bug: 155053195
Test: ran unit tests from test_common.py
Test: generated an incremental OTA which previously failed
Change-Id: Ic0b0a112656533eca78dee31517deff7e3c8d7cc
Merged-In: Ic0b0a112656533eca78dee31517deff7e3c8d7cc
parent e414a3fd
Loading
Loading
Loading
Loading
+29 −5
Original line number Diff line number Diff line
@@ -335,8 +335,11 @@ class BuildInfo(object):
  _RO_PRODUCT_RESOLVE_PROPS = ["ro.product.brand", "ro.product.device",
                               "ro.product.manufacturer", "ro.product.model",
                               "ro.product.name"]
  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = ["product", "odm", "vendor",
                                            "system_ext", "system"]
  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_CURRENT = [
      "product", "odm", "vendor", "system_ext", "system"]
  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_ANDROID_10 = [
      "product", "product_services", "odm", "vendor", "system"]
  _RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_LEGACY = []

  def __init__(self, info_dict, oem_dicts=None):
    """Initializes a BuildInfo instance with the given dicts.
@@ -446,16 +449,16 @@ class BuildInfo(object):
    if prop_val:
      return prop_val

    default_source_order = self._GetRoProductPropsDefaultSourceOrder()
    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:
      source_order = BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
      source_order = default_source_order

    # Check that all sources in ro.product.property_source_order are valid
    if any([x not in BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER
            for x in source_order]):
    if any([x not in default_source_order for x in source_order]):
      raise ExternalError(
          "Invalid ro.product.property_source_order '{}'".format(source_order))

@@ -469,6 +472,27 @@ class BuildInfo(object):

    raise ExternalError("couldn't resolve {}".format(prop))

  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.info_dict.get("build.prop", {}).get(
        "ro.build.version.codename")
    if android_codename == "REL":
      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.
      # We are checking for "9" or less, and using "< 10" is well outside of
      # possible floating point rounding.
      try:
        android_version_val = float(android_version)
      except ValueError:
        android_version_val = 0
      if android_version_val < 10:
        return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_LEGACY
    return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_CURRENT

  def GetOemProperty(self, key):
    if self.oem_props is not None and key in self.oem_props:
      return self.oem_dicts[0][key]
+80 −0
Original line number Diff line number Diff line
@@ -107,6 +107,51 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
      },
  ]

  TEST_INFO_DICT_PROPERTY_SOURCE_ORDER = {
      'build.prop' : {
          'ro.build.fingerprint' : 'build-fingerprint',
          'ro.product.property_source_order' :
              'product,odm,vendor,system_ext,system',
      },
      'system.build.prop' : {
          'ro.product.system.device' : 'system-product-device',
      },
      'vendor.build.prop' : {
          'ro.product.vendor.device' : 'vendor-product-device',
      },
  }

  TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_10 = {
      'build.prop' : {
          'ro.build.fingerprint' : 'build-fingerprint',
          'ro.product.property_source_order' :
              'product,product_services,odm,vendor,system',
          'ro.build.version.release' : '10',
          'ro.build.version.codename' : 'REL',
      },
      'system.build.prop' : {
          'ro.product.system.device' : 'system-product-device',
      },
      'vendor.build.prop' : {
          'ro.product.vendor.device' : 'vendor-product-device',
      },
  }

  TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_9 = {
      'build.prop' : {
          'ro.product.device' : 'product-device',
          'ro.build.fingerprint' : 'build-fingerprint',
          'ro.build.version.release' : '9',
          'ro.build.version.codename' : 'REL',
      },
      'system.build.prop' : {
          'ro.product.system.device' : 'system-product-device',
      },
      'vendor.build.prop' : {
          'ro.product.vendor.device' : 'vendor-product-device',
      },
  }

  def test_init(self):
    target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
    self.assertEqual('product-device', target_info.device)
@@ -253,6 +298,41 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
        ],
        script_writer.lines)

  def test_ResolveRoProductProperty_FromVendor(self):
    info_dict = copy.deepcopy(self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER)
    info = common.BuildInfo(info_dict, None)
    self.assertEqual('vendor-product-device',
                     info.GetBuildProp('ro.product.device'))

  def test_ResolveRoProductProperty_FromSystem(self):
    info_dict = copy.deepcopy(self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER)
    del info_dict['vendor.build.prop']['ro.product.vendor.device']
    info = common.BuildInfo(info_dict, None)
    self.assertEqual('system-product-device',
                     info.GetBuildProp('ro.product.device'))

  def test_ResolveRoProductProperty_InvalidPropertySearchOrder(self):
    info_dict = copy.deepcopy(self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER)
    info_dict['build.prop']['ro.product.property_source_order'] = 'bad-source'
    with self.assertRaisesRegexp(common.ExternalError,
        'Invalid ro.product.property_source_order'):
      info = common.BuildInfo(info_dict, None)
      info.GetBuildProp('ro.product.device')

  def test_ResolveRoProductProperty_Android10PropertySearchOrder(self):
    info_dict = copy.deepcopy(
        self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_10)
    info = common.BuildInfo(info_dict, None)
    self.assertEqual('vendor-product-device',
                     info.GetBuildProp('ro.product.device'))

  def test_ResolveRoProductProperty_Android9PropertySearchOrder(self):
    info_dict = copy.deepcopy(
        self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_9)
    info = common.BuildInfo(info_dict, None)
    self.assertEqual('product-device',
                     info.GetBuildProp('ro.product.device'))


class CommonZipTest(test_utils.ReleaseToolsTestCase):