diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py index 1a4f7e15b7..9715aa180c 100755 --- a/tools/releasetools/ota_from_target_files.py +++ b/tools/releasetools/ota_from_target_files.py @@ -241,6 +241,9 @@ POSTINSTALL_CONFIG = 'META/postinstall_config.txt' DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt' AB_PARTITIONS = 'META/ab_partitions.txt' UNZIP_PATTERN = ['IMAGES/*', 'META/*', 'OTA/*', 'RADIO/*'] +# Files to be unzipped for target diffing purpose. +TARGET_DIFFING_UNZIP_PATTERN = ['BOOT', 'RECOVERY', 'SYSTEM/*', 'VENDOR/*', + 'PRODUCT/*', 'SYSTEM_EXT/*', 'ODM/*'] RETROFIT_DAP_UNZIP_PATTERN = ['OTA/super_*.img', AB_PARTITIONS] @@ -539,7 +542,7 @@ class Payload(object): self.payload_properties = None self.secondary = secondary - def _Run(self, cmd): + def _Run(self, cmd): # pylint: disable=no-self-use # Don't pipe (buffer) the output if verbose is set. Let # brillo_update_payload write to stdout/stderr directly, so its progress can # be monitored. @@ -2005,8 +2008,7 @@ def GetTargetFilesZipForRetrofitDynamicPartitions(input_file, return target_file -def WriteABOTAPackageWithBrilloScript(target_file, output_file, - source_file=None): +def GenerateAbOtaPackage(target_file, output_file, source_file=None): """Generates an Android OTA package that has A/B update payload.""" # Stage the output zip package for package signing. if not OPTIONS.no_signing: @@ -2104,6 +2106,66 @@ def WriteABOTAPackageWithBrilloScript(target_file, output_file, FinalizeMetadata(metadata, staging_file, output_file, needed_property_files) +def GenerateNonAbOtaPackage(target_file, output_file, source_file=None): + """Generates a non-A/B OTA package.""" + # Sanity check the loaded info dicts first. + if OPTIONS.info_dict.get("no_recovery") == "true": + raise common.ExternalError( + "--- target build has specified no recovery ---") + + # Non-A/B OTAs rely on /cache partition to store temporary files. + cache_size = OPTIONS.info_dict.get("cache_size") + if cache_size is None: + logger.warning("--- can't determine the cache partition size ---") + OPTIONS.cache_size = cache_size + + if OPTIONS.extra_script is not None: + with open(OPTIONS.extra_script) as fp: + OPTIONS.extra_script = fp.read() + + if OPTIONS.extracted_input is not None: + OPTIONS.input_tmp = OPTIONS.extracted_input + else: + logger.info("unzipping target target-files...") + OPTIONS.input_tmp = common.UnzipTemp(target_file, UNZIP_PATTERN) + OPTIONS.target_tmp = OPTIONS.input_tmp + + # If the caller explicitly specified the device-specific extensions path via + # -s / --device_specific, use that. Otherwise, use META/releasetools.py if it + # is present in the target target_files. Otherwise, take the path of the file + # from 'tool_extensions' in the info dict and look for that in the local + # filesystem, relative to the current directory. + if OPTIONS.device_specific is None: + from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") + if os.path.exists(from_input): + logger.info("(using device-specific extensions from target_files)") + OPTIONS.device_specific = from_input + else: + OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions") + + if OPTIONS.device_specific is not None: + OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) + + # Generate a full OTA. + if source_file is None: + with zipfile.ZipFile(target_file) as input_zip: + WriteFullOTAPackage( + input_zip, + output_file) + + # Generate an incremental OTA. + else: + logger.info("unzipping source target-files...") + OPTIONS.source_tmp = common.UnzipTemp( + OPTIONS.incremental_source, UNZIP_PATTERN) + with zipfile.ZipFile(target_file) as input_zip, \ + zipfile.ZipFile(source_file) as source_zip: + WriteBlockIncrementalOTAPackage( + input_zip, + source_zip, + output_file) + + def main(argv): def option_handler(o, a): @@ -2278,76 +2340,29 @@ def main(argv): OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key]) if ab_update: - WriteABOTAPackageWithBrilloScript( + GenerateAbOtaPackage( target_file=args[0], output_file=args[1], source_file=OPTIONS.incremental_source) - logger.info("done.") - return - - # Sanity check the loaded info dicts first. - if OPTIONS.info_dict.get("no_recovery") == "true": - raise common.ExternalError( - "--- target build has specified no recovery ---") - - # Non-A/B OTAs rely on /cache partition to store temporary files. - cache_size = OPTIONS.info_dict.get("cache_size") - if cache_size is None: - logger.warning("--- can't determine the cache partition size ---") - OPTIONS.cache_size = cache_size - - if OPTIONS.extra_script is not None: - with open(OPTIONS.extra_script) as fp: - OPTIONS.extra_script = fp.read() - - if OPTIONS.extracted_input is not None: - OPTIONS.input_tmp = OPTIONS.extracted_input else: - logger.info("unzipping target target-files...") - OPTIONS.input_tmp = common.UnzipTemp(args[0], UNZIP_PATTERN) - OPTIONS.target_tmp = OPTIONS.input_tmp + GenerateNonAbOtaPackage( + target_file=args[0], + output_file=args[1], + source_file=OPTIONS.incremental_source) - # If the caller explicitly specified the device-specific extensions path via - # -s / --device_specific, use that. Otherwise, use META/releasetools.py if it - # is present in the target target_files. Otherwise, take the path of the file - # from 'tool_extensions' in the info dict and look for that in the local - # filesystem, relative to the current directory. - if OPTIONS.device_specific is None: - from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") - if os.path.exists(from_input): - logger.info("(using device-specific extensions from target_files)") - OPTIONS.device_specific = from_input - else: - OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions") + # Post OTA generation works. + if OPTIONS.incremental_source is not None and OPTIONS.log_diff: + logger.info("Generating diff logs...") + logger.info("Unzipping target-files for diffing...") + target_dir = common.UnzipTemp(args[0], TARGET_DIFFING_UNZIP_PATTERN) + source_dir = common.UnzipTemp( + OPTIONS.incremental_source, TARGET_DIFFING_UNZIP_PATTERN) - if OPTIONS.device_specific is not None: - OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) - - # Generate a full OTA. - if OPTIONS.incremental_source is None: - with zipfile.ZipFile(args[0], 'r') as input_zip: - WriteFullOTAPackage( - input_zip, - output_file=args[1]) - - # Generate an incremental OTA. - else: - logger.info("unzipping source target-files...") - OPTIONS.source_tmp = common.UnzipTemp( - OPTIONS.incremental_source, UNZIP_PATTERN) - with zipfile.ZipFile(args[0], 'r') as input_zip, \ - zipfile.ZipFile(OPTIONS.incremental_source, 'r') as source_zip: - WriteBlockIncrementalOTAPackage( - input_zip, - source_zip, - output_file=args[1]) - - if OPTIONS.log_diff: - with open(OPTIONS.log_diff, 'w') as out_file: - import target_files_diff - target_files_diff.recursiveDiff( - '', OPTIONS.source_tmp, OPTIONS.input_tmp, out_file) + with open(OPTIONS.log_diff, 'w') as out_file: + import target_files_diff + target_files_diff.recursiveDiff( + '', source_dir, target_dir, out_file) logger.info("done.")