Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2694249b authored by Tao Bao's avatar Tao Bao
Browse files

releasetools: Use "ota-downgrade=yes" for --override_timestamp.

We used to write a fake post-timestamp into package metadata for
"--override_timestamp", which allows a package to be pushed based on
the fake timestamp. This CL stops doing that by using the designated
"ota-downgrade=yes" instead, but keeping the "--override_timestamp" flag
for backward compatibility.

Now both "--override_timestamp" and "--downgrade" allow pushing packages
with downgrade timestamps. The only differenece is that "--downgrade"
enforces a data wiping, because it's intended a real downgrade (based on
Android version or security patch level). "--override_timestamp" serves
the path of a legit "upgrade", but unfortunately with build timestamps
in reverse order (e.g. the two builds are cut from different branches).

With this CL, we write "post-timestamp" to all packages.

Bug: 77811049
Test: Generate an incremental pakcage with "--override_timestamp".
Test: Generate an incremental pakcage with "--downgrade".
Test: python -m unittest test_ota_from_target_files
Change-Id: I4ae4ce77cb600a06ffd9b15b6d4c730314aa0b79
Merged-In: I4ae4ce77cb600a06ffd9b15b6d4c730314aa0b79
(cherry picked from commit faa8e0b7)
parent 5b870d15
Loading
Loading
Loading
Loading
+34 −43
Original line number Diff line number Diff line
@@ -65,24 +65,29 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package
      when installed.

  --downgrade
      Intentionally generate an incremental OTA that updates from a newer
      build to an older one (based on timestamp comparison). "post-timestamp"
      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. Please also check the
      doc for --override_timestamp below.
      Intentionally generate an incremental OTA that updates from a newer build
      to an older one (e.g. downgrading from P preview back to O MR1).
      "ota-downgrade=yes" will be set in the package metadata file. A data wipe
      will always be enforced when using this flag, 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. Please
      also check the comment 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.
      Intentionally generate an incremental OTA that updates from a newer build
      to an older one (based on timestamp comparison), by setting the downgrade
      flag in the package metadata. This differs from --downgrade flag, as we
      don't enforce a data wipe with this flag. Because we know for sure this is
      NOT an actual downgrade case, but two builds happen to be cut in a reverse
      order (e.g. from two branches). 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.

      We used to set a fake timestamp in the package metadata for this flow. But
      now we consolidate the two cases (i.e. an actual downgrade, or a downgrade
      based on timestamp) with the same "ota-downgrade=yes" flag, with the
      difference being whether "ota-wipe=yes" is set.

  -e  (--extra_script)  <file>
      Insert the contents of file at the end of the update script.
@@ -180,7 +185,6 @@ OPTIONS.verify = False
OPTIONS.patch_threshold = 0.95
OPTIONS.wipe_user_data = False
OPTIONS.downgrade = False
OPTIONS.timestamp = False
OPTIONS.extra_script = None
OPTIONS.worker_threads = multiprocessing.cpu_count() // 2
if OPTIONS.worker_threads == 0:
@@ -898,23 +902,16 @@ def HandleDowngradeMetadata(metadata, target_info, source_info):

  if OPTIONS.downgrade:
    if not is_downgrade:
      raise RuntimeError("--downgrade specified but no downgrade detected: "
                         "pre: %s, post: %s" % (pre_timestamp, post_timestamp))
      raise RuntimeError(
          "--downgrade or --override_timestamp 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("--override_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:
      raise RuntimeError("Downgrade detected based on timestamp check: "
                         "pre: %s, post: %s. Need to specify "
                         "--override_timestamp OR --downgrade to allow "
                         "building the incremental." % (pre_timestamp,
                                                        post_timestamp))
    metadata["post-timestamp"] = post_timestamp
      raise RuntimeError(
          "Downgrade detected based on timestamp check: pre: %s, post: %s. "
          "Need to specify --override_timestamp OR --downgrade to allow "
          "building the incremental." % (pre_timestamp, post_timestamp))


def GetPackageMetadata(target_info, source_info=None):
@@ -922,7 +919,7 @@ def GetPackageMetadata(target_info, source_info=None):

  It generates a dict() that contains the info to be written into an OTA
  package (META-INF/com/android/metadata). It also handles the detection of
  downgrade / timestamp override / data wipe based on the global options.
  downgrade / data wipe based on the global options.

  Args:
    target_info: The BuildInfo instance that holds the target build info.
@@ -963,11 +960,12 @@ def GetPackageMetadata(target_info, source_info=None):
  else:
    metadata['pre-device'] = target_info.device

  # Detect downgrades, or fill in the post-timestamp.
  # Use the actual post-timestamp, even for a downgrade case.
  metadata['post-timestamp'] = target_info.GetBuildProp('ro.build.date.utc')

  # Detect downgrades and set up downgrade flags accordingly.
  if is_incremental:
    HandleDowngradeMetadata(metadata, target_info, source_info)
  else:
    metadata['post-timestamp'] = target_info.GetBuildProp('ro.build.date.utc')

  return metadata

@@ -1791,7 +1789,7 @@ def main(argv):
      OPTIONS.downgrade = True
      OPTIONS.wipe_user_data = True
    elif o == "--override_timestamp":
      OPTIONS.timestamp = True
      OPTIONS.downgrade = True
    elif o in ("-o", "--oem_settings"):
      OPTIONS.oem_source = a.split(',')
    elif o == "--oem_no_mount":
@@ -1869,19 +1867,12 @@ def main(argv):
    sys.exit(1)

  if OPTIONS.downgrade:
    # Sanity check to enforce a data wipe.
    if not OPTIONS.wipe_user_data:
      raise ValueError("Cannot downgrade without a data wipe")

    # We should only allow downgrading incrementals (as opposed to full).
    # Otherwise the device may go back from arbitrary build with this full
    # OTA package.
    if OPTIONS.incremental_source is None:
      raise ValueError("Cannot generate downgradable full OTAs")

  assert not (OPTIONS.downgrade and OPTIONS.timestamp), \
      "Cannot have --downgrade AND --override_timestamp both"

  # Load the build info dicts from the zip directly or the extracted input
  # directory. We don't need to unzip the entire target-files zips, because they
  # won't be needed for A/B OTAs (brillo_update_payload does that on its own).
+1 −25
Original line number Diff line number Diff line
@@ -524,31 +524,7 @@ class OtaFromTargetFilesTest(unittest.TestCase):
            'post-build-incremental' : 'build-version-incremental-target',
            'post-sdk-level' : '27',
            'post-security-patch-level' : '2017-12-01',
            'pre-device' : 'product-device',
            'pre-build' : 'build-fingerprint-source',
            'pre-build-incremental' : 'build-version-incremental-source',
        },
        metadata)

  def test_GetPackageMetadata_overrideTimestamp(self):
    target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
    source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
    self._test_GetPackageMetadata_swapBuildTimestamps(
        target_info_dict, source_info_dict)

    target_info = BuildInfo(target_info_dict, None)
    source_info = BuildInfo(source_info_dict, None)
    common.OPTIONS.incremental_source = ''
    common.OPTIONS.timestamp = True
    metadata = GetPackageMetadata(target_info, source_info)
    self.assertDictEqual(
        {
            'ota-type' : 'BLOCK',
            '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' : '1500000001',
            'post-timestamp' : '1400000000',
            'pre-device' : 'product-device',
            'pre-build' : 'build-fingerprint-source',
            'pre-build-incremental' : 'build-version-incremental-source',