Merge "Detect downgrade by checking build time for all partitions" into main am: fb5630b393
am: fb96253429
Original change: https://android-review.googlesource.com/c/platform/build/+/2878035 Change-Id: Idf3e9596dbdce573e0ce321d46b13af762f3b1f6 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -1038,7 +1038,11 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None):
|
||||
partition_timestamps_flags = []
|
||||
# Enforce a max timestamp this payload can be applied on top of.
|
||||
if OPTIONS.downgrade:
|
||||
max_timestamp = source_info.GetBuildProp("ro.build.date.utc")
|
||||
# When generating ota between merged target-files, partition build date can
|
||||
# decrease in target, at the same time as ro.build.date.utc increases,
|
||||
# so always pick largest value.
|
||||
max_timestamp = max(source_info.GetBuildProp("ro.build.date.utc"),
|
||||
str(metadata.postcondition.timestamp))
|
||||
partition_timestamps_flags = GeneratePartitionTimestampFlagsDowngrade(
|
||||
metadata.precondition.partition_state,
|
||||
metadata.postcondition.partition_state
|
||||
|
@@ -364,26 +364,66 @@ def HandleDowngradeMetadata(metadata_proto, target_info, source_info):
|
||||
# Only incremental OTAs are allowed to reach here.
|
||||
assert OPTIONS.incremental_source is not None
|
||||
|
||||
# used for logging upon errors
|
||||
log_downgrades = []
|
||||
log_upgrades = []
|
||||
|
||||
post_timestamp = target_info.GetBuildProp("ro.build.date.utc")
|
||||
pre_timestamp = source_info.GetBuildProp("ro.build.date.utc")
|
||||
is_downgrade = int(post_timestamp) < int(pre_timestamp)
|
||||
if int(post_timestamp) < int(pre_timestamp):
|
||||
logger.info(f"ro.build.date.utc pre timestamp: {pre_timestamp}, "
|
||||
f"post timestamp: {post_timestamp}. Downgrade detected.")
|
||||
log_downgrades.append(f"ro.build.date.utc pre: {pre_timestamp} post: {post_timestamp}")
|
||||
else:
|
||||
logger.info(f"ro.build.date.utc pre timestamp: {pre_timestamp}, "
|
||||
f"post timestamp: {post_timestamp}.")
|
||||
log_upgrades.append(f"ro.build.date.utc pre: {pre_timestamp} post: {post_timestamp}")
|
||||
|
||||
# When merging system and vendor target files, it is not enough
|
||||
# to check ro.build.date.utc, the timestamp for each partition must
|
||||
# be checked.
|
||||
if source_info.is_ab:
|
||||
ab_partitions = set(source_info.get("ab_partitions"))
|
||||
for partition in sorted(set(PARTITIONS_WITH_BUILD_PROP) & ab_partitions):
|
||||
|
||||
partition_prop = source_info.get('{}.build.prop'.format(partition))
|
||||
# Skip if the partition is missing, or it doesn't have a build.prop
|
||||
if not partition_prop or not partition_prop.build_props:
|
||||
continue
|
||||
partition_prop = target_info.get('{}.build.prop'.format(partition))
|
||||
# Skip if the partition is missing, or it doesn't have a build.prop
|
||||
if not partition_prop or not partition_prop.build_props:
|
||||
continue
|
||||
|
||||
post_timestamp = target_info.GetPartitionBuildProp(
|
||||
'ro.build.date.utc', partition)
|
||||
pre_timestamp = source_info.GetPartitionBuildProp(
|
||||
'ro.build.date.utc', partition)
|
||||
if int(post_timestamp) < int(pre_timestamp):
|
||||
logger.info(f"Partition {partition} pre timestamp: {pre_timestamp}, "
|
||||
f"post time: {post_timestamp}. Downgrade detected.")
|
||||
log_downgrades.append(f"{partition} pre: {pre_timestamp} post: {post_timestamp}")
|
||||
else:
|
||||
logger.info(f"Partition {partition} pre timestamp: {pre_timestamp}, "
|
||||
f"post timestamp: {post_timestamp}.")
|
||||
log_upgrades.append(f"{partition} pre: {pre_timestamp} post: {post_timestamp}")
|
||||
|
||||
if OPTIONS.spl_downgrade:
|
||||
metadata_proto.spl_downgrade = True
|
||||
|
||||
if OPTIONS.downgrade:
|
||||
if not is_downgrade:
|
||||
if len(log_downgrades) == 0:
|
||||
raise RuntimeError(
|
||||
"--downgrade or --override_timestamp specified but no downgrade "
|
||||
"detected: pre: %s, post: %s" % (pre_timestamp, post_timestamp))
|
||||
"detected. Current values for ro.build.date.utc: " + ', '.join(log_upgrades))
|
||||
metadata_proto.downgrade = True
|
||||
else:
|
||||
if is_downgrade:
|
||||
if len(log_downgrades) != 0:
|
||||
raise RuntimeError(
|
||||
"Downgrade detected based on timestamp check: pre: %s, post: %s. "
|
||||
"Downgrade detected based on timestamp check in ro.build.date.utc. "
|
||||
"Need to specify --override_timestamp OR --downgrade to allow "
|
||||
"building the incremental." % (pre_timestamp, post_timestamp))
|
||||
|
||||
"building the incremental. Downgrades detected for: "
|
||||
+ ', '.join(log_downgrades))
|
||||
|
||||
def ComputeRuntimeBuildInfos(default_build_info, boot_variable_values):
|
||||
"""Returns a set of build info objects that may exist during runtime."""
|
||||
|
@@ -163,6 +163,20 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
||||
'oem_fingerprint_properties': 'ro.product.device ro.product.brand',
|
||||
}
|
||||
|
||||
TEST_TARGET_VENDOR_INFO_DICT = common.PartitionBuildProps.FromDictionary(
|
||||
'vendor', {
|
||||
'ro.vendor.build.date.utc' : '87654321',
|
||||
'ro.product.vendor.device':'vendor-device',
|
||||
'ro.vendor.build.fingerprint': 'build-fingerprint-vendor'}
|
||||
)
|
||||
|
||||
TEST_SOURCE_VENDOR_INFO_DICT = common.PartitionBuildProps.FromDictionary(
|
||||
'vendor', {
|
||||
'ro.vendor.build.date.utc' : '12345678',
|
||||
'ro.product.vendor.device':'vendor-device',
|
||||
'ro.vendor.build.fingerprint': 'build-fingerprint-vendor'}
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
self.testdata_dir = test_utils.get_testdata_dir()
|
||||
self.assertTrue(os.path.exists(self.testdata_dir))
|
||||
@@ -351,6 +365,13 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
||||
source_info['build.prop'].build_props['ro.build.date.utc'],
|
||||
target_info['build.prop'].build_props['ro.build.date.utc'])
|
||||
|
||||
@staticmethod
|
||||
def _test_GetPackageMetadata_swapVendorBuildTimestamps(target_info, source_info):
|
||||
(target_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc'],
|
||||
source_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc']) = (
|
||||
source_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc'],
|
||||
target_info['vendor.build.prop'].build_props['ro.vendor.build.date.utc'])
|
||||
|
||||
def test_GetPackageMetadata_unintentionalDowngradeDetected(self):
|
||||
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
||||
source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
|
||||
@@ -363,6 +384,24 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
||||
self.assertRaises(RuntimeError, self.GetLegacyOtaMetadata, target_info,
|
||||
source_info)
|
||||
|
||||
def test_GetPackageMetadata_unintentionalVendorDowngradeDetected(self):
|
||||
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
||||
target_info_dict['ab_update'] = 'true'
|
||||
target_info_dict['ab_partitions'] = ['vendor']
|
||||
target_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_TARGET_VENDOR_INFO_DICT)
|
||||
source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
|
||||
source_info_dict['ab_update'] = 'true'
|
||||
source_info_dict['ab_partitions'] = ['vendor']
|
||||
source_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_SOURCE_VENDOR_INFO_DICT)
|
||||
self._test_GetPackageMetadata_swapVendorBuildTimestamps(
|
||||
target_info_dict, source_info_dict)
|
||||
|
||||
target_info = common.BuildInfo(target_info_dict, None)
|
||||
source_info = common.BuildInfo(source_info_dict, None)
|
||||
common.OPTIONS.incremental_source = ''
|
||||
self.assertRaises(RuntimeError, self.GetLegacyOtaMetadata, target_info,
|
||||
source_info)
|
||||
|
||||
def test_GetPackageMetadata_downgrade(self):
|
||||
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
||||
source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
|
||||
@@ -397,6 +436,55 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
|
||||
},
|
||||
metadata)
|
||||
|
||||
def test_GetPackageMetadata_vendorDowngrade(self):
|
||||
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
|
||||
target_info_dict['ab_update'] = 'true'
|
||||
target_info_dict['ab_partitions'] = ['vendor']
|
||||
target_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_TARGET_VENDOR_INFO_DICT)
|
||||
source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
|
||||
source_info_dict['ab_update'] = 'true'
|
||||
source_info_dict['ab_partitions'] = ['vendor']
|
||||
source_info_dict["vendor.build.prop"] = copy.deepcopy(self.TEST_SOURCE_VENDOR_INFO_DICT)
|
||||
self._test_GetPackageMetadata_swapVendorBuildTimestamps(
|
||||
target_info_dict, source_info_dict)
|
||||
|
||||
target_info = common.BuildInfo(target_info_dict, None)
|
||||
source_info = common.BuildInfo(source_info_dict, None)
|
||||
common.OPTIONS.incremental_source = ''
|
||||
common.OPTIONS.downgrade = True
|
||||
common.OPTIONS.wipe_user_data = True
|
||||
common.OPTIONS.spl_downgrade = True
|
||||
metadata = self.GetLegacyOtaMetadata(target_info, source_info)
|
||||
# Reset spl_downgrade so other tests are unaffected
|
||||
common.OPTIONS.spl_downgrade = False
|
||||
|
||||
self.assertDictEqual(
|
||||
{
|
||||
'ota-downgrade': 'yes',
|
||||
'ota-type': 'AB',
|
||||
'ota-required-cache': '0',
|
||||
'ota-wipe': 'yes',
|
||||
'post-build': 'build-fingerprint-target',
|
||||
'post-build-incremental': 'build-version-incremental-target',
|
||||
'post-sdk-level': '27',
|
||||
'post-security-patch-level': '2017-12-01',
|
||||
'post-timestamp': '1500000000',
|
||||
'pre-device': 'product-device',
|
||||
'pre-build': 'build-fingerprint-source',
|
||||
'pre-build-incremental': 'build-version-incremental-source',
|
||||
'spl-downgrade': 'yes',
|
||||
},
|
||||
metadata)
|
||||
|
||||
post_build = GetPackageMetadata(target_info, source_info).postcondition
|
||||
self.assertEqual('vendor', post_build.partition_state[0].partition_name)
|
||||
self.assertEqual('12345678', post_build.partition_state[0].version)
|
||||
|
||||
pre_build = GetPackageMetadata(target_info, source_info).precondition
|
||||
self.assertEqual('vendor', pre_build.partition_state[0].partition_name)
|
||||
self.assertEqual('87654321', pre_build.partition_state[0].version)
|
||||
|
||||
|
||||
@test_utils.SkipIfExternalToolsUnavailable()
|
||||
def test_GetTargetFilesZipForSecondaryImages(self):
|
||||
input_file = construct_target_files(secondary=True)
|
||||
|
Reference in New Issue
Block a user