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