diff options
author | Kelvin Zhang <zhangkelvin@google.com> | 2020-09-04 12:37:45 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-09-04 12:37:45 +0000 |
commit | 7a1364a36a573d0eca13397340adcc4bf0d2be66 (patch) | |
tree | 684a1a1b47c2a4b5d1354f0e6b62f11d923106ff | |
parent | b7c32f9021cc28f46b8986f12c525e916c63a7e1 (diff) | |
parent | 49fe034137e023dc9fe0bf4839f0c7ba9691dfe6 (diff) | |
download | build-7a1364a36a573d0eca13397340adcc4bf0d2be66.tar.gz |
Merge "Generate partition timestamps in ota_from_target_files" am: 49fe034137
Original change: https://android-review.googlesource.com/c/platform/build/+/1402687
Change-Id: I23b48a511fded51330d7620ec748d36225175e2f
-rw-r--r-- | tools/releasetools/common.py | 10 | ||||
-rwxr-xr-x | tools/releasetools/ota_from_target_files.py | 30 | ||||
-rw-r--r-- | tools/releasetools/ota_utils.py | 12 | ||||
-rw-r--r-- | tools/releasetools/test_ota_from_target_files.py | 158 |
4 files changed, 124 insertions, 86 deletions
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 56785d64c0..c77d8c68d5 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -118,7 +118,7 @@ AVB_PARTITIONS = ('boot', 'dtbo', 'odm', 'product', 'recovery', 'system', AVB_VBMETA_PARTITIONS = ('vbmeta_system', 'vbmeta_vendor') # Partitions that should have their care_map added to META/care_map.pb -PARTITIONS_WITH_CARE_MAP = ( +PARTITIONS_WITH_CARE_MAP = [ 'system', 'vendor', 'product', @@ -126,7 +126,7 @@ PARTITIONS_WITH_CARE_MAP = ( 'odm', 'vendor_dlkm', 'odm_dlkm', -) +] class ErrorCode(object): @@ -729,10 +729,14 @@ def LoadInfoDict(input_file, repacking=False): fingerprint = build_info.GetPartitionFingerprint(partition) if fingerprint: d["avb_{}_salt".format(partition)] = sha256(fingerprint.encode()).hexdigest() - + try: + d["ab_partitions"] = read_helper("META/ab_partitions.txt").split("\n") + except KeyError: + logger.warning("Can't find META/ab_partitions.txt") return d + def LoadListFromFile(file_path): with open(file_path) as f: return f.read().splitlines() diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py index 93a3e0edc7..2833397ed8 100755 --- a/tools/releasetools/ota_from_target_files.py +++ b/tools/releasetools/ota_from_target_files.py @@ -778,7 +778,7 @@ def GetTargetFilesZipForRetrofitDynamicPartitions(input_file, with open(new_ab_partitions, 'w') as f: for partition in ab_partitions: if (partition in dynamic_partition_list and - partition not in super_block_devices): + partition not in super_block_devices): logger.info("Dropping %s from ab_partitions.txt", partition) continue f.write(partition + "\n") @@ -825,31 +825,49 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None): compression=zipfile.ZIP_DEFLATED) if source_file is not None: + assert "ab_partitions" in OPTIONS.source_info_dict, \ + "META/ab_partitions.txt is required for ab_update." + assert "ab_partitions" in OPTIONS.target_info_dict, \ + "META/ab_partitions.txt is required for ab_update." target_info = common.BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts) source_info = common.BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts) else: + assert "ab_partitions" in OPTIONS.info_dict, \ + "META/ab_partitions.txt is required for ab_update." target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts) source_info = None - # Metadata to comply with Android OTA package format. - metadata = GetPackageMetadata(target_info, source_info) - if OPTIONS.retrofit_dynamic_partitions: target_file = GetTargetFilesZipForRetrofitDynamicPartitions( target_file, target_info.get("super_block_devices").strip().split(), target_info.get("dynamic_partition_list").strip().split()) elif OPTIONS.skip_postinstall: target_file = GetTargetFilesZipWithoutPostinstallConfig(target_file) + # Target_file may have been modified, reparse ab_partitions + with zipfile.ZipFile(target_file, allowZip64=True) as zfp: + target_info.info_dict['ab_partitions'] = zfp.read( + AB_PARTITIONS).strip().split("\n") + # Metadata to comply with Android OTA package format. + metadata = GetPackageMetadata(target_info, source_info) # Generate payload. payload = Payload() + partition_timestamps = [] # Enforce a max timestamp this payload can be applied on top of. if OPTIONS.downgrade: max_timestamp = source_info.GetBuildProp("ro.build.date.utc") else: max_timestamp = str(metadata.postcondition.timestamp) + partition_timestamps = [ + part.partition_name + ":" + part.version + for part in metadata.postcondition.partition_state] additional_args = ["--max_timestamp", max_timestamp] + if partition_timestamps: + additional_args.extend( + ["--partition_timestamps", ",".join( + partition_timestamps)] + ) payload.Generate(target_file, source_file, additional_args) @@ -877,7 +895,7 @@ def GenerateAbOtaPackage(target_file, output_file, source_file=None): # into A/B OTA package. target_zip = zipfile.ZipFile(target_file, "r") if (target_info.get("verity") == "true" or - target_info.get("avb_enable") == "true"): + target_info.get("avb_enable") == "true"): care_map_list = [x for x in ["care_map.pb", "care_map.txt"] if "META/" + x in target_zip.namelist()] @@ -1073,7 +1091,7 @@ def main(argv): # use_dynamic_partitions but target build does. if (OPTIONS.source_info_dict and OPTIONS.source_info_dict.get("use_dynamic_partitions") != "true" and - OPTIONS.target_info_dict.get("use_dynamic_partitions") == "true"): + OPTIONS.target_info_dict.get("use_dynamic_partitions") == "true"): if OPTIONS.target_info_dict.get("dynamic_partition_retrofit") != "true": raise common.ExternalError( "Expect to generate incremental OTA for retrofitting dynamic " diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py index 2e26a0543c..d444d41f83 100644 --- a/tools/releasetools/ota_utils.py +++ b/tools/releasetools/ota_utils.py @@ -162,10 +162,18 @@ def UpdateDeviceState(device_state, build_info, boot_variable_values, def UpdatePartitionStates(partition_states): """Update the per-partition state according to its build.prop""" - + if not build_info.is_ab: + return build_info_set = ComputeRuntimeBuildInfos(build_info, boot_variable_values) - for partition in PARTITIONS_WITH_CARE_MAP: + assert "ab_partitions" in build_info.info_dict,\ + "ab_partitions property required for ab update." + ab_partitions = set(build_info.info_dict.get("ab_partitions")) + + # delta_generator will error out on unused timestamps, + # so only generate timestamps for dynamic partitions + # used in OTA update. + for partition in sorted(set(PARTITIONS_WITH_CARE_MAP) & ab_partitions): partition_prop = build_info.info_dict.get( '{}.build.prop'.format(partition)) # Skip if the partition is missing, or it doesn't have a build.prop diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py index 6f5e78fbfd..84cd4c809a 100644 --- a/tools/releasetools/test_ota_from_target_files.py +++ b/tools/releasetools/test_ota_from_target_files.py @@ -30,7 +30,7 @@ from ota_from_target_files import ( GetTargetFilesZipForSecondaryImages, GetTargetFilesZipWithoutPostinstallConfig, Payload, PayloadSigner, POSTINSTALL_CONFIG, - StreamingPropertyFiles) + StreamingPropertyFiles, AB_PARTITIONS) from test_utils import PropertyFilesTestCase @@ -166,7 +166,7 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.no_signing = False common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } common.OPTIONS.search_path = test_utils.get_search_path() @@ -179,40 +179,42 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): def test_GetPackageMetadata_abOta_full(self): target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT) target_info_dict['ab_update'] = 'true' + target_info_dict['ab_partitions'] = [] target_info = common.BuildInfo(target_info_dict, None) metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-type' : 'AB', - 'ota-required-cache' : '0', - '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', + 'ota-type': 'AB', + 'ota-required-cache': '0', + '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', }, metadata) def test_GetPackageMetadata_abOta_incremental(self): target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT) target_info_dict['ab_update'] = 'true' + target_info_dict['ab_partitions'] = [] target_info = common.BuildInfo(target_info_dict, None) source_info = common.BuildInfo(self.TEST_SOURCE_INFO_DICT, None) common.OPTIONS.incremental_source = '' metadata = self.GetLegacyOtaMetadata(target_info, source_info) self.assertDictEqual( { - 'ota-type' : 'AB', - 'ota-required-cache' : '0', - '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', + 'ota-type': 'AB', + 'ota-required-cache': '0', + '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', }, metadata) @@ -221,14 +223,14 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-type' : 'BLOCK', - 'ota-required-cache' : '0', - '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', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + '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', }, metadata) @@ -239,16 +241,16 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): metadata = self.GetLegacyOtaMetadata(target_info, source_info) self.assertDictEqual( { - 'ota-type' : 'BLOCK', - 'ota-required-cache' : '0', - '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', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + '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', }, metadata) @@ -258,15 +260,15 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-type' : 'BLOCK', - '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', + 'ota-type': 'BLOCK', + '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', }, metadata) @@ -276,15 +278,15 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): metadata = self.GetLegacyOtaMetadata(target_info) self.assertDictEqual( { - 'ota-retrofit-dynamic-partitions' : 'yes', - 'ota-type' : 'BLOCK', - 'ota-required-cache' : '0', - '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', + 'ota-retrofit-dynamic-partitions': 'yes', + 'ota-type': 'BLOCK', + 'ota-required-cache': '0', + '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', }, metadata) @@ -322,18 +324,18 @@ class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase): self.assertDictEqual( { - 'ota-downgrade' : 'yes', - 'ota-type' : 'BLOCK', - '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' : '1400000000', - 'pre-device' : 'product-device', - 'pre-build' : 'build-fingerprint-source', - 'pre-build-incremental' : 'build-version-incremental-source', + 'ota-downgrade': 'yes', + 'ota-type': 'BLOCK', + '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': '1400000000', + 'pre-device': 'product-device', + 'pre-build': 'build-fingerprint-source', + 'pre-build-incremental': 'build-version-incremental-source', }, metadata) @@ -770,7 +772,7 @@ class AbOtaPropertyFilesTest(PropertyFilesTestCase): common.OPTIONS.payload_signer_args = None common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } def test_init(self): @@ -904,7 +906,8 @@ class AbOtaPropertyFilesTest(PropertyFilesTestCase): with zipfile.ZipFile(zip_file, 'r') as zip_fp: raw_metadata = property_files.GetPropertyFilesString( zip_fp, reserve_space=False) - property_files_string = property_files.Finalize(zip_fp, len(raw_metadata)) + property_files_string = property_files.Finalize( + zip_fp, len(raw_metadata)) tokens = self._parse_property_files_string(property_files_string) # "7" includes the four entries above, two metadata entries, and one entry @@ -937,7 +940,7 @@ class PayloadSignerTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.payload_signer_args = [] common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } def _assertFilesEqual(self, file1, file2): @@ -955,7 +958,7 @@ class PayloadSignerTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.package_key = os.path.join( self.testdata_dir, 'testkey_with_passwd') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : 'foo', + common.OPTIONS.package_key: 'foo', } payload_signer = PayloadSigner() self.assertEqual('openssl', payload_signer.signer) @@ -1032,7 +1035,7 @@ class PayloadTest(test_utils.ReleaseToolsTestCase): common.OPTIONS.payload_signer_args = None common.OPTIONS.package_key = os.path.join(self.testdata_dir, 'testkey') common.OPTIONS.key_passwords = { - common.OPTIONS.package_key : None, + common.OPTIONS.package_key: None, } @staticmethod @@ -1187,8 +1190,8 @@ class PayloadTest(test_utils.ReleaseToolsTestCase): # Then assert these entries are stored. for entry_info in verify_zip.infolist(): if entry_info.filename not in ( - Payload.SECONDARY_PAYLOAD_BIN, - Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT): + Payload.SECONDARY_PAYLOAD_BIN, + Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT): continue self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type) @@ -1198,6 +1201,7 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'recovery_api_version=3', 'fstab_version=2', 'recovery_as_boot=true', + 'ab_update=true', ] BUILD_PROP = [ @@ -1359,6 +1363,7 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'ro.product.vendor.name=vendor-product-std', 'VENDOR/etc/build_pro.prop': 'ro.product.vendor.name=vendor-product-pro', + AB_PARTITIONS: '\n'.join(['system', 'vendor']), }, self.test_dir) common.OPTIONS.boot_variable_file = common.MakeTempFile() @@ -1410,6 +1415,8 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): 'import /vendor/etc/build_${ro.boot.sku_name}.prop', ]) self.writeFiles({ + 'META/misc_info.txt': '\n'.join(self.MISC_INFO), + 'META/ab_partitions.txt': '\n'.join(['system', 'vendor', 'product']), 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP), 'VENDOR/build.prop': '\n'.join(vendor_build_prop), 'VENDOR/etc/build_std.prop': @@ -1446,6 +1453,7 @@ class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase): ] self.writeFiles({ 'META/misc_info.txt': '\n'.join(self.MISC_INFO), + 'META/ab_partitions.txt': '\n'.join(['system', 'vendor', 'product']), 'SYSTEM/build.prop': '\n'.join(source_build_prop), 'VENDOR/build.prop': '\n'.join(vendor_build_prop), 'VENDOR/etc/build_std.prop': |