Push a file-like object to the device.

    Args:
      src_file: File-like object for reading from
      filename: Filename to push to on the device
      st_mode: stat mode for filename on the device
      mtime: modification time to set for the file on the device
      timeout: Timeout to use for the send operation.

    Raises:
      AdbProtocolError: If we get an unexpected response.
      AdbRemoteError: If there's a remote error (but valid protocol).

def send(self, src_file, filename, st_mode=DEFAULT_PUSH_MODE, mtime=None,
           timeout=None):
    """Push a file-like object to the device.

    Args:
      src_file: File-like object for reading from
      filename: Filename to push to on the device
      st_mode: stat mode for filename on the device
      mtime: modification time to set for the file on the device
      timeout: Timeout to use for the send operation.

    Raises:
      AdbProtocolError: If we get an unexpected response.
      AdbRemoteError: If there's a remote error (but valid protocol).
    """
    transport = DataFilesyncTransport(self.stream)
    transport.write_data('SEND', '%s,%s' % (filename, st_mode), timeout)

    try:
      while True:
        data = src_file.read(MAX_PUSH_DATA_BYTES)
        if not data:
          break
        transport.write_data('DATA', data, timeout)

      mtime = mtime or int(time.time())
      transport.write_message(
          FilesyncMessageTypes.DoneMessage('DONE', mtime), timeout)
    except usb_exceptions.AdbStreamClosedError:
      # Try to do one last read to see if we can get any more information,
      # ignoring any errors for this Read attempt. Note that this always
      # raises, either a new AdbRemoteError, or the AdbStreamClosedError.
      self._check_for_fail_message(transport, sys.exc_info(), timeout)

    data_msg = transport.read_message(timeout)
    data_msg.assert_command_is('OKAY')