From 9f884e6c552bc40b3696d526c7479183304e8220 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 28 Feb 2017 11:48:48 -0800 Subject: [PATCH] releasetools: Add support for --override_timestamp. We use the timestamps in builds to determine a downgrade, which might not be always the truth. For examples, two builds cut from different branches may carry timestamps in a reverse order. An incremental package won't be able to be pushed nor applied, based on the timestamp comparison. We used to handle such a case with manual work, by setting the post-timestamp to (pre-timestamp + 1) in the package metadata. This CL automates the process by adding a new flag --override_timestamp. Note that it doesn't change anything in the installed image, but only affects the assertions for pushing / installing the package. With the change in this CL: - If it's a downgrade without any extra flag, fail the package generation (we only print warnings prior to this CL); - If it's a downgrade with --downgrade flag, generate a downgrade package with forced data wipe (same as before); - If it's a downgrade with --override_timestamp, generate a normal incremental with hacked timestamp (pre-timestamp + 1) (new in this CL to avoid the manual change); - If it's not a downgrade but with any of the above two flags specified, fail the package generation. Bug: 33744169 Test: Generate an incremental from builds with reversed timestamps. Change-Id: I8b187d32708b4a7c3e20f8c6adb8f9527b73b965 Merged-In: I8b187d32708b4a7c3e20f8c6adb8f9527b73b965 (cherry picked from commit 3e6161a3b33da5a46c80c79e2d815168923e83c3) --- tools/releasetools/ota_from_target_files.py | 40 +++++++++++++++------ 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py index 3224305440..27adb94e35 100755 --- a/tools/releasetools/ota_from_target_files.py +++ b/tools/releasetools/ota_from_target_files.py @@ -75,7 +75,19 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package will be replaced by "ota-downgrade=yes" in the metadata file. A data wipe will always be enforced, so "ota-wipe=yes" will also be included in the metadata file. The update-binary in the source build will be used in - the OTA package, unless --binary flag is specified. + the OTA package, unless --binary flag is specified. Please also check the + doc for --override_timestamp below. + + --override_timestamp + Intentionally generate an incremental OTA that updates from a newer + build to an older one (based on timestamp comparison), by overriding the + timestamp in package metadata. This differs from --downgrade flag: we + know for sure this is NOT an actual downgrade case, but two builds are + cut in a reverse order. A legit use case is that we cut a new build C + (after having A and B), but want to enfore an update path of A -> C -> B. + Specifying --downgrade may not help since that would enforce a data wipe + for C -> B update. The value of "post-timestamp" will be set to the newer + timestamp plus one, so that the package can be pushed and applied. -e (--extra_script) Insert the contents of file at the end of the update script. @@ -141,6 +153,7 @@ OPTIONS.patch_threshold = 0.95 OPTIONS.wipe_user_data = False OPTIONS.omit_prereq = False OPTIONS.downgrade = False +OPTIONS.timestamp = False OPTIONS.extra_script = None OPTIONS.aslr_mode = True OPTIONS.worker_threads = multiprocessing.cpu_count() // 2 @@ -775,20 +788,21 @@ def HandleDowngradeMetadata(metadata): is_downgrade = long(post_timestamp) < long(pre_timestamp) if OPTIONS.downgrade: - metadata["ota-downgrade"] = "yes" if not is_downgrade: raise RuntimeError("--downgrade specified but no downgrade detected: " "pre: %s, post: %s" % (pre_timestamp, post_timestamp)) + metadata["ota-downgrade"] = "yes" + elif OPTIONS.timestamp: + if not is_downgrade: + raise RuntimeError("--timestamp specified but no timestamp hack needed: " + "pre: %s, post: %s" % (pre_timestamp, post_timestamp)) + metadata["post-timestamp"] = str(long(pre_timestamp) + 1) else: if is_downgrade: - # Non-fatal here to allow generating such a package which may require - # manual work to adjust the post-timestamp. A legit use case is that we - # cut a new build C (after having A and B), but want to enfore the - # update path of A -> C -> B. Specifying --downgrade may not help since - # that would enforce a data wipe for C -> B update. - print("\nWARNING: downgrade detected: pre: %s, post: %s.\n" - "The package may not be deployed properly. " - "Try --downgrade?\n" % (pre_timestamp, post_timestamp)) + raise RuntimeError("Downgrade detected based on timestamp check: " + "pre: %s, post: %s. Need to specify --timestamp OR " + "--downgrade to allow building the incremental." % ( + pre_timestamp, post_timestamp)) metadata["post-timestamp"] = post_timestamp @@ -1853,6 +1867,8 @@ def main(argv): elif o == "--downgrade": OPTIONS.downgrade = True OPTIONS.wipe_user_data = True + elif o == "--override_timestamp": + OPTIONS.timestamp = True elif o in ("-o", "--oem_settings"): OPTIONS.oem_source = a elif o == "--oem_no_mount": @@ -1907,6 +1923,7 @@ def main(argv): "wipe_user_data", "no_prereq", "downgrade", + "override_timestamp", "extra_script=", "worker_threads=", "aslr_mode=", @@ -1939,6 +1956,9 @@ def main(argv): raise ValueError("Cannot generate downgradable full OTAs - consider" "using --omit_prereq?") + assert not (OPTIONS.downgrade and OPTIONS.timestamp), \ + "Cannot have --downgrade AND --override_timestamp both" + # Load the dict file from the zip directly to have a peek at the OTA type. # For packages using A/B update, unzipping is not needed. input_zip = zipfile.ZipFile(args[0], "r")