Add option to specify ADB binary in test runner.
BUG=430957
Review URL: https://codereview.chromium.org/711113002
Cr-Commit-Position: refs/heads/master@{#304913}
diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py
index 971fc4ee..8d7866dc 100644
--- a/build/android/pylib/android_commands.py
+++ b/build/android/pylib/android_commands.py
@@ -314,11 +314,7 @@
device: If given, adb commands are only send to the device of this ID.
Otherwise commands are sent to all attached devices.
"""
- adb_dir = os.path.dirname(constants.GetAdbPath())
- if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep):
- # Required by third_party/android_testrunner to call directly 'adb'.
- os.environ['PATH'] += os.pathsep + adb_dir
- self._adb = adb_interface.AdbInterface()
+ self._adb = adb_interface.AdbInterface(constants.GetAdbPath())
if device:
self._adb.SetTargetSerial(device)
self._device = device
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py
index 29da6012..da28eeb 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants.py
@@ -246,8 +246,21 @@
return Wrapper
-@_Memoize
+def SetAdbPath(adb_path):
+ os.environ['ADB_PATH'] = adb_path
+
+
def GetAdbPath():
+ # Check if a custom adb path as been set. If not, try to find adb
+ # on the system.
+ if os.environ.get('ADB_PATH'):
+ return os.environ.get('ADB_PATH')
+ else:
+ return _FindAdbPath()
+
+
+@_Memoize
+def _FindAdbPath():
if os.environ.get('ANDROID_SDK_ROOT'):
return 'adb'
# If envsetup.sh hasn't been sourced and there's no adb in the path,
@@ -260,7 +273,6 @@
logging.debug('No adb found in $PATH, fallback to checked in binary.')
return os.path.join(ANDROID_SDK_ROOT, 'platform-tools', 'adb')
-
# Exit codes
ERROR_EXIT_CODE = 1
WARNING_EXIT_CODE = 88
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py
index 23f77c3e..c7ea310 100644
--- a/build/android/pylib/device/adb_wrapper.py
+++ b/build/android/pylib/device/adb_wrapper.py
@@ -12,6 +12,7 @@
import os
from pylib import cmd_helper
+from pylib import constants
from pylib.device import decorators
from pylib.device import device_errors
from pylib.utils import timeout_retry
@@ -49,7 +50,7 @@
@classmethod
@decorators.WithTimeoutAndRetries
def _RunAdbCmd(cls, arg_list, timeout=None, retries=None, check_error=True):
- cmd = ['adb'] + arg_list
+ cmd = [constants.GetAdbPath()] + arg_list
exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
cmd, timeout_retry.CurrentTimeoutThread().GetRemainingTime())
if exit_code != 0:
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py
index 1fb973bd..2ba3f727 100755
--- a/build/android/pylib/device/device_utils_test.py
+++ b/build/android/pylib/device/device_utils_test.py
@@ -215,9 +215,14 @@
return type(self).AndroidCommandsCalls(self, cmd_ret, comp)
def setUp(self):
+ self._get_adb_path_patch = mock.patch('pylib.constants.GetAdbPath',
+ mock.Mock(return_value='adb'))
+ self._get_adb_path_patch.start()
self.device = device_utils.DeviceUtils(
'0123456789abcdef', default_timeout=1, default_retries=0)
+ def tearDown(self):
+ self._get_adb_path_patch.stop()
class DeviceUtilsNewImplTest(mock_calls.TestCase):
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index bce79d5..b483d2b 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -91,6 +91,9 @@
group.add_option('-e', '--environment', default='local',
help=('Test environment to run in. Must be one of: %s' %
', '.join(constants.VALID_ENVIRONMENTS)))
+ group.add_option('--adb-path',
+ help=('Specify the absolute path of the adb binary that '
+ 'should be used.'))
option_parser.add_option_group(group)
@@ -102,6 +105,12 @@
constants.SetBuildDirectory(options.build_directory)
if options.output_directory:
constants.SetOutputDirectort(options.output_directory)
+ if options.adb_path:
+ constants.SetAdbPath(options.adb_path)
+ # Some things such as Forwarder require ADB to be in the environment path.
+ adb_dir = os.path.dirname(constants.GetAdbPath())
+ if adb_dir and adb_dir not in os.environ['PATH'].split(os.pathsep):
+ os.environ['PATH'] = adb_dir + os.pathsep + os.environ['PATH']
if options.environment not in constants.VALID_ENVIRONMENTS:
error_func('--environment must be one of: %s' %
', '.join(constants.VALID_ENVIRONMENTS))
diff --git a/third_party/android_testrunner/README.chromium b/third_party/android_testrunner/README.chromium
index 7d382a1..6ca8498f 100644
--- a/third_party/android_testrunner/README.chromium
+++ b/third_party/android_testrunner/README.chromium
@@ -18,6 +18,8 @@
bugs in run_command.py.
4. Fixed a bug where wait_time wasn't properly respected in
_WaitForShellCommandContents.
+5. Added option to specify the ADB binary that should be used instead of always
+ using the ADB in the environment path.
Here is the detail steps
1. Checkout Android source code
diff --git a/third_party/android_testrunner/adb_interface.py b/third_party/android_testrunner/adb_interface.py
index 93e19632..306f186 100644
--- a/third_party/android_testrunner/adb_interface.py
+++ b/third_party/android_testrunner/adb_interface.py
@@ -34,11 +34,19 @@
class AdbInterface:
"""Helper class for communicating with Android device via adb."""
- # argument to pass to adb, to direct command to specific device
- _target_arg = ""
-
DEVICE_TRACE_DIR = "/data/test_results/"
+ def __init__(self, adb_path='adb'):
+ """Constructor.
+
+ Args:
+ adb_path: Absolute path to the adb binary that should be used. Defaults
+ to the adb in the environment path.
+ """
+ self._adb_path = adb_path
+ # argument to pass to adb, to direct command to specific device
+ self._target_arg = ""
+
def SetEmulatorTarget(self):
"""Direct all future commands to the only running emulator."""
self._target_arg = "-e"
@@ -66,7 +74,7 @@
Raises:
WaitForResponseTimedOutError if device does not respond to command within time
"""
- adb_cmd = "adb %s %s" % (self._target_arg, command_string)
+ adb_cmd = "%s %s %s" % (self._adb_path, self._target_arg, command_string)
logger.SilentLog("about to run %s" % adb_cmd)
return run_command.RunCommand(adb_cmd, timeout_time=timeout_time,
retry_count=retry_count)