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