• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""This module wraps Android's adb tool.
6
7This is a thin wrapper around the adb interface. Any additional complexity
8should be delegated to a higher level (ex. DeviceUtils).
9"""
10
11import collections
12# pylint: disable=import-error
13# pylint: disable=no-name-in-module
14import distutils.version as du_version
15import errno
16import logging
17import os
18import posixpath
19import re
20import subprocess
21
22from devil import base_error
23from devil import devil_env
24from devil.android import decorators
25from devil.android import device_errors
26from devil.utils import cmd_helper
27from devil.utils import lazy
28from devil.utils import timeout_retry
29
30with devil_env.SysPath(devil_env.DEPENDENCY_MANAGER_PATH):
31  import dependency_manager  # pylint: disable=import-error
32
33logger = logging.getLogger(__name__)
34
35
36ADB_KEYS_FILE = '/data/misc/adb/adb_keys'
37ADB_HOST_KEYS_DIR = os.path.join(os.path.expanduser('~'), '.android')
38
39DEFAULT_TIMEOUT = 30
40DEFAULT_RETRIES = 2
41
42_ADB_VERSION_RE = re.compile(r'Android Debug Bridge version (\d+\.\d+\.\d+)')
43_EMULATOR_RE = re.compile(r'^emulator-[0-9]+$')
44_DEVICE_NOT_FOUND_RE = re.compile(r"error: device '(?P<serial>.+)' not found")
45_READY_STATE = 'device'
46_VERITY_DISABLE_RE = re.compile(r'(V|v)erity (is )?(already )?disabled'
47                                r'|Successfully disabled verity')
48_VERITY_ENABLE_RE = re.compile(r'(V|v)erity (is )?(already )?enabled'
49                               r'|Successfully enabled verity')
50_WAITING_FOR_DEVICE_RE = re.compile(r'- waiting for device -')
51
52
53def VerifyLocalFileExists(path):
54  """Verifies a local file exists.
55
56  Args:
57    path: Path to the local file.
58
59  Raises:
60    IOError: If the file doesn't exist.
61  """
62  if not os.path.exists(path):
63    raise IOError(errno.ENOENT, os.strerror(errno.ENOENT), path)
64
65
66def _CreateAdbEnvironment():
67  adb_env = dict(os.environ)
68  adb_env['ADB_LIBUSB'] = '0'
69  return adb_env
70
71
72def _FindAdb():
73  try:
74    return devil_env.config.LocalPath('adb')
75  except dependency_manager.NoPathFoundError:
76    pass
77
78  try:
79    return os.path.join(devil_env.config.LocalPath('android_sdk'),
80                        'platform-tools', 'adb')
81  except dependency_manager.NoPathFoundError:
82    pass
83
84  try:
85    return devil_env.config.FetchPath('adb')
86  except dependency_manager.NoPathFoundError:
87    raise device_errors.NoAdbError()
88
89
90def _GetVersion():
91  # pylint: disable=protected-access
92  raw_version = AdbWrapper._RunAdbCmd(['version'], timeout=2, retries=0)
93  for l in raw_version.splitlines():
94    m = _ADB_VERSION_RE.search(l)
95    if m:
96      return m.group(1)
97  return None
98
99
100def _ShouldRetryAdbCmd(exc):
101  # Errors are potentially transient and should be retried, with the exception
102  # of NoAdbError. Exceptions [e.g. generated from SIGTERM handler] should be
103  # raised.
104  return (isinstance(exc, base_error.BaseError) and
105          not isinstance(exc, device_errors.NoAdbError))
106
107
108DeviceStat = collections.namedtuple('DeviceStat',
109                                    ['st_mode', 'st_size', 'st_time'])
110
111
112def _IsExtraneousLine(line, send_cmd):
113  """Determine if a line read from stdout in persistent shell is extraneous.
114
115  The results output to stdout by the persistent shell process
116  (in PersistentShell below) often include "extraneous" lines that are
117  not part of the output of the shell command. These "extraneous" lines
118  do not always appear and are of two forms: shell prompt lines and lines
119  that just duplicate what the input command was. This function
120  detects these extraneous lines. Since all these lines have the
121  original command in them, that is what it detects ror.
122
123  Args:
124      line: Output line to check.
125      send_cmd: Command that was sent to adb persistent shell.
126  """
127  return send_cmd.rstrip() in line
128
129
130class AdbWrapper(object):
131  """A wrapper around a local Android Debug Bridge executable."""
132
133  _ADB_ENV = _CreateAdbEnvironment()
134
135  _adb_path = lazy.WeakConstant(_FindAdb)
136  _adb_version = lazy.WeakConstant(_GetVersion)
137
138  def __init__(self, device_serial):
139    """Initializes the AdbWrapper.
140
141    Args:
142      device_serial: The device serial number as a string.
143    """
144    if not device_serial:
145      raise ValueError('A device serial must be specified')
146    self._device_serial = str(device_serial)
147
148  class PersistentShell(object):
149    '''Class to use persistent shell for ADB.
150
151    This class allows a persistent ADB shell to be created, where multiple
152    commands can be passed into it. This avoids the overhead of starting
153    up a new ADB shell for each command.
154
155    Example of use:
156    with PersistentShell('123456789') as pshell:
157        pshell.RunCommand('which ls')
158        pshell.RunCommand('echo TEST', close=True)
159    '''
160    def __init__(self, serial):
161      """Initialization function:
162
163      Args:
164        serial: Serial number of device.
165      """
166      self._cmd = [AdbWrapper.GetAdbPath(), '-s', serial, 'shell']
167      self._process = None
168
169    def __enter__(self):
170      self.Start()
171      self.WaitForReady()
172      return self
173
174    def __exit__(self, exc_type, exc_value, tb):
175      self.Stop()
176
177    def Start(self):
178      """Start the shell."""
179      if self._process is not None:
180        raise RuntimeError('Persistent shell already running.')
181      # pylint: disable=protected-access
182      self._process = subprocess.Popen(self._cmd,
183                                       stdin=subprocess.PIPE,
184                                       stdout=subprocess.PIPE,
185                                       shell=False,
186                                       env=AdbWrapper._ADB_ENV)
187
188    def WaitForReady(self):
189      """Wait for the shell to be ready after starting.
190
191      Sends an echo command, then waits until it gets a response.
192      """
193      self._process.stdin.write('echo\n')
194      output_line = self._process.stdout.readline()
195      while output_line.rstrip() != '':
196        output_line = self._process.stdout.readline()
197
198    def RunCommand(self, command, close=False):
199      """Runs an ADB command and returns the output.
200
201      Note that there can be approximately 40 ms of additional latency
202      between sending the command and receiving the results if close=False
203      due to the use of Nagle's algorithm in the TCP socket between the
204      adb server and client. To avoid this extra latency, set close=True.
205
206      Args:
207        command: Command to send.
208      Returns:
209        The command output, given as a list of lines, and the exit code
210      """
211
212      if close:
213        def run_cmd(cmd):
214          send_cmd = '( %s ); echo $?; exit;\n' % cmd.rstrip()
215          (output, _) = self._process.communicate(send_cmd)
216          self._process = None
217          for x in output.rstrip().splitlines():
218            yield x
219
220      else:
221        def run_cmd(cmd):
222          send_cmd = '( %s ); echo DONE:$?;\n' % cmd.rstrip()
223          self._process.stdin.write(send_cmd)
224          while True:
225            output_line = self._process.stdout.readline().rstrip()
226            if output_line[:5] == 'DONE:':
227              yield output_line[5:]
228              break
229            yield output_line
230
231      result = [line for line in run_cmd(command)
232                if not _IsExtraneousLine(line, command)]
233
234      return (result[:-1], int(result[-1]))
235
236    def Stop(self):
237      """Stops the ADB process if it is still running."""
238      if self._process is not None:
239        self._process.stdin.write('exit\n')
240        self._process = None
241
242  @classmethod
243  def GetAdbPath(cls):
244    return cls._adb_path.read()
245
246  @classmethod
247  def Version(cls):
248    return cls._adb_version.read()
249
250  @classmethod
251  def _BuildAdbCmd(cls, args, device_serial, cpu_affinity=None):
252    if cpu_affinity is not None:
253      cmd = ['taskset', '-c', str(cpu_affinity)]
254    else:
255      cmd = []
256    cmd.append(cls.GetAdbPath())
257    if device_serial is not None:
258      cmd.extend(['-s', device_serial])
259    cmd.extend(args)
260    return cmd
261
262  # pylint: disable=unused-argument
263  @classmethod
264  @decorators.WithTimeoutAndConditionalRetries(_ShouldRetryAdbCmd)
265  def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None,
266                 check_error=True, cpu_affinity=None, additional_env=None):
267    if timeout:
268      remaining = timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime()
269      if remaining:
270        # Use a slightly smaller timeout than remaining time to ensure that we
271        # have time to collect output from the command.
272        timeout = 0.95 * remaining
273      else:
274        timeout = None
275    env = cls._ADB_ENV.copy()
276    if additional_env:
277      env.update(additional_env)
278    try:
279      status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
280          cls._BuildAdbCmd(args, device_serial, cpu_affinity=cpu_affinity),
281          timeout, env=env)
282    except OSError as e:
283      if e.errno in (errno.ENOENT, errno.ENOEXEC):
284        raise device_errors.NoAdbError(msg=str(e))
285      else:
286        raise
287
288    # Best effort to catch errors from adb; unfortunately adb is very
289    # inconsistent with error reporting so many command failures present
290    # differently.
291    if status != 0 or (check_error and output.startswith('error:')):
292      not_found_m = _DEVICE_NOT_FOUND_RE.match(output)
293      device_waiting_m = _WAITING_FOR_DEVICE_RE.match(output)
294      if (device_waiting_m is not None
295          or (not_found_m is not None and
296              not_found_m.group('serial') == device_serial)):
297        raise device_errors.DeviceUnreachableError(device_serial)
298      else:
299        raise device_errors.AdbCommandFailedError(
300            args, output, status, device_serial)
301
302    return output
303  # pylint: enable=unused-argument
304
305  def _RunDeviceAdbCmd(self, args, timeout, retries, check_error=True):
306    """Runs an adb command on the device associated with this object.
307
308    Args:
309      args: A list of arguments to adb.
310      timeout: Timeout in seconds.
311      retries: Number of retries.
312      check_error: Check that the command doesn't return an error message. This
313        does check the error status of adb but DOES NOT check the exit status
314        of shell commands.
315
316    Returns:
317      The output of the command.
318    """
319    return self._RunAdbCmd(args, timeout=timeout, retries=retries,
320                           device_serial=self._device_serial,
321                           check_error=check_error)
322
323  def _IterRunDeviceAdbCmd(self, args, iter_timeout, timeout,
324                           check_error=True):
325    """Runs an adb command and returns an iterator over its output lines.
326
327    Args:
328      args: A list of arguments to adb.
329      iter_timeout: Timeout for each iteration in seconds.
330      timeout: Timeout for the entire command in seconds.
331      check_error: Check that the command succeeded. This does check the
332        error status of the adb command but DOES NOT check the exit status
333        of shell commands.
334
335    Yields:
336      The output of the command line by line.
337    """
338    return cmd_helper.IterCmdOutputLines(
339        self._BuildAdbCmd(args, self._device_serial),
340        iter_timeout=iter_timeout,
341        timeout=timeout,
342        env=self._ADB_ENV,
343        check_status=check_error)
344
345  def __eq__(self, other):
346    """Consider instances equal if they refer to the same device.
347
348    Args:
349      other: The instance to compare equality with.
350
351    Returns:
352      True if the instances are considered equal, false otherwise.
353    """
354    return self._device_serial == str(other)
355
356  def __str__(self):
357    """The string representation of an instance.
358
359    Returns:
360      The device serial number as a string.
361    """
362    return self._device_serial
363
364  def __repr__(self):
365    return '%s(\'%s\')' % (self.__class__.__name__, self)
366
367  # pylint: disable=unused-argument
368  @classmethod
369  def IsServerOnline(cls):
370    status, output = cmd_helper.GetCmdStatusAndOutput(['pgrep', 'adb'])
371    output = [int(x) for x in output.split()]
372    logger.info('PIDs for adb found: %r', output)
373    return status == 0
374  # pylint: enable=unused-argument
375
376  @classmethod
377  def KillServer(cls, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
378    cls._RunAdbCmd(['kill-server'], timeout=timeout, retries=retries)
379
380  @classmethod
381  def StartServer(cls, keys=None, timeout=DEFAULT_TIMEOUT,
382                  retries=DEFAULT_RETRIES):
383    """Starts the ADB server.
384
385    Args:
386      keys: (optional) List of local ADB keys to use to auth with devices.
387      timeout: (optional) Timeout per try in seconds.
388      retries: (optional) Number of retries to attempt.
389    """
390    additional_env = {}
391    if keys:
392      additional_env['ADB_VENDOR_KEYS'] = ':'.join(keys)
393    # CPU affinity is used to reduce adb instability http://crbug.com/268450
394    cls._RunAdbCmd(['start-server'], timeout=timeout, retries=retries,
395                   cpu_affinity=0, additional_env=additional_env)
396
397  @classmethod
398  def GetDevices(cls, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
399    """DEPRECATED. Refer to Devices(...) below."""
400    # TODO(jbudorick): Remove this function once no more clients are using it.
401    return cls.Devices(timeout=timeout, retries=retries)
402
403  @classmethod
404  def Devices(cls, desired_state=_READY_STATE, long_list=False,
405              timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
406    """Get the list of active attached devices.
407
408    Args:
409      desired_state: If not None, limit the devices returned to only those
410        in the given state.
411      long_list: Whether to use the long listing format.
412      timeout: (optional) Timeout per try in seconds.
413      retries: (optional) Number of retries to attempt.
414
415    Yields:
416      AdbWrapper instances.
417    """
418    lines = cls._RawDevices(long_list=long_list, timeout=timeout,
419                            retries=retries)
420    if long_list:
421      return [
422        [AdbWrapper(line[0])] + line[1:]
423        for line in lines
424        if (len(line) >= 2 and (not desired_state or line[1] == desired_state))
425      ]
426    else:
427      return [
428        AdbWrapper(line[0])
429        for line in lines
430        if (len(line) == 2 and (not desired_state or line[1] == desired_state))
431      ]
432
433  @classmethod
434  def _RawDevices(cls, long_list=False, timeout=DEFAULT_TIMEOUT,
435                  retries=DEFAULT_RETRIES):
436    cmd = ['devices']
437    if long_list:
438      cmd.append('-l')
439    output = cls._RunAdbCmd(cmd, timeout=timeout, retries=retries)
440    return [line.split() for line in output.splitlines()[1:]]
441
442  def GetDeviceSerial(self):
443    """Gets the device serial number associated with this object.
444
445    Returns:
446      Device serial number as a string.
447    """
448    return self._device_serial
449
450  def Push(self, local, remote, timeout=60 * 5, retries=DEFAULT_RETRIES):
451    """Pushes a file from the host to the device.
452
453    Args:
454      local: Path on the host filesystem.
455      remote: Path on the device filesystem.
456      timeout: (optional) Timeout per try in seconds.
457      retries: (optional) Number of retries to attempt.
458    """
459    VerifyLocalFileExists(local)
460
461    if (du_version.LooseVersion(self.Version()) <
462        du_version.LooseVersion('1.0.36')):
463
464      # Different versions of adb handle pushing a directory to an existing
465      # directory differently.
466
467      # In the version packaged with the M SDK, 1.0.32, the following push:
468      #   foo/bar -> /sdcard/foo/bar
469      # where bar is an existing directory both on the host and the device
470      # results in the contents of bar/ on the host being pushed to bar/ on
471      # the device, i.e.
472      #   foo/bar/A -> /sdcard/foo/bar/A
473      #   foo/bar/B -> /sdcard/foo/bar/B
474      #   ... etc.
475
476      # In the version packaged with the N SDK, 1.0.36, the same push under
477      # the same conditions results in a second bar/ directory being created
478      # underneath the first bar/ directory on the device, i.e.
479      #   foo/bar/A -> /sdcard/foo/bar/bar/A
480      #   foo/bar/B -> /sdcard/foo/bar/bar/B
481      #   ... etc.
482
483      # In order to provide a consistent interface to clients, we check whether
484      # the target is an existing directory on the device and, if so, modifies
485      # the target passed to adb to emulate the behavior on 1.0.36 and above.
486
487      # Note that this behavior may have started before 1.0.36; that's simply
488      # the earliest version we've confirmed thus far.
489
490      try:
491        self.Shell('test -d %s' % remote, timeout=timeout, retries=retries)
492        remote = posixpath.join(remote, posixpath.basename(local))
493      except device_errors.AdbShellCommandFailedError:
494        # The target directory doesn't exist on the device, so we can use it
495        # without modification.
496        pass
497
498    self._RunDeviceAdbCmd(['push', local, remote], timeout, retries)
499
500  def Pull(self, remote, local, timeout=60 * 5, retries=DEFAULT_RETRIES):
501    """Pulls a file from the device to the host.
502
503    Args:
504      remote: Path on the device filesystem.
505      local: Path on the host filesystem.
506      timeout: (optional) Timeout per try in seconds.
507      retries: (optional) Number of retries to attempt.
508    """
509    cmd = ['pull', remote, local]
510    self._RunDeviceAdbCmd(cmd, timeout, retries)
511    try:
512      VerifyLocalFileExists(local)
513    except IOError:
514      raise device_errors.AdbCommandFailedError(
515          cmd,
516          'File pulled from the device did not arrive on the host: %s' % local,
517          device_serial=str(self))
518
519  def StartShell(self, cmd):
520    """Starts a subprocess on the device and returns a handle to the process.
521
522    Args:
523      args: A sequence of program arguments. The executable to run is the first
524        item in the sequence.
525
526    Returns:
527      An instance of subprocess.Popen associated with the live process.
528    """
529    return cmd_helper.StartCmd(
530        self._BuildAdbCmd(['shell'] + cmd, self._device_serial))
531
532  def Shell(self, command, expect_status=0, timeout=DEFAULT_TIMEOUT,
533            retries=DEFAULT_RETRIES):
534    """Runs a shell command on the device.
535
536    Args:
537      command: A string with the shell command to run.
538      expect_status: (optional) Check that the command's exit status matches
539        this value. Default is 0. If set to None the test is skipped.
540      timeout: (optional) Timeout per try in seconds.
541      retries: (optional) Number of retries to attempt.
542
543    Returns:
544      The output of the shell command as a string.
545
546    Raises:
547      device_errors.AdbCommandFailedError: If the exit status doesn't match
548        |expect_status|.
549    """
550    if expect_status is None:
551      args = ['shell', command]
552    else:
553      args = ['shell', '( %s );echo %%$?' % command.rstrip()]
554    output = self._RunDeviceAdbCmd(args, timeout, retries, check_error=False)
555    if expect_status is not None:
556      output_end = output.rfind('%')
557      if output_end < 0:
558        # causes the status string to become empty and raise a ValueError
559        output_end = len(output)
560
561      try:
562        status = int(output[output_end + 1:])
563      except ValueError:
564        logger.warning('exit status of shell command %r missing.', command)
565        raise device_errors.AdbShellCommandFailedError(
566            command, output, status=None, device_serial=self._device_serial)
567      output = output[:output_end]
568      if status != expect_status:
569        raise device_errors.AdbShellCommandFailedError(
570            command, output, status=status, device_serial=self._device_serial)
571    return output
572
573  def IterShell(self, command, timeout):
574    """Runs a shell command and returns an iterator over its output lines.
575
576    Args:
577      command: A string with the shell command to run.
578      timeout: Timeout in seconds.
579
580    Yields:
581      The output of the command line by line.
582    """
583    args = ['shell', command]
584    return cmd_helper.IterCmdOutputLines(
585      self._BuildAdbCmd(args, self._device_serial), timeout=timeout,
586      env=self._ADB_ENV)
587
588  def Ls(self, path, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
589    """List the contents of a directory on the device.
590
591    Args:
592      path: Path on the device filesystem.
593      timeout: (optional) Timeout per try in seconds.
594      retries: (optional) Number of retries to attempt.
595
596    Returns:
597      A list of pairs (filename, stat) for each file found in the directory,
598      where the stat object has the properties: st_mode, st_size, and st_time.
599
600    Raises:
601      AdbCommandFailedError if |path| does not specify a valid and accessible
602          directory in the device, or the output of "adb ls" command is less
603          than four columns
604    """
605    def ParseLine(line, cmd):
606      cols = line.split(None, 3)
607      if len(cols) < 4:
608        raise device_errors.AdbCommandFailedError(
609            cmd, line, "the output should be 4 columns, but is only %d columns"
610            % len(cols), device_serial=self._device_serial)
611      filename = cols.pop()
612      stat = DeviceStat(*[int(num, base=16) for num in cols])
613      return (filename, stat)
614
615    cmd = ['ls', path]
616    lines = self._RunDeviceAdbCmd(
617        cmd, timeout=timeout, retries=retries).splitlines()
618    if lines:
619      return [ParseLine(line, cmd) for line in lines]
620    else:
621      raise device_errors.AdbCommandFailedError(
622          cmd, 'path does not specify an accessible directory in the device',
623          device_serial=self._device_serial)
624
625  def Logcat(self, clear=False, dump=False, filter_specs=None,
626             logcat_format=None, ring_buffer=None, iter_timeout=None,
627             check_error=True, timeout=None, retries=DEFAULT_RETRIES):
628    """Get an iterable over the logcat output.
629
630    Args:
631      clear: If true, clear the logcat.
632      dump: If true, dump the current logcat contents.
633      filter_specs: If set, a list of specs to filter the logcat.
634      logcat_format: If set, the format in which the logcat should be output.
635        Options include "brief", "process", "tag", "thread", "raw", "time",
636        "threadtime", and "long"
637      ring_buffer: If set, a list of alternate ring buffers to request.
638        Options include "main", "system", "radio", "events", "crash" or "all".
639        The default is equivalent to ["main", "system", "crash"].
640      iter_timeout: If set and neither clear nor dump is set, the number of
641        seconds to wait between iterations. If no line is found before the
642        given number of seconds elapses, the iterable will yield None.
643      check_error: Whether to check the exit status of the logcat command.
644      timeout: (optional) If set, timeout per try in seconds. If clear or dump
645        is set, defaults to DEFAULT_TIMEOUT.
646      retries: (optional) If clear or dump is set, the number of retries to
647        attempt. Otherwise, does nothing.
648
649    Yields:
650      logcat output line by line.
651    """
652    cmd = ['logcat']
653    use_iter = True
654    if clear:
655      cmd.append('-c')
656      use_iter = False
657    if dump:
658      cmd.append('-d')
659      use_iter = False
660    if logcat_format:
661      cmd.extend(['-v', logcat_format])
662    if ring_buffer:
663      for buffer_name in ring_buffer:
664        cmd.extend(['-b', buffer_name])
665    if filter_specs:
666      cmd.extend(filter_specs)
667
668    if use_iter:
669      return self._IterRunDeviceAdbCmd(
670          cmd, iter_timeout, timeout, check_error=check_error)
671    else:
672      timeout = timeout if timeout is not None else DEFAULT_TIMEOUT
673      output = self._RunDeviceAdbCmd(
674          cmd, timeout, retries, check_error=check_error)
675      return output.splitlines()
676
677  def Forward(self, local, remote, allow_rebind=False,
678              timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
679    """Forward socket connections from the local socket to the remote socket.
680
681    Sockets are specified by one of:
682      tcp:<port>
683      localabstract:<unix domain socket name>
684      localreserved:<unix domain socket name>
685      localfilesystem:<unix domain socket name>
686      dev:<character device name>
687      jdwp:<process pid> (remote only)
688
689    Args:
690      local: The host socket.
691      remote: The device socket.
692      allow_rebind: A boolean indicating whether adb may rebind a local socket;
693        otherwise, the default, an exception is raised if the local socket is
694        already being forwarded.
695      timeout: (optional) Timeout per try in seconds.
696      retries: (optional) Number of retries to attempt.
697    """
698    cmd = ['forward']
699    if not allow_rebind:
700      cmd.append('--no-rebind')
701    cmd.extend([str(local), str(remote)])
702    output = self._RunDeviceAdbCmd(cmd, timeout, retries).strip()
703    if output:
704      logger.warning('Unexpected output from "adb forward": %s', output)
705
706  def ForwardRemove(self, local, timeout=DEFAULT_TIMEOUT,
707                    retries=DEFAULT_RETRIES):
708    """Remove a forward socket connection.
709
710    Args:
711      local: The host socket.
712      timeout: (optional) Timeout per try in seconds.
713      retries: (optional) Number of retries to attempt.
714    """
715    self._RunDeviceAdbCmd(['forward', '--remove', str(local)], timeout,
716                          retries)
717
718  def ForwardList(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
719    """List all currently forwarded socket connections.
720
721    Args:
722      timeout: (optional) Timeout per try in seconds.
723      retries: (optional) Number of retries to attempt.
724    Returns:
725      The output of adb forward --list as a string.
726    """
727    if (du_version.LooseVersion(self.Version()) >=
728        du_version.LooseVersion('1.0.36')):
729      # Starting in 1.0.36, this can occasionally fail with a protocol fault.
730      # As this interrupts all connections with all devices, we instead just
731      # return an empty list. This may give clients an inaccurate result, but
732      # that's usually better than crashing the adb server.
733
734      # TODO(jbudorick): Determine an appropriate upper version bound for this
735      # once b/31811775 is fixed.
736      return ''
737
738    return self._RunDeviceAdbCmd(['forward', '--list'], timeout, retries)
739
740  def JDWP(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
741    """List of PIDs of processes hosting a JDWP transport.
742
743    Args:
744      timeout: (optional) Timeout per try in seconds.
745      retries: (optional) Number of retries to attempt.
746
747    Returns:
748      A list of PIDs as strings.
749    """
750    return [a.strip() for a in
751            self._RunDeviceAdbCmd(['jdwp'], timeout, retries).split('\n')]
752
753  def Install(self, apk_path, forward_lock=False, allow_downgrade=False,
754              reinstall=False, sd_card=False, timeout=60 * 2,
755              retries=DEFAULT_RETRIES):
756    """Install an apk on the device.
757
758    Args:
759      apk_path: Host path to the APK file.
760      forward_lock: (optional) If set forward-locks the app.
761      allow_downgrade: (optional) If set, allows for downgrades.
762      reinstall: (optional) If set reinstalls the app, keeping its data.
763      sd_card: (optional) If set installs on the SD card.
764      timeout: (optional) Timeout per try in seconds.
765      retries: (optional) Number of retries to attempt.
766    """
767    VerifyLocalFileExists(apk_path)
768    cmd = ['install']
769    if forward_lock:
770      cmd.append('-l')
771    if reinstall:
772      cmd.append('-r')
773    if sd_card:
774      cmd.append('-s')
775    if allow_downgrade:
776      cmd.append('-d')
777    cmd.append(apk_path)
778    output = self._RunDeviceAdbCmd(cmd, timeout, retries)
779    if 'Success' not in output:
780      raise device_errors.AdbCommandFailedError(
781          cmd, output, device_serial=self._device_serial)
782
783  def InstallMultiple(self, apk_paths, forward_lock=False, reinstall=False,
784                      sd_card=False, allow_downgrade=False, partial=False,
785                      timeout=60 * 2, retries=DEFAULT_RETRIES):
786    """Install an apk with splits on the device.
787
788    Args:
789      apk_paths: Host path to the APK file.
790      forward_lock: (optional) If set forward-locks the app.
791      reinstall: (optional) If set reinstalls the app, keeping its data.
792      sd_card: (optional) If set installs on the SD card.
793      allow_downgrade: (optional) Allow versionCode downgrade.
794      partial: (optional) Package ID if apk_paths doesn't include all .apks.
795      timeout: (optional) Timeout per try in seconds.
796      retries: (optional) Number of retries to attempt.
797    """
798    for path in apk_paths:
799      VerifyLocalFileExists(path)
800    cmd = ['install-multiple']
801    if forward_lock:
802      cmd.append('-l')
803    if reinstall:
804      cmd.append('-r')
805    if sd_card:
806      cmd.append('-s')
807    if allow_downgrade:
808      cmd.append('-d')
809    if partial:
810      cmd.extend(('-p', partial))
811    cmd.extend(apk_paths)
812    output = self._RunDeviceAdbCmd(cmd, timeout, retries)
813    if 'Success' not in output:
814      raise device_errors.AdbCommandFailedError(
815          cmd, output, device_serial=self._device_serial)
816
817  def Uninstall(self, package, keep_data=False, timeout=DEFAULT_TIMEOUT,
818                retries=DEFAULT_RETRIES):
819    """Remove the app |package| from the device.
820
821    Args:
822      package: The package to uninstall.
823      keep_data: (optional) If set keep the data and cache directories.
824      timeout: (optional) Timeout per try in seconds.
825      retries: (optional) Number of retries to attempt.
826    """
827    cmd = ['uninstall']
828    if keep_data:
829      cmd.append('-k')
830    cmd.append(package)
831    output = self._RunDeviceAdbCmd(cmd, timeout, retries)
832    if 'Failure' in output or 'Exception' in output:
833      raise device_errors.AdbCommandFailedError(
834          cmd, output, device_serial=self._device_serial)
835
836  def Backup(self, path, packages=None, apk=False, shared=False,
837             nosystem=True, include_all=False, timeout=DEFAULT_TIMEOUT,
838             retries=DEFAULT_RETRIES):
839    """Write an archive of the device's data to |path|.
840
841    Args:
842      path: Local path to store the backup file.
843      packages: List of to packages to be backed up.
844      apk: (optional) If set include the .apk files in the archive.
845      shared: (optional) If set buckup the device's SD card.
846      nosystem: (optional) If set exclude system applications.
847      include_all: (optional) If set back up all installed applications and
848        |packages| is optional.
849      timeout: (optional) Timeout per try in seconds.
850      retries: (optional) Number of retries to attempt.
851    """
852    cmd = ['backup', '-f', path]
853    if apk:
854      cmd.append('-apk')
855    if shared:
856      cmd.append('-shared')
857    if nosystem:
858      cmd.append('-nosystem')
859    if include_all:
860      cmd.append('-all')
861    if packages:
862      cmd.extend(packages)
863    assert bool(packages) ^ bool(include_all), (
864        'Provide \'packages\' or set \'include_all\' but not both.')
865    ret = self._RunDeviceAdbCmd(cmd, timeout, retries)
866    VerifyLocalFileExists(path)
867    return ret
868
869  def Restore(self, path, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
870    """Restore device contents from the backup archive.
871
872    Args:
873      path: Host path to the backup archive.
874      timeout: (optional) Timeout per try in seconds.
875      retries: (optional) Number of retries to attempt.
876    """
877    VerifyLocalFileExists(path)
878    self._RunDeviceAdbCmd(['restore'] + [path], timeout, retries)
879
880  def WaitForDevice(self, timeout=60 * 5, retries=DEFAULT_RETRIES):
881    """Block until the device is online.
882
883    Args:
884      timeout: (optional) Timeout per try in seconds.
885      retries: (optional) Number of retries to attempt.
886    """
887    self._RunDeviceAdbCmd(['wait-for-device'], timeout, retries)
888
889  def GetState(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
890    """Get device state.
891
892    Args:
893      timeout: (optional) Timeout per try in seconds.
894      retries: (optional) Number of retries to attempt.
895
896    Returns:
897      One of 'offline', 'bootloader', or 'device'.
898    """
899    # TODO(jbudorick): Revert to using get-state once it doesn't cause a
900    # a protocol fault.
901    # return self._RunDeviceAdbCmd(['get-state'], timeout, retries).strip()
902
903    lines = self._RawDevices(timeout=timeout, retries=retries)
904    for line in lines:
905      if len(line) >= 2 and line[0] == self._device_serial:
906        return line[1]
907    return 'offline'
908
909  def GetDevPath(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
910    """Gets the device path.
911
912    Args:
913      timeout: (optional) Timeout per try in seconds.
914      retries: (optional) Number of retries to attempt.
915
916    Returns:
917      The device path (e.g. usb:3-4)
918    """
919    return self._RunDeviceAdbCmd(['get-devpath'], timeout, retries)
920
921  def Remount(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
922    """Remounts the /system partition on the device read-write."""
923    self._RunDeviceAdbCmd(['remount'], timeout, retries)
924
925  def Reboot(self, to_bootloader=False, timeout=60 * 5,
926             retries=DEFAULT_RETRIES):
927    """Reboots the device.
928
929    Args:
930      to_bootloader: (optional) If set reboots to the bootloader.
931      timeout: (optional) Timeout per try in seconds.
932      retries: (optional) Number of retries to attempt.
933    """
934    if to_bootloader:
935      cmd = ['reboot-bootloader']
936    else:
937      cmd = ['reboot']
938    self._RunDeviceAdbCmd(cmd, timeout, retries)
939
940  def Root(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
941    """Restarts the adbd daemon with root permissions, if possible.
942
943    Args:
944      timeout: (optional) Timeout per try in seconds.
945      retries: (optional) Number of retries to attempt.
946    """
947    output = self._RunDeviceAdbCmd(['root'], timeout, retries)
948    if 'cannot' in output:
949      raise device_errors.AdbCommandFailedError(
950          ['root'], output, device_serial=self._device_serial)
951
952  def Emu(self, cmd, timeout=DEFAULT_TIMEOUT,
953               retries=DEFAULT_RETRIES):
954    """Runs an emulator console command.
955
956    See http://developer.android.com/tools/devices/emulator.html#console
957
958    Args:
959      cmd: The command to run on the emulator console.
960      timeout: (optional) Timeout per try in seconds.
961      retries: (optional) Number of retries to attempt.
962
963    Returns:
964      The output of the emulator console command.
965    """
966    if isinstance(cmd, basestring):
967      cmd = [cmd]
968    return self._RunDeviceAdbCmd(['emu'] + cmd, timeout, retries)
969
970  def DisableVerity(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
971    """Disable Marshmallow's Verity security feature.
972
973    Returns:
974      The output of the disable-verity command as a string.
975    """
976    output = self._RunDeviceAdbCmd(['disable-verity'], timeout, retries)
977    if output and not _VERITY_DISABLE_RE.search(output):
978      raise device_errors.AdbCommandFailedError(
979          ['disable-verity'], output, device_serial=self._device_serial)
980    return output
981
982  def EnableVerity(self, timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES):
983    """Enable Marshmallow's Verity security feature.
984
985    Returns:
986      The output of the enable-verity command as a string.
987    """
988    output = self._RunDeviceAdbCmd(['enable-verity'], timeout, retries)
989    if output and not _VERITY_ENABLE_RE.search(output):
990      raise device_errors.AdbCommandFailedError(
991          ['enable-verity'], output, device_serial=self._device_serial)
992    return output
993
994  @property
995  def is_emulator(self):
996    return _EMULATOR_RE.match(self._device_serial)
997
998  @property
999  def is_ready(self):
1000    try:
1001      return self.GetState() == _READY_STATE
1002    except device_errors.CommandFailedError:
1003      return False
1004