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=unused-argument | 9 # pylint: disable=unused-argument |
10 | 10 |
11 import collections | 11 import collections |
12 import contextlib | 12 import contextlib |
13 import itertools | 13 import itertools |
14 import logging | 14 import logging |
15 import multiprocessing | 15 import multiprocessing |
16 import os | 16 import os |
17 import posixpath | 17 import posixpath |
18 import re | 18 import re |
19 import shutil | 19 import shutil |
20 import sys | 20 import sys |
21 import tempfile | 21 import tempfile |
22 import time | 22 import time |
23 import zipfile | 23 import zipfile |
24 | 24 |
25 import pylib.android_commands | 25 import pylib.android_commands |
26 from pylib import cmd_helper | 26 from pylib import cmd_helper |
27 from pylib import constants | 27 from pylib import constants |
| 28 from pylib import device_signal |
28 from pylib.device import adb_wrapper | 29 from pylib.device import adb_wrapper |
29 from pylib.device import decorators | 30 from pylib.device import decorators |
30 from pylib.device import device_errors | 31 from pylib.device import device_errors |
31 from pylib.device import intent | 32 from pylib.device import intent |
32 from pylib.device import logcat_monitor | 33 from pylib.device import logcat_monitor |
33 from pylib.device.commands import install_commands | 34 from pylib.device.commands import install_commands |
34 from pylib.utils import apk_helper | 35 from pylib.utils import apk_helper |
35 from pylib.utils import base_error | 36 from pylib.utils import base_error |
36 from pylib.utils import device_temp_file | 37 from pylib.utils import device_temp_file |
37 from pylib.utils import host_utils | 38 from pylib.utils import host_utils |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 return '' | 567 return '' |
567 elif len(output) == 1: | 568 elif len(output) == 1: |
568 return output[0] | 569 return output[0] |
569 else: | 570 else: |
570 msg = 'one line of output was expected, but got: %s' | 571 msg = 'one line of output was expected, but got: %s' |
571 raise device_errors.CommandFailedError(msg % output, str(self)) | 572 raise device_errors.CommandFailedError(msg % output, str(self)) |
572 else: | 573 else: |
573 return output | 574 return output |
574 | 575 |
575 @decorators.WithTimeoutAndRetriesFromInstance() | 576 @decorators.WithTimeoutAndRetriesFromInstance() |
576 def KillAll(self, process_name, signum=9, as_root=False, blocking=False, | 577 def KillAll(self, process_name, signum=device_signal.SIGKILL, as_root=False, |
577 timeout=None, retries=None): | 578 blocking=False, quiet=False, timeout=None, retries=None): |
578 """Kill all processes with the given name on the device. | 579 """Kill all processes with the given name on the device. |
579 | 580 |
580 Args: | 581 Args: |
581 process_name: A string containing the name of the process to kill. | 582 process_name: A string containing the name of the process to kill. |
582 signum: An integer containing the signal number to send to kill. Defaults | 583 signum: An integer containing the signal number to send to kill. Defaults |
583 to 9 (SIGKILL). | 584 to SIGKILL (9). |
584 as_root: A boolean indicating whether the kill should be executed with | 585 as_root: A boolean indicating whether the kill should be executed with |
585 root privileges. | 586 root privileges. |
586 blocking: A boolean indicating whether we should wait until all processes | 587 blocking: A boolean indicating whether we should wait until all processes |
587 with the given |process_name| are dead. | 588 with the given |process_name| are dead. |
| 589 quiet: A boolean indicating whether to ignore the fact that no processes |
| 590 to kill were found. |
588 timeout: timeout in seconds | 591 timeout: timeout in seconds |
589 retries: number of retries | 592 retries: number of retries |
590 | 593 |
| 594 Returns: |
| 595 The number of processes attempted to kill. |
| 596 |
591 Raises: | 597 Raises: |
592 CommandFailedError if no process was killed. | 598 CommandFailedError if no process was killed and |quiet| is False. |
593 CommandTimeoutError on timeout. | 599 CommandTimeoutError on timeout. |
594 DeviceUnreachableError on missing device. | 600 DeviceUnreachableError on missing device. |
595 """ | 601 """ |
596 pids = self._GetPidsImpl(process_name) | 602 pids = self.GetPids(process_name) |
597 if not pids: | 603 if not pids: |
598 raise device_errors.CommandFailedError( | 604 if quiet: |
599 'No process "%s"' % process_name, str(self)) | 605 return 0 |
| 606 else: |
| 607 raise device_errors.CommandFailedError( |
| 608 'No process "%s"' % process_name, str(self)) |
600 | 609 |
601 cmd = ['kill', '-%d' % signum] + pids.values() | 610 cmd = ['kill', '-%d' % signum] + pids.values() |
602 self.RunShellCommand(cmd, as_root=as_root, check_return=True) | 611 self.RunShellCommand(cmd, as_root=as_root, check_return=True) |
603 | 612 |
604 if blocking: | 613 if blocking: |
| 614 # TODO(perezu): use timeout_retry.WaitFor |
605 wait_period = 0.1 | 615 wait_period = 0.1 |
606 while self._GetPidsImpl(process_name): | 616 while self.GetPids(process_name): |
607 time.sleep(wait_period) | 617 time.sleep(wait_period) |
608 | 618 |
609 return len(pids) | 619 return len(pids) |
610 | 620 |
611 @decorators.WithTimeoutAndRetriesFromInstance() | 621 @decorators.WithTimeoutAndRetriesFromInstance() |
612 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None, | 622 def StartActivity(self, intent_obj, blocking=False, trace_file_name=None, |
613 force_stop=False, timeout=None, retries=None): | 623 force_stop=False, timeout=None, retries=None): |
614 """Start package's activity on the device. | 624 """Start package's activity on the device. |
615 | 625 |
616 Args: | 626 Args: |
(...skipping 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1346 retries: number of retries | 1356 retries: number of retries |
1347 | 1357 |
1348 Returns: | 1358 Returns: |
1349 A dict mapping process name to PID for each process that contained the | 1359 A dict mapping process name to PID for each process that contained the |
1350 provided |process_name|. | 1360 provided |process_name|. |
1351 | 1361 |
1352 Raises: | 1362 Raises: |
1353 CommandTimeoutError on timeout. | 1363 CommandTimeoutError on timeout. |
1354 DeviceUnreachableError on missing device. | 1364 DeviceUnreachableError on missing device. |
1355 """ | 1365 """ |
1356 return self._GetPidsImpl(process_name) | |
1357 | |
1358 def _GetPidsImpl(self, process_name): | |
1359 procs_pids = {} | 1366 procs_pids = {} |
1360 for line in self.RunShellCommand('ps', check_return=True): | 1367 for line in self.RunShellCommand('ps', check_return=True): |
1361 try: | 1368 try: |
1362 ps_data = line.split() | 1369 ps_data = line.split() |
1363 if process_name in ps_data[-1]: | 1370 if process_name in ps_data[-1]: |
1364 procs_pids[ps_data[-1]] = ps_data[1] | 1371 procs_pids[ps_data[-1]] = ps_data[1] |
1365 except IndexError: | 1372 except IndexError: |
1366 pass | 1373 pass |
1367 return procs_pids | 1374 return procs_pids |
1368 | 1375 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1531 """Returns client cache.""" | 1538 """Returns client cache.""" |
1532 if client_name not in self._client_caches: | 1539 if client_name not in self._client_caches: |
1533 self._client_caches[client_name] = {} | 1540 self._client_caches[client_name] = {} |
1534 return self._client_caches[client_name] | 1541 return self._client_caches[client_name] |
1535 | 1542 |
1536 def _ClearCache(self): | 1543 def _ClearCache(self): |
1537 """Clears all caches.""" | 1544 """Clears all caches.""" |
1538 for client in self._client_caches: | 1545 for client in self._client_caches: |
1539 self._client_caches[client].clear() | 1546 self._client_caches[client].clear() |
1540 self._cache.clear() | 1547 self._cache.clear() |
OLD | NEW |