Merge "Add an option to input the boot variables for OTA package generation" am: 1ca7b10456
Change-Id: I33bbd3bb27fcba8f6a40e7c79b78c6751a7fc817
This commit is contained in:
commit
0dbde58c9b
2 changed files with 179 additions and 41 deletions
|
@ -189,6 +189,13 @@ A/B OTA specific options
|
|||
--payload_signer_key_size <key_size>
|
||||
Deprecated. Use the '--payload_signer_maximum_signature_size' instead.
|
||||
|
||||
--boot_variable_file <path>
|
||||
A file that contains the possible values of ro.boot.* properties. It's
|
||||
used to calculate the possible runtime fingerprints when some
|
||||
ro.product.* properties are overridden by the 'import' statement.
|
||||
The file expects one property per line, and each line has the following
|
||||
format: 'prop_name=value1,value2'. e.g. 'ro.boot.product.sku=std,pro'
|
||||
|
||||
--skip_postinstall
|
||||
Skip the postinstall hooks when generating an A/B OTA package (default:
|
||||
False). Note that this discards ALL the hooks, including non-optional
|
||||
|
@ -257,8 +264,8 @@ 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
|
||||
OPTIONS.force_non_ab = False
|
||||
OPTIONS.boot_variable_file = None
|
||||
|
||||
|
||||
METADATA_NAME = 'META-INF/com/android/metadata'
|
||||
|
@ -931,8 +938,18 @@ def GetPackageMetadata(target_info, source_info=None):
|
|||
assert isinstance(target_info, common.BuildInfo)
|
||||
assert source_info is None or isinstance(source_info, common.BuildInfo)
|
||||
|
||||
separator = '|'
|
||||
|
||||
boot_variable_values = {}
|
||||
if OPTIONS.boot_variable_file:
|
||||
d = common.LoadDictionaryFromFile(OPTIONS.boot_variable_file)
|
||||
for key, values in d.items():
|
||||
boot_variable_values[key] = [val.strip() for val in values.split(',')]
|
||||
|
||||
post_build_devices, post_build_fingerprints = \
|
||||
CalculateRuntimeDevicesAndFingerprints(target_info, boot_variable_values)
|
||||
metadata = {
|
||||
'post-build' : target_info.fingerprint,
|
||||
'post-build': separator.join(sorted(post_build_fingerprints)),
|
||||
'post-build-incremental': target_info.GetBuildProp(
|
||||
'ro.build.version.incremental'),
|
||||
'post-sdk-level': target_info.GetBuildProp(
|
||||
|
@ -955,12 +972,15 @@ def GetPackageMetadata(target_info, source_info=None):
|
|||
|
||||
is_incremental = source_info is not None
|
||||
if is_incremental:
|
||||
metadata['pre-build'] = source_info.fingerprint
|
||||
pre_build_devices, pre_build_fingerprints = \
|
||||
CalculateRuntimeDevicesAndFingerprints(source_info,
|
||||
boot_variable_values)
|
||||
metadata['pre-build'] = separator.join(sorted(pre_build_fingerprints))
|
||||
metadata['pre-build-incremental'] = source_info.GetBuildProp(
|
||||
'ro.build.version.incremental')
|
||||
metadata['pre-device'] = source_info.device
|
||||
metadata['pre-device'] = separator.join(sorted(pre_build_devices))
|
||||
else:
|
||||
metadata['pre-device'] = target_info.device
|
||||
metadata['pre-device'] = separator.join(sorted(post_build_devices))
|
||||
|
||||
# Use the actual post-timestamp, even for a downgrade case.
|
||||
metadata['post-timestamp'] = target_info.GetBuildProp('ro.build.date.utc')
|
||||
|
@ -1972,24 +1992,24 @@ def GenerateNonAbOtaPackage(target_file, output_file, source_file=None):
|
|||
output_file)
|
||||
|
||||
|
||||
def CalculateRuntimeFingerprints():
|
||||
"""Returns a set of runtime fingerprints based on the boot variables."""
|
||||
def CalculateRuntimeDevicesAndFingerprints(build_info, boot_variable_values):
|
||||
"""Returns a tuple of sets for runtime devices and fingerprints"""
|
||||
|
||||
build_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
|
||||
device_names = {build_info.device}
|
||||
fingerprints = {build_info.fingerprint}
|
||||
|
||||
if not OPTIONS.boot_variable_values:
|
||||
return fingerprints
|
||||
if not boot_variable_values:
|
||||
return device_names, 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()
|
||||
keys = boot_variable_values.keys()
|
||||
value_list = 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)
|
||||
info_dict = copy.deepcopy(build_info.info_dict)
|
||||
for partition in common.PARTITIONS_WITH_CARE_MAP:
|
||||
partition_prop_key = "{}.build.prop".format(partition)
|
||||
old_props = info_dict[partition_prop_key]
|
||||
|
@ -1997,9 +2017,10 @@ def CalculateRuntimeFingerprints():
|
|||
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
|
||||
new_build_info = common.BuildInfo(info_dict, build_info.oem_dicts)
|
||||
device_names.add(new_build_info.device)
|
||||
fingerprints.add(new_build_info.fingerprint)
|
||||
return device_names, fingerprints
|
||||
|
||||
|
||||
def main(argv):
|
||||
|
@ -2077,6 +2098,8 @@ def main(argv):
|
|||
OPTIONS.disable_fec_computation = True
|
||||
elif o == "--force_non_ab":
|
||||
OPTIONS.force_non_ab = True
|
||||
elif o == "--boot_variable_file":
|
||||
OPTIONS.boot_variable_file = a
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
@ -2114,6 +2137,7 @@ def main(argv):
|
|||
"output_metadata_path=",
|
||||
"disable_fec_computation",
|
||||
"force_non_ab",
|
||||
"boot_variable_file=",
|
||||
], extra_option_handler=option_handler)
|
||||
|
||||
if len(args) != 2:
|
||||
|
|
|
@ -27,7 +27,7 @@ from ota_from_target_files import (
|
|||
GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
|
||||
Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
|
||||
StreamingPropertyFiles, WriteFingerprintAssertion,
|
||||
CalculateRuntimeFingerprints)
|
||||
CalculateRuntimeDevicesAndFingerprints)
|
||||
|
||||
|
||||
def construct_target_files(secondary=False):
|
||||
|
@ -1334,6 +1334,9 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
|
|||
'ro.build.version.incremental=version-incremental',
|
||||
'ro.build.type=build-type',
|
||||
'ro.build.tags=build-tags',
|
||||
'ro.build.version.sdk=30',
|
||||
'ro.build.version.security_patch=2020',
|
||||
'ro.build.date.utc=12345678'
|
||||
]
|
||||
|
||||
VENDOR_BUILD_PROP = [
|
||||
|
@ -1345,11 +1348,12 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
|
|||
def setUp(self):
|
||||
common.OPTIONS.oem_dicts = None
|
||||
self.test_dir = common.MakeTempDir()
|
||||
self.writeFiles({'META/misc_info.txt': '\n'.join(self.MISC_INFO)})
|
||||
self.writeFiles({'META/misc_info.txt': '\n'.join(self.MISC_INFO)},
|
||||
self.test_dir)
|
||||
|
||||
def writeFiles(self, contents_dict):
|
||||
def writeFiles(self, contents_dict, out_dir):
|
||||
for path, content in contents_dict.items():
|
||||
abs_path = os.path.join(self.test_dir, path)
|
||||
abs_path = os.path.join(out_dir, path)
|
||||
dir_name = os.path.dirname(abs_path)
|
||||
if not os.path.exists(dir_name):
|
||||
os.makedirs(dir_name)
|
||||
|
@ -1371,12 +1375,14 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
|
|||
self.writeFiles({
|
||||
'SYSTEM/build.prop': '\n'.join(build_prop),
|
||||
'VENDOR/build.prop': '\n'.join(self.VENDOR_BUILD_PROP),
|
||||
})
|
||||
common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
|
||||
}, self.test_dir)
|
||||
|
||||
self.assertEqual({
|
||||
self.constructFingerprint('product-brand/product-name/product-device')
|
||||
}, CalculateRuntimeFingerprints())
|
||||
build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
|
||||
expected = ({'product-device'},
|
||||
{self.constructFingerprint(
|
||||
'product-brand/product-name/product-device')})
|
||||
self.assertEqual(expected,
|
||||
CalculateRuntimeDevicesAndFingerprints(build_info, {}))
|
||||
|
||||
def test_CalculatePossibleFingerprints_single_override(self):
|
||||
vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
|
||||
|
@ -1390,20 +1396,22 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
|
|||
'ro.product.vendor.name=vendor-product-std',
|
||||
'VENDOR/etc/build_pro.prop':
|
||||
'ro.product.vendor.name=vendor-product-pro',
|
||||
})
|
||||
common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
|
||||
common.OPTIONS.boot_variable_values = {
|
||||
'ro.boot.sku_name': ['std', 'pro']
|
||||
}
|
||||
}, self.test_dir)
|
||||
|
||||
self.assertEqual({
|
||||
build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
|
||||
boot_variable_values = {'ro.boot.sku_name': ['std', 'pro']}
|
||||
|
||||
expected = ({'vendor-product-device'}, {
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-name/vendor-product-device'),
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-std/vendor-product-device'),
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-pro/vendor-product-device'),
|
||||
}, CalculateRuntimeFingerprints())
|
||||
})
|
||||
self.assertEqual(
|
||||
expected, CalculateRuntimeDevicesAndFingerprints(
|
||||
build_info, boot_variable_values))
|
||||
|
||||
def test_CalculatePossibleFingerprints_multiple_overrides(self):
|
||||
vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
|
||||
|
@ -1422,14 +1430,17 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
|
|||
'ro.product.vendor.name=vendor-product-pro',
|
||||
'VENDOR/etc/build_product2.prop':
|
||||
'ro.product.vendor.device=vendor-device-product2',
|
||||
})
|
||||
common.OPTIONS.info_dict = common.LoadInfoDict(self.test_dir)
|
||||
common.OPTIONS.boot_variable_values = {
|
||||
}, self.test_dir)
|
||||
|
||||
build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
|
||||
boot_variable_values = {
|
||||
'ro.boot.sku_name': ['std', 'pro'],
|
||||
'ro.boot.device_name': ['product1', 'product2'],
|
||||
}
|
||||
|
||||
self.assertEqual({
|
||||
expected_devices = {'vendor-product-device', 'vendor-device-product1',
|
||||
'vendor-device-product2'}
|
||||
expected_fingerprints = {
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-name/vendor-product-device'),
|
||||
self.constructFingerprint(
|
||||
|
@ -1439,5 +1450,108 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
|
|||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-std/vendor-device-product2'),
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-pro/vendor-device-product2'),
|
||||
}, CalculateRuntimeFingerprints())
|
||||
'vendor-product-brand/vendor-product-pro/vendor-device-product2')
|
||||
}
|
||||
self.assertEqual((expected_devices, expected_fingerprints),
|
||||
CalculateRuntimeDevicesAndFingerprints(
|
||||
build_info, boot_variable_values))
|
||||
|
||||
def test_GetPackageMetadata_full_package(self):
|
||||
vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
|
||||
vendor_build_prop.extend([
|
||||
'import /vendor/etc/build_${ro.boot.sku_name}.prop',
|
||||
])
|
||||
self.writeFiles({
|
||||
'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
|
||||
'VENDOR/build.prop': '\n'.join(vendor_build_prop),
|
||||
'VENDOR/etc/build_std.prop':
|
||||
'ro.product.vendor.name=vendor-product-std',
|
||||
'VENDOR/etc/build_pro.prop':
|
||||
'ro.product.vendor.name=vendor-product-pro',
|
||||
}, self.test_dir)
|
||||
|
||||
common.OPTIONS.boot_variable_file = common.MakeTempFile()
|
||||
with open(common.OPTIONS.boot_variable_file, 'w') as f:
|
||||
f.write('ro.boot.sku_name=std,pro')
|
||||
|
||||
build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
|
||||
metadata = GetPackageMetadata(build_info)
|
||||
self.assertEqual('vendor-product-device', metadata['pre-device'])
|
||||
fingerprints = [
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-name/vendor-product-device'),
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-pro/vendor-product-device'),
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-std/vendor-product-device'),
|
||||
]
|
||||
self.assertEqual('|'.join(fingerprints), metadata['post-build'])
|
||||
|
||||
def test_GetPackageMetadata_incremental_package(self):
|
||||
vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
|
||||
vendor_build_prop.extend([
|
||||
'import /vendor/etc/build_${ro.boot.sku_name}.prop',
|
||||
])
|
||||
self.writeFiles({
|
||||
'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
|
||||
'VENDOR/build.prop': '\n'.join(vendor_build_prop),
|
||||
'VENDOR/etc/build_std.prop':
|
||||
'ro.product.vendor.device=vendor-device-std',
|
||||
'VENDOR/etc/build_pro.prop':
|
||||
'ro.product.vendor.device=vendor-device-pro',
|
||||
}, self.test_dir)
|
||||
|
||||
common.OPTIONS.boot_variable_file = common.MakeTempFile()
|
||||
with open(common.OPTIONS.boot_variable_file, 'w') as f:
|
||||
f.write('ro.boot.sku_name=std,pro')
|
||||
|
||||
source_dir = common.MakeTempDir()
|
||||
source_build_prop = [
|
||||
'ro.build.version.release=source-version-release',
|
||||
'ro.build.id=source-build-id',
|
||||
'ro.build.version.incremental=source-version-incremental',
|
||||
'ro.build.type=build-type',
|
||||
'ro.build.tags=build-tags',
|
||||
'ro.build.version.sdk=29',
|
||||
'ro.build.version.security_patch=2020',
|
||||
'ro.build.date.utc=12340000'
|
||||
]
|
||||
self.writeFiles({
|
||||
'META/misc_info.txt': '\n'.join(self.MISC_INFO),
|
||||
'SYSTEM/build.prop': '\n'.join(source_build_prop),
|
||||
'VENDOR/build.prop': '\n'.join(vendor_build_prop),
|
||||
'VENDOR/etc/build_std.prop':
|
||||
'ro.product.vendor.device=vendor-device-std',
|
||||
'VENDOR/etc/build_pro.prop':
|
||||
'ro.product.vendor.device=vendor-device-pro',
|
||||
}, source_dir)
|
||||
common.OPTIONS.incremental_source = source_dir
|
||||
|
||||
target_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
|
||||
source_info = common.BuildInfo(common.LoadInfoDict(source_dir))
|
||||
|
||||
metadata = GetPackageMetadata(target_info, source_info)
|
||||
self.assertEqual(
|
||||
'vendor-device-pro|vendor-device-std|vendor-product-device',
|
||||
metadata['pre-device'])
|
||||
suffix = ':source-version-release/source-build-id/' \
|
||||
'source-version-incremental:build-type/build-tags'
|
||||
pre_fingerprints = [
|
||||
'vendor-product-brand/vendor-product-name/vendor-device-pro'
|
||||
'{}'.format(suffix),
|
||||
'vendor-product-brand/vendor-product-name/vendor-device-std'
|
||||
'{}'.format(suffix),
|
||||
'vendor-product-brand/vendor-product-name/vendor-product-device'
|
||||
'{}'.format(suffix),
|
||||
]
|
||||
self.assertEqual('|'.join(pre_fingerprints), metadata['pre-build'])
|
||||
|
||||
post_fingerprints = [
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-name/vendor-device-pro'),
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-name/vendor-device-std'),
|
||||
self.constructFingerprint(
|
||||
'vendor-product-brand/vendor-product-name/vendor-product-device'),
|
||||
]
|
||||
self.assertEqual('|'.join(post_fingerprints), metadata['post-build'])
|
||||
|
|
Loading…
Reference in a new issue