Downloads a file to the device.

    Args:
      source_file: A filename or file-like object to download to the device.
      source_len: Optional length of source_file. If source_file is a file-like
          object and source_len is not provided, source_file is read into
          memory.
      info_cb: Optional callback accepting FastbootMessage for text sent from
          the bootloader.
      progress_callback: Optional callback called with the percent of the
          source_file downloaded. Note, this doesn't include progress of the
          actual flashing.

    Returns:
      Response to a download request, normally nothing.

def download(self, source_file, source_len=0,
               info_cb=DEFAULT_MESSAGE_CALLBACK, progress_callback=None):
    """Downloads a file to the device.

    Args:
      source_file: A filename or file-like object to download to the device.
      source_len: Optional length of source_file. If source_file is a file-like
          object and source_len is not provided, source_file is read into
          memory.
      info_cb: Optional callback accepting FastbootMessage for text sent from
          the bootloader.
      progress_callback: Optional callback called with the percent of the
          source_file downloaded. Note, this doesn't include progress of the
          actual flashing.

    Returns:
      Response to a download request, normally nothing.
    """
    if isinstance(source_file, six.string_types):
      source_len = os.stat(source_file).st_size
      source_file = open(source_file)

    if source_len == 0:
      # Fall back to storing it all in memory :(
      data = source_file.read()
      source_file = six.StringIO(data)
      source_len = len(data)

    self._protocol.send_command('download', '%08x' % source_len)
    return self._protocol.handle_data_sending(
        source_file, source_len, info_cb, progress_callback=progress_callback)