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