| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Provides a variety of device interactions based on adb. | 5 """Provides a variety of device interactions based on adb. |
| 6 | 6 |
| 7 Eventually, this will be based on adb_wrapper. | 7 Eventually, this will be based on adb_wrapper. |
| 8 """ | 8 """ |
| 9 # pylint: disable=W0613 | 9 # pylint: disable=W0613 |
| 10 | 10 |
| 11 import logging | 11 import logging |
| 12 import multiprocessing | 12 import multiprocessing |
| 13 import os | 13 import os |
| 14 import pipes | 14 import re |
| 15 import sys | 15 import sys |
| 16 import tempfile | 16 import tempfile |
| 17 import time | 17 import time |
| 18 import zipfile | 18 import zipfile |
| 19 | 19 |
| 20 import pylib.android_commands | 20 import pylib.android_commands |
| 21 from pylib import cmd_helper |
| 21 from pylib.device import adb_wrapper | 22 from pylib.device import adb_wrapper |
| 22 from pylib.device import decorators | 23 from pylib.device import decorators |
| 23 from pylib.device import device_errors | 24 from pylib.device import device_errors |
| 24 from pylib.device.commands import install_commands | 25 from pylib.device.commands import install_commands |
| 25 from pylib.utils import apk_helper | 26 from pylib.utils import apk_helper |
| 26 from pylib.utils import host_utils | 27 from pylib.utils import host_utils |
| 27 from pylib.utils import parallelizer | 28 from pylib.utils import parallelizer |
| 28 | 29 |
| 29 _DEFAULT_TIMEOUT = 30 | 30 _DEFAULT_TIMEOUT = 30 |
| 30 _DEFAULT_RETRIES = 3 | 31 _DEFAULT_RETRIES = 3 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 47 """Restarts the adb server. | 48 """Restarts the adb server. |
| 48 | 49 |
| 49 Raises: | 50 Raises: |
| 50 CommandFailedError if we fail to kill or restart the server. | 51 CommandFailedError if we fail to kill or restart the server. |
| 51 """ | 52 """ |
| 52 pylib.android_commands.AndroidCommands().RestartAdbServer() | 53 pylib.android_commands.AndroidCommands().RestartAdbServer() |
| 53 | 54 |
| 54 | 55 |
| 55 class DeviceUtils(object): | 56 class DeviceUtils(object): |
| 56 | 57 |
| 58 _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$') |
| 59 |
| 57 def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT, | 60 def __init__(self, device, default_timeout=_DEFAULT_TIMEOUT, |
| 58 default_retries=_DEFAULT_RETRIES): | 61 default_retries=_DEFAULT_RETRIES): |
| 59 """DeviceUtils constructor. | 62 """DeviceUtils constructor. |
| 60 | 63 |
| 61 Args: | 64 Args: |
| 62 device: Either a device serial, an existing AdbWrapper instance, an | 65 device: Either a device serial, an existing AdbWrapper instance, an |
| 63 an existing AndroidCommands instance, or nothing. | 66 an existing AndroidCommands instance, or nothing. |
| 64 default_timeout: An integer containing the default number of seconds to | 67 default_timeout: An integer containing the default number of seconds to |
| 65 wait for an operation to complete if no explicit value | 68 wait for an operation to complete if no explicit value |
| 66 is provided. | 69 is provided. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 80 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) | 83 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) |
| 81 self.old_interface = device | 84 self.old_interface = device |
| 82 elif not device: | 85 elif not device: |
| 83 self.adb = adb_wrapper.AdbWrapper('') | 86 self.adb = adb_wrapper.AdbWrapper('') |
| 84 self.old_interface = pylib.android_commands.AndroidCommands() | 87 self.old_interface = pylib.android_commands.AndroidCommands() |
| 85 else: | 88 else: |
| 86 raise ValueError('Unsupported type passed for argument "device"') | 89 raise ValueError('Unsupported type passed for argument "device"') |
| 87 self._commands_installed = None | 90 self._commands_installed = None |
| 88 self._default_timeout = default_timeout | 91 self._default_timeout = default_timeout |
| 89 self._default_retries = default_retries | 92 self._default_retries = default_retries |
| 93 self._cache = {} |
| 90 assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)) | 94 assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)) |
| 91 assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR)) | 95 assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR)) |
| 92 | 96 |
| 93 @decorators.WithTimeoutAndRetriesFromInstance() | 97 @decorators.WithTimeoutAndRetriesFromInstance() |
| 94 def IsOnline(self, timeout=None, retries=None): | 98 def IsOnline(self, timeout=None, retries=None): |
| 95 """Checks whether the device is online. | 99 """Checks whether the device is online. |
| 96 | 100 |
| 97 Args: | 101 Args: |
| 98 timeout: timeout in seconds | 102 timeout: timeout in seconds |
| 99 retries: number of retries | 103 retries: number of retries |
| (...skipping 20 matching lines...) Expand all Loading... |
| 120 Returns: | 124 Returns: |
| 121 True if adbd has root privileges, False otherwise. | 125 True if adbd has root privileges, False otherwise. |
| 122 | 126 |
| 123 Raises: | 127 Raises: |
| 124 CommandTimeoutError on timeout. | 128 CommandTimeoutError on timeout. |
| 125 DeviceUnreachableError on missing device. | 129 DeviceUnreachableError on missing device. |
| 126 """ | 130 """ |
| 127 return self._HasRootImpl() | 131 return self._HasRootImpl() |
| 128 | 132 |
| 129 def _HasRootImpl(self): | 133 def _HasRootImpl(self): |
| 130 return self.old_interface.IsRootEnabled() | 134 try: |
| 135 self._RunShellCommandImpl('ls /root', check_return=True) |
| 136 return True |
| 137 except device_errors.AdbShellCommandFailedError: |
| 138 return False |
| 131 | 139 |
| 132 @decorators.WithTimeoutAndRetriesFromInstance() | 140 @decorators.WithTimeoutAndRetriesFromInstance() |
| 133 def EnableRoot(self, timeout=None, retries=None): | 141 def EnableRoot(self, timeout=None, retries=None): |
| 134 """Restarts adbd with root privileges. | 142 """Restarts adbd with root privileges. |
| 135 | 143 |
| 136 Args: | 144 Args: |
| 137 timeout: timeout in seconds | 145 timeout: timeout in seconds |
| 138 retries: number of retries | 146 retries: number of retries |
| 139 | 147 |
| 140 Raises: | 148 Raises: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 The device's path to its SD card. | 183 The device's path to its SD card. |
| 176 | 184 |
| 177 Raises: | 185 Raises: |
| 178 CommandFailedError if the external storage path could not be determined. | 186 CommandFailedError if the external storage path could not be determined. |
| 179 CommandTimeoutError on timeout. | 187 CommandTimeoutError on timeout. |
| 180 DeviceUnreachableError on missing device. | 188 DeviceUnreachableError on missing device. |
| 181 """ | 189 """ |
| 182 return self._GetExternalStoragePathImpl() | 190 return self._GetExternalStoragePathImpl() |
| 183 | 191 |
| 184 def _GetExternalStoragePathImpl(self): | 192 def _GetExternalStoragePathImpl(self): |
| 185 try: | 193 if 'external_storage' in self._cache: |
| 186 return self.old_interface.GetExternalStorage() | 194 return self._cache['external_storage'] |
| 187 except AssertionError as e: | 195 |
| 188 raise device_errors.CommandFailedError( | 196 value = self._RunShellCommandImpl('echo $EXTERNAL_STORAGE', |
| 189 str(e), device=str(self)), None, sys.exc_info()[2] | 197 single_line=True, |
| 198 check_return=True) |
| 199 if not value: |
| 200 raise device_errors.CommandFailedError('$EXTERNAL_STORAGE is not set', |
| 201 str(self)) |
| 202 self._cache['external_storage'] = value |
| 203 return value |
| 190 | 204 |
| 191 @decorators.WithTimeoutAndRetriesFromInstance() | 205 @decorators.WithTimeoutAndRetriesFromInstance() |
| 192 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): | 206 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): |
| 193 """Wait for the device to fully boot. | 207 """Wait for the device to fully boot. |
| 194 | 208 |
| 195 This means waiting for the device to boot, the package manager to be | 209 This means waiting for the device to boot, the package manager to be |
| 196 available, and the SD card to be ready. It can optionally mean waiting | 210 available, and the SD card to be ready. It can optionally mean waiting |
| 197 for wifi to come up, too. | 211 for wifi to come up, too. |
| 198 | 212 |
| 199 Args: | 213 Args: |
| 200 wifi: A boolean indicating if we should wait for wifi to come up or not. | 214 wifi: A boolean indicating if we should wait for wifi to come up or not. |
| 201 timeout: timeout in seconds | 215 timeout: timeout in seconds |
| 202 retries: number of retries | 216 retries: number of retries |
| 203 | 217 |
| 204 Raises: | 218 Raises: |
| 205 CommandFailedError on failure. | 219 CommandFailedError on failure. |
| 206 CommandTimeoutError if one of the component waits times out. | 220 CommandTimeoutError if one of the component waits times out. |
| 207 DeviceUnreachableError if the device becomes unresponsive. | 221 DeviceUnreachableError if the device becomes unresponsive. |
| 208 """ | 222 """ |
| 209 self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) | 223 self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) |
| 210 | 224 |
| 211 def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): | 225 def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): |
| 212 if timeout is None: | 226 if timeout is None: |
| 213 timeout = self._default_timeout | 227 timeout = self._default_timeout |
| 214 self.old_interface.WaitForSystemBootCompleted(timeout) | 228 self.old_interface.WaitForSystemBootCompleted(timeout) |
| 215 self.old_interface.WaitForDevicePm() | 229 self.old_interface.WaitForDevicePm() |
| 216 self.old_interface.WaitForSdCardReady(timeout) | 230 self.old_interface.WaitForSdCardReady(timeout) |
| 217 if wifi: | 231 if wifi: |
| 218 while not 'Wi-Fi is enabled' in ( | 232 while not 'Wi-Fi is enabled' in ( |
| 219 self._RunShellCommandImpl('dumpsys wifi')): | 233 self.old_interface.RunShellCommand('dumpsys wifi')): |
| 220 time.sleep(1) | 234 time.sleep(1) |
| 221 | 235 |
| 222 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT | 236 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT |
| 223 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES | 237 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES |
| 224 | 238 |
| 225 @decorators.WithTimeoutAndRetriesDefaults( | 239 @decorators.WithTimeoutAndRetriesDefaults( |
| 226 REBOOT_DEFAULT_TIMEOUT, | 240 REBOOT_DEFAULT_TIMEOUT, |
| 227 REBOOT_DEFAULT_RETRIES) | 241 REBOOT_DEFAULT_RETRIES) |
| 228 def Reboot(self, block=True, timeout=None, retries=None): | 242 def Reboot(self, block=True, timeout=None, retries=None): |
| 229 """Reboot the device. | 243 """Reboot the device. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 out = self.old_interface.Install(apk_path, reinstall=reinstall) | 299 out = self.old_interface.Install(apk_path, reinstall=reinstall) |
| 286 for line in out.splitlines(): | 300 for line in out.splitlines(): |
| 287 if 'Failure' in line: | 301 if 'Failure' in line: |
| 288 raise device_errors.CommandFailedError( | 302 raise device_errors.CommandFailedError( |
| 289 line.strip(), device=str(self)) | 303 line.strip(), device=str(self)) |
| 290 except AssertionError as e: | 304 except AssertionError as e: |
| 291 raise device_errors.CommandFailedError( | 305 raise device_errors.CommandFailedError( |
| 292 str(e), device=str(self)), None, sys.exc_info()[2] | 306 str(e), device=str(self)), None, sys.exc_info()[2] |
| 293 | 307 |
| 294 @decorators.WithTimeoutAndRetriesFromInstance() | 308 @decorators.WithTimeoutAndRetriesFromInstance() |
| 295 def RunShellCommand(self, cmd, check_return=False, as_root=False, cwd=None, | 309 def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None, |
| 296 env=None, timeout=None, retries=None): | 310 as_root=False, single_line=False, |
| 311 timeout=None, retries=None): |
| 297 """Run an ADB shell command. | 312 """Run an ADB shell command. |
| 298 | 313 |
| 299 TODO(jbudorick) Switch the default value of check_return to True after | 314 The command to run |cmd| should be a sequence of program arguments or else |
| 300 AndroidCommands is gone. | 315 a single string. |
| 316 |
| 317 When |cmd| is a sequence, it is assumed to contain the name of the command |
| 318 to run followed by its arguments. In this case, arguments are passed to the |
| 319 command exactly as given, without any further processing by the shell. This |
| 320 allows to easily pass arguments containing spaces or special characters |
| 321 without having to worry about getting quoting right. Whenever possible, it |
| 322 is recomended to pass |cmd| as a sequence. |
| 323 |
| 324 When |cmd| is given as a string, it will be interpreted and run by the |
| 325 shell on the device. |
| 326 |
| 327 This behaviour is consistent with that of command runners in cmd_helper as |
| 328 well as Python's own subprocess.Popen. |
| 329 |
| 330 TODO(perezju) Change the default of |check_return| to True when callers |
| 331 have switched to the new behaviour. |
| 301 | 332 |
| 302 Args: | 333 Args: |
| 303 cmd: A list containing the command to run on the device and any arguments. | 334 cmd: A string with the full command to run on the device, or a sequence |
| 335 containing the command and its arguments. |
| 304 check_return: A boolean indicating whether or not the return code should | 336 check_return: A boolean indicating whether or not the return code should |
| 305 be checked. | 337 be checked. |
| 306 as_root: A boolean indicating whether the shell command should be run | |
| 307 with root privileges. | |
| 308 cwd: The device directory in which the command should be run. | 338 cwd: The device directory in which the command should be run. |
| 309 env: The environment variables with which the command should be run. | 339 env: The environment variables with which the command should be run. |
| 340 as_root: A boolean indicating whether the shell command should be run |
| 341 with root privileges. |
| 342 single_line: A boolean indicating if a single line of output is expected, |
| 343 and the caller wants to retrieve the value of that line. The default |
| 344 behaviour is to return a list of output lines. |
| 310 timeout: timeout in seconds | 345 timeout: timeout in seconds |
| 311 retries: number of retries | 346 retries: number of retries |
| 312 | 347 |
| 313 Returns: | 348 Returns: |
| 314 The output of the command. | 349 The output of the command either as list of lines or, when single_line is |
| 350 True, the value contained in the single expected line of output. |
| 315 | 351 |
| 316 Raises: | 352 Raises: |
| 317 CommandFailedError if check_return is True and the return code is nozero. | 353 AdbShellCommandFailedError if check_return is True and the exit code of |
| 354 the command run on the device is non-zero. |
| 355 CommandFailedError if single_line is True but the output consists of |
| 356 either zero or more than one lines. |
| 318 CommandTimeoutError on timeout. | 357 CommandTimeoutError on timeout. |
| 319 DeviceUnreachableError on missing device. | 358 DeviceUnreachableError on missing device. |
| 320 """ | 359 """ |
| 321 return self._RunShellCommandImpl( | 360 return self._RunShellCommandImpl(cmd, check_return=check_return, cwd=cwd, |
| 322 cmd, check_return=check_return, as_root=as_root, cwd=cwd, env=env, | 361 env=env, as_root=as_root, single_line=single_line) |
| 323 timeout=timeout) | |
| 324 | 362 |
| 325 def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False, | 363 def _RunShellCommandImpl(self, cmd, check_return=False, cwd=None, env=None, |
| 326 cwd=None, env=None, timeout=None): | 364 as_root=False, single_line=False): |
| 327 # TODO(jbudorick): Remove the timeout parameter once this is no longer | 365 def env_quote(key, value): |
| 328 # backed by AndroidCommands. | 366 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key): |
| 329 if isinstance(cmd, list): | 367 raise KeyError('Invalid shell variable name %r' % key) |
| 330 cmd = ' '.join(cmd) | 368 # using double quotes here to allow interpolation of shell variables |
| 369 return '%s=%s' % (key, cmd_helper.DoubleQuote(value)) |
| 370 |
| 371 if not isinstance(cmd, basestring): |
| 372 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd) |
| 331 if as_root and not self._HasRootImpl(): | 373 if as_root and not self._HasRootImpl(): |
| 332 cmd = 'su -c %s' % cmd | 374 cmd = 'su -c %s' % cmd |
| 333 if env: | 375 if env: |
| 334 cmd = '%s %s' % ( | 376 env = ' '.join(env_quote(k, v) for k, v in env.iteritems()) |
| 335 ' '.join('%s=%s' % (k, v) for k, v in env.iteritems()), cmd) | 377 cmd = '%s %s' % (env, cmd) |
| 336 if cwd: | 378 if cwd: |
| 337 cmd = 'cd %s && %s' % (cwd, cmd) | 379 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd) |
| 338 if check_return: | 380 |
| 339 code, output = self.old_interface.GetShellCommandStatusAndOutput( | 381 try: |
| 340 cmd, timeout_time=timeout) | 382 # TODO(perezju) still need to make sure that we call a version of |
| 341 if int(code) != 0: | 383 # adb.Shell without a timeout-and-retries wrapper. |
| 342 raise device_errors.AdbCommandFailedError( | 384 output = self.adb.Shell(cmd, expect_rc=0) |
| 343 cmd.split(), 'Nonzero exit code (%d)' % code, device=str(self)) | 385 except device_errors.AdbShellCommandFailedError as e: |
| 386 if check_return: |
| 387 raise |
| 388 else: |
| 389 output = e.output |
| 390 |
| 391 output = output.splitlines() |
| 392 if single_line: |
| 393 if len(output) != 1: |
| 394 msg = 'exactly one line of output expected, but got: %s' |
| 395 raise device_errors.CommandFailedError(msg % output) |
| 396 return output[0] |
| 344 else: | 397 else: |
| 345 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout) | 398 return output |
| 346 return output | |
| 347 | 399 |
| 348 @decorators.WithTimeoutAndRetriesFromInstance() | 400 @decorators.WithTimeoutAndRetriesFromInstance() |
| 349 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, | 401 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, |
| 350 timeout=None, retries=None): | 402 timeout=None, retries=None): |
| 351 """Kill all processes with the given name on the device. | 403 """Kill all processes with the given name on the device. |
| 352 | 404 |
| 353 Args: | 405 Args: |
| 354 process_name: A string containing the name of the process to kill. | 406 process_name: A string containing the name of the process to kill. |
| 355 signum: An integer containing the signal number to send to kill. Defaults | 407 signum: An integer containing the signal number to send to kill. Defaults |
| 356 to 9 (SIGKILL). | 408 to 9 (SIGKILL). |
| 357 as_root: A boolean indicating whether the kill should be executed with | 409 as_root: A boolean indicating whether the kill should be executed with |
| 358 root privileges. | 410 root privileges. |
| 359 blocking: A boolean indicating whether we should wait until all processes | 411 blocking: A boolean indicating whether we should wait until all processes |
| 360 with the given |process_name| are dead. | 412 with the given |process_name| are dead. |
| 361 timeout: timeout in seconds | 413 timeout: timeout in seconds |
| 362 retries: number of retries | 414 retries: number of retries |
| 363 | 415 |
| 364 Raises: | 416 Raises: |
| 365 CommandFailedError if no process was killed. | 417 CommandFailedError if no process was killed. |
| 366 CommandTimeoutError on timeout. | 418 CommandTimeoutError on timeout. |
| 367 DeviceUnreachableError on missing device. | 419 DeviceUnreachableError on missing device. |
| 368 """ | 420 """ |
| 369 pids = self._GetPidsImpl(process_name) | 421 pids = self._GetPidsImpl(process_name) |
| 370 if not pids: | 422 if not pids: |
| 371 raise device_errors.CommandFailedError( | 423 raise device_errors.CommandFailedError( |
| 372 'No process "%s"' % process_name, device=str(self)) | 424 'No process "%s"' % process_name, device=str(self)) |
| 373 | 425 |
| 374 cmd = 'kill -%d %s' % (signum, ' '.join(pids.values())) | 426 cmd = ['kill', '-%d' % signum] + pids.values() |
| 375 self._RunShellCommandImpl(cmd, as_root=as_root) | 427 self._RunShellCommandImpl(cmd, as_root=as_root, check_return=True) |
| 376 | 428 |
| 377 if blocking: | 429 if blocking: |
| 378 wait_period = 0.1 | 430 wait_period = 0.1 |
| 379 while self._GetPidsImpl(process_name): | 431 while self._GetPidsImpl(process_name): |
| 380 time.sleep(wait_period) | 432 time.sleep(wait_period) |
| 381 | 433 |
| 382 return len(pids) | 434 return len(pids) |
| 383 | 435 |
| 384 @decorators.WithTimeoutAndRetriesFromInstance() | 436 @decorators.WithTimeoutAndRetriesFromInstance() |
| 385 def StartActivity(self, intent, blocking=False, trace_file_name=None, | 437 def StartActivity(self, intent, blocking=False, trace_file_name=None, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 | 568 |
| 517 Raises: | 569 Raises: |
| 518 CommandFailedError on failure. | 570 CommandFailedError on failure. |
| 519 CommandTimeoutError on timeout. | 571 CommandTimeoutError on timeout. |
| 520 DeviceUnreachableError on missing device. | 572 DeviceUnreachableError on missing device. |
| 521 """ | 573 """ |
| 522 | 574 |
| 523 files = [] | 575 files = [] |
| 524 for h, d in host_device_tuples: | 576 for h, d in host_device_tuples: |
| 525 if os.path.isdir(h): | 577 if os.path.isdir(h): |
| 526 self._RunShellCommandImpl(['mkdir', '-p', '"%s"' % d], | 578 self._RunShellCommandImpl(['mkdir', '-p', d], check_return=True) |
| 527 check_return=True) | |
| 528 files += self._GetChangedFilesImpl(h, d) | 579 files += self._GetChangedFilesImpl(h, d) |
| 529 | 580 |
| 530 if not files: | 581 if not files: |
| 531 return | 582 return |
| 532 | 583 |
| 533 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) | 584 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) |
| 534 file_count = len(files) | 585 file_count = len(files) |
| 535 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) | 586 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) |
| 536 for h, _ in host_device_tuples) | 587 for h, _ in host_device_tuples) |
| 537 dir_file_count = 0 | 588 dir_file_count = 0 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 551 | 602 |
| 552 if dir_push_duration < push_duration and ( | 603 if dir_push_duration < push_duration and ( |
| 553 dir_push_duration < zip_duration or not self._commands_installed): | 604 dir_push_duration < zip_duration or not self._commands_installed): |
| 554 self._PushChangedFilesIndividually(host_device_tuples) | 605 self._PushChangedFilesIndividually(host_device_tuples) |
| 555 elif push_duration < zip_duration or not self._commands_installed: | 606 elif push_duration < zip_duration or not self._commands_installed: |
| 556 self._PushChangedFilesIndividually(files) | 607 self._PushChangedFilesIndividually(files) |
| 557 else: | 608 else: |
| 558 self._PushChangedFilesZipped(files) | 609 self._PushChangedFilesZipped(files) |
| 559 self._RunShellCommandImpl( | 610 self._RunShellCommandImpl( |
| 560 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], | 611 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], |
| 561 as_root=True) | 612 as_root=True, check_return=True) |
| 562 | 613 |
| 563 def _GetChangedFilesImpl(self, host_path, device_path): | 614 def _GetChangedFilesImpl(self, host_path, device_path): |
| 564 real_host_path = os.path.realpath(host_path) | 615 real_host_path = os.path.realpath(host_path) |
| 565 try: | 616 try: |
| 566 real_device_path = self._RunShellCommandImpl( | 617 real_device_path = self._RunShellCommandImpl( |
| 567 ['realpath', device_path], check_return=True) | 618 ['realpath', device_path], single_line=True, check_return=True) |
| 568 real_device_path = real_device_path[0] | |
| 569 except device_errors.CommandFailedError: | 619 except device_errors.CommandFailedError: |
| 570 return [(host_path, device_path)] | 620 return [(host_path, device_path)] |
| 571 | 621 |
| 572 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base | 622 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base |
| 573 # this function on mtime. | 623 # this function on mtime. |
| 574 # pylint: disable=W0212 | 624 # pylint: disable=W0212 |
| 575 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum( | 625 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum( |
| 576 real_host_path, real_device_path) | 626 real_host_path, real_device_path) |
| 577 # pylint: enable=W0212 | 627 # pylint: enable=W0212 |
| 578 | 628 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 target=DeviceUtils._CreateDeviceZip, | 700 target=DeviceUtils._CreateDeviceZip, |
| 651 args=(zip_file.name, files)) | 701 args=(zip_file.name, files)) |
| 652 zip_proc.start() | 702 zip_proc.start() |
| 653 zip_proc.join() | 703 zip_proc.join() |
| 654 | 704 |
| 655 zip_on_device = '%s/tmp.zip' % self._GetExternalStoragePathImpl() | 705 zip_on_device = '%s/tmp.zip' % self._GetExternalStoragePathImpl() |
| 656 try: | 706 try: |
| 657 self.adb.Push(zip_file.name, zip_on_device) | 707 self.adb.Push(zip_file.name, zip_on_device) |
| 658 self._RunShellCommandImpl( | 708 self._RunShellCommandImpl( |
| 659 ['unzip', zip_on_device], | 709 ['unzip', zip_on_device], |
| 660 as_root=True, check_return=True, | 710 as_root=True, |
| 661 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR}) | 711 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR}, |
| 712 check_return=True) |
| 662 finally: | 713 finally: |
| 663 if zip_proc.is_alive(): | 714 if zip_proc.is_alive(): |
| 664 zip_proc.terminate() | 715 zip_proc.terminate() |
| 665 if self._IsOnlineImpl(): | 716 if self._IsOnlineImpl(): |
| 666 self._RunShellCommandImpl(['rm', zip_on_device]) | 717 self._RunShellCommandImpl(['rm', zip_on_device], check_return=True) |
| 667 | 718 |
| 668 @staticmethod | 719 @staticmethod |
| 669 def _CreateDeviceZip(zip_path, host_device_tuples): | 720 def _CreateDeviceZip(zip_path, host_device_tuples): |
| 670 with zipfile.ZipFile(zip_path, 'w') as zip_file: | 721 with zipfile.ZipFile(zip_path, 'w') as zip_file: |
| 671 for host_path, device_path in host_device_tuples: | 722 for host_path, device_path in host_device_tuples: |
| 672 if os.path.isfile(host_path): | 723 if os.path.isfile(host_path): |
| 673 zip_file.write(host_path, device_path, zipfile.ZIP_DEFLATED) | 724 zip_file.write(host_path, device_path, zipfile.ZIP_DEFLATED) |
| 674 else: | 725 else: |
| 675 for hd, _, files in os.walk(host_path): | 726 for hd, _, files in os.walk(host_path): |
| 676 dd = '%s/%s' % (device_path, os.path.relpath(host_path, hd)) | 727 dd = '%s/%s' % (device_path, os.path.relpath(host_path, hd)) |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 as_root: A boolean indicating whether the write should be executed with | 843 as_root: A boolean indicating whether the write should be executed with |
| 793 root privileges. | 844 root privileges. |
| 794 timeout: timeout in seconds | 845 timeout: timeout in seconds |
| 795 retries: number of retries | 846 retries: number of retries |
| 796 | 847 |
| 797 Raises: | 848 Raises: |
| 798 CommandFailedError if the file could not be written on the device. | 849 CommandFailedError if the file could not be written on the device. |
| 799 CommandTimeoutError on timeout. | 850 CommandTimeoutError on timeout. |
| 800 DeviceUnreachableError on missing device. | 851 DeviceUnreachableError on missing device. |
| 801 """ | 852 """ |
| 802 self._RunShellCommandImpl('echo {1} > {0}'.format(device_path, | 853 cmd = 'echo %s > %s' % (cmd_helper.SingleQuote(text), |
| 803 pipes.quote(text)), check_return=True, as_root=as_root) | 854 cmd_helper.SingleQuote(device_path)) |
| 855 self._RunShellCommandImpl(cmd, as_root=as_root, check_return=True) |
| 804 | 856 |
| 805 @decorators.WithTimeoutAndRetriesFromInstance() | 857 @decorators.WithTimeoutAndRetriesFromInstance() |
| 806 def Ls(self, device_path, timeout=None, retries=None): | 858 def Ls(self, device_path, timeout=None, retries=None): |
| 807 """Lists the contents of a directory on the device. | 859 """Lists the contents of a directory on the device. |
| 808 | 860 |
| 809 Args: | 861 Args: |
| 810 device_path: A string containing the path of the directory on the device | 862 device_path: A string containing the path of the directory on the device |
| 811 to list. | 863 to list. |
| 812 timeout: timeout in seconds | 864 timeout: timeout in seconds |
| 813 retries: number of retries | 865 retries: number of retries |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 provided |process_name|. | 962 provided |process_name|. |
| 911 | 963 |
| 912 Raises: | 964 Raises: |
| 913 CommandTimeoutError on timeout. | 965 CommandTimeoutError on timeout. |
| 914 DeviceUnreachableError on missing device. | 966 DeviceUnreachableError on missing device. |
| 915 """ | 967 """ |
| 916 return self._GetPidsImpl(process_name) | 968 return self._GetPidsImpl(process_name) |
| 917 | 969 |
| 918 def _GetPidsImpl(self, process_name): | 970 def _GetPidsImpl(self, process_name): |
| 919 procs_pids = {} | 971 procs_pids = {} |
| 920 for line in self._RunShellCommandImpl('ps'): | 972 for line in self._RunShellCommandImpl('ps', check_return=True): |
| 921 try: | 973 try: |
| 922 ps_data = line.split() | 974 ps_data = line.split() |
| 923 if process_name in ps_data[-1]: | 975 if process_name in ps_data[-1]: |
| 924 procs_pids[ps_data[-1]] = ps_data[1] | 976 procs_pids[ps_data[-1]] = ps_data[1] |
| 925 except IndexError: | 977 except IndexError: |
| 926 pass | 978 pass |
| 927 return procs_pids | 979 return procs_pids |
| 928 | 980 |
| 929 @decorators.WithTimeoutAndRetriesFromInstance() | 981 @decorators.WithTimeoutAndRetriesFromInstance() |
| 930 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): | 982 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 Returns: | 1060 Returns: |
| 1009 A Parallelizer operating over |devices|. | 1061 A Parallelizer operating over |devices|. |
| 1010 """ | 1062 """ |
| 1011 if not devices or len(devices) == 0: | 1063 if not devices or len(devices) == 0: |
| 1012 devices = pylib.android_commands.GetAttachedDevices() | 1064 devices = pylib.android_commands.GetAttachedDevices() |
| 1013 parallelizer_type = (parallelizer.Parallelizer if async | 1065 parallelizer_type = (parallelizer.Parallelizer if async |
| 1014 else parallelizer.SyncParallelizer) | 1066 else parallelizer.SyncParallelizer) |
| 1015 return parallelizer_type([ | 1067 return parallelizer_type([ |
| 1016 d if isinstance(d, DeviceUtils) else DeviceUtils(d) | 1068 d if isinstance(d, DeviceUtils) else DeviceUtils(d) |
| 1017 for d in devices]) | 1069 for d in devices]) |
| OLD | NEW |