Пример #1
0
  def Write(self, data, timeout):
    """Write data to this stream, using the given timeouts.PolledTimeout."""
    if not self.remote_id:
      raise usb_exceptions.AdbStreamClosedError(
          'Cannot Write() to half-opened %s', self)
    if self.closed_state != self.ClosedState.OPEN:
      raise usb_exceptions.AdbStreamClosedError(
          'Cannot Write() to closed %s', self)
    elif self._expecting_okay:
      raise usb_exceptions.AdbProtocolError(
          'Previous WRTE failed, %s in unknown state', self)

    # Make sure we only have one WRTE in flight at a time, because ADB doesn't
    # identify which WRTE it is ACK'ing when it sends the OKAY message back.
    with self._write_lock:
      self._expecting_okay = True
      self._SendCommand('WRTE', timeout, data)
      self._ReadMessagesUntilTrue(lambda: not self._expecting_okay, timeout)
Пример #2
0
    def read_for_stream(self, stream_transport, timeout_ms=None):
        """Attempt to read a packet for the given stream transport.

    Will read packets from self.transport until one intended for the given
    AdbStream is found.  If another thread is already reading packets, this will
    block until that thread reads a packet for this stream, or timeout expires.
    Note that this method always returns None, but if a packet was read for the
    given stream, it will have been added to that stream's message queue.

    This is somewhat tricky to do - first we check if there's a message already
    in our queue.  If not, then we try to use our AdbConnection to read a
    message for this stream.

    If some other thread is already doing reads, then read_for_stream() will sit
    in a tight loop, with a short delay, checking our message queue for a
    message from the other thread.

    Note that we must pass the queue in from the AdbStream, rather than looking
    it up in the AdbConnection's map, because the AdbConnection may have
    removed the queue from its map (while it still had messages in it).  The
    AdbStream itself maintains a reference to the queue to avoid dropping those
    messages.

    The AdbMessage read is guaranteed to be one of 'OKAY', 'WRTE', or 'CLSE'.
    If it was a WRTE message, then it will have been automatically ACK'd with an
    OKAY message, if it was a CLSE message it will have been ACK'd with a
    corresponding CLSE message, and this AdbStream will be marked as closed.

    Args:
      stream_transport: The AdbStreamTransport for the stream that is reading
        an AdbMessage from this AdbConnection.
      timeout_ms: If provided, timeout, in milliseconds, to use.  Note this
        timeout applies to this entire call, not for each individual Read, since
        there may be multiple reads if messages for other streams are read.
        This argument may be a timeouts.PolledTimeout.

    Returns:
      AdbMessage that was read, guaranteed to be one of 'OKAY', 'CLSE', or
    'WRTE' command.

    Raises:
      AdbTimeoutError: If we don't get a packet for this stream before
        timeout expires.
      AdbStreamClosedError: If the given stream has been closed.
    """
        timeout = timeouts.PolledTimeout.from_millis(timeout_ms)
        # Bail when the timeout expires, or when we no longer have the given stream
        # in our map (it may have been closed, we don't want to leave a thread
        # hanging in this loop when that happens).
        while (not timeout.has_expired()
               and stream_transport.local_id in self._stream_transport_map):
            try:
                # Block for up to 10ms to rate-limit how fast we spin.
                return stream_transport.message_queue.get(True, .01)
            except Queue.Empty:
                pass

            # If someone else has the Lock, just keep checking our queue.
            if not self._reader_lock.acquire(False):
                continue

            try:
                # Now that we've acquired the Lock, we have to check the queue again,
                # just in case someone had the Lock but hadn't yet added our message
                # to the queue when we checked the first time.  Now that we have the
                # Lock ourselves, we're sure there are no potentially in-flight reads.
                try:
                    return stream_transport.message_queue.get_nowait()
                except Queue.Empty:
                    pass

                while not timeout.has_expired():
                    msg = self._handle_message_for_stream(
                        stream_transport, self.transport.read_message(timeout),
                        timeout)
                    if msg:
                        return msg
            finally:
                self._reader_lock.release()

        if timeout.has_expired():
            raise usb_exceptions.AdbTimeoutError('Read timed out for %s',
                                                 stream_transport)

        # The stream is no longer in the map, so it's closed, but check for any
        # queued messages.
        try:
            return stream_transport.message_queue.get_nowait()
        except Queue.Empty:
            raise usb_exceptions.AdbStreamClosedError(
                'Attempt to read from closed or unknown %s', stream_transport)