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