aboutsummaryrefslogtreecommitdiff
path: root/mobly/controllers/android_device_lib/adb.py
diff options
context:
space:
mode:
Diffstat (limited to 'mobly/controllers/android_device_lib/adb.py')
-rw-r--r--mobly/controllers/android_device_lib/adb.py175
1 files changed, 101 insertions, 74 deletions
diff --git a/mobly/controllers/android_device_lib/adb.py b/mobly/controllers/android_device_lib/adb.py
index 8b55b65..721dcc7 100644
--- a/mobly/controllers/android_device_lib/adb.py
+++ b/mobly/controllers/android_device_lib/adb.py
@@ -33,7 +33,9 @@ ADB_ROOT_RETRY_ATTEMPTS = 3
ADB_ROOT_RETRY_ATTEMPT_INTERVAL_SEC = 10
# Qualified class name of the default instrumentation test runner.
-DEFAULT_INSTRUMENTATION_RUNNER = 'com.android.common.support.test.runner.AndroidJUnitRunner'
+DEFAULT_INSTRUMENTATION_RUNNER = (
+ 'com.android.common.support.test.runner.AndroidJUnitRunner'
+)
# `adb shell getprop` can take surprisingly long, when the device is a
# networked virtual device.
@@ -43,7 +45,8 @@ DEFAULT_GETPROPS_RETRY_SLEEP_SEC = 1
# The regex pattern indicating the `adb connect` command did not fail.
PATTERN_ADB_CONNECT_SUCCESS = re.compile(
- r'^connected to .*|^already connected to .*')
+ r'^connected to .*|^already connected to .*'
+)
class Error(Exception):
@@ -72,9 +75,12 @@ class AdbError(Error):
self.serial = serial
def __str__(self):
- return ('Error executing adb cmd "%s". ret: %d, stdout: %s, stderr: %s') % (
- utils.cli_cmd_to_string(
- self.cmd), self.ret_code, self.stdout, self.stderr)
+ return 'Error executing adb cmd "%s". ret: %d, stdout: %s, stderr: %s' % (
+ utils.cli_cmd_to_string(self.cmd),
+ self.ret_code,
+ self.stdout,
+ self.stderr,
+ )
class AdbTimeoutError(Error):
@@ -96,7 +102,9 @@ class AdbTimeoutError(Error):
def __str__(self):
return 'Timed out executing command "%s" after %ss.' % (
- utils.cli_cmd_to_string(self.cmd), self.timeout)
+ utils.cli_cmd_to_string(self.cmd),
+ self.timeout,
+ )
def is_adb_available():
@@ -190,16 +198,19 @@ class AdbProxy:
if stderr:
stderr.write(err)
- logging.debug('cmd: %s, stdout: %s, stderr: %s, ret: %s',
- utils.cli_cmd_to_string(args), out, err, ret)
+ logging.debug(
+ 'cmd: %s, stdout: %s, stderr: %s, ret: %s',
+ utils.cli_cmd_to_string(args),
+ out,
+ err,
+ ret,
+ )
if ret == 0:
return out
else:
- raise AdbError(cmd=args,
- stdout=out,
- stderr=err,
- ret_code=ret,
- serial=self.serial)
+ raise AdbError(
+ cmd=args, stdout=out, stderr=err, ret_code=ret, serial=self.serial
+ )
def _execute_and_process_stdout(self, args, shell, handler) -> bytes:
"""Executes adb commands and processes the stdout with a handler.
@@ -217,11 +228,13 @@ class AdbProxy:
Raises:
AdbError: The adb command exit code is not 0.
"""
- proc = subprocess.Popen(args,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=shell,
- bufsize=1)
+ proc = subprocess.Popen(
+ args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=shell,
+ bufsize=1,
+ )
out = '[elided, processed via handler]'
try:
# Even if the process dies, stdout.readline still works
@@ -241,8 +254,13 @@ class AdbProxy:
handler(line)
ret = proc.returncode
- logging.debug('cmd: %s, stdout: %s, stderr: %s, ret: %s',
- utils.cli_cmd_to_string(args), out, err, ret)
+ logging.debug(
+ 'cmd: %s, stdout: %s, stderr: %s, ret: %s',
+ utils.cli_cmd_to_string(args),
+ out,
+ err,
+ ret,
+ )
if ret == 0:
return err
else:
@@ -291,12 +309,13 @@ class AdbProxy:
out = self._exec_cmd(adb_cmd, shell=shell, timeout=timeout, stderr=stderr)
return out
- def _execute_adb_and_process_stdout(self, name, args, shell,
- handler) -> bytes:
+ def _execute_adb_and_process_stdout(
+ self, name, args, shell, handler
+ ) -> bytes:
adb_cmd = self._construct_adb_cmd(name, args, shell=shell)
- err = self._execute_and_process_stdout(adb_cmd,
- shell=shell,
- handler=handler)
+ err = self._execute_and_process_stdout(
+ adb_cmd, shell=shell, handler=handler
+ )
return err
def _parse_getprop_output(self, output):
@@ -357,16 +376,13 @@ class AdbProxy:
Raises:
AdbError: if the connection failed.
"""
- stdout = self._exec_adb_cmd('connect',
- address,
- shell=False,
- timeout=None,
- stderr=None)
+ stdout = self._exec_adb_cmd(
+ 'connect', address, shell=False, timeout=None, stderr=None
+ )
if PATTERN_ADB_CONNECT_SUCCESS.match(stdout.decode('utf-8')) is None:
- raise AdbError(cmd=f'connect {address}',
- stdout=stdout,
- stderr='',
- ret_code=0)
+ raise AdbError(
+ cmd=f'connect {address}', stdout=stdout, stderr='', ret_code=0
+ )
return stdout
def getprop(self, prop_name, timeout=DEFAULT_GETPROP_TIMEOUT_SEC):
@@ -383,8 +399,11 @@ class AdbProxy:
A string that is the value of the property, or None if the property
doesn't exist.
"""
- return self.shell(['getprop', prop_name],
- timeout=timeout).decode('utf-8').strip()
+ return (
+ self.shell(['getprop', prop_name], timeout=timeout)
+ .decode('utf-8')
+ .strip()
+ )
def getprops(self, prop_names):
"""Get multiple properties of the device.
@@ -436,17 +455,19 @@ class AdbProxy:
def forward(self, args=None, shell=False) -> bytes:
with ADB_PORT_LOCK:
- return self._exec_adb_cmd('forward',
- args,
- shell,
- timeout=None,
- stderr=None)
-
- def instrument(self,
- package,
- options=None,
- runner=None,
- handler=None) -> bytes:
+ return self._exec_adb_cmd(
+ 'forward', args, shell, timeout=None, stderr=None
+ )
+
+ def reverse(self, args=None, shell=False) -> bytes:
+ with ADB_PORT_LOCK:
+ return self._exec_adb_cmd(
+ 'reverse', args, shell, timeout=None, stderr=None
+ )
+
+ def instrument(
+ self, package, options=None, runner=None, handler=None
+ ) -> bytes:
"""Runs an instrumentation command on the device.
This is a convenience wrapper to avoid parameter formatting.
@@ -487,21 +508,28 @@ class AdbProxy:
options_list.append('-e %s %s' % (option_key, option_value))
options_string = ' '.join(options_list)
- instrumentation_command = 'am instrument -r -w %s %s/%s' % (options_string,
- package, runner)
- logging.info('AndroidDevice|%s: Executing adb shell %s', self.serial,
- instrumentation_command)
+ instrumentation_command = 'am instrument -r -w %s %s/%s' % (
+ options_string,
+ package,
+ runner,
+ )
+ logging.info(
+ 'AndroidDevice|%s: Executing adb shell %s',
+ self.serial,
+ instrumentation_command,
+ )
if handler is None:
- return self._exec_adb_cmd('shell',
- instrumentation_command,
- shell=False,
- timeout=None,
- stderr=None)
+ return self._exec_adb_cmd(
+ 'shell',
+ instrumentation_command,
+ shell=False,
+ timeout=None,
+ stderr=None,
+ )
else:
- return self._execute_adb_and_process_stdout('shell',
- instrumentation_command,
- shell=False,
- handler=handler)
+ return self._execute_adb_and_process_stdout(
+ 'shell', instrumentation_command, shell=False, handler=handler
+ )
def root(self) -> bytes:
"""Enables ADB root mode on the device.
@@ -520,16 +548,18 @@ class AdbProxy:
retry_interval = ADB_ROOT_RETRY_ATTEMPT_INTERVAL_SEC
for attempt in range(ADB_ROOT_RETRY_ATTEMPTS):
try:
- return self._exec_adb_cmd('root',
- args=None,
- shell=False,
- timeout=None,
- stderr=None)
+ return self._exec_adb_cmd(
+ 'root', args=None, shell=False, timeout=None, stderr=None
+ )
except AdbError as e:
if attempt + 1 < ADB_ROOT_RETRY_ATTEMPTS:
- logging.debug('Retry the command "%s" since Error "%s" occurred.' %
- (utils.cli_cmd_to_string(
- e.cmd), e.stderr.decode('utf-8').strip()))
+ logging.debug(
+ 'Retry the command "%s" since Error "%s" occurred.'
+ % (
+ utils.cli_cmd_to_string(e.cmd),
+ e.stderr.decode('utf-8').strip(),
+ )
+ )
# Buffer between "adb root" commands.
time.sleep(retry_interval)
retry_interval *= 2
@@ -537,7 +567,6 @@ class AdbProxy:
raise e
def __getattr__(self, name):
-
def adb_call(args=None, shell=False, timeout=None, stderr=None) -> bytes:
"""Wrapper for an ADB command.
@@ -554,10 +583,8 @@ class AdbProxy:
Returns:
The output of the adb command run if exit code is 0.
"""
- return self._exec_adb_cmd(name,
- args,
- shell=shell,
- timeout=timeout,
- stderr=stderr)
+ return self._exec_adb_cmd(
+ name, args, shell=shell, timeout=timeout, stderr=stderr
+ )
return adb_call