1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-02-21 12:28:44 +00:00

adb_shell: Now handles return codes from ADB

As of ADB 1.0.35/Android N, it will return the exit code of the command that it runs
This code handles this scenario as before WA treated a return code from ADB as an
error with ADB.
This commit is contained in:
Sebastian Goscik 2016-04-04 10:47:40 +01:00
parent 391b0b01fc
commit b17ae78d6b
2 changed files with 31 additions and 6 deletions

View File

@ -26,7 +26,9 @@ import logging
import re import re
from wlauto.exceptions import DeviceError, ConfigError, HostError, WAError from wlauto.exceptions import DeviceError, ConfigError, HostError, WAError
from wlauto.utils.misc import check_output, escape_single_quotes, escape_double_quotes, get_null from wlauto.utils.misc import (check_output, escape_single_quotes,
escape_double_quotes, get_null,
CalledProcessErrorWithStderr)
MAX_TRIES = 5 MAX_TRIES = 5
@ -266,7 +268,7 @@ am_start_error = re.compile(r"Error: Activity class {[\w|.|/]*} does not exist")
def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False): # NOQA def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False): # NOQA
# pylint: disable=too-many-branches # pylint: disable=too-many-branches, too-many-locals, too-many-statements
_check_env() _check_env()
if as_root: if as_root:
command = 'echo \'{}\' | su'.format(escape_single_quotes(command)) command = 'echo \'{}\' | su'.format(escape_single_quotes(command))
@ -275,7 +277,15 @@ def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=Fals
logger.debug(full_command) logger.debug(full_command)
if check_exit_code: if check_exit_code:
actual_command = "adb {} shell '({}); echo; echo $?'".format(device_string, escape_single_quotes(command)) actual_command = "adb {} shell '({}); echo; echo $?'".format(device_string, escape_single_quotes(command))
raw_output, error = check_output(actual_command, timeout, shell=True) try:
raw_output, error = check_output(actual_command, timeout, shell=True)
except CalledProcessErrorWithStderr as e:
raw_output = e.output
error = e.error
exit_code = e.returncode
if exit_code == 1:
logger.debug("Exit code 1 could be either the return code of the command or mean ADB failed")
if raw_output: if raw_output:
if raw_output.endswith('\r\n'): if raw_output.endswith('\r\n'):
newline = '\r\n' newline = '\r\n'
@ -311,7 +321,14 @@ def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=Fals
else: else:
raise DeviceError('adb has returned early; did not get an exit code. Was kill-server invoked?') raise DeviceError('adb has returned early; did not get an exit code. Was kill-server invoked?')
else: # do not check exit code else: # do not check exit code
output, _ = check_output(full_command, timeout, shell=True) try:
output, _ = check_output(full_command, timeout, shell=True)
except CalledProcessErrorWithStderr as e:
output = e.output
error = e.error
exit_code = e.returncode
if e.returncode == 1:
logger.debug("Got Exit code 1, could be either the return code of the command or mean ADB failed")
return output return output

View File

@ -27,12 +27,13 @@ import imp
import string import string
import threading import threading
import signal import signal
import subprocess
import pkgutil import pkgutil
import traceback import traceback
import logging import logging
import random import random
import hashlib import hashlib
import subprocess
from subprocess import CalledProcessError
from datetime import datetime, timedelta from datetime import datetime, timedelta
from operator import mul, itemgetter from operator import mul, itemgetter
from StringIO import StringIO from StringIO import StringIO
@ -81,6 +82,13 @@ class TimeoutError(Exception):
return '\n'.join([self.message, 'OUTPUT:', self.output or '']) return '\n'.join([self.message, 'OUTPUT:', self.output or ''])
class CalledProcessErrorWithStderr(CalledProcessError):
def __init__(self, *args, **kwargs):
self.error = kwargs.pop("error")
super(CalledProcessErrorWithStderr, self).__init__(*args, **kwargs)
def check_output(command, timeout=None, ignore=None, **kwargs): def check_output(command, timeout=None, ignore=None, **kwargs):
"""This is a version of subprocess.check_output that adds a timeout parameter to kill """This is a version of subprocess.check_output that adds a timeout parameter to kill
the subprocess if it does not return within the specified time.""" the subprocess if it does not return within the specified time."""
@ -120,7 +128,7 @@ def check_output(command, timeout=None, ignore=None, **kwargs):
if retcode == -9: # killed, assume due to timeout callback if retcode == -9: # killed, assume due to timeout callback
raise TimeoutError(command, output='\n'.join([output, error])) raise TimeoutError(command, output='\n'.join([output, error]))
elif ignore != 'all' and retcode not in ignore: elif ignore != 'all' and retcode not in ignore:
raise subprocess.CalledProcessError(retcode, command, output='\n'.join([output, error])) raise CalledProcessErrorWithStderr(retcode, command, output=output, error=error)
return output, error return output, error