Loading tools/releasetools/add_img_to_target_files.py +5 −3 Original line number Diff line number Diff line Loading @@ -548,17 +548,19 @@ def AddCareMapForAbOta(output_zip, ab_partitions, image_paths): care_map_list += care_map # adds fingerprint field to the care_map build_props = OPTIONS.info_dict.get(partition + ".build.prop", {}) # TODO(xunchang) revisit the fingerprint calculation for care_map. partition_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 x in build_props] present_props = [x for x in prop_name_list if partition_props and partition_props.GetProp(x)] 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 = build_props[property_id] fingerprint = partition_props.GetProp(property_id) care_map_list += [property_id, fingerprint] if not care_map_list: Loading tools/releasetools/build_image.py +3 −3 Original line number Diff line number Diff line Loading @@ -509,9 +509,9 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): d = {} if "build.prop" in glob_dict: bp = glob_dict["build.prop"] if "ro.build.date.utc" in bp: d["timestamp"] = bp["ro.build.date.utc"] timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc") if timestamp: d["timestamp"] = timestamp def copy_prop(src_p, dest_p): """Copy a property from the global dictionary. Loading tools/releasetools/check_target_files_vintf.py +2 −1 Original line number Diff line number Diff line Loading @@ -80,8 +80,9 @@ 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'].get( shipping_api_level = info_dict['vendor.build.prop'].GetProp( 'ro.product.first_api_level') if not shipping_api_level: logger.warning('Cannot determine ro.product.first_api_level') Loading tools/releasetools/common.py +99 −46 Original line number Diff line number Diff line Loading @@ -423,6 +423,14 @@ 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 Loading @@ -431,9 +439,10 @@ class BuildInfo(object): prop = prop.replace("ro.product", "ro.product.{}".format(partition)) else: prop = prop.replace("ro.", "ro.{}.".format(partition)) try: return self.info_dict.get("{}.build.prop".format(partition), {})[prop] except KeyError: prop_val = self._GetRawBuildProp(prop, partition) if prop_val is not None: return prop_val raise ExternalError("couldn't find %s in %s.build.prop" % (prop, partition)) Loading @@ -442,20 +451,21 @@ class BuildInfo(object): if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS: return self._ResolveRoProductBuildProp(prop) try: return self.info_dict.get("build.prop", {})[prop] except KeyError: prop_val = self._GetRawBuildProp(prop, None) if prop_val is not None: return prop_val raise ExternalError("couldn't find %s in build.prop" % (prop,)) def _ResolveRoProductBuildProp(self, prop): """Resolves the inquired ro.product.* build property""" prop_val = self.info_dict.get("build.prop", {}).get(prop) prop_val = self._GetRawBuildProp(prop, None) 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") source_order_val = self._GetRawBuildProp( "ro.product.property_source_order", None) if source_order_val: source_order = source_order_val.split(",") else: Loading @@ -466,11 +476,10 @@ class BuildInfo(object): raise ExternalError( "Invalid ro.product.property_source_order '{}'".format(source_order)) for source in source_order: for source_partition in source_order: source_prop = prop.replace( "ro.product", "ro.product.{}".format(source), 1) prop_val = self.info_dict.get( "{}.build.prop".format(source), {}).get(source_prop) "ro.product", "ro.product.{}".format(source_partition), 1) prop_val = self._GetRawBuildProp(source_prop, source_partition) if prop_val: return prop_val Loading @@ -479,11 +488,9 @@ 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.info_dict.get("build.prop", {}).get( "ro.build.version.codename") android_codename = self._GetRawBuildProp("ro.build.version.codename", None) if android_codename == "REL": android_version = self.info_dict.get("build.prop", {}).get( "ro.build.version.release") android_version = self._GetRawBuildProp("ro.build.version.release", None) if android_version == "10": return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_ANDROID_10 # NOTE: float() conversion of android_version will have rounding error. Loading Loading @@ -566,6 +573,20 @@ 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. Loading Loading @@ -603,16 +624,7 @@ def LoadInfoDict(input_file, repacking=False): "input_file must be a path str when doing repacking" def read_helper(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) return ReadFromInputFile(input_file, fn) try: d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n")) Loading Loading @@ -675,13 +687,8 @@ 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] = 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[partition_prop] = PartitionBuildProps.FromInputFile( input_file, partition) d["build.prop"] = d["system.build.prop"] # Set up the salt (based on fingerprint) that will be used when adding AVB Loading @@ -696,15 +703,6 @@ 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() Loading @@ -727,6 +725,61 @@ 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 dictionary of build properties for the given partition. prop_overrides: a dict of list. And each list holds the overridden values for props_allow_override. """ def __init__(self, input_file, name): self.input_file = input_file self.partition = name self.props_allow_override = [props.format(name) for props in [ 'ro.product.{}.name', 'ro.product.{}.device']] self.build_props = {} self.prop_overrides = {} @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): """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) props.build_props = LoadDictionaryFromLines(data.split('\n')) return props 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): Loading tools/releasetools/test_add_img_to_target_files.py +38 −28 Original line number Diff line number Diff line Loading @@ -128,13 +128,16 @@ class AddImagesToTargetFilesTest(test_utils.ReleaseToolsTestCase): 'vendor_image_size' : 40960, 'system_verity_block_device': '/dev/block/system', 'vendor_verity_block_device': '/dev/block/vendor', 'system.build.prop': { 'system.build.prop': common.PartitionBuildProps.FromDictionary( 'system', { 'ro.system.build.fingerprint': 'google/sailfish/12345:user/dev-keys', }, 'vendor.build.prop': { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys', }, 'google/sailfish/12345:user/dev-keys'} ), 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( 'vendor', { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys'} ), } # Prepare the META/ folder. Loading Loading @@ -211,13 +214,16 @@ class AddImagesToTargetFilesTest(test_utils.ReleaseToolsTestCase): 'vendor_image_size': 40960, 'avb_system_hashtree_enable': 'true', 'avb_vendor_hashtree_enable': 'true', 'system.build.prop': { 'system.build.prop': common.PartitionBuildProps.FromDictionary( 'system', { 'ro.system.build.fingerprint': 'google/sailfish/12345:user/dev-keys', }, 'vendor.build.prop': { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys', } 'google/sailfish/12345:user/dev-keys'} ), 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( 'vendor', { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys'} ), } AddCareMapForAbOta(None, ['system', 'vendor'], image_paths) Loading Loading @@ -263,12 +269,16 @@ class AddImagesToTargetFilesTest(test_utils.ReleaseToolsTestCase): 'vendor_image_size': 40960, 'system_verity_block_device': '/dev/block/system', 'vendor_verity_block_device': '/dev/block/vendor', 'system.build.prop': { 'ro.system.build.thumbprint': 'google/sailfish/123:user/dev-keys', }, 'vendor.build.prop' : { 'ro.vendor.build.thumbprint': 'google/sailfish/456:user/dev-keys', }, 'system.build.prop': common.PartitionBuildProps.FromDictionary( 'system', { 'ro.system.build.thumbprint': 'google/sailfish/123:user/dev-keys'} ), 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( 'vendor', { 'ro.vendor.build.thumbprint': 'google/sailfish/456:user/dev-keys'} ), } AddCareMapForAbOta(None, ['system', 'vendor'], image_paths) Loading Loading
tools/releasetools/add_img_to_target_files.py +5 −3 Original line number Diff line number Diff line Loading @@ -548,17 +548,19 @@ def AddCareMapForAbOta(output_zip, ab_partitions, image_paths): care_map_list += care_map # adds fingerprint field to the care_map build_props = OPTIONS.info_dict.get(partition + ".build.prop", {}) # TODO(xunchang) revisit the fingerprint calculation for care_map. partition_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 x in build_props] present_props = [x for x in prop_name_list if partition_props and partition_props.GetProp(x)] 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 = build_props[property_id] fingerprint = partition_props.GetProp(property_id) care_map_list += [property_id, fingerprint] if not care_map_list: Loading
tools/releasetools/build_image.py +3 −3 Original line number Diff line number Diff line Loading @@ -509,9 +509,9 @@ def ImagePropFromGlobalDict(glob_dict, mount_point): d = {} if "build.prop" in glob_dict: bp = glob_dict["build.prop"] if "ro.build.date.utc" in bp: d["timestamp"] = bp["ro.build.date.utc"] timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc") if timestamp: d["timestamp"] = timestamp def copy_prop(src_p, dest_p): """Copy a property from the global dictionary. Loading
tools/releasetools/check_target_files_vintf.py +2 −1 Original line number Diff line number Diff line Loading @@ -80,8 +80,9 @@ 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'].get( shipping_api_level = info_dict['vendor.build.prop'].GetProp( 'ro.product.first_api_level') if not shipping_api_level: logger.warning('Cannot determine ro.product.first_api_level') Loading
tools/releasetools/common.py +99 −46 Original line number Diff line number Diff line Loading @@ -423,6 +423,14 @@ 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 Loading @@ -431,9 +439,10 @@ class BuildInfo(object): prop = prop.replace("ro.product", "ro.product.{}".format(partition)) else: prop = prop.replace("ro.", "ro.{}.".format(partition)) try: return self.info_dict.get("{}.build.prop".format(partition), {})[prop] except KeyError: prop_val = self._GetRawBuildProp(prop, partition) if prop_val is not None: return prop_val raise ExternalError("couldn't find %s in %s.build.prop" % (prop, partition)) Loading @@ -442,20 +451,21 @@ class BuildInfo(object): if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS: return self._ResolveRoProductBuildProp(prop) try: return self.info_dict.get("build.prop", {})[prop] except KeyError: prop_val = self._GetRawBuildProp(prop, None) if prop_val is not None: return prop_val raise ExternalError("couldn't find %s in build.prop" % (prop,)) def _ResolveRoProductBuildProp(self, prop): """Resolves the inquired ro.product.* build property""" prop_val = self.info_dict.get("build.prop", {}).get(prop) prop_val = self._GetRawBuildProp(prop, None) 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") source_order_val = self._GetRawBuildProp( "ro.product.property_source_order", None) if source_order_val: source_order = source_order_val.split(",") else: Loading @@ -466,11 +476,10 @@ class BuildInfo(object): raise ExternalError( "Invalid ro.product.property_source_order '{}'".format(source_order)) for source in source_order: for source_partition in source_order: source_prop = prop.replace( "ro.product", "ro.product.{}".format(source), 1) prop_val = self.info_dict.get( "{}.build.prop".format(source), {}).get(source_prop) "ro.product", "ro.product.{}".format(source_partition), 1) prop_val = self._GetRawBuildProp(source_prop, source_partition) if prop_val: return prop_val Loading @@ -479,11 +488,9 @@ 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.info_dict.get("build.prop", {}).get( "ro.build.version.codename") android_codename = self._GetRawBuildProp("ro.build.version.codename", None) if android_codename == "REL": android_version = self.info_dict.get("build.prop", {}).get( "ro.build.version.release") android_version = self._GetRawBuildProp("ro.build.version.release", None) if android_version == "10": return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_ANDROID_10 # NOTE: float() conversion of android_version will have rounding error. Loading Loading @@ -566,6 +573,20 @@ 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. Loading Loading @@ -603,16 +624,7 @@ def LoadInfoDict(input_file, repacking=False): "input_file must be a path str when doing repacking" def read_helper(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) return ReadFromInputFile(input_file, fn) try: d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n")) Loading Loading @@ -675,13 +687,8 @@ 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] = 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[partition_prop] = PartitionBuildProps.FromInputFile( input_file, partition) d["build.prop"] = d["system.build.prop"] # Set up the salt (based on fingerprint) that will be used when adding AVB Loading @@ -696,15 +703,6 @@ 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() Loading @@ -727,6 +725,61 @@ 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 dictionary of build properties for the given partition. prop_overrides: a dict of list. And each list holds the overridden values for props_allow_override. """ def __init__(self, input_file, name): self.input_file = input_file self.partition = name self.props_allow_override = [props.format(name) for props in [ 'ro.product.{}.name', 'ro.product.{}.device']] self.build_props = {} self.prop_overrides = {} @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): """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) props.build_props = LoadDictionaryFromLines(data.split('\n')) return props 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): Loading
tools/releasetools/test_add_img_to_target_files.py +38 −28 Original line number Diff line number Diff line Loading @@ -128,13 +128,16 @@ class AddImagesToTargetFilesTest(test_utils.ReleaseToolsTestCase): 'vendor_image_size' : 40960, 'system_verity_block_device': '/dev/block/system', 'vendor_verity_block_device': '/dev/block/vendor', 'system.build.prop': { 'system.build.prop': common.PartitionBuildProps.FromDictionary( 'system', { 'ro.system.build.fingerprint': 'google/sailfish/12345:user/dev-keys', }, 'vendor.build.prop': { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys', }, 'google/sailfish/12345:user/dev-keys'} ), 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( 'vendor', { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys'} ), } # Prepare the META/ folder. Loading Loading @@ -211,13 +214,16 @@ class AddImagesToTargetFilesTest(test_utils.ReleaseToolsTestCase): 'vendor_image_size': 40960, 'avb_system_hashtree_enable': 'true', 'avb_vendor_hashtree_enable': 'true', 'system.build.prop': { 'system.build.prop': common.PartitionBuildProps.FromDictionary( 'system', { 'ro.system.build.fingerprint': 'google/sailfish/12345:user/dev-keys', }, 'vendor.build.prop': { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys', } 'google/sailfish/12345:user/dev-keys'} ), 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( 'vendor', { 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys'} ), } AddCareMapForAbOta(None, ['system', 'vendor'], image_paths) Loading Loading @@ -263,12 +269,16 @@ class AddImagesToTargetFilesTest(test_utils.ReleaseToolsTestCase): 'vendor_image_size': 40960, 'system_verity_block_device': '/dev/block/system', 'vendor_verity_block_device': '/dev/block/vendor', 'system.build.prop': { 'ro.system.build.thumbprint': 'google/sailfish/123:user/dev-keys', }, 'vendor.build.prop' : { 'ro.vendor.build.thumbprint': 'google/sailfish/456:user/dev-keys', }, 'system.build.prop': common.PartitionBuildProps.FromDictionary( 'system', { 'ro.system.build.thumbprint': 'google/sailfish/123:user/dev-keys'} ), 'vendor.build.prop': common.PartitionBuildProps.FromDictionary( 'vendor', { 'ro.vendor.build.thumbprint': 'google/sailfish/456:user/dev-keys'} ), } AddCareMapForAbOta(None, ['system', 'vendor'], image_paths) Loading