def _VerifyReplyCommand(cls, header, expected_ids): # Header is (ID, ...). command_id = adb_protocol.Wire2ID(header[0]) if command_id not in cls._VALID_IDS: raise usb_exceptions.AdbCommandFailureException( 'Command failed; incorrect header: %s' % header) if command_id not in expected_ids: if command_id == 'FAIL': raise usb_exceptions.AdbCommandFailureException( 'Command failed.') raise adb_protocol.InvalidResponseError( 'Expected one of %s, got %s' % (expected_ids, command_id)) return command_id
def Read(self, expected_ids, read_data=True): """Read ADB messages and return FileSync packets.""" if self.send_buffer: self._Flush() # Read one filesync packet off the recv buffer. header_data = self._ReadBuffered(self.recv_header_len) header = struct.unpack(self.recv_header_format, header_data) # Header is (ID, ...). command_id = self.wire_to_id[header[0]] if command_id not in expected_ids: if command_id == 'FAIL': raise usb_exceptions.AdbCommandFailureException( 'Command failed.') raise adb_protocol.InvalidResponseError( 'Expected one of %s, got %s' % (expected_ids, command_id)) if not read_data: return command_id, header[1:] # Header is (ID, ..., size). size = header[-1] data = self._ReadBuffered(size) return command_id, header[1:-1], data
def StreamingCommand(cls, usb, service, command='', timeout_ms=None): """One complete set of USB packets for a single command. Sends service:command in a new connection, reading the data for the response. All the data is held in memory, large responses will be slow and can fill up memory. Args: usb: USB device handle with BulkRead and BulkWrite methods. service: The service on the device to talk to. command: The command to send to the service. timeout_ms: Timeout for USB packets, in milliseconds. Raises: InterleavedDataError: Multiple streams running over usb. InvalidCommandError: Got an unexpected response command. Yields: The responses from the service. """ warnings.warn( DeprecationWarning( "This method may fail with utf-8 multi-bytes sequences")) if not isinstance(command, bytes): command = command.encode('utf8') connection = cls.Open(usb, destination=b'%s:%s' % (service, command), timeout_ms=timeout_ms) if connection is None: raise usb_exceptions.AdbCommandFailureException( 'Command failed: Device immediately closed the stream.') for data in connection.ReadUntilClose(): # TODO: find a fix for this code without changing public API yield data.decode('utf-8')
def Close(self): self._Send('CLSE', arg0=self.local_id, arg1=self.remote_id) cmd, data = self.ReadUntil('CLSE') if cmd != 'CLSE': if cmd == 'FAIL': raise usb_exceptions.AdbCommandFailureException('Command failed.', data) raise InvalidCommandError('Expected a CLSE response, got %s (%s)', cmd, data)
def Write(self, data): """Write a packet and expect an Ack.""" self._Send(b'WRTE', arg0=self.local_id, arg1=self.remote_id, data=data) # Expect an ack in response. cmd, okay_data = self.ReadUntil(b'OKAY') if cmd != b'OKAY': if cmd == b'FAIL': raise usb_exceptions.AdbCommandFailureException( 'Command failed.', okay_data) raise InvalidCommandError( 'Expected an OKAY in response to a WRITE, got %s (%s)', cmd, okay_data) return len(data)
def _ReadBuffered(self, size): # Ensure recv buffer has enough data. while len(self.recv_buffer) < size: try: msg = self.adb.ReadUntil('WRTE') except adb_protocol.InvalidResponseError as e: raise usb_exceptions.AdbCommandFailureException( 'Command failed: %s' % e) self.recv_buffer += msg.data result = self.recv_buffer[:size] self.recv_buffer = self.recv_buffer[size:] return result
def ReadUntilClose(self): """Yield packets until a Close packet is received.""" while True: cmd, data = self.ReadUntil(b'CLSE', b'WRTE') if cmd == b'CLSE': self._Send(b'CLSE', arg0=self.local_id, arg1=self.remote_id) break if cmd != b'WRTE': if cmd == b'FAIL': raise usb_exceptions.AdbCommandFailureException( 'Command failed.', data) raise InvalidCommandError( 'Expected a WRITE or a CLOSE, got %s (%s)', cmd, data) yield data