Read a message from this transport and return it.

    Reads a message of RECV_MSG_TYPE and returns it.  Note that this method
    abstracts the data length and data read so that the caller simply gets the
    data along with the header in the returned message.

    Args:
      timeout: timeouts.PolledTimeout to use for the operation.

    Returns:
      An instance of self.RECV_MSG_TYPE that was read from self.stream.

    Raises:
      AdbProtocolError: If an invalid response is received.
      AdbRemoteError: If a FAIL response is received.

def read_message(self, timeout=None):
    """Read a message from this transport and return it.

    Reads a message of RECV_MSG_TYPE and returns it.  Note that this method
    abstracts the data length and data read so that the caller simply gets the
    data along with the header in the returned message.

    Args:
      timeout: timeouts.PolledTimeout to use for the operation.

    Returns:
      An instance of self.RECV_MSG_TYPE that was read from self.stream.

    Raises:
      AdbProtocolError: If an invalid response is received.
      AdbRemoteError: If a FAIL response is received.
    """
    raw_data = self.stream.read(
        struct.calcsize(self.RECV_MSG_TYPE.struct_format), timeout)
    try:
      raw_message = struct.unpack(self.RECV_MSG_TYPE.struct_format, raw_data)
    except struct.error:
      raise usb_exceptions.AdbProtocolError(
          '%s expected format "%s", got data %s', self,
          self.RECV_MSG_TYPE.struct_format, raw_data)

    if raw_message[0] not in self.WIRE_TO_CMD:
      raise usb_exceptions.AdbProtocolError(
          'Unrecognized command id: %s', raw_message)

    # Swap out the wire command with the string equivalent.
    raw_message = (self.WIRE_TO_CMD[raw_message[0]],) + raw_message[1:]

    if self.RECV_MSG_TYPE.has_data and raw_message[-1]:
      # For messages that have data, the length of the data is the last field
      # in the struct.  We do another read and swap out that length for the
      # actual data read before we create the namedtuple to return.
      data_len = raw_message[-1]
      raw_message = raw_message[:-1] + (self.stream.read(data_len, timeout),)

    if raw_message[0] not in self.VALID_RESPONSES:
      raise usb_exceptions.AdbProtocolError(
          '%s not a valid response for %s', raw_message[0], self)
    if raw_message[0] == 'FAIL':
      raise usb_exceptions.AdbRemoteError(
          'Remote ADB failure: %s', raw_message)
    return self.RECV_MSG_TYPE(*raw_message)