cheets: Add a script to keep adb connections alive
This change wraps the GTS invocation around a context that continuously
polls adb and reconnects any lost connections.
BUG=b:34280955
TEST=test_that minnie cheets_GTS.4.1_r1.GtsGmscoreHostTestCases
Change-Id: I5cd8b070a85bd3cd240ed99ec5adc987cfa5b1bc
Reviewed-on: https://chromium-review.googlesource.com/434161
Commit-Ready: Luis Hector Chavez <lhchavez@chromium.org>
Tested-by: Luis Hector Chavez <lhchavez@chromium.org>
Reviewed-by: Luis Hector Chavez <lhchavez@chromium.org>
diff --git a/server/cros/tradefed_test.py b/server/cros/tradefed_test.py
index 186e0f1..fde0229 100644
--- a/server/cros/tradefed_test.py
+++ b/server/cros/tradefed_test.py
@@ -34,6 +34,7 @@
import urlparse
from autotest_lib.client.bin import utils as client_utils
+from autotest_lib.client.common_lib import base_utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import dev_server
from autotest_lib.server import afe_utils
@@ -140,6 +141,38 @@
logging.info('Released cache lock.')
+@contextlib.contextmanager
+def adb_keepalive(target, extra_paths):
+ """A context manager that keeps the adb connection alive.
+
+ AdbKeepalive will spin off a new process that will continuously poll for
+ adb's connected state, and will attempt to reconnect if it ever goes down.
+ This is the only way we can currently recover safely from (intentional)
+ reboots.
+
+ @param target: the hostname and port of the DUT.
+ @param extra_paths: any additional components to the PATH environment
+ variable.
+ """
+ from autotest_lib.client.common_lib.cros import adb_keepalive as module
+ # |__file__| returns the absolute path of the compiled bytecode of the
+ # module. We want to run the original .py file, so we need to change the
+ # extension back.
+ script_filename = module.__file__.replace('.pyc', '.py')
+ job = base_utils.BgJob([script_filename, target],
+ nickname='adb_keepalive', stderr_level=logging.DEBUG,
+ stdout_tee=base_utils.TEE_TO_LOGS,
+ stderr_tee=base_utils.TEE_TO_LOGS,
+ extra_paths=extra_paths)
+
+ try:
+ yield
+ finally:
+ # The adb_keepalive.py script runs forever until SIGTERM is sent.
+ base_utils.nuke_subprocess(job.sp)
+ base_utils.join_bg_jobs([job])
+
+
class TradefedTest(test.test):
"""Base class to prepare DUT to run tests via tradefed."""
version = 1
@@ -192,6 +225,9 @@
"""
return _ChromeLogin(self._host)
+ def _get_adb_target(self):
+ return '{}:{}'.format(self._host.hostname, self._host.port)
+
def _try_adb_connect(self):
"""Attempts to connect to adb on the DUT.
@@ -200,7 +236,7 @@
# This may fail return failure due to a race condition in adb connect
# (b/29370989). If adb is already connected, this command will
# immediately return success.
- hostport = '{}:{}'.format(self._host.hostname, self._host.port)
+ hostport = self._get_adb_target()
result = self._run(
'adb',
args=('connect', hostport),
@@ -261,6 +297,9 @@
# This starts adbd.
self._android_shell('setprop sys.usb.config mtp,adb')
+ # Also let it be automatically started upon reboot.
+ self._android_shell('setprop persist.sys.usb.config mtp,adb')
+
# adbd may take some time to come up. Repeatedly try to connect to adb.
utils.poll_for_condition(lambda: self._try_adb_connect(),
exception=error.TestFail(
diff --git a/server/site_tests/cheets_GTS/cheets_GTS.py b/server/site_tests/cheets_GTS/cheets_GTS.py
index 2b179d2..940d838 100644
--- a/server/site_tests/cheets_GTS/cheets_GTS.py
+++ b/server/site_tests/cheets_GTS/cheets_GTS.py
@@ -57,14 +57,16 @@
gts_tradefed_args = ['run', 'commandAndExit', 'gts',
'--skip-device-info', '--module', target_package]
# Run GTS via tradefed and obtain stdout, sterr as output.
- output = self._run(
- gts_tradefed,
- args=gts_tradefed_args,
- verbose=True,
- # Make sure to tee tradefed stdout/stderr to autotest logs
- # already during the test run.
- stdout_tee=utils.TEE_TO_LOGS,
- stderr_tee=utils.TEE_TO_LOGS)
+ with tradefed_test.adb_keepalive(self._get_adb_target(),
+ self._install_paths):
+ output = self._run(
+ gts_tradefed,
+ args=gts_tradefed_args,
+ verbose=True,
+ # Make sure to tee tradefed stdout/stderr to autotest logs
+ # already during the test run.
+ stdout_tee=utils.TEE_TO_LOGS,
+ stderr_tee=utils.TEE_TO_LOGS)
# Parse stdout to obtain datetime IDs of directories into which tradefed
# wrote result xml files and logs.
datetime_id = self._parse_tradefed_datetime(output)