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