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