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