adb_wrapper.py revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson# Copyright 2013 The Chromium Authors. All rights reserved.
2e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson# Use of this source code is governed by a BSD-style license that can be
3e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson# found in the LICENSE file.
4e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
5e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson"""This module wraps Android's adb tool.
6e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
7e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian ParkinsonThis is a thin wrapper around the adb interface. Any additional complexity
8e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonshould be delegated to a higher level (ex. DeviceUtils).
9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson"""
10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport errno
12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport os
13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonfrom pylib import cmd_helper
15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonfrom pylib.device import decorators
16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonfrom pylib.device import device_errors
17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson_DEFAULT_TIMEOUT = 30
20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson_DEFAULT_RETRIES = 2
21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsondef _VerifyLocalFileExists(path):
24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  """Verifies a local file exists.
25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  Args:
27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    path: Path to the local file.
28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  Raises:
30e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    IOError: If the file doesn't exist.
31e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  """
32e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  if not os.path.exists(path):
33e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    raise IOError(errno.ENOENT, os.strerror(errno.ENOENT), path)
34e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
35e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
36e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonclass AdbWrapper(object):
37e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  """A wrapper around a local Android Debug Bridge executable."""
38e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
39e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def __init__(self, device_serial):
40e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Initializes the AdbWrapper.
41e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
42e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
43e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      device_serial: The device serial number as a string.
44e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
45e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._device_serial = str(device_serial)
46e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
47e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  # pylint: disable=W0613
48e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  @classmethod
49e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  @decorators.WithTimeoutAndRetries
50e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def _RunAdbCmd(cls, arg_list, timeout=None, retries=None, check_error=True):
51e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    cmd = ['adb'] + arg_list
52e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    exit_code, output = cmd_helper.GetCmdStatusAndOutput(cmd)
53e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if exit_code != 0:
54e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      raise device_errors.CommandFailedError(
55e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson          cmd, 'returned non-zero exit code %s, output: %s' %
56e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson          (exit_code, output))
57e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    # This catches some errors, including when the device drops offline;
58e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    # unfortunately adb is very inconsistent with error reporting so many
59e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    # command failures present differently.
60e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if check_error and output[:len('error:')] == 'error:':
61e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      raise device_errors.CommandFailedError(arg_list, output)
62e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return output
63e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  # pylint: enable=W0613
64e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
65e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def _DeviceAdbCmd(self, arg_list, timeout, retries, check_error=True):
66e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Runs an adb command on the device associated with this object.
67e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
68e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
69e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      arg_list: A list of arguments to adb.
70e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: Timeout in seconds.
71e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: Number of retries.
72e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      check_error: Check that the command doesn't return an error message. This
73e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        does NOT check the return code of shell commands.
74e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
75e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
76e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      The output of the command.
77e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
78e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return self._RunAdbCmd(
79e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        ['-s', self._device_serial] + arg_list, timeout=timeout,
80e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        retries=retries, check_error=check_error)
81e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
82e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def __eq__(self, other):
83e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Consider instances equal if they refer to the same device.
84e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
85e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
86e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      other: The instance to compare equality with.
87e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
88e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
89e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      True if the instances are considered equal, false otherwise.
90e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
91e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return self._device_serial == str(other)
92e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
93e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def __str__(self):
94e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """The string representation of an instance.
95e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
96e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
97e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      The device serial number as a string.
98e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
99e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return self._device_serial
100e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
101e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def __repr__(self):
102e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return '%s(\'%s\')' % (self.__class__.__name__, self)
103e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
104e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  # TODO(craigdh): Determine the filter criteria that should be supported.
105e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  @classmethod
106e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def GetDevices(cls, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
107e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Get the list of active attached devices.
108e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
109e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
110e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
111e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
112e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
113e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Yields:
114e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      AdbWrapper instances.
115e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
116e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    output = cls._RunAdbCmd(['devices'], timeout=timeout, retries=retries)
117e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    lines = [line.split() for line in output.split('\n')]
118e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return [AdbWrapper(line[0]) for line in lines
119e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            if len(line) == 2 and line[1] == 'device']
120e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
121e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def GetDeviceSerial(self):
122e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Gets the device serial number associated with this object.
123e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
124e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
125e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      Device serial number as a string.
126e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
127e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return self._device_serial
128e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
129e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Push(self, local, remote, timeout=60*5, retries=_DEFAULT_RETRIES):
130e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Pushes a file from the host to the device.
131e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
132e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
133e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      local: Path on the host filesystem.
134e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      remote: Path on the device filesystem.
135e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
136e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
137e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
138e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    _VerifyLocalFileExists(local)
139e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._DeviceAdbCmd(['push', local, remote], timeout, retries)
140e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
141e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Pull(self, remote, local, timeout=60*5, retries=_DEFAULT_RETRIES):
142e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Pulls a file from the device to the host.
143e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
144e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
145e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      remote: Path on the device filesystem.
146e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      local: Path on the host filesystem.
147e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
148e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
149e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
150e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._DeviceAdbCmd(['pull', remote, local], timeout, retries)
151e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    _VerifyLocalFileExists(local)
152e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
153e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Shell(self, command, expect_rc=None, timeout=_DEFAULT_TIMEOUT,
154e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            retries=_DEFAULT_RETRIES):
155e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Runs a shell command on the device.
156e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
157e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
158e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      command: The shell command to run.
159e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      expect_rc: (optional) If set checks that the command's return code matches
160e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        this value.
161e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
162e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
163e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
164e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
165e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      The output of the shell command as a string.
166e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
167e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Raises:
168e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      device_errors.CommandFailedError: If the return code doesn't match
169e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        |expect_rc|.
170e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
171e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if expect_rc is None:
172e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      actual_command = command
173e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    else:
174e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      actual_command = '%s; echo $?;' % command
175e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    output = self._DeviceAdbCmd(
176e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        ['shell', actual_command], timeout, retries, check_error=False)
177e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if expect_rc is not None:
178e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      output_end = output.rstrip().rfind('\n') + 1
179e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      rc = output[output_end:].strip()
180e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      output = output[:output_end]
181e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      if int(rc) != expect_rc:
182e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        raise device_errors.CommandFailedError(
183e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            ['shell', command],
184e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            'shell command exited with code: %s' % rc,
185e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            self._device_serial)
186e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return output
187e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
188e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Logcat(self, filter_spec=None, timeout=_DEFAULT_TIMEOUT,
189e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson             retries=_DEFAULT_RETRIES):
190e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Get the logcat output.
191e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
192e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
193e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      filter_spec: (optional) Spec to filter the logcat.
194e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
195e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
196e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
197e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
198e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      logcat output as a string.
199e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
200e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    cmd = ['logcat']
201e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if filter_spec is not None:
202e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append(filter_spec)
203e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return self._DeviceAdbCmd(cmd, timeout, retries, check_error=False)
204e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
205e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Forward(self, local, remote, timeout=_DEFAULT_TIMEOUT,
206e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson              retries=_DEFAULT_RETRIES):
207e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Forward socket connections from the local socket to the remote socket.
208e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
209e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Sockets are specified by one of:
210e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      tcp:<port>
211e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      localabstract:<unix domain socket name>
212e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      localreserved:<unix domain socket name>
213e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      localfilesystem:<unix domain socket name>
214e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      dev:<character device name>
215e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      jdwp:<process pid> (remote only)
216e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
217e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
218e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      local: The host socket.
219e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      remote: The device socket.
220e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
221e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
222e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
223e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._DeviceAdbCmd(['forward', str(local), str(remote)], timeout, retries)
224e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
225e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def JDWP(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
226e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """List of PIDs of processes hosting a JDWP transport.
227e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
228e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
229e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
230e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
231e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
232e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
233e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      A list of PIDs as strings.
234e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
235e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return [a.strip() for a in
236e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            self._DeviceAdbCmd(['jdwp'], timeout, retries).split('\n')]
237e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
238e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Install(self, apk_path, forward_lock=False, reinstall=False,
239e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson              sd_card=False, timeout=60*2, retries=_DEFAULT_RETRIES):
240e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Install an apk on the device.
241e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
242e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
243e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      apk_path: Host path to the APK file.
244e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      forward_lock: (optional) If set forward-locks the app.
245e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      reinstall: (optional) If set reinstalls the app, keeping its data.
246e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      sd_card: (optional) If set installs on the SD card.
247e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
248e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
249e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
250e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    _VerifyLocalFileExists(apk_path)
251e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    cmd = ['install']
252e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if forward_lock:
253e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-l')
254e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if reinstall:
255e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-r')
256e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if sd_card:
257e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-s')
258e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    cmd.append(apk_path)
259e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    output = self._DeviceAdbCmd(cmd, timeout, retries)
260e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if 'Success' not in output:
261e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      raise device_errors.CommandFailedError(cmd, output)
262e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
263e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Uninstall(self, package, keep_data=False, timeout=_DEFAULT_TIMEOUT,
264e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                retries=_DEFAULT_RETRIES):
265e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Remove the app |package| from the device.
266e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
267e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
268e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      package: The package to uninstall.
269e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      keep_data: (optional) If set keep the data and cache directories.
270e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
271e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
272e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
273e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    cmd = ['uninstall']
274e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if keep_data:
275e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-k')
276e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    cmd.append(package)
277e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    output = self._DeviceAdbCmd(cmd, timeout, retries)
278e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if 'Failure' in output:
279e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      raise device_errors.CommandFailedError(cmd, output)
280e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
281e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Backup(self, path, packages=None, apk=False, shared=False,
282e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson             nosystem=True, include_all=False, timeout=_DEFAULT_TIMEOUT,
283e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson             retries=_DEFAULT_RETRIES):
284e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Write an archive of the device's data to |path|.
285e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
286e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
287e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      path: Local path to store the backup file.
288e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      packages: List of to packages to be backed up.
289e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      apk: (optional) If set include the .apk files in the archive.
290e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      shared: (optional) If set buckup the device's SD card.
291e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      nosystem: (optional) If set exclude system applications.
292e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      include_all: (optional) If set back up all installed applications and
293e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        |packages| is optional.
294e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
295e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
296e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
297e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    cmd = ['backup', path]
298e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if apk:
299e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-apk')
300e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if shared:
301e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-shared')
302e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if nosystem:
303e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-nosystem')
304e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if include_all:
305e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.append('-all')
306e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if packages:
307e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd.extend(packages)
308e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    assert bool(packages) ^ bool(include_all), (
309e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        'Provide \'packages\' or set \'include_all\' but not both.')
310e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    ret = self._DeviceAdbCmd(cmd, timeout, retries)
311e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    _VerifyLocalFileExists(path)
312e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return ret
313e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
314e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Restore(self, path, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
315e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Restore device contents from the backup archive.
316e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
317e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
318e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      path: Host path to the backup archive.
319e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
320e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
321e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
322e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    _VerifyLocalFileExists(path)
323e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._DeviceAdbCmd(['restore'] + [path], timeout, retries)
324e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
325e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def WaitForDevice(self, timeout=60*5, retries=_DEFAULT_RETRIES):
326e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Block until the device is online.
327e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
328e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
329e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
330e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
331e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
332e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._DeviceAdbCmd(['wait-for-device'], timeout, retries)
333e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
334e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def GetState(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
335e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Get device state.
336e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
337e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
338e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
339e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
340e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
341e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
342e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      One of 'offline', 'bootloader', or 'device'.
343e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
344e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return self._DeviceAdbCmd(['get-state'], timeout, retries).strip()
345e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
346e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def GetDevPath(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
347e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Gets the device path.
348e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
349e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
350e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
351e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
352e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
353e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Returns:
354e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      The device path (e.g. usb:3-4)
355e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
356e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    return self._DeviceAdbCmd(['get-devpath'], timeout, retries)
357e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
358e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Remount(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
359e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Remounts the /system partition on the device read-write."""
360e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._DeviceAdbCmd(['remount'], timeout, retries)
361e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
362e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Reboot(self, to_bootloader=False, timeout=60*5,
363e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson             retries=_DEFAULT_RETRIES):
364e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Reboots the device.
365e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
366e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
367e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      to_bootloader: (optional) If set reboots to the bootloader.
368e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
369e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
370e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
371e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if to_bootloader:
372e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd = ['reboot-bootloader']
373e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    else:
374e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      cmd = ['reboot']
375e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    self._DeviceAdbCmd(cmd, timeout, retries)
376e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
377e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson  def Root(self, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES):
378e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """Restarts the adbd daemon with root permissions, if possible.
379e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
380e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    Args:
381e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      timeout: (optional) Timeout per try in seconds.
382e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      retries: (optional) Number of retries to attempt.
383e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    """
384e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    output = self._DeviceAdbCmd(['root'], timeout, retries)
385e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    if 'cannot' in output:
386e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson      raise device_errors.CommandFailedError(['root'], output)
387e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
388e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson