diff options
Diffstat (limited to 'catapult/devil/devil/android/sdk/adb_wrapper.py')
-rw-r--r-- | catapult/devil/devil/android/sdk/adb_wrapper.py | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/catapult/devil/devil/android/sdk/adb_wrapper.py b/catapult/devil/devil/android/sdk/adb_wrapper.py index 099a0f8a..2fbe9638 100644 --- a/catapult/devil/devil/android/sdk/adb_wrapper.py +++ b/catapult/devil/devil/android/sdk/adb_wrapper.py @@ -19,6 +19,7 @@ import posixpath import re import subprocess +from devil import base_error from devil import devil_env from devil.android import decorators from devil.android import device_errors @@ -96,7 +97,11 @@ def _GetVersion(): def _ShouldRetryAdbCmd(exc): - return not isinstance(exc, device_errors.NoAdbError) + # Errors are potentially transient and should be retried, with the exception + # of NoAdbError. Exceptions [e.g. generated from SIGTERM handler] should be + # raised. + return (isinstance(exc, base_error.BaseError) and + not isinstance(exc, device_errors.NoAdbError)) DeviceStat = collections.namedtuple('DeviceStat', @@ -257,13 +262,15 @@ class AdbWrapper(object): @classmethod @decorators.WithTimeoutAndConditionalRetries(_ShouldRetryAdbCmd) def _RunAdbCmd(cls, args, timeout=None, retries=None, device_serial=None, - check_error=True, cpu_affinity=None): - # pylint: disable=no-member + check_error=True, cpu_affinity=None, + ensure_logs_on_timeout=False): + timeout = timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime() + if ensure_logs_on_timeout: + timeout = 0.95 * timeout try: status, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( cls._BuildAdbCmd(args, device_serial, cpu_affinity=cpu_affinity), - timeout_retry.CurrentTimeoutThreadGroup().GetRemainingTime(), - env=cls._ADB_ENV) + timeout, env=cls._ADB_ENV) except OSError as e: if e.errno in (errno.ENOENT, errno.ENOEXEC): raise device_errors.NoAdbError(msg=str(e)) @@ -287,7 +294,9 @@ class AdbWrapper(object): return output # pylint: enable=unused-argument - def _RunDeviceAdbCmd(self, args, timeout, retries, check_error=True): + def _RunDeviceAdbCmd( + self, args, timeout, retries, check_error=True, + ensure_logs_on_timeout=False): """Runs an adb command on the device associated with this object. Args: @@ -302,7 +311,8 @@ class AdbWrapper(object): """ return self._RunAdbCmd(args, timeout=timeout, retries=retries, device_serial=self._device_serial, - check_error=check_error) + check_error=check_error, + ensure_logs_on_timeout=ensure_logs_on_timeout) def _IterRunDeviceAdbCmd(self, args, iter_timeout, timeout): """Runs an adb command and returns an iterator over its output lines. @@ -497,14 +507,17 @@ class AdbWrapper(object): return cmd_helper.StartCmd( self._BuildAdbCmd(['shell'] + cmd, self._device_serial)) - def Shell(self, command, expect_status=0, timeout=DEFAULT_TIMEOUT, - retries=DEFAULT_RETRIES): + def Shell(self, command, expect_status=0, ensure_logs_on_timeout=False, + timeout=DEFAULT_TIMEOUT, retries=DEFAULT_RETRIES): """Runs a shell command on the device. Args: command: A string with the shell command to run. expect_status: (optional) Check that the command's exit status matches this value. Default is 0. If set to None the test is skipped. + ensure_logs_on_timeout: If True, will use a timeout that is 5% smaller + than the remaining time on the thread watchdog for the internal adb + command, which allows to retrive logs on timeout. timeout: (optional) Timeout per try in seconds. retries: (optional) Number of retries to attempt. @@ -519,7 +532,9 @@ class AdbWrapper(object): args = ['shell', command] else: args = ['shell', '( %s );echo %%$?' % command.rstrip()] - output = self._RunDeviceAdbCmd(args, timeout, retries, check_error=False) + output = self._RunDeviceAdbCmd( + args, timeout, retries, check_error=False, + ensure_logs_on_timeout=ensure_logs_on_timeout) if expect_status is not None: output_end = output.rfind('%') if output_end < 0: |