Merge "Infers custom vendor partitions."

This commit is contained in:
Daniel Norman
2022-05-02 16:25:58 +00:00
committed by Gerrit Code Review
2 changed files with 102 additions and 50 deletions

View File

@@ -100,19 +100,15 @@ def ValidateConfigLists():
has_error = False has_error = False
# Check that partitions only come from one input. # Check that partitions only come from one input.
for partition in _FRAMEWORK_PARTITIONS.union(_VENDOR_PARTITIONS): framework_partitions = ItemListToPartitionSet(OPTIONS.framework_item_list)
image_path = 'IMAGES/{}.img'.format(partition.lower().replace('/', '')) vendor_partitions = ItemListToPartitionSet(OPTIONS.vendor_item_list)
in_framework = ( from_both = framework_partitions.intersection(vendor_partitions)
any(item.startswith(partition) for item in OPTIONS.framework_item_list) if from_both:
or image_path in OPTIONS.framework_item_list)
in_vendor = (
any(item.startswith(partition) for item in OPTIONS.vendor_item_list) or
image_path in OPTIONS.vendor_item_list)
if in_framework and in_vendor:
logger.error( logger.error(
'Cannot extract items from %s for both the framework and vendor' 'Cannot extract items from the same partition in both the '
' builds. Please ensure only one merge config item list' 'framework and vendor builds. Please ensure only one merge config '
' includes %s.', partition, partition) 'item list (or inferred list) includes each partition: %s' %
','.join(from_both))
has_error = True has_error = True
if any([ if any([
@@ -131,7 +127,8 @@ def ValidateConfigLists():
# system partition). The following regex matches this and extracts the # system partition). The following regex matches this and extracts the
# partition name. # partition name.
_PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$') _PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/.*$')
_IMAGE_PARTITION_PATTERN = re.compile(r'^IMAGES/(.*)\.img$')
def ItemListToPartitionSet(item_list): def ItemListToPartitionSet(item_list):
@@ -154,62 +151,89 @@ def ItemListToPartitionSet(item_list):
partition_set = set() partition_set = set()
for item in item_list: for item in item_list:
partition_match = _PARTITION_ITEM_PATTERN.search(item.strip()) for pattern in (_PARTITION_ITEM_PATTERN, _IMAGE_PARTITION_PATTERN):
partition_tag = partition_match.group( partition_match = pattern.search(item.strip())
1).lower() if partition_match else None if partition_match:
partition = partition_match.group(1).lower()
if partition_tag: # These directories in target-files are not actual partitions.
partition_set.add(partition_tag) if partition not in ('meta', 'images'):
partition_set.add(partition)
return partition_set return partition_set
# Partitions that are grabbed from the framework partial build by default. # Partitions that are grabbed from the framework partial build by default.
_FRAMEWORK_PARTITIONS = { _FRAMEWORK_PARTITIONS = {
'system', 'product', 'system_ext', 'system_other', 'root', 'system_dlkm' 'system', 'product', 'system_ext', 'system_other', 'root', 'system_dlkm',
} 'vbmeta_system'
# Partitions that are grabbed from the vendor partial build by default.
_VENDOR_PARTITIONS = {
'vendor', 'odm', 'oem', 'boot', 'vendor_boot', 'recovery',
'prebuilt_images', 'radio', 'data', 'vendor_dlkm', 'odm_dlkm'
} }
def InferItemList(input_namelist, framework): def InferItemList(input_namelist, framework):
item_list = [] item_set = set()
# Some META items are grabbed from partial builds directly. # Some META items are always grabbed from partial builds directly.
# Others are combined in merge_meta.py. # Others are combined in merge_meta.py.
if framework: if framework:
item_list.extend([ item_set.update([
'META/liblz4.so', 'META/liblz4.so',
'META/postinstall_config.txt', 'META/postinstall_config.txt',
'META/update_engine_config.txt', 'META/update_engine_config.txt',
'META/zucchini_config.txt', 'META/zucchini_config.txt',
]) ])
else: # vendor else: # vendor
item_list.extend([ item_set.update([
'META/kernel_configs.txt', 'META/kernel_configs.txt',
'META/kernel_version.txt', 'META/kernel_version.txt',
'META/otakeys.txt', 'META/otakeys.txt',
'META/pack_radioimages.txt',
'META/releasetools.py', 'META/releasetools.py',
'OTA/android-info.txt',
]) ])
# Grab a set of items for the expected partitions in the partial build. # Grab a set of items for the expected partitions in the partial build.
for partition in (_FRAMEWORK_PARTITIONS if framework else _VENDOR_PARTITIONS): seen_partitions = []
for namelist in input_namelist: for namelist in input_namelist:
if namelist.startswith('%s/' % partition.upper()): if namelist.endswith('/'):
continue
partition = namelist.split('/')[0].lower()
# META items are grabbed above, or merged later.
if partition == 'meta':
continue
if partition == 'images':
image_partition, extension = os.path.splitext(os.path.basename(namelist))
if image_partition == 'vbmeta':
# Always regenerate vbmeta.img since it depends on hash information
# from both builds.
continue
if extension in ('.img', '.map'):
# Include image files in IMAGES/* if the partition comes from
# the expected set.
if (framework and image_partition in _FRAMEWORK_PARTITIONS) or (
not framework and image_partition not in _FRAMEWORK_PARTITIONS):
item_set.add(namelist)
elif not framework:
# Include all miscellaneous non-image files in IMAGES/* from
# the vendor build.
item_set.add(namelist)
continue
# Skip already-visited partitions.
if partition in seen_partitions:
continue
seen_partitions.append(partition)
if (framework and partition in _FRAMEWORK_PARTITIONS) or (
not framework and partition not in _FRAMEWORK_PARTITIONS):
fs_config_prefix = '' if partition == 'system' else '%s_' % partition fs_config_prefix = '' if partition == 'system' else '%s_' % partition
item_list.extend([ item_set.update([
'%s/*' % partition.upper(), '%s/*' % partition.upper(),
'IMAGES/%s.img' % partition,
'IMAGES/%s.map' % partition,
'META/%sfilesystem_config.txt' % fs_config_prefix, 'META/%sfilesystem_config.txt' % fs_config_prefix,
]) ])
break
return sorted(item_list) return sorted(item_set)
def InferFrameworkMiscInfoKeys(input_namelist): def InferFrameworkMiscInfoKeys(input_namelist):
@@ -223,8 +247,8 @@ def InferFrameworkMiscInfoKeys(input_namelist):
] ]
for partition in _FRAMEWORK_PARTITIONS: for partition in _FRAMEWORK_PARTITIONS:
for namelist in input_namelist: for partition_dir in ('%s/' % partition.upper(), 'SYSTEM/%s/' % partition):
if namelist.startswith('%s/' % partition.upper()): if partition_dir in input_namelist:
fs_type_prefix = '' if partition == 'system' else '%s_' % partition fs_type_prefix = '' if partition == 'system' else '%s_' % partition
keys.extend([ keys.extend([
'avb_%s_hashtree_enable' % partition, 'avb_%s_hashtree_enable' % partition,

View File

@@ -108,20 +108,27 @@ class MergeUtilsTest(test_utils.ReleaseToolsTestCase):
def test_ItemListToPartitionSet(self): def test_ItemListToPartitionSet(self):
item_list = [ item_list = [
'IMAGES/system_ext.img',
'META/apexkeys.txt', 'META/apexkeys.txt',
'META/apkcerts.txt', 'META/apkcerts.txt',
'META/filesystem_config.txt', 'META/filesystem_config.txt',
'PRODUCT/*', 'PRODUCT/*',
'SYSTEM/*', 'SYSTEM/*',
'SYSTEM_EXT/*', 'SYSTEM/system_ext/*',
] ]
partition_set = merge_utils.ItemListToPartitionSet(item_list) partition_set = merge_utils.ItemListToPartitionSet(item_list)
self.assertEqual(set(['product', 'system', 'system_ext']), partition_set) self.assertEqual(set(['product', 'system', 'system_ext']), partition_set)
def test_InferItemList_Framework(self): def test_InferItemList_Framework(self):
zip_namelist = [ zip_namelist = [
'IMAGES/product.img',
'IMAGES/product.map',
'IMAGES/system.img',
'IMAGES/system.map',
'SYSTEM/my_system_file', 'SYSTEM/my_system_file',
'PRODUCT/my_product_file', 'PRODUCT/my_product_file',
# Device does not use a separate system_ext partition.
'SYSTEM/system_ext/system_ext_file',
] ]
item_list = merge_utils.InferItemList(zip_namelist, framework=True) item_list = merge_utils.InferItemList(zip_namelist, framework=True)
@@ -147,37 +154,55 @@ class MergeUtilsTest(test_utils.ReleaseToolsTestCase):
zip_namelist = [ zip_namelist = [
'VENDOR/my_vendor_file', 'VENDOR/my_vendor_file',
'ODM/my_odm_file', 'ODM/my_odm_file',
'IMAGES/odm.img',
'IMAGES/odm.map',
'IMAGES/vendor.img',
'IMAGES/vendor.map',
'IMAGES/my_custom_image.img',
'IMAGES/my_custom_file.txt',
'IMAGES/vbmeta.img',
'CUSTOM_PARTITION/my_custom_file',
# Leftover framework pieces that shouldn't be grabbed.
'IMAGES/system.img',
'SYSTEM/system_file',
] ]
item_list = merge_utils.InferItemList(zip_namelist, framework=False) item_list = merge_utils.InferItemList(zip_namelist, framework=False)
expected_vendor_item_list = [ expected_vendor_item_list = [
'CUSTOM_PARTITION/*',
'IMAGES/my_custom_file.txt',
'IMAGES/my_custom_image.img',
'IMAGES/odm.img', 'IMAGES/odm.img',
'IMAGES/odm.map', 'IMAGES/odm.map',
'IMAGES/vendor.img', 'IMAGES/vendor.img',
'IMAGES/vendor.map', 'IMAGES/vendor.map',
'META/custom_partition_filesystem_config.txt',
'META/kernel_configs.txt', 'META/kernel_configs.txt',
'META/kernel_version.txt', 'META/kernel_version.txt',
'META/odm_filesystem_config.txt', 'META/odm_filesystem_config.txt',
'META/otakeys.txt', 'META/otakeys.txt',
'META/pack_radioimages.txt',
'META/releasetools.py', 'META/releasetools.py',
'META/vendor_filesystem_config.txt', 'META/vendor_filesystem_config.txt',
'ODM/*', 'ODM/*',
'OTA/android-info.txt',
'VENDOR/*', 'VENDOR/*',
] ]
self.assertEqual(item_list, expected_vendor_item_list) self.assertEqual(item_list, expected_vendor_item_list)
def test_InferFrameworkMiscInfoKeys(self): def test_InferFrameworkMiscInfoKeys(self):
zip_namelist = [ zip_namelist = [
'SYSTEM/my_system_file', 'PRODUCT/',
'SYSTEM_EXT/my_system_ext_file', 'SYSTEM/',
'SYSTEM/system_ext/',
] ]
keys = merge_utils.InferFrameworkMiscInfoKeys(zip_namelist) keys = merge_utils.InferFrameworkMiscInfoKeys(zip_namelist)
expected_keys = [ expected_keys = [
'ab_update', 'ab_update',
'avb_product_add_hashtree_footer_args',
'avb_product_hashtree_enable',
'avb_system_add_hashtree_footer_args', 'avb_system_add_hashtree_footer_args',
'avb_system_ext_add_hashtree_footer_args', 'avb_system_ext_add_hashtree_footer_args',
'avb_system_ext_hashtree_enable', 'avb_system_ext_hashtree_enable',
@@ -186,10 +211,13 @@ class MergeUtilsTest(test_utils.ReleaseToolsTestCase):
'avb_vbmeta_system_algorithm', 'avb_vbmeta_system_algorithm',
'avb_vbmeta_system_key_path', 'avb_vbmeta_system_key_path',
'avb_vbmeta_system_rollback_index_location', 'avb_vbmeta_system_rollback_index_location',
'building_product_image',
'building_system_ext_image', 'building_system_ext_image',
'building_system_image', 'building_system_image',
'default_system_dev_certificate', 'default_system_dev_certificate',
'fs_type', 'fs_type',
'product_disable_sparse',
'product_fs_type',
'system_disable_sparse', 'system_disable_sparse',
'system_ext_disable_sparse', 'system_ext_disable_sparse',
'system_ext_fs_type', 'system_ext_fs_type',