Chromium Code Reviews| 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 |
| 32 _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$') | |
|
jbudorick
2014/10/17 09:04:53
Not sure about having this at this scope; it shoul
perezju
2014/10/17 11:17:09
Done.
| |
| 31 | 33 |
| 32 | 34 |
| 33 @decorators.WithExplicitTimeoutAndRetries( | 35 @decorators.WithExplicitTimeoutAndRetries( |
| 34 _DEFAULT_TIMEOUT, _DEFAULT_RETRIES) | 36 _DEFAULT_TIMEOUT, _DEFAULT_RETRIES) |
| 35 def GetAVDs(): | 37 def GetAVDs(): |
| 36 """Returns a list of Android Virtual Devices. | 38 """Returns a list of Android Virtual Devices. |
| 37 | 39 |
| 38 Returns: | 40 Returns: |
| 39 A list containing the configured AVDs. | 41 A list containing the configured AVDs. |
| 40 """ | 42 """ |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) | 82 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) |
| 81 self.old_interface = device | 83 self.old_interface = device |
| 82 elif not device: | 84 elif not device: |
| 83 self.adb = adb_wrapper.AdbWrapper('') | 85 self.adb = adb_wrapper.AdbWrapper('') |
| 84 self.old_interface = pylib.android_commands.AndroidCommands() | 86 self.old_interface = pylib.android_commands.AndroidCommands() |
| 85 else: | 87 else: |
| 86 raise ValueError('Unsupported type passed for argument "device"') | 88 raise ValueError('Unsupported type passed for argument "device"') |
| 87 self._commands_installed = None | 89 self._commands_installed = None |
| 88 self._default_timeout = default_timeout | 90 self._default_timeout = default_timeout |
| 89 self._default_retries = default_retries | 91 self._default_retries = default_retries |
| 92 self._cache = {} | |
| 90 assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)) | 93 assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)) |
| 91 assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR)) | 94 assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR)) |
| 92 | 95 |
| 93 @decorators.WithTimeoutAndRetriesFromInstance() | 96 @decorators.WithTimeoutAndRetriesFromInstance() |
| 94 def IsOnline(self, timeout=None, retries=None): | 97 def IsOnline(self, timeout=None, retries=None): |
| 95 """Checks whether the device is online. | 98 """Checks whether the device is online. |
| 96 | 99 |
| 97 Args: | 100 Args: |
| 98 timeout: timeout in seconds | 101 timeout: timeout in seconds |
| 99 retries: number of retries | 102 retries: number of retries |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 120 Returns: | 123 Returns: |
| 121 True if adbd has root privileges, False otherwise. | 124 True if adbd has root privileges, False otherwise. |
| 122 | 125 |
| 123 Raises: | 126 Raises: |
| 124 CommandTimeoutError on timeout. | 127 CommandTimeoutError on timeout. |
| 125 DeviceUnreachableError on missing device. | 128 DeviceUnreachableError on missing device. |
| 126 """ | 129 """ |
| 127 return self._HasRootImpl() | 130 return self._HasRootImpl() |
| 128 | 131 |
| 129 def _HasRootImpl(self): | 132 def _HasRootImpl(self): |
| 130 return self.old_interface.IsRootEnabled() | 133 try: |
|
jbudorick
2014/10/17 09:04:53
Sneaking a conversion in here, I see.
| |
| 134 self._RunShellCommandImpl('ls /root') | |
| 135 return True | |
| 136 except device_errors.AdbShellCommandFailedError: | |
| 137 return False | |
| 131 | 138 |
| 132 @decorators.WithTimeoutAndRetriesFromInstance() | 139 @decorators.WithTimeoutAndRetriesFromInstance() |
| 133 def EnableRoot(self, timeout=None, retries=None): | 140 def EnableRoot(self, timeout=None, retries=None): |
| 134 """Restarts adbd with root privileges. | 141 """Restarts adbd with root privileges. |
| 135 | 142 |
| 136 Args: | 143 Args: |
| 137 timeout: timeout in seconds | 144 timeout: timeout in seconds |
| 138 retries: number of retries | 145 retries: number of retries |
| 139 | 146 |
| 140 Raises: | 147 Raises: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 The device's path to its SD card. | 182 The device's path to its SD card. |
| 176 | 183 |
| 177 Raises: | 184 Raises: |
| 178 CommandFailedError if the external storage path could not be determined. | 185 CommandFailedError if the external storage path could not be determined. |
| 179 CommandTimeoutError on timeout. | 186 CommandTimeoutError on timeout. |
| 180 DeviceUnreachableError on missing device. | 187 DeviceUnreachableError on missing device. |
| 181 """ | 188 """ |
| 182 return self._GetExternalStoragePathImpl() | 189 return self._GetExternalStoragePathImpl() |
| 183 | 190 |
| 184 def _GetExternalStoragePathImpl(self): | 191 def _GetExternalStoragePathImpl(self): |
| 185 try: | 192 if 'external_storage' in self._cache: |
|
jbudorick
2014/10/17 09:04:53
Another sneaky conversion.
| |
| 186 return self.old_interface.GetExternalStorage() | 193 return self._cache['external_storage'] |
| 187 except AssertionError as e: | 194 |
| 188 raise device_errors.CommandFailedError( | 195 value = self._RunShellCommandImpl('echo $EXTERNAL_STORAGE').rstrip() |
| 189 str(e), device=str(self)), None, sys.exc_info()[2] | 196 if not value: |
| 197 raise device_errors.CommandFailedError('$EXTERNAL_STORAGE is not set', | |
| 198 str(self)) | |
| 199 self._cache['external_storage'] = value | |
| 200 return value | |
| 190 | 201 |
| 191 @decorators.WithTimeoutAndRetriesFromInstance() | 202 @decorators.WithTimeoutAndRetriesFromInstance() |
| 192 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): | 203 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): |
| 193 """Wait for the device to fully boot. | 204 """Wait for the device to fully boot. |
| 194 | 205 |
| 195 This means waiting for the device to boot, the package manager to be | 206 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 | 207 available, and the SD card to be ready. It can optionally mean waiting |
| 197 for wifi to come up, too. | 208 for wifi to come up, too. |
| 198 | 209 |
| 199 Args: | 210 Args: |
| 200 wifi: A boolean indicating if we should wait for wifi to come up or not. | 211 wifi: A boolean indicating if we should wait for wifi to come up or not. |
| 201 timeout: timeout in seconds | 212 timeout: timeout in seconds |
| 202 retries: number of retries | 213 retries: number of retries |
| 203 | 214 |
| 204 Raises: | 215 Raises: |
| 205 CommandFailedError on failure. | 216 CommandFailedError on failure. |
| 206 CommandTimeoutError if one of the component waits times out. | 217 CommandTimeoutError if one of the component waits times out. |
| 207 DeviceUnreachableError if the device becomes unresponsive. | 218 DeviceUnreachableError if the device becomes unresponsive. |
| 208 """ | 219 """ |
| 209 self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) | 220 self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) |
| 210 | 221 |
| 211 def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): | 222 def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): |
| 212 if timeout is None: | 223 if timeout is None: |
| 213 timeout = self._default_timeout | 224 timeout = self._default_timeout |
| 214 self.old_interface.WaitForSystemBootCompleted(timeout) | 225 self.old_interface.WaitForSystemBootCompleted(timeout) |
| 215 self.old_interface.WaitForDevicePm() | 226 self.old_interface.WaitForDevicePm() |
| 216 self.old_interface.WaitForSdCardReady(timeout) | 227 self.old_interface.WaitForSdCardReady(timeout) |
| 217 if wifi: | 228 if wifi: |
| 218 while not 'Wi-Fi is enabled' in ( | 229 while not 'Wi-Fi is enabled' in ( |
| 219 self._RunShellCommandImpl('dumpsys wifi')): | 230 self.old_interface.RunShellCommand('dumpsys wifi')): |
|
jbudorick
2014/10/17 09:04:53
What's up with this? Is this because of the unit t
perezju
2014/10/17 11:17:09
Yes, because all the others are calls to old_inter
jbudorick
2014/10/17 15:48:00
Hmm. I'm not really a fan of either of those optio
| |
| 220 time.sleep(1) | 231 time.sleep(1) |
| 221 | 232 |
| 222 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT | 233 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT |
| 223 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES | 234 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES |
| 224 | 235 |
| 225 @decorators.WithTimeoutAndRetriesDefaults( | 236 @decorators.WithTimeoutAndRetriesDefaults( |
| 226 REBOOT_DEFAULT_TIMEOUT, | 237 REBOOT_DEFAULT_TIMEOUT, |
| 227 REBOOT_DEFAULT_RETRIES) | 238 REBOOT_DEFAULT_RETRIES) |
| 228 def Reboot(self, block=True, timeout=None, retries=None): | 239 def Reboot(self, block=True, timeout=None, retries=None): |
| 229 """Reboot the device. | 240 """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) | 296 out = self.old_interface.Install(apk_path, reinstall=reinstall) |
| 286 for line in out.splitlines(): | 297 for line in out.splitlines(): |
| 287 if 'Failure' in line: | 298 if 'Failure' in line: |
| 288 raise device_errors.CommandFailedError( | 299 raise device_errors.CommandFailedError( |
| 289 line.strip(), device=str(self)) | 300 line.strip(), device=str(self)) |
| 290 except AssertionError as e: | 301 except AssertionError as e: |
| 291 raise device_errors.CommandFailedError( | 302 raise device_errors.CommandFailedError( |
| 292 str(e), device=str(self)), None, sys.exc_info()[2] | 303 str(e), device=str(self)), None, sys.exc_info()[2] |
| 293 | 304 |
| 294 @decorators.WithTimeoutAndRetriesFromInstance() | 305 @decorators.WithTimeoutAndRetriesFromInstance() |
| 295 def RunShellCommand(self, cmd, check_return=False, as_root=False, cwd=None, | 306 def RunShellCommand(self, cmd, check_return=False, want_lines=True, |
| 296 env=None, timeout=None, retries=None): | 307 cwd=None, env=None, as_root=False, |
| 308 timeout=None, retries=None): | |
| 297 """Run an ADB shell command. | 309 """Run an ADB shell command. |
| 298 | 310 |
| 299 TODO(jbudorick) Switch the default value of check_return to True after | 311 When the command to run |cmd| is given as a string, it will be interpreted |
| 300 AndroidCommands is gone. | 312 and run by the shell on the device. |
| 313 | |
| 314 Alternatively, one can supply |cmd| as a sequence containing the name of | |
| 315 the command to run followed by its arguments. In this case, arguments are | |
| 316 passed to the command exactly as given, without any further processing by | |
| 317 the shell. This allows to easily pass arguments containing spaces or | |
| 318 special characters without having to worry about getting quoting right. | |
| 319 | |
| 320 TODO(perezju) Remove the options |check_return| and |want_lines|, | |
| 321 or change their default vaules, when callers have switched to the new | |
| 322 behaviour. | |
| 301 | 323 |
| 302 Args: | 324 Args: |
| 303 cmd: A list containing the command to run on the device and any arguments. | 325 cmd: A string with the full command to run on the device, or a sequence |
| 326 containing the command and its arguments. | |
| 304 check_return: A boolean indicating whether or not the return code should | 327 check_return: A boolean indicating whether or not the return code should |
| 305 be checked. | 328 be checked. |
| 306 as_root: A boolean indicating whether the shell command should be run | 329 want_lines: A boolean indicating whether to return the output of the |
|
jbudorick
2014/10/17 09:04:53
After looking at this and thinking about it, I'm n
| |
| 307 with root privileges. | 330 command as a list of lines or a single string. |
| 308 cwd: The device directory in which the command should be run. | 331 cwd: The device directory in which the command should be run. |
| 309 env: The environment variables with which the command should be run. | 332 env: The environment variables with which the command should be run. |
| 333 as_root: A boolean indicating whether the shell command should be run | |
| 334 with root privileges. | |
| 310 timeout: timeout in seconds | 335 timeout: timeout in seconds |
| 311 retries: number of retries | 336 retries: number of retries |
| 312 | 337 |
| 313 Returns: | 338 Returns: |
| 314 The output of the command. | 339 The output of the command either as list of lines, when want_lines is |
| 340 True, or a single string, otherwise. | |
| 315 | 341 |
| 316 Raises: | 342 Raises: |
| 317 CommandFailedError if check_return is True and the return code is nozero. | 343 AdbShellCommandFailedError if check_return is True and the exit code of |
| 344 the command run on the device is non-zero. | |
| 318 CommandTimeoutError on timeout. | 345 CommandTimeoutError on timeout. |
| 319 DeviceUnreachableError on missing device. | 346 DeviceUnreachableError on missing device. |
| 320 """ | 347 """ |
| 321 return self._RunShellCommandImpl( | 348 try: |
|
jbudorick
2014/10/17 09:04:53
This implementation all should move into the _Impl
perezju
2014/10/17 11:17:09
Done.
| |
| 322 cmd, check_return=check_return, as_root=as_root, cwd=cwd, env=env, | 349 output = self._RunShellCommandImpl(cmd, cwd=cwd, env=env, as_root=as_root) |
| 323 timeout=timeout) | 350 except device_errors.AdbShellCommandFailedError as e: |
| 351 if check_return: | |
| 352 raise | |
| 353 else: | |
| 354 output = e.output | |
| 355 if want_lines: | |
| 356 output = output.splitlines() | |
| 357 return output | |
| 324 | 358 |
| 325 def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False, | 359 def _RunShellCommandImpl(self, cmd, cwd=None, env=None, as_root=False): |
|
jbudorick
2014/10/17 09:04:53
You'll have to restore the options you split betwe
| |
| 326 cwd=None, env=None, timeout=None): | 360 '''Implementation of RunShellCommand. |
| 327 # TODO(jbudorick): Remove the timeout parameter once this is no longer | 361 |
| 328 # backed by AndroidCommands. | 362 Note that this function already implements the proposed new behaviour of |
| 329 if isinstance(cmd, list): | 363 RunShellCommand (i.e, check_return=True, want_lines=False) and is available |
| 330 cmd = ' '.join(cmd) | 364 to be used by other DeviceUtils' methods. |
| 365 ''' | |
| 366 def env_quote(key, value): | |
| 367 if not _VALID_SHELL_VARIABLE.match(key): | |
| 368 raise KeyError('Invalid shell variable name %r' % key) | |
| 369 # using cmd_helper.dquote to quote but allow interpolation of shell vars | |
| 370 return '%s=%s' % (key, cmd_helper.dquote(value)) | |
|
jbudorick
2014/10/17 09:04:53
Maybe the dquote functionality should just live in
| |
| 371 | |
| 372 if not isinstance(cmd, basestring): | |
| 373 cmd = ' '.join(cmd_helper.quote(s) for s in cmd) | |
|
jbudorick
2014/10/17 09:04:53
I really don't like the 'quote = pipes.quote' in p
| |
| 331 if as_root and not self._HasRootImpl(): | 374 if as_root and not self._HasRootImpl(): |
| 332 cmd = 'su -c %s' % cmd | 375 cmd = 'su -c %s' % cmd |
| 333 if env: | 376 if env is not None: |
|
jbudorick
2014/10/17 09:04:53
As below, this change only matters if env is empty
perezju
2014/10/17 11:17:09
Acknowledged.
| |
| 334 cmd = '%s %s' % ( | 377 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) | 378 cmd = '%s %s' % (env, cmd) |
| 336 if cwd: | 379 if cwd is not None: |
|
jbudorick
2014/10/17 09:04:53
The only time when this change matters is if cwd i
| |
| 337 cmd = 'cd %s && %s' % (cwd, cmd) | 380 cmd = 'cd %s && %s' % (cmd_helper.quote(cwd), cmd) |
| 338 if check_return: | 381 # TODO(perezju) still need to make sure that we call a version of adb.Shell |
| 339 code, output = self.old_interface.GetShellCommandStatusAndOutput( | 382 # without a timeout-and-retries wrapper. |
| 340 cmd, timeout_time=timeout) | 383 return self.adb.Shell(cmd, expect_rc=0) |
| 341 if int(code) != 0: | |
| 342 raise device_errors.AdbCommandFailedError( | |
| 343 cmd.split(), 'Nonzero exit code (%d)' % code, device=str(self)) | |
| 344 else: | |
| 345 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout) | |
| 346 return output | |
| 347 | 384 |
| 348 @decorators.WithTimeoutAndRetriesFromInstance() | 385 @decorators.WithTimeoutAndRetriesFromInstance() |
| 349 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, | 386 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, |
| 350 timeout=None, retries=None): | 387 timeout=None, retries=None): |
| 351 """Kill all processes with the given name on the device. | 388 """Kill all processes with the given name on the device. |
| 352 | 389 |
| 353 Args: | 390 Args: |
| 354 process_name: A string containing the name of the process to kill. | 391 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 | 392 signum: An integer containing the signal number to send to kill. Defaults |
| 356 to 9 (SIGKILL). | 393 to 9 (SIGKILL). |
| 357 as_root: A boolean indicating whether the kill should be executed with | 394 as_root: A boolean indicating whether the kill should be executed with |
| 358 root privileges. | 395 root privileges. |
| 359 blocking: A boolean indicating whether we should wait until all processes | 396 blocking: A boolean indicating whether we should wait until all processes |
| 360 with the given |process_name| are dead. | 397 with the given |process_name| are dead. |
| 361 timeout: timeout in seconds | 398 timeout: timeout in seconds |
| 362 retries: number of retries | 399 retries: number of retries |
| 363 | 400 |
| 364 Raises: | 401 Raises: |
| 365 CommandFailedError if no process was killed. | 402 CommandFailedError if no process was killed. |
| 366 CommandTimeoutError on timeout. | 403 CommandTimeoutError on timeout. |
| 367 DeviceUnreachableError on missing device. | 404 DeviceUnreachableError on missing device. |
| 368 """ | 405 """ |
| 369 pids = self._GetPidsImpl(process_name) | 406 pids = self._GetPidsImpl(process_name) |
| 370 if not pids: | 407 if not pids: |
| 371 raise device_errors.CommandFailedError( | 408 raise device_errors.CommandFailedError( |
| 372 'No process "%s"' % process_name, device=str(self)) | 409 'No process "%s"' % process_name, device=str(self)) |
| 373 | 410 |
| 374 cmd = 'kill -%d %s' % (signum, ' '.join(pids.values())) | 411 cmd = ['kill', '-%d' % signum] + pids.values() |
| 375 self._RunShellCommandImpl(cmd, as_root=as_root) | 412 self._RunShellCommandImpl(cmd, as_root=as_root) |
| 376 | 413 |
| 377 if blocking: | 414 if blocking: |
| 378 wait_period = 0.1 | 415 wait_period = 0.1 |
| 379 while self._GetPidsImpl(process_name): | 416 while self._GetPidsImpl(process_name): |
| 380 time.sleep(wait_period) | 417 time.sleep(wait_period) |
| 381 | 418 |
| 382 return len(pids) | 419 return len(pids) |
| 383 | 420 |
| 384 @decorators.WithTimeoutAndRetriesFromInstance() | 421 @decorators.WithTimeoutAndRetriesFromInstance() |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 | 553 |
| 517 Raises: | 554 Raises: |
| 518 CommandFailedError on failure. | 555 CommandFailedError on failure. |
| 519 CommandTimeoutError on timeout. | 556 CommandTimeoutError on timeout. |
| 520 DeviceUnreachableError on missing device. | 557 DeviceUnreachableError on missing device. |
| 521 """ | 558 """ |
| 522 | 559 |
| 523 files = [] | 560 files = [] |
| 524 for h, d in host_device_tuples: | 561 for h, d in host_device_tuples: |
| 525 if os.path.isdir(h): | 562 if os.path.isdir(h): |
| 526 self._RunShellCommandImpl(['mkdir', '-p', '"%s"' % d], | 563 self._RunShellCommandImpl(['mkdir', '-p', d]) |
|
jbudorick
2014/10/17 09:04:53
following from my comments on the _Impl split, res
perezju
2014/10/17 11:17:09
All Done.
| |
| 527 check_return=True) | |
| 528 files += self._GetChangedFilesImpl(h, d) | 564 files += self._GetChangedFilesImpl(h, d) |
| 529 | 565 |
| 530 if not files: | 566 if not files: |
| 531 return | 567 return |
| 532 | 568 |
| 533 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) | 569 size = sum(host_utils.GetRecursiveDiskUsage(h) for h, _ in files) |
| 534 file_count = len(files) | 570 file_count = len(files) |
| 535 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) | 571 dir_size = sum(host_utils.GetRecursiveDiskUsage(h) |
| 536 for h, _ in host_device_tuples) | 572 for h, _ in host_device_tuples) |
| 537 dir_file_count = 0 | 573 dir_file_count = 0 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 557 else: | 593 else: |
| 558 self._PushChangedFilesZipped(files) | 594 self._PushChangedFilesZipped(files) |
| 559 self._RunShellCommandImpl( | 595 self._RunShellCommandImpl( |
| 560 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], | 596 ['chmod', '-R', '777'] + [d for _, d in host_device_tuples], |
| 561 as_root=True) | 597 as_root=True) |
| 562 | 598 |
| 563 def _GetChangedFilesImpl(self, host_path, device_path): | 599 def _GetChangedFilesImpl(self, host_path, device_path): |
| 564 real_host_path = os.path.realpath(host_path) | 600 real_host_path = os.path.realpath(host_path) |
| 565 try: | 601 try: |
| 566 real_device_path = self._RunShellCommandImpl( | 602 real_device_path = self._RunShellCommandImpl( |
| 567 ['realpath', device_path], check_return=True) | 603 ['realpath', device_path]).rstrip() |
|
jbudorick
2014/10/17 09:04:53
and here.
| |
| 568 real_device_path = real_device_path[0] | |
| 569 except device_errors.CommandFailedError: | 604 except device_errors.CommandFailedError: |
| 570 return [(host_path, device_path)] | 605 return [(host_path, device_path)] |
| 571 | 606 |
| 572 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base | 607 # TODO(jbudorick): Move the md5 logic up into DeviceUtils or base |
| 573 # this function on mtime. | 608 # this function on mtime. |
| 574 # pylint: disable=W0212 | 609 # pylint: disable=W0212 |
| 575 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum( | 610 host_hash_tuples, device_hash_tuples = self.old_interface._RunMd5Sum( |
| 576 real_host_path, real_device_path) | 611 real_host_path, real_device_path) |
| 577 # pylint: enable=W0212 | 612 # pylint: enable=W0212 |
| 578 | 613 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 target=DeviceUtils._CreateDeviceZip, | 685 target=DeviceUtils._CreateDeviceZip, |
| 651 args=(zip_file.name, files)) | 686 args=(zip_file.name, files)) |
| 652 zip_proc.start() | 687 zip_proc.start() |
| 653 zip_proc.join() | 688 zip_proc.join() |
| 654 | 689 |
| 655 zip_on_device = '%s/tmp.zip' % self._GetExternalStoragePathImpl() | 690 zip_on_device = '%s/tmp.zip' % self._GetExternalStoragePathImpl() |
| 656 try: | 691 try: |
| 657 self.adb.Push(zip_file.name, zip_on_device) | 692 self.adb.Push(zip_file.name, zip_on_device) |
| 658 self._RunShellCommandImpl( | 693 self._RunShellCommandImpl( |
| 659 ['unzip', zip_on_device], | 694 ['unzip', zip_on_device], |
| 660 as_root=True, check_return=True, | 695 as_root=True, |
|
jbudorick
2014/10/17 09:04:53
and here.
| |
| 661 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR}) | 696 env={'PATH': '$PATH:%s' % install_commands.BIN_DIR}) |
| 662 finally: | 697 finally: |
| 663 if zip_proc.is_alive(): | 698 if zip_proc.is_alive(): |
| 664 zip_proc.terminate() | 699 zip_proc.terminate() |
| 665 if self._IsOnlineImpl(): | 700 if self._IsOnlineImpl(): |
| 666 self._RunShellCommandImpl(['rm', zip_on_device]) | 701 self._RunShellCommandImpl(['rm', zip_on_device]) |
| 667 | 702 |
| 668 @staticmethod | 703 @staticmethod |
| 669 def _CreateDeviceZip(zip_path, host_device_tuples): | 704 def _CreateDeviceZip(zip_path, host_device_tuples): |
| 670 with zipfile.ZipFile(zip_path, 'w') as zip_file: | 705 with zipfile.ZipFile(zip_path, 'w') as zip_file: |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 as_root: A boolean indicating whether the write should be executed with | 827 as_root: A boolean indicating whether the write should be executed with |
| 793 root privileges. | 828 root privileges. |
| 794 timeout: timeout in seconds | 829 timeout: timeout in seconds |
| 795 retries: number of retries | 830 retries: number of retries |
| 796 | 831 |
| 797 Raises: | 832 Raises: |
| 798 CommandFailedError if the file could not be written on the device. | 833 CommandFailedError if the file could not be written on the device. |
| 799 CommandTimeoutError on timeout. | 834 CommandTimeoutError on timeout. |
| 800 DeviceUnreachableError on missing device. | 835 DeviceUnreachableError on missing device. |
| 801 """ | 836 """ |
| 802 self._RunShellCommandImpl('echo {1} > {0}'.format(device_path, | 837 cmd = 'echo %s > %s' % (cmd_helper.quote(text), |
| 803 pipes.quote(text)), check_return=True, as_root=as_root) | 838 cmd_helper.quote(device_path)) |
| 839 self._RunShellCommandImpl(cmd, as_root=as_root) | |
|
jbudorick
2014/10/17 09:04:53
and here.
| |
| 804 | 840 |
| 805 @decorators.WithTimeoutAndRetriesFromInstance() | 841 @decorators.WithTimeoutAndRetriesFromInstance() |
| 806 def Ls(self, device_path, timeout=None, retries=None): | 842 def Ls(self, device_path, timeout=None, retries=None): |
| 807 """Lists the contents of a directory on the device. | 843 """Lists the contents of a directory on the device. |
| 808 | 844 |
| 809 Args: | 845 Args: |
| 810 device_path: A string containing the path of the directory on the device | 846 device_path: A string containing the path of the directory on the device |
| 811 to list. | 847 to list. |
| 812 timeout: timeout in seconds | 848 timeout: timeout in seconds |
| 813 retries: number of retries | 849 retries: number of retries |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 910 provided |process_name|. | 946 provided |process_name|. |
| 911 | 947 |
| 912 Raises: | 948 Raises: |
| 913 CommandTimeoutError on timeout. | 949 CommandTimeoutError on timeout. |
| 914 DeviceUnreachableError on missing device. | 950 DeviceUnreachableError on missing device. |
| 915 """ | 951 """ |
| 916 return self._GetPidsImpl(process_name) | 952 return self._GetPidsImpl(process_name) |
| 917 | 953 |
| 918 def _GetPidsImpl(self, process_name): | 954 def _GetPidsImpl(self, process_name): |
| 919 procs_pids = {} | 955 procs_pids = {} |
| 920 for line in self._RunShellCommandImpl('ps'): | 956 for line in self._RunShellCommandImpl('ps').splitlines(): |
| 921 try: | 957 try: |
| 922 ps_data = line.split() | 958 ps_data = line.split() |
| 923 if process_name in ps_data[-1]: | 959 if process_name in ps_data[-1]: |
| 924 procs_pids[ps_data[-1]] = ps_data[1] | 960 procs_pids[ps_data[-1]] = ps_data[1] |
| 925 except IndexError: | 961 except IndexError: |
| 926 pass | 962 pass |
| 927 return procs_pids | 963 return procs_pids |
| 928 | 964 |
| 929 @decorators.WithTimeoutAndRetriesFromInstance() | 965 @decorators.WithTimeoutAndRetriesFromInstance() |
| 930 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): | 966 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: | 1044 Returns: |
| 1009 A Parallelizer operating over |devices|. | 1045 A Parallelizer operating over |devices|. |
| 1010 """ | 1046 """ |
| 1011 if not devices or len(devices) == 0: | 1047 if not devices or len(devices) == 0: |
| 1012 devices = pylib.android_commands.GetAttachedDevices() | 1048 devices = pylib.android_commands.GetAttachedDevices() |
| 1013 parallelizer_type = (parallelizer.Parallelizer if async | 1049 parallelizer_type = (parallelizer.Parallelizer if async |
| 1014 else parallelizer.SyncParallelizer) | 1050 else parallelizer.SyncParallelizer) |
| 1015 return parallelizer_type([ | 1051 return parallelizer_type([ |
| 1016 d if isinstance(d, DeviceUtils) else DeviceUtils(d) | 1052 d if isinstance(d, DeviceUtils) else DeviceUtils(d) |
| 1017 for d in devices]) | 1053 for d in devices]) |
| OLD | NEW |