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:
parent
391b0b01fc
commit
b17ae78d6b
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user