# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import array
import copy
import functools
import heapq
import itertools
import logging
import multiprocessing
import os
import os.path
import re
import sys
import threading
import zlib
from collections import deque, namedtuple, OrderedDict

import common
from images import EmptyImage
from rangelib import RangeSet

__all__ = ["BlockImageDiff"]

logger = logging.getLogger(__name__)

# The tuple contains the style and bytes of a bsdiff|imgdiff patch.
PatchInfo = namedtuple("PatchInfo", ["imgdiff", "content"])


def compute_patch(srcfile, tgtfile, imgdiff=False):
  """Calls bsdiff|imgdiff to compute the patch data, returns a PatchInfo."""
  patchfile = common.MakeTempFile(prefix='patch-')

  cmd = ['imgdiff', '-z'] if imgdiff else ['bsdiff']
  cmd.extend([srcfile, tgtfile, patchfile])

  # Don't dump the bsdiff/imgdiff commands, which are not useful for the case
  # here, since they contain temp filenames only.
  proc = common.Run(cmd, verbose=False)
  output, _ = proc.communicate()

  if proc.returncode != 0:
    raise ValueError(output)

  with open(patchfile, 'rb') as f:
    return PatchInfo(imgdiff, f.read())


class Transfer(object):
  def __init__(self, tgt_name, src_name, tgt_ranges, src_ranges, tgt_sha1,
               src_sha1, style, by_id):
    self.tgt_name = tgt_name
    self.src_name = src_name
    self.tgt_ranges = tgt_ranges
    self.src_ranges = src_ranges
    self.tgt_sha1 = tgt_sha1
    self.src_sha1 = src_sha1
    self.style = style

    # We use OrderedDict rather than dict so that the output is repeatable;
    # otherwise it would depend on the hash values of the Transfer objects.
    self.goes_before = OrderedDict()
    self.goes_after = OrderedDict()

    self.stash_before = []
    self.use_stash = []

    self.id = len(by_id)
    by_id.append(self)

    self._patch_info = None

  @property
  def patch_info(self):
    return self._patch_info

  @patch_info.setter
  def patch_info(self, info):
    if info:
      assert self.style == "diff"
    self._patch_info = info

  def NetStashChange(self):
    return (sum(sr.size() for (_, sr) in self.stash_before) -
            sum(sr.size() for (_, sr) in self.use_stash))

  def ConvertToNew(self):
    assert self.style != "new"
    self.use_stash = []
    self.style = "new"
    self.src_ranges = RangeSet()
    self.patch_info = None

  def __str__(self):
    return (str(self.id) + ": <" + str(self.src_ranges) + " " + self.style +
            " to " + str(self.tgt_ranges) + ">")


@functools.total_ordering
class HeapItem(object):
  def __init__(self, item):
    self.item = item
    # Negate the score since python's heap is a min-heap and we want the
    # maximum score.
    self.score = -item.score

  def clear(self):
    self.item = None

  def __bool__(self):
    return self.item is not None

  # Python 2 uses __nonzero__, while Python 3 uses __bool__.
  __nonzero__ = __bool__

  # The rest operations are generated by functools.total_ordering decorator.
  def __eq__(self, other):
    return self.score == other.score

  def __le__(self, other):
    return self.score <= other.score


class ImgdiffStats(object):
  """A class that collects imgdiff stats.

  It keeps track of the files that will be applied imgdiff while generating
  BlockImageDiff. It also logs the ones that cannot use imgdiff, with specific
  reasons. The stats is only meaningful when imgdiff not being disabled by the
  caller of BlockImageDiff. In addition, only files with supported types
  (BlockImageDiff.FileTypeSupportedByImgdiff()) are allowed to be logged.
  """

  USED_IMGDIFF = "APK files diff'd with imgdiff"
  USED_IMGDIFF_LARGE_APK = "Large APK files split and diff'd with imgdiff"

  # Reasons for not applying imgdiff on APKs.
  SKIPPED_NONMONOTONIC = "Not used imgdiff due to having non-monotonic ranges"
  SKIPPED_SHARED_BLOCKS = "Not used imgdiff due to using shared blocks"
  SKIPPED_INCOMPLETE = "Not used imgdiff due to incomplete RangeSet"

  # The list of valid reasons, which will also be the dumped order in a report.
  REASONS = (
      USED_IMGDIFF,
      USED_IMGDIFF_LARGE_APK,
      SKIPPED_NONMONOTONIC,
      SKIPPED_SHARED_BLOCKS,
      SKIPPED_INCOMPLETE,
  )

  def  __init__(self):
    self.stats = {}

  def Log(self, filename, reason):
    """Logs why imgdiff can or cannot be applied to the given filename.

    Args:
      filename: The filename string.
      reason: One of the reason constants listed in REASONS.

    Raises:
      AssertionError: On unsupported filetypes or invalid reason.
    """
    assert BlockImageDiff.FileTypeSupportedByImgdiff(filename)
    assert reason in self.REASONS

    if reason not in self.stats:
      self.stats[reason] = set()
    self.stats[reason].add(filename)

  def Report(self):
    """Prints a report of the collected imgdiff stats."""

    def print_header(header, separator):
      logger.info(header)
      logger.info('%s\n', separator * len(header))

    print_header('  Imgdiff Stats Report  ', '=')
    for key in self.REASONS:
      if key not in self.stats:
        continue
      values = self.stats[key]
      section_header = ' {} (count: {}) '.format(key, len(values))
      print_header(section_header, '-')
      logger.info(''.join(['  {}\n'.format(name) for name in values]))


class BlockImageDiff(object):
  """Generates the diff of two block image objects.

  BlockImageDiff works on two image objects. An image object is anything that
  provides the following attributes:

     blocksize: the size in bytes of a block, currently must be 4096.

     total_blocks: the total size of the partition/image, in blocks.

     care_map: a RangeSet containing which blocks (in the range [0,
       total_blocks) we actually care about; i.e. which blocks contain data.

     file_map: a dict that partitions the blocks contained in care_map into
         smaller domains that are useful for doing diffs on. (Typically a domain
         is a file, and the key in file_map is the pathname.)

     clobbered_blocks: a RangeSet containing which blocks contain data but may
         be altered by the FS. They need to be excluded when verifying the
         partition integrity.

     ReadRangeSet(): a function that takes a RangeSet and returns the data
         contained in the image blocks of that RangeSet. The data is returned as
         a list or tuple of strings; concatenating the elements together should
         produce the requested data. Implementations are free to break up the
         data into list/tuple elements in any way that is convenient.

     RangeSha1(): a function that returns (as a hex string) the SHA-1 hash of
         all the data in the specified range.

     TotalSha1(): a function that returns (as a hex string) the SHA-1 hash of
         all the data in the image (ie, all the blocks in the care_map minus
         clobbered_blocks, or including the clobbered blocks if
         include_clobbered_blocks is True).

  When creating a BlockImageDiff, the src image may be None, in which case the
  list of transfers produced will never read from the original image.
  """

  def __init__(self, tgt, src=None, threads=None, version=4,
               disable_imgdiff=False):
    if threads is None:
      threads = multiprocessing.cpu_count() // 2
      if threads == 0:
        threads = 1
    self.threads = threads
    self.version = version
    self.transfers = []
    self.src_basenames = {}
    self.src_numpatterns = {}
    self._max_stashed_size = 0
    self.touched_src_ranges = RangeSet()
    self.touched_src_sha1 = None
    self.disable_imgdiff = disable_imgdiff
    self.imgdiff_stats = ImgdiffStats() if not disable_imgdiff else None

    assert version in (3, 4)

    self.tgt = tgt
    if src is None:
      src = EmptyImage()
    self.src = src

    # The updater code that installs the patch always uses 4k blocks.
    assert tgt.blocksize == 4096
    assert src.blocksize == 4096

    # The range sets in each filemap should comprise a partition of
    # the care map.
    self.AssertPartition(src.care_map, src.file_map.values())
    self.AssertPartition(tgt.care_map, tgt.file_map.values())

  @property
  def max_stashed_size(self):
    return self._max_stashed_size

  @staticmethod
  def FileTypeSupportedByImgdiff(filename):
    """Returns whether the file type is supported by imgdiff."""
    return filename.lower().endswith(('.apk', '.jar', '.zip'))

  def CanUseImgdiff(self, name, tgt_ranges, src_ranges, large_apk=False):
    """Checks whether we can apply imgdiff for the given RangeSets.

    For files in ZIP format (e.g., APKs, JARs, etc.) we would like to use
    'imgdiff -z' if possible. Because it usually produces significantly smaller
    patches than bsdiff.

    This is permissible if all of the following conditions hold.
      - The imgdiff hasn't been disabled by the caller (e.g. squashfs);
      - The file type is supported by imgdiff;
      - The source and target blocks are monotonic (i.e. the data is stored with
        blocks in increasing order);
      - Both files don't contain shared blocks;
      - Both files have complete lists of blocks;
      - We haven't removed any blocks from the source set.

    If all these conditions are satisfied, concatenating all the blocks in the
    RangeSet in order will produce a valid ZIP file (plus possibly extra zeros
    in the last block). imgdiff is fine with extra zeros at the end of the file.

    Args:
      name: The filename to be diff'd.
      tgt_ranges: The target RangeSet.
      src_ranges: The source RangeSet.
      large_apk: Whether this is to split a large APK.

    Returns:
      A boolean result.
    """
    if self.disable_imgdiff or not self.FileTypeSupportedByImgdiff(name):
      return False

    if not tgt_ranges.monotonic or not src_ranges.monotonic:
      self.imgdiff_stats.Log(name, ImgdiffStats.SKIPPED_NONMONOTONIC)
      return False

    if (tgt_ranges.extra.get('uses_shared_blocks') or
        src_ranges.extra.get('uses_shared_blocks')):
      self.imgdiff_stats.Log(name, ImgdiffStats.SKIPPED_SHARED_BLOCKS)
      return False

    if tgt_ranges.extra.get('incomplete') or src_ranges.extra.get('incomplete'):
      self.imgdiff_stats.Log(name, ImgdiffStats.SKIPPED_INCOMPLETE)
      return False

    reason = (ImgdiffStats.USED_IMGDIFF_LARGE_APK if large_apk
              else ImgdiffStats.USED_IMGDIFF)
    self.imgdiff_stats.Log(name, reason)
    return True

  def Compute(self, prefix):
    # When looking for a source file to use as the diff input for a
    # target file, we try:
    #   1) an exact path match if available, otherwise
    #   2) a exact basename match if available, otherwise
    #   3) a basename match after all runs of digits are replaced by
    #      "#" if available, otherwise
    #   4) we have no source for this target.
    self.AbbreviateSourceNames()
    self.FindTransfers()

    self.FindSequenceForTransfers()

    # Ensure the runtime stash size is under the limit.
    if common.OPTIONS.cache_size is not None:
      stash_limit = (common.OPTIONS.cache_size *
                     common.OPTIONS.stash_threshold / self.tgt.blocksize)
      # Ignore the stash limit and calculate the maximum simultaneously stashed
      # blocks needed.
      _, max_stashed_blocks = self.ReviseStashSize(ignore_stash_limit=True)

      # We cannot stash more blocks than the stash limit simultaneously. As a
      # result, some 'diff' commands will be converted to new; leading to an
      # unintended large package. To mitigate this issue, we can carefully
      # choose the transfers for conversion. The number '1024' can be further
      # tweaked here to balance the package size and build time.
      if max_stashed_blocks > stash_limit + 1024:
        self.SelectAndConvertDiffTransfersToNew(
            max_stashed_blocks - stash_limit)
        # Regenerate the sequence as the graph has changed.
        self.FindSequenceForTransfers()

      # Revise the stash size again to keep the size under limit.
      self.ReviseStashSize()

    # Double-check our work.
    self.AssertSequenceGood()
    self.AssertSha1Good()

    self.ComputePatches(prefix)
    self.WriteTransfers(prefix)

    # Report the imgdiff stats.
    if not self.disable_imgdiff:
      self.imgdiff_stats.Report()

  def WriteTransfers(self, prefix):
    def WriteSplitTransfers(out, style, target_blocks):
      """Limit the size of operand in command 'new' and 'zero' to 1024 blocks.

      This prevents the target size of one command from being too large; and
      might help to avoid fsync errors on some devices."""

      assert style == "new" or style == "zero"
      blocks_limit = 1024
      total = 0
      while target_blocks:
        blocks_to_write = target_blocks.first(blocks_limit)
        out.append("%s %s\n" % (style, blocks_to_write.to_string_raw()))
        total += blocks_to_write.size()
        target_blocks = target_blocks.subtract(blocks_to_write)
      return total

    out = []
    total = 0

    # In BBOTA v3+, it uses the hash of the stashed blocks as the stash slot
    # id. 'stashes' records the map from 'hash' to the ref count. The stash
    # will be freed only if the count decrements to zero.
    stashes = {}
    stashed_blocks = 0
    max_stashed_blocks = 0

    for xf in self.transfers:

      for _, sr in xf.stash_before:
        sh = self.src.RangeSha1(sr)
        if sh in stashes:
          stashes[sh] += 1
        else:
          stashes[sh] = 1
          stashed_blocks += sr.size()
          self.touched_src_ranges = self.touched_src_ranges.union(sr)
          out.append("stash %s %s\n" % (sh, sr.to_string_raw()))

      if stashed_blocks > max_stashed_blocks:
        max_stashed_blocks = stashed_blocks

      free_string = []
      free_size = 0

      #   <# blocks> <src ranges>
      #     OR
      #   <# blocks> <src ranges> <src locs> <stash refs...>
      #     OR
      #   <# blocks> - <stash refs...>

      size = xf.src_ranges.size()
      src_str_buffer = [str(size)]

      unstashed_src_ranges = xf.src_ranges
      mapped_stashes = []
      for _, sr in xf.use_stash:
        unstashed_src_ranges = unstashed_src_ranges.subtract(sr)
        sh = self.src.RangeSha1(sr)
        sr = xf.src_ranges.map_within(sr)
        mapped_stashes.append(sr)
        assert sh in stashes
        src_str_buffer.append("%s:%s" % (sh, sr.to_string_raw()))
        stashes[sh] -= 1
        if stashes[sh] == 0:
          free_string.append("free %s\n" % (sh,))
          free_size += sr.size()
          stashes.pop(sh)

      if unstashed_src_ranges:
        src_str_buffer.insert(1, unstashed_src_ranges.to_string_raw())
        if xf.use_stash:
          mapped_unstashed = xf.src_ranges.map_within(unstashed_src_ranges)
          src_str_buffer.insert(2, mapped_unstashed.to_string_raw())
          mapped_stashes.append(mapped_unstashed)
          self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)
      else:
        src_str_buffer.insert(1, "-")
        self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)

      src_str = " ".join(src_str_buffer)

      # version 3+:
      #   zero <rangeset>
      #   new <rangeset>
      #   erase <rangeset>
      #   bsdiff patchstart patchlen srchash tgthash <tgt rangeset> <src_str>
      #   imgdiff patchstart patchlen srchash tgthash <tgt rangeset> <src_str>
      #   move hash <tgt rangeset> <src_str>

      tgt_size = xf.tgt_ranges.size()

      if xf.style == "new":
        assert xf.tgt_ranges
        assert tgt_size == WriteSplitTransfers(out, xf.style, xf.tgt_ranges)
        total += tgt_size
      elif xf.style == "move":
        assert xf.tgt_ranges
        assert xf.src_ranges.size() == tgt_size
        if xf.src_ranges != xf.tgt_ranges:
          # take into account automatic stashing of overlapping blocks
          if xf.src_ranges.overlaps(xf.tgt_ranges):
            temp_stash_usage = stashed_blocks + xf.src_ranges.size()
            if temp_stash_usage > max_stashed_blocks:
              max_stashed_blocks = temp_stash_usage

          self.touched_src_ranges = self.touched_src_ranges.union(
              xf.src_ranges)

          out.append("%s %s %s %s\n" % (
              xf.style,
              xf.tgt_sha1,
              xf.tgt_ranges.to_string_raw(), src_str))
          total += tgt_size
      elif xf.style in ("bsdiff", "imgdiff"):
        assert xf.tgt_ranges
        assert xf.src_ranges
        # take into account automatic stashing of overlapping blocks
        if xf.src_ranges.overlaps(xf.tgt_ranges):
          temp_stash_usage = stashed_blocks + xf.src_ranges.size()
          if temp_stash_usage > max_stashed_blocks:
            max_stashed_blocks = temp_stash_usage

        self.touched_src_ranges = self.touched_src_ranges.union(xf.src_ranges)

        out.append("%s %d %d %s %s %s %s\n" % (
            xf.style,
            xf.patch_start, xf.patch_len,
            xf.src_sha1,
            xf.tgt_sha1,
            xf.tgt_ranges.to_string_raw(), src_str))
        total += tgt_size
      elif xf.style == "zero":
        assert xf.tgt_ranges
        to_zero = xf.tgt_ranges.subtract(xf.src_ranges)
        assert WriteSplitTransfers(out, xf.style, to_zero) == to_zero.size()
        total += to_zero.size()
      else:
        raise ValueError("unknown transfer style '%s'\n" % xf.style)

      if free_string:
        out.append("".join(free_string))
        stashed_blocks -= free_size

      if common.OPTIONS.cache_size is not None:
        # Sanity check: abort if we're going to need more stash space than
        # the allowed size (cache_size * threshold). There are two purposes
        # of having a threshold here. a) Part of the cache may have been
        # occupied by some recovery logs. b) It will buy us some time to deal
        # with the oversize issue.
        cache_size = common.OPTIONS.cache_size
        stash_threshold = common.OPTIONS.stash_threshold
        max_allowed = cache_size * stash_threshold
        assert max_stashed_blocks * self.tgt.blocksize <= max_allowed, \
               'Stash size %d (%d * %d) exceeds the limit %d (%d * %.2f)' % (
                   max_stashed_blocks * self.tgt.blocksize, max_stashed_blocks,
                   self.tgt.blocksize, max_allowed, cache_size,
                   stash_threshold)

    self.touched_src_sha1 = self.src.RangeSha1(self.touched_src_ranges)

    if self.tgt.hashtree_info:
      out.append("compute_hash_tree {} {} {} {} {}\n".format(
          self.tgt.hashtree_info.hashtree_range.to_string_raw(),
          self.tgt.hashtree_info.filesystem_range.to_string_raw(),
          self.tgt.hashtree_info.hash_algorithm,
          self.tgt.hashtree_info.salt,
          self.tgt.hashtree_info.root_hash))

    # Zero out extended blocks as a workaround for bug 20881595.
    if self.tgt.extended:
      assert (WriteSplitTransfers(out, "zero", self.tgt.extended) ==
              self.tgt.extended.size())
      total += self.tgt.extended.size()

    # We erase all the blocks on the partition that a) don't contain useful
    # data in the new image; b) will not be touched by dm-verity. Out of those
    # blocks, we erase the ones that won't be used in this update at the
    # beginning of an update. The rest would be erased at the end. This is to
    # work around the eMMC issue observed on some devices, which may otherwise
    # get starving for clean blocks and thus fail the update. (b/28347095)
    all_tgt = RangeSet(data=(0, self.tgt.total_blocks))
    all_tgt_minus_extended = all_tgt.subtract(self.tgt.extended)
    new_dontcare = all_tgt_minus_extended.subtract(self.tgt.care_map)

    erase_first = new_dontcare.subtract(self.touched_src_ranges)
    if erase_first:
      out.insert(0, "erase %s\n" % (erase_first.to_string_raw(),))

    erase_last = new_dontcare.subtract(erase_first)
    if erase_last:
      out.append("erase %s\n" % (erase_last.to_string_raw(),))

    out.insert(0, "%d\n" % (self.version,))   # format version number
    out.insert(1, "%d\n" % (total,))
    # v3+: the number of stash slots is unused.
    out.insert(2, "0\n")
    out.insert(3, str(max_stashed_blocks) + "\n")

    with open(prefix + ".transfer.list", "w") as f:
      for i in out:
        f.write(i)

    self._max_stashed_size = max_stashed_blocks * self.tgt.blocksize
    OPTIONS = common.OPTIONS
    if OPTIONS.cache_size is not None:
      max_allowed = OPTIONS.cache_size * OPTIONS.stash_threshold
      logger.info(
          "max stashed blocks: %d  (%d bytes), limit: %d bytes (%.2f%%)\n",
          max_stashed_blocks, self._max_stashed_size, max_allowed,
          self._max_stashed_size * 100.0 / max_allowed)
    else:
      logger.info(
          "max stashed blocks: %d  (%d bytes), limit: <unknown>\n",
          max_stashed_blocks, self._max_stashed_size)

  def ReviseStashSize(self, ignore_stash_limit=False):
    """ Revises the transfers to keep the stash size within the size limit.

    Iterates through the transfer list and calculates the stash size each
    transfer generates. Converts the affected transfers to new if we reach the
    stash limit.

    Args:
      ignore_stash_limit: Ignores the stash limit and calculates the max
      simultaneous stashed blocks instead. No change will be made to the
      transfer list with this flag.

    Return:
      A tuple of (tgt blocks converted to new, max stashed blocks)
    """
    logger.info("Revising stash size...")
    stash_map = {}

    # Create the map between a stash and its def/use points. For example, for a
    # given stash of (raw_id, sr), stash_map[raw_id] = (sr, def_cmd, use_cmd).
    for xf in self.transfers:
      # Command xf defines (stores) all the stashes in stash_before.
      for stash_raw_id, sr in xf.stash_before:
        stash_map[stash_raw_id] = (sr, xf)

      # Record all the stashes command xf uses.
      for stash_raw_id, _ in xf.use_stash:
        stash_map[stash_raw_id] += (xf,)

    max_allowed_blocks = None
    if not ignore_stash_limit:
      # Compute the maximum blocks available for stash based on /cache size and
      # the threshold.
      cache_size = common.OPTIONS.cache_size
      stash_threshold = common.OPTIONS.stash_threshold
      max_allowed_blocks = cache_size * stash_threshold / self.tgt.blocksize

    # See the comments for 'stashes' in WriteTransfers().
    stashes = {}
    stashed_blocks = 0
    new_blocks = 0
    max_stashed_blocks = 0

    # Now go through all the commands. Compute the required stash size on the
    # fly. If a command requires excess stash than available, it deletes the
    # stash by replacing the command that uses the stash with a "new" command
    # instead.
    for xf in self.transfers:
      replaced_cmds = []

      # xf.stash_before generates explicit stash commands.
      for stash_raw_id, sr in xf.stash_before:
        # Check the post-command stashed_blocks.
        stashed_blocks_after = stashed_blocks
        sh = self.src.RangeSha1(sr)
        if sh not in stashes:
          stashed_blocks_after += sr.size()

        if max_allowed_blocks and stashed_blocks_after > max_allowed_blocks:
          # We cannot stash this one for a later command. Find out the command
          # that will use this stash and replace the command with "new".
          use_cmd = stash_map[stash_raw_id][2]
          replaced_cmds.append(use_cmd)
          logger.info("%10d  %9s  %s", sr.size(), "explicit", use_cmd)
        else:
          # Update the stashes map.
          if sh in stashes:
            stashes[sh] += 1
          else:
            stashes[sh] = 1
          stashed_blocks = stashed_blocks_after
          max_stashed_blocks = max(max_stashed_blocks, stashed_blocks)

      # "move" and "diff" may introduce implicit stashes in BBOTA v3. Prior to
      # ComputePatches(), they both have the style of "diff".
      if xf.style == "diff":
        assert xf.tgt_ranges and xf.src_ranges
        if xf.src_ranges.overlaps(xf.tgt_ranges):
          if (max_allowed_blocks and
              stashed_blocks + xf.src_ranges.size() > max_allowed_blocks):
            replaced_cmds.append(xf)
            logger.info("%10d  %9s  %s", xf.src_ranges.size(), "implicit", xf)
          else:
            # The whole source ranges will be stashed for implicit stashes.
            max_stashed_blocks = max(max_stashed_blocks,
                                     stashed_blocks + xf.src_ranges.size())

      # Replace the commands in replaced_cmds with "new"s.
      for cmd in replaced_cmds:
        # It no longer uses any commands in "use_stash". Remove the def points
        # for all those stashes.
        for stash_raw_id, sr in cmd.use_stash:
          def_cmd = stash_map[stash_raw_id][1]
          assert (stash_raw_id, sr) in def_cmd.stash_before
          def_cmd.stash_before.remove((stash_raw_id, sr))

        # Add up blocks that violates space limit and print total number to
        # screen later.
        new_blocks += cmd.tgt_ranges.size()
        cmd.ConvertToNew()

      # xf.use_stash may generate free commands.
      for _, sr in xf.use_stash:
        sh = self.src.RangeSha1(sr)
        assert sh in stashes
        stashes[sh] -= 1
        if stashes[sh] == 0:
          stashed_blocks -= sr.size()
          stashes.pop(sh)

    num_of_bytes = new_blocks * self.tgt.blocksize
    logger.info(
        "  Total %d blocks (%d bytes) are packed as new blocks due to "
        "insufficient cache size. Maximum blocks stashed simultaneously: %d",
        new_blocks, num_of_bytes, max_stashed_blocks)
    return new_blocks, max_stashed_blocks

  def ComputePatches(self, prefix):
    logger.info("Reticulating splines...")
    diff_queue = []
    patch_num = 0
    with open(prefix + ".new.dat", "wb") as new_f:
      for index, xf in enumerate(self.transfers):
        if xf.style == "zero":
          tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
          logger.info(
              "%10d %10d (%6.2f%%) %7s %s %s", tgt_size, tgt_size, 100.0,
              xf.style, xf.tgt_name, str(xf.tgt_ranges))

        elif xf.style == "new":
          self.tgt.WriteRangeDataToFd(xf.tgt_ranges, new_f)
          tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
          logger.info(
              "%10d %10d (%6.2f%%) %7s %s %s", tgt_size, tgt_size, 100.0,
              xf.style, xf.tgt_name, str(xf.tgt_ranges))

        elif xf.style == "diff":
          # We can't compare src and tgt directly because they may have
          # the same content but be broken up into blocks differently, eg:
          #
          #    ["he", "llo"]  vs  ["h", "ello"]
          #
          # We want those to compare equal, ideally without having to
          # actually concatenate the strings (these may be tens of
          # megabytes).
          if xf.src_sha1 == xf.tgt_sha1:
            # These are identical; we don't need to generate a patch,
            # just issue copy commands on the device.
            xf.style = "move"
            xf.patch_info = None
            tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
            if xf.src_ranges != xf.tgt_ranges:
              logger.info(
                  "%10d %10d (%6.2f%%) %7s %s %s (from %s)", tgt_size, tgt_size,
                  100.0, xf.style,
                  xf.tgt_name if xf.tgt_name == xf.src_name else (
                      xf.tgt_name + " (from " + xf.src_name + ")"),
                  str(xf.tgt_ranges), str(xf.src_ranges))
          else:
            if xf.patch_info:
              # We have already generated the patch (e.g. during split of large
              # APKs or reduction of stash size)
              imgdiff = xf.patch_info.imgdiff
            else:
              imgdiff = self.CanUseImgdiff(
                  xf.tgt_name, xf.tgt_ranges, xf.src_ranges)
            xf.style = "imgdiff" if imgdiff else "bsdiff"
            diff_queue.append((index, imgdiff, patch_num))
            patch_num += 1

        else:
          assert False, "unknown style " + xf.style

    patches = self.ComputePatchesForInputList(diff_queue, False)

    offset = 0
    with open(prefix + ".patch.dat", "wb") as patch_fd:
      for index, patch_info, _ in patches:
        xf = self.transfers[index]
        xf.patch_len = len(patch_info.content)
        xf.patch_start = offset
        offset += xf.patch_len
        patch_fd.write(patch_info.content)

        tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
        logger.info(
            "%10d %10d (%6.2f%%) %7s %s %s %s", xf.patch_len, tgt_size,
            xf.patch_len * 100.0 / tgt_size, xf.style,
            xf.tgt_name if xf.tgt_name == xf.src_name else (
                xf.tgt_name + " (from " + xf.src_name + ")"),
            xf.tgt_ranges, xf.src_ranges)

  def AssertSha1Good(self):
    """Check the SHA-1 of the src & tgt blocks in the transfer list.

    Double check the SHA-1 value to avoid the issue in b/71908713, where
    SparseImage.RangeSha1() messed up with the hash calculation in multi-thread
    environment. That specific problem has been fixed by protecting the
    underlying generator function 'SparseImage._GetRangeData()' with lock.
    """
    for xf in self.transfers:
      tgt_sha1 = self.tgt.RangeSha1(xf.tgt_ranges)
      assert xf.tgt_sha1 == tgt_sha1
      if xf.style == "diff":
        src_sha1 = self.src.RangeSha1(xf.src_ranges)
        assert xf.src_sha1 == src_sha1

  def AssertSequenceGood(self):
    # Simulate the sequences of transfers we will output, and check that:
    # - we never read a block after writing it, and
    # - we write every block we care about exactly once.

    # Start with no blocks having been touched yet.
    touched = array.array("B", b"\0" * self.tgt.total_blocks)

    # Imagine processing the transfers in order.
    for xf in self.transfers:
      # Check that the input blocks for this transfer haven't yet been touched.

      x = xf.src_ranges
      for _, sr in xf.use_stash:
        x = x.subtract(sr)

      for s, e in x:
        # Source image could be larger. Don't check the blocks that are in the
        # source image only. Since they are not in 'touched', and won't ever
        # be touched.
        for i in range(s, min(e, self.tgt.total_blocks)):
          assert touched[i] == 0

      # Check that the output blocks for this transfer haven't yet
      # been touched, and touch all the blocks written by this
      # transfer.
      for s, e in xf.tgt_ranges:
        for i in range(s, e):
          assert touched[i] == 0
          touched[i] = 1

    if self.tgt.hashtree_info:
      for s, e in self.tgt.hashtree_info.hashtree_range:
        for i in range(s, e):
          assert touched[i] == 0
          touched[i] = 1

    # Check that we've written every target block.
    for s, e in self.tgt.care_map:
      for i in range(s, e):
        assert touched[i] == 1

  def FindSequenceForTransfers(self):
    """Finds a sequence for the given transfers.

     The goal is to minimize the violation of order dependencies between these
     transfers, so that fewer blocks are stashed when applying the update.
    """

    # Clear the existing dependency between transfers
    for xf in self.transfers:
      xf.goes_before = OrderedDict()
      xf.goes_after = OrderedDict()

      xf.stash_before = []
      xf.use_stash = []

    # Find the ordering dependencies among transfers (this is O(n^2)
    # in the number of transfers).
    self.GenerateDigraph()
    # Find a sequence of transfers that satisfies as many ordering
    # dependencies as possible (heuristically).
    self.FindVertexSequence()
    # Fix up the ordering dependencies that the sequence didn't
    # satisfy.
    self.ReverseBackwardEdges()
    self.ImproveVertexSequence()

  def ImproveVertexSequence(self):
    logger.info("Improving vertex order...")

    # At this point our digraph is acyclic; we reversed any edges that
    # were backwards in the heuristically-generated sequence.  The
    # previously-generated order is still acceptable, but we hope to
    # find a better order that needs less memory for stashed data.
    # Now we do a topological sort to generate a new vertex order,
    # using a greedy algorithm to choose which vertex goes next
    # whenever we have a choice.

    # Make a copy of the edge set; this copy will get destroyed by the
    # algorithm.
    for xf in self.transfers:
      xf.incoming = xf.goes_after.copy()
      xf.outgoing = xf.goes_before.copy()

    L = []   # the new vertex order

    # S is the set of sources in the remaining graph; we always choose
    # the one that leaves the least amount of stashed data after it's
    # executed.
    S = [(u.NetStashChange(), u.order, u) for u in self.transfers
         if not u.incoming]
    heapq.heapify(S)

    while S:
      _, _, xf = heapq.heappop(S)
      L.append(xf)
      for u in xf.outgoing:
        del u.incoming[xf]
        if not u.incoming:
          heapq.heappush(S, (u.NetStashChange(), u.order, u))

    # if this fails then our graph had a cycle.
    assert len(L) == len(self.transfers)

    self.transfers = L
    for i, xf in enumerate(L):
      xf.order = i

  def ReverseBackwardEdges(self):
    """Reverse unsatisfying edges and compute pairs of stashed blocks.

    For each transfer, make sure it properly stashes the blocks it touches and
    will be used by later transfers. It uses pairs of (stash_raw_id, range) to
    record the blocks to be stashed. 'stash_raw_id' is an id that uniquely
    identifies each pair. Note that for the same range (e.g. RangeSet("1-5")),
    it is possible to have multiple pairs with different 'stash_raw_id's. Each
    'stash_raw_id' will be consumed by one transfer. In BBOTA v3+, identical
    blocks will be written to the same stash slot in WriteTransfers().
    """

    logger.info("Reversing backward edges...")
    in_order = 0
    out_of_order = 0
    stash_raw_id = 0
    stash_size = 0

    for xf in self.transfers:
      for u in xf.goes_before.copy():
        # xf should go before u
        if xf.order < u.order:
          # it does, hurray!
          in_order += 1
        else:
          # it doesn't, boo.  modify u to stash the blocks that it
          # writes that xf wants to read, and then require u to go
          # before xf.
          out_of_order += 1

          overlap = xf.src_ranges.intersect(u.tgt_ranges)
          assert overlap

          u.stash_before.append((stash_raw_id, overlap))
          xf.use_stash.append((stash_raw_id, overlap))
          stash_raw_id += 1
          stash_size += overlap.size()

          # reverse the edge direction; now xf must go after u
          del xf.goes_before[u]
          del u.goes_after[xf]
          xf.goes_after[u] = None    # value doesn't matter
          u.goes_before[xf] = None

    logger.info(
        "  %d/%d dependencies (%.2f%%) were violated; %d source blocks "
        "stashed.", out_of_order, in_order + out_of_order,
        (out_of_order * 100.0 / (in_order + out_of_order)) if (
            in_order + out_of_order) else 0.0,
        stash_size)

  def FindVertexSequence(self):
    logger.info("Finding vertex sequence...")

    # This is based on "A Fast & Effective Heuristic for the Feedback
    # Arc Set Problem" by P. Eades, X. Lin, and W.F. Smyth.  Think of
    # it as starting with the digraph G and moving all the vertices to
    # be on a horizontal line in some order, trying to minimize the
    # number of edges that end up pointing to the left.  Left-pointing
    # edges will get removed to turn the digraph into a DAG.  In this
    # case each edge has a weight which is the number of source blocks
    # we'll lose if that edge is removed; we try to minimize the total
    # weight rather than just the number of edges.

    # Make a copy of the edge set; this copy will get destroyed by the
    # algorithm.
    for xf in self.transfers:
      xf.incoming = xf.goes_after.copy()
      xf.outgoing = xf.goes_before.copy()
      xf.score = sum(xf.outgoing.values()) - sum(xf.incoming.values())

    # We use an OrderedDict instead of just a set so that the output
    # is repeatable; otherwise it would depend on the hash values of
    # the transfer objects.
    G = OrderedDict()
    for xf in self.transfers:
      G[xf] = None
    s1 = deque()  # the left side of the sequence, built from left to right
    s2 = deque()  # the right side of the sequence, built from right to left

    heap = []
    for xf in self.transfers:
      xf.heap_item = HeapItem(xf)
      heap.append(xf.heap_item)
    heapq.heapify(heap)

    # Use OrderedDict() instead of set() to preserve the insertion order. Need
    # to use 'sinks[key] = None' to add key into the set. sinks will look like
    # { key1: None, key2: None, ... }.
    sinks = OrderedDict.fromkeys(u for u in G if not u.outgoing)
    sources = OrderedDict.fromkeys(u for u in G if not u.incoming)

    def adjust_score(iu, delta):
      iu.score += delta
      iu.heap_item.clear()
      iu.heap_item = HeapItem(iu)
      heapq.heappush(heap, iu.heap_item)

    while G:
      # Put all sinks at the end of the sequence.
      while sinks:
        new_sinks = OrderedDict()
        for u in sinks:
          if u not in G:
            continue
          s2.appendleft(u)
          del G[u]
          for iu in u.incoming:
            adjust_score(iu, -iu.outgoing.pop(u))
            if not iu.outgoing:
              new_sinks[iu] = None
        sinks = new_sinks

      # Put all the sources at the beginning of the sequence.
      while sources:
        new_sources = OrderedDict()
        for u in sources:
          if u not in G:
            continue
          s1.append(u)
          del G[u]
          for iu in u.outgoing:
            adjust_score(iu, +iu.incoming.pop(u))
            if not iu.incoming:
              new_sources[iu] = None
        sources = new_sources

      if not G:
        break

      # Find the "best" vertex to put next.  "Best" is the one that
      # maximizes the net difference in source blocks saved we get by
      # pretending it's a source rather than a sink.

      while True:
        u = heapq.heappop(heap)
        if u and u.item in G:
          u = u.item
          break

      s1.append(u)
      del G[u]
      for iu in u.outgoing:
        adjust_score(iu, +iu.incoming.pop(u))
        if not iu.incoming:
          sources[iu] = None

      for iu in u.incoming:
        adjust_score(iu, -iu.outgoing.pop(u))
        if not iu.outgoing:
          sinks[iu] = None

    # Now record the sequence in the 'order' field of each transfer,
    # and by rearranging self.transfers to be in the chosen sequence.

    new_transfers = []
    for x in itertools.chain(s1, s2):
      x.order = len(new_transfers)
      new_transfers.append(x)
      del x.incoming
      del x.outgoing

    self.transfers = new_transfers

  def GenerateDigraph(self):
    logger.info("Generating digraph...")

    # Each item of source_ranges will be:
    #   - None, if that block is not used as a source,
    #   - an ordered set of transfers.
    source_ranges = []
    for b in self.transfers:
      for s, e in b.src_ranges:
        if e > len(source_ranges):
          source_ranges.extend([None] * (e-len(source_ranges)))
        for i in range(s, e):
          if source_ranges[i] is None:
            source_ranges[i] = OrderedDict.fromkeys([b])
          else:
            source_ranges[i][b] = None

    for a in self.transfers:
      intersections = OrderedDict()
      for s, e in a.tgt_ranges:
        for i in range(s, e):
          if i >= len(source_ranges):
            break
          # Add all the Transfers in source_ranges[i] to the (ordered) set.
          if source_ranges[i] is not None:
            for j in source_ranges[i]:
              intersections[j] = None

      for b in intersections:
        if a is b:
          continue

        # If the blocks written by A are read by B, then B needs to go before A.
        i = a.tgt_ranges.intersect(b.src_ranges)
        if i:
          if b.src_name == "__ZERO":
            # the cost of removing source blocks for the __ZERO domain
            # is (nearly) zero.
            size = 0
          else:
            size = i.size()
          b.goes_before[a] = size
          a.goes_after[b] = size

  def ComputePatchesForInputList(self, diff_queue, compress_target):
    """Returns a list of patch information for the input list of transfers.

      Args:
        diff_queue: a list of transfers with style 'diff'
        compress_target: If True, compresses the target ranges of each
            transfers; and save the size.

      Returns:
        A list of (transfer order, patch_info, compressed_size) tuples.
    """

    if not diff_queue:
      return []

    if self.threads > 1:
      logger.info("Computing patches (using %d threads)...", self.threads)
    else:
      logger.info("Computing patches...")

    diff_total = len(diff_queue)
    patches = [None] * diff_total
    error_messages = []

    # Using multiprocessing doesn't give additional benefits, due to the
    # pattern of the code. The diffing work is done by subprocess.call, which
    # already runs in a separate process (not affected much by the GIL -
    # Global Interpreter Lock). Using multiprocess also requires either a)
    # writing the diff input files in the main process before forking, or b)
    # reopening the image file (SparseImage) in the worker processes. Doing
    # neither of them further improves the performance.
    lock = threading.Lock()

    def diff_worker():
      while True:
        with lock:
          if not diff_queue:
            return
          xf_index, imgdiff, patch_index = diff_queue.pop()
          xf = self.transfers[xf_index]

        message = []
        compressed_size = None

        patch_info = xf.patch_info
        if not patch_info:
          src_file = common.MakeTempFile(prefix="src-")
          with open(src_file, "wb") as fd:
            self.src.WriteRangeDataToFd(xf.src_ranges, fd)

          tgt_file = common.MakeTempFile(prefix="tgt-")
          with open(tgt_file, "wb") as fd:
            self.tgt.WriteRangeDataToFd(xf.tgt_ranges, fd)

          try:
            patch_info = compute_patch(src_file, tgt_file, imgdiff)
          except ValueError as e:
            message.append(
                "Failed to generate %s for %s: tgt=%s, src=%s:\n%s" % (
                    "imgdiff" if imgdiff else "bsdiff",
                    xf.tgt_name if xf.tgt_name == xf.src_name else
                    xf.tgt_name + " (from " + xf.src_name + ")",
                    xf.tgt_ranges, xf.src_ranges, e.message))

        if compress_target:
          tgt_data = self.tgt.ReadRangeSet(xf.tgt_ranges)
          try:
            # Compresses with the default level
            compress_obj = zlib.compressobj(6, zlib.DEFLATED, -zlib.MAX_WBITS)
            compressed_data = (compress_obj.compress("".join(tgt_data))
                               + compress_obj.flush())
            compressed_size = len(compressed_data)
          except zlib.error as e:
            message.append(
                "Failed to compress the data in target range {} for {}:\n"
                "{}".format(xf.tgt_ranges, xf.tgt_name, e.message))

        if message:
          with lock:
            error_messages.extend(message)

        with lock:
          patches[patch_index] = (xf_index, patch_info, compressed_size)

    threads = [threading.Thread(target=diff_worker)
               for _ in range(self.threads)]
    for th in threads:
      th.start()
    while threads:
      threads.pop().join()

    if error_messages:
      logger.error('ERROR:')
      logger.error('\n'.join(error_messages))
      logger.error('\n\n\n')
      sys.exit(1)

    return patches

  def SelectAndConvertDiffTransfersToNew(self, violated_stash_blocks):
    """Converts the diff transfers to reduce the max simultaneous stash.

    Since the 'new' data is compressed with deflate, we can select the 'diff'
    transfers for conversion by comparing its patch size with the size of the
    compressed data. Ideally, we want to convert the transfers with a small
    size increase, but using a large number of stashed blocks.
    """
    TransferSizeScore = namedtuple("TransferSizeScore",
                                   "xf, used_stash_blocks, score")

    logger.info("Selecting diff commands to convert to new.")
    diff_queue = []
    for xf in self.transfers:
      if xf.style == "diff" and xf.src_sha1 != xf.tgt_sha1:
        use_imgdiff = self.CanUseImgdiff(xf.tgt_name, xf.tgt_ranges,
                                         xf.src_ranges)
        diff_queue.append((xf.order, use_imgdiff, len(diff_queue)))

    # Remove the 'move' transfers, and compute the patch & compressed size
    # for the remaining.
    result = self.ComputePatchesForInputList(diff_queue, True)

    conversion_candidates = []
    for xf_index, patch_info, compressed_size in result:
      xf = self.transfers[xf_index]
      if not xf.patch_info:
        xf.patch_info = patch_info

      size_ratio = len(xf.patch_info.content) * 100.0 / compressed_size
      diff_style = "imgdiff" if xf.patch_info.imgdiff else "bsdiff"
      logger.info("%s, target size: %d blocks, style: %s, patch size: %d,"
                  " compression_size: %d, ratio %.2f%%", xf.tgt_name,
                  xf.tgt_ranges.size(), diff_style,
                  len(xf.patch_info.content), compressed_size, size_ratio)

      used_stash_blocks = sum(sr.size() for _, sr in xf.use_stash)
      # Convert the transfer to new if the compressed size is smaller or equal.
      # We don't need to maintain the stash_before lists here because the
      # graph will be regenerated later.
      if len(xf.patch_info.content) >= compressed_size:
        # Add the transfer to the candidate list with negative score. And it
        # will be converted later.
        conversion_candidates.append(TransferSizeScore(xf, used_stash_blocks,
                                                       -1))
      elif used_stash_blocks > 0:
        # This heuristic represents the size increase in the final package to
        # remove per unit of stashed data.
        score = ((compressed_size - len(xf.patch_info.content)) * 100.0
                 / used_stash_blocks)
        conversion_candidates.append(TransferSizeScore(xf, used_stash_blocks,
                                                       score))
    # Transfers with lower score (i.e. less expensive to convert) will be
    # converted first.
    conversion_candidates.sort(key=lambda x: x.score)

    # TODO(xunchang), improve the logic to find the transfers to convert, e.g.
    # convert the ones that contribute to the max stash, run ReviseStashSize
    # multiple times etc.
    removed_stashed_blocks = 0
    for xf, used_stash_blocks, _ in conversion_candidates:
      logger.info("Converting %s to new", xf.tgt_name)
      xf.ConvertToNew()
      removed_stashed_blocks += used_stash_blocks
      # Experiments show that we will get a smaller package size if we remove
      # slightly more stashed blocks than the violated stash blocks.
      if removed_stashed_blocks >= violated_stash_blocks:
        break

    logger.info("Removed %d stashed blocks", removed_stashed_blocks)

  def FindTransfers(self):
    """Parse the file_map to generate all the transfers."""

    def AddSplitTransfersWithFixedSizeChunks(tgt_name, src_name, tgt_ranges,
                                             src_ranges, style, by_id):
      """Add one or multiple Transfer()s by splitting large files.

      For BBOTA v3, we need to stash source blocks for resumable feature.
      However, with the growth of file size and the shrink of the cache
      partition source blocks are too large to be stashed. If a file occupies
      too many blocks, we split it into smaller pieces by getting multiple
      Transfer()s.

      The downside is that after splitting, we may increase the package size
      since the split pieces don't align well. According to our experiments,
      1/8 of the cache size as the per-piece limit appears to be optimal.
      Compared to the fixed 1024-block limit, it reduces the overall package
      size by 30% for volantis, and 20% for angler and bullhead."""

      pieces = 0
      while (tgt_ranges.size() > max_blocks_per_transfer and
             src_ranges.size() > max_blocks_per_transfer):
        tgt_split_name = "%s-%d" % (tgt_name, pieces)
        src_split_name = "%s-%d" % (src_name, pieces)
        tgt_first = tgt_ranges.first(max_blocks_per_transfer)
        src_first = src_ranges.first(max_blocks_per_transfer)

        Transfer(tgt_split_name, src_split_name, tgt_first, src_first,
                 self.tgt.RangeSha1(tgt_first), self.src.RangeSha1(src_first),
                 style, by_id)

        tgt_ranges = tgt_ranges.subtract(tgt_first)
        src_ranges = src_ranges.subtract(src_first)
        pieces += 1

      # Handle remaining blocks.
      if tgt_ranges.size() or src_ranges.size():
        # Must be both non-empty.
        assert tgt_ranges.size() and src_ranges.size()
        tgt_split_name = "%s-%d" % (tgt_name, pieces)
        src_split_name = "%s-%d" % (src_name, pieces)
        Transfer(tgt_split_name, src_split_name, tgt_ranges, src_ranges,
                 self.tgt.RangeSha1(tgt_ranges), self.src.RangeSha1(src_ranges),
                 style, by_id)

    def AddSplitTransfers(tgt_name, src_name, tgt_ranges, src_ranges, style,
                          by_id):
      """Find all the zip files and split the others with a fixed chunk size.

      This function will construct a list of zip archives, which will later be
      split by imgdiff to reduce the final patch size. For the other files,
      we will plainly split them based on a fixed chunk size with the potential
      patch size penalty.
      """

      assert style == "diff"

      # Change nothing for small files.
      if (tgt_ranges.size() <= max_blocks_per_transfer and
          src_ranges.size() <= max_blocks_per_transfer):
        Transfer(tgt_name, src_name, tgt_ranges, src_ranges,
                 self.tgt.RangeSha1(tgt_ranges), self.src.RangeSha1(src_ranges),
                 style, by_id)
        return

      # Split large APKs with imgdiff, if possible. We're intentionally checking
      # file types one more time (CanUseImgdiff() checks that as well), before
      # calling the costly RangeSha1()s.
      if (self.FileTypeSupportedByImgdiff(tgt_name) and
          self.tgt.RangeSha1(tgt_ranges) != self.src.RangeSha1(src_ranges)):
        if self.CanUseImgdiff(tgt_name, tgt_ranges, src_ranges, True):
          large_apks.append((tgt_name, src_name, tgt_ranges, src_ranges))
          return

      AddSplitTransfersWithFixedSizeChunks(tgt_name, src_name, tgt_ranges,
                                           src_ranges, style, by_id)

    def AddTransfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id,
                    split=False):
      """Wrapper function for adding a Transfer()."""

      # We specialize diff transfers only (which covers bsdiff/imgdiff/move);
      # otherwise add the Transfer() as is.
      if style != "diff" or not split:
        Transfer(tgt_name, src_name, tgt_ranges, src_ranges,
                 self.tgt.RangeSha1(tgt_ranges), self.src.RangeSha1(src_ranges),
                 style, by_id)
        return

      # Handle .odex files specially to analyze the block-wise difference. If
      # most of the blocks are identical with only few changes (e.g. header),
      # we will patch the changed blocks only. This avoids stashing unchanged
      # blocks while patching. We limit the analysis to files without size
      # changes only. This is to avoid sacrificing the OTA generation cost too
      # much.
      if (tgt_name.split(".")[-1].lower() == 'odex' and
          tgt_ranges.size() == src_ranges.size()):

        # 0.5 threshold can be further tuned. The tradeoff is: if only very
        # few blocks remain identical, we lose the opportunity to use imgdiff
        # that may have better compression ratio than bsdiff.
        crop_threshold = 0.5

        tgt_skipped = RangeSet()
        src_skipped = RangeSet()
        tgt_size = tgt_ranges.size()
        tgt_changed = 0
        for src_block, tgt_block in zip(src_ranges.next_item(),
                                        tgt_ranges.next_item()):
          src_rs = RangeSet(str(src_block))
          tgt_rs = RangeSet(str(tgt_block))
          if self.src.ReadRangeSet(src_rs) == self.tgt.ReadRangeSet(tgt_rs):
            tgt_skipped = tgt_skipped.union(tgt_rs)
            src_skipped = src_skipped.union(src_rs)
          else:
            tgt_changed += tgt_rs.size()

          # Terminate early if no clear sign of benefits.
          if tgt_changed > tgt_size * crop_threshold:
            break

        if tgt_changed < tgt_size * crop_threshold:
          assert tgt_changed + tgt_skipped.size() == tgt_size
          logger.info(
              '%10d %10d (%6.2f%%) %s', tgt_skipped.size(), tgt_size,
              tgt_skipped.size() * 100.0 / tgt_size, tgt_name)
          AddSplitTransfers(
              "%s-skipped" % (tgt_name,),
              "%s-skipped" % (src_name,),
              tgt_skipped, src_skipped, style, by_id)

          # Intentionally change the file extension to avoid being imgdiff'd as
          # the files are no longer in their original format.
          tgt_name = "%s-cropped" % (tgt_name,)
          src_name = "%s-cropped" % (src_name,)
          tgt_ranges = tgt_ranges.subtract(tgt_skipped)
          src_ranges = src_ranges.subtract(src_skipped)

          # Possibly having no changed blocks.
          if not tgt_ranges:
            return

      # Add the transfer(s).
      AddSplitTransfers(
          tgt_name, src_name, tgt_ranges, src_ranges, style, by_id)

    def ParseAndValidateSplitInfo(patch_size, tgt_ranges, src_ranges,
                                  split_info):
      """Parse the split_info and return a list of info tuples.

      Args:
        patch_size: total size of the patch file.
        tgt_ranges: Ranges of the target file within the original image.
        src_ranges: Ranges of the source file within the original image.
        split_info format:
          imgdiff version#
          count of pieces
          <patch_size_1> <tgt_size_1> <src_ranges_1>
          ...
          <patch_size_n> <tgt_size_n> <src_ranges_n>

      Returns:
        [patch_start, patch_len, split_tgt_ranges, split_src_ranges]
      """

      version = int(split_info[0])
      assert version == 2
      count = int(split_info[1])
      assert len(split_info) - 2 == count

      split_info_list = []
      patch_start = 0
      tgt_remain = copy.deepcopy(tgt_ranges)
      # each line has the format <patch_size>, <tgt_size>, <src_ranges>
      for line in split_info[2:]:
        info = line.split()
        assert len(info) == 3
        patch_length = int(info[0])

        split_tgt_size = int(info[1])
        assert split_tgt_size % 4096 == 0
        assert split_tgt_size // 4096 <= tgt_remain.size()
        split_tgt_ranges = tgt_remain.first(split_tgt_size // 4096)
        tgt_remain = tgt_remain.subtract(split_tgt_ranges)

        # Find the split_src_ranges within the image file from its relative
        # position in file.
        split_src_indices = RangeSet.parse_raw(info[2])
        split_src_ranges = RangeSet()
        for r in split_src_indices:
          curr_range = src_ranges.first(r[1]).subtract(src_ranges.first(r[0]))
          assert not split_src_ranges.overlaps(curr_range)
          split_src_ranges = split_src_ranges.union(curr_range)

        split_info_list.append((patch_start, patch_length,
                                split_tgt_ranges, split_src_ranges))
        patch_start += patch_length

      # Check that the sizes of all the split pieces add up to the final file
      # size for patch and target.
      assert tgt_remain.size() == 0
      assert patch_start == patch_size
      return split_info_list

    def SplitLargeApks():
      """Split the large apks files.

      Example: Chrome.apk will be split into
        src-0: Chrome.apk-0, tgt-0: Chrome.apk-0
        src-1: Chrome.apk-1, tgt-1: Chrome.apk-1
        ...

      After the split, the target pieces are continuous and block aligned; and
      the source pieces are mutually exclusive. During the split, we also
      generate and save the image patch between src-X & tgt-X. This patch will
      be valid because the block ranges of src-X & tgt-X will always stay the
      same afterwards; but there's a chance we don't use the patch if we
      convert the "diff" command into "new" or "move" later.
      """

      while True:
        with transfer_lock:
          if not large_apks:
            return
          tgt_name, src_name, tgt_ranges, src_ranges = large_apks.pop(0)

        src_file = common.MakeTempFile(prefix="src-")
        tgt_file = common.MakeTempFile(prefix="tgt-")
        with open(src_file, "wb") as src_fd:
          self.src.WriteRangeDataToFd(src_ranges, src_fd)
        with open(tgt_file, "wb") as tgt_fd:
          self.tgt.WriteRangeDataToFd(tgt_ranges, tgt_fd)

        patch_file = common.MakeTempFile(prefix="patch-")
        patch_info_file = common.MakeTempFile(prefix="split_info-")
        cmd = ["imgdiff", "-z",
               "--block-limit={}".format(max_blocks_per_transfer),
               "--split-info=" + patch_info_file,
               src_file, tgt_file, patch_file]
        proc = common.Run(cmd)
        imgdiff_output, _ = proc.communicate()
        assert proc.returncode == 0, \
            "Failed to create imgdiff patch between {} and {}:\n{}".format(
                src_name, tgt_name, imgdiff_output)

        with open(patch_info_file) as patch_info:
          lines = patch_info.readlines()

        patch_size_total = os.path.getsize(patch_file)
        split_info_list = ParseAndValidateSplitInfo(patch_size_total,
                                                    tgt_ranges, src_ranges,
                                                    lines)
        for index, (patch_start, patch_length, split_tgt_ranges,
                    split_src_ranges) in enumerate(split_info_list):
          with open(patch_file, 'rb') as f:
            f.seek(patch_start)
            patch_content = f.read(patch_length)

          split_src_name = "{}-{}".format(src_name, index)
          split_tgt_name = "{}-{}".format(tgt_name, index)
          split_large_apks.append((split_tgt_name,
                                   split_src_name,
                                   split_tgt_ranges,
                                   split_src_ranges,
                                   patch_content))

    logger.info("Finding transfers...")

    large_apks = []
    split_large_apks = []
    cache_size = common.OPTIONS.cache_size
    split_threshold = 0.125
    assert cache_size is not None
    max_blocks_per_transfer = int(cache_size * split_threshold /
                                  self.tgt.blocksize)
    empty = RangeSet()
    for tgt_fn, tgt_ranges in sorted(self.tgt.file_map.items()):
      if tgt_fn == "__ZERO":
        # the special "__ZERO" domain is all the blocks not contained
        # in any file and that are filled with zeros.  We have a
        # special transfer style for zero blocks.
        src_ranges = self.src.file_map.get("__ZERO", empty)
        AddTransfer(tgt_fn, "__ZERO", tgt_ranges, src_ranges,
                    "zero", self.transfers)
        continue

      elif tgt_fn == "__COPY":
        # "__COPY" domain includes all the blocks not contained in any
        # file and that need to be copied unconditionally to the target.
        AddTransfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
        continue

      elif tgt_fn == "__HASHTREE":
        continue

      elif tgt_fn in self.src.file_map:
        # Look for an exact pathname match in the source.
        AddTransfer(tgt_fn, tgt_fn, tgt_ranges, self.src.file_map[tgt_fn],
                    "diff", self.transfers, True)
        continue

      b = os.path.basename(tgt_fn)
      if b in self.src_basenames:
        # Look for an exact basename match in the source.
        src_fn = self.src_basenames[b]
        AddTransfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
                    "diff", self.transfers, True)
        continue

      b = re.sub("[0-9]+", "#", b)
      if b in self.src_numpatterns:
        # Look for a 'number pattern' match (a basename match after
        # all runs of digits are replaced by "#").  (This is useful
        # for .so files that contain version numbers in the filename
        # that get bumped.)
        src_fn = self.src_numpatterns[b]
        AddTransfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
                    "diff", self.transfers, True)
        continue

      AddTransfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)

    transfer_lock = threading.Lock()
    threads = [threading.Thread(target=SplitLargeApks)
               for _ in range(self.threads)]
    for th in threads:
      th.start()
    while threads:
      threads.pop().join()

    # Sort the split transfers for large apks to generate a determinate package.
    split_large_apks.sort()
    for (tgt_name, src_name, tgt_ranges, src_ranges,
         patch) in split_large_apks:
      transfer_split = Transfer(tgt_name, src_name, tgt_ranges, src_ranges,
                                self.tgt.RangeSha1(tgt_ranges),
                                self.src.RangeSha1(src_ranges),
                                "diff", self.transfers)
      transfer_split.patch_info = PatchInfo(True, patch)

  def AbbreviateSourceNames(self):
    for k in self.src.file_map.keys():
      b = os.path.basename(k)
      self.src_basenames[b] = k
      b = re.sub("[0-9]+", "#", b)
      self.src_numpatterns[b] = k

  @staticmethod
  def AssertPartition(total, seq):
    """Assert that all the RangeSets in 'seq' form a partition of the
    'total' RangeSet (ie, they are nonintersecting and their union
    equals 'total')."""

    so_far = RangeSet()
    for i in seq:
      assert not so_far.overlaps(i)
      so_far = so_far.union(i)
    assert so_far == total
