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