From 8e2086e6e32ff51ab94d62753df8a6c85180802b Mon Sep 17 00:00:00 2001 From: Steven Laver Date: Mon, 27 Apr 2020 16:26:31 -0700 Subject: [PATCH] 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 --- tools/releasetools/common.py | 34 +++++++++++-- tools/releasetools/test_common.py | 80 +++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 5 deletions(-) diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 5cf48102d..2f89a7095 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -336,8 +336,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. @@ -447,16 +450,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)) @@ -470,6 +473,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] diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py index 551f626b9..f1971d3b4 100644 --- a/tools/releasetools/test_common.py +++ b/tools/releasetools/test_common.py @@ -108,6 +108,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) @@ -254,6 +299,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):