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