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 |