aboutsummaryrefslogtreecommitdiff
path: root/catapult/devil/devil/android/sdk/adb_wrapper.py
diff options
context:
space:
mode:
Diffstat (limited to 'catapult/devil/devil/android/sdk/adb_wrapper.py')
-rw-r--r--catapult/devil/devil/android/sdk/adb_wrapper.py35
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: