1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-01-31 10:10:46 +00:00

android: Handle variation in ADB behaviour

On older combinations of ADB/Android versions, the adb host command always
exits with 0 if it was able to run the command on the target, even if the
command failed (https://code.google.com/p/android/issues/detail?id=3254).

When we need the target's exit code (check_exit_code=True), we currently work
around this behaviour by echoing the target's exit code after the command and
parsing it out of the output.

The ADB behaviour is now "fixed" on newer versions with newer Androids (It's not
clear which versions these are and it appears that different builds of ADB with
the same version number differ in this respect). For those version combinations
adb_shell will currently raise a CalledProcessError when check_exit_code=False
and the target command fails.

So lets now use the "echo $?" trick whether or not we need the exit code.

Fixes https://github.com/ARM-software/devlib/issues/85
This commit is contained in:
Brendan Jackman 2017-01-25 12:06:38 +00:00
parent 76c4a725ed
commit 44fe0370f8

View File

@ -335,13 +335,15 @@ def adb_shell(device, command, timeout=None, check_exit_code=False,
if as_root: if as_root:
command = 'echo \'{}\' | su'.format(escape_single_quotes(command)) command = 'echo \'{}\' | su'.format(escape_single_quotes(command))
device_part = ['-s', device] if device else [] device_part = ['-s', device] if device else []
device_string = ' {} {}'.format(*device_part) if device_part else ''
full_command = 'adb{} shell "{}"'.format(device_string, # On older combinations of ADB/Android versions, the adb host command always
escape_double_quotes(command)) # exits with 0 if it was able to run the command on the target, even if the
logger.debug(full_command) # command failed (https://code.google.com/p/android/issues/detail?id=3254).
if check_exit_code: # Homogenise this behaviour by running the command then echoing the exit
# code.
adb_shell_command = '({}); echo \"\n$?\"'.format(command) adb_shell_command = '({}); echo \"\n$?\"'.format(command)
actual_command = ['adb'] + device_part + ['shell', adb_shell_command] actual_command = ['adb'] + device_part + ['shell', adb_shell_command]
logger.debug('adb {} shell {}'.format(' '.join(device_part), command))
raw_output, error = check_output(actual_command, timeout, shell=False) raw_output, error = check_output(actual_command, timeout, shell=False)
if raw_output: if raw_output:
try: try:
@ -353,11 +355,13 @@ def adb_shell(device, command, timeout=None, check_exit_code=False,
exit_code = '969696' # just because exit_code = '969696' # just because
output = '' output = ''
if check_exit_code:
exit_code = exit_code.strip() exit_code = exit_code.strip()
if exit_code.isdigit(): if exit_code.isdigit():
if int(exit_code): if int(exit_code):
message = 'Got exit code {}\nfrom: {}\nSTDOUT: {}\nSTDERR: {}' message = ('Got exit code {}\nfrom target command: {}\n'
raise TargetError(message.format(exit_code, full_command, output, error)) 'STDOUT: {}\nSTDERR: {}')
raise TargetError(message.format(exit_code, command, output, error))
elif AM_START_ERROR.findall(output): elif AM_START_ERROR.findall(output):
message = 'Could not start activity; got the following:' message = 'Could not start activity; got the following:'
message += '\n{}'.format(AM_START_ERROR.findall(output)[0]) message += '\n{}'.format(AM_START_ERROR.findall(output)[0])
@ -370,8 +374,7 @@ def adb_shell(device, command, timeout=None, check_exit_code=False,
message = 'adb has returned early; did not get an exit code. '\ message = 'adb has returned early; did not get an exit code. '\
'Was kill-server invoked?' 'Was kill-server invoked?'
raise TargetError(message) raise TargetError(message)
else: # do not check exit code
output, _ = check_output(full_command, timeout, shell=True)
return output return output