From 37eef461a6c610a58681c28c06139ce6b7a9d7de Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Mon, 29 Jul 2019 14:15:39 +0100 Subject: [PATCH 1/2] android/adb: Enable fall back for `su` command Commit 89c40fb switched from using `echo CMD | su` to `su -c CMD` however not all modern versions of `su` support this format. Automatically try and detect if the new style is supported when connecting and if not, fall back to the old implementation. --- devlib/utils/android.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/devlib/utils/android.py b/devlib/utils/android.py index 71907d807..cb31e4622 100755 --- a/devlib/utils/android.py +++ b/devlib/utils/android.py @@ -239,6 +239,7 @@ class AdbConnection(object): active_connections = defaultdict(int) default_timeout = 10 ls_command = 'ls' + su_cmd = 'su -c {}' @property def name(self): @@ -264,6 +265,7 @@ def _setup_ls(self): self.ls_command = 'ls' logger.debug("ls command is set to {}".format(self.ls_command)) + # pylint: disable=unused-argument def __init__(self, device=None, timeout=None, platform=None, adb_server=None): self.timeout = timeout if timeout is not None else self.default_timeout @@ -274,6 +276,7 @@ def __init__(self, device=None, timeout=None, platform=None, adb_server=None): adb_connect(self.device) AdbConnection.active_connections[self.device] += 1 self._setup_ls() + self._setup_su() def push(self, source, dest, timeout=None): if timeout is None: @@ -303,7 +306,7 @@ def execute(self, command, timeout=None, check_exit_code=False, as_root=False, strip_colors=True, will_succeed=False): try: return adb_shell(self.device, command, timeout, check_exit_code, - as_root, adb_server=self.adb_server) + as_root, adb_server=self.adb_server, su_cmd=self.su_cmd) except TargetStableError as e: if will_succeed: raise TargetTransientError(e) @@ -326,6 +329,18 @@ def cancel_running_command(self): pass + def _setup_su(self): + try: + # Try the new style of invoking `su` + self.execute('ls', timeout=self.timeout, as_root=True, + check_exit_code=True) + # If failure assume either old style or unrooted. Here we will assume + # old style and root status will be verified later. + except (TargetStableError, TargetTransientError, TimeoutError): + self.su_cmd = 'echo {} | su' + logger.debug("su command is set to {}".format(quote(self.su_cmd))) + + def fastboot_command(command, timeout=None, device=None): _check_env() target = '-s {}'.format(quote(device)) if device else '' @@ -423,7 +438,7 @@ def _ping(device): # pylint: disable=too-many-locals def adb_shell(device, command, timeout=None, check_exit_code=False, - as_root=False, adb_server=None): # NOQA + as_root=False, adb_server=None, su_cmd='su -c {}'): # NOQA _check_env() parts = ['adb'] if adb_server is not None: @@ -431,7 +446,7 @@ def adb_shell(device, command, timeout=None, check_exit_code=False, if device is not None: parts += ['-s', device] parts += ['shell', - command if not as_root else 'su -c {}'.format(quote(command))] + command if not as_root else su_cmd.format(quote(command))] logger.debug(' '.join(quote(part) for part in parts)) # On older combinations of ADB/Android versions, the adb host command always From 2ac4a1c443b2f8ef14a7962ba812454fde41c1c1 Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Tue, 30 Jul 2019 13:37:48 +0100 Subject: [PATCH 2/2] utils/android: Move private method to end of class --- devlib/utils/android.py | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/devlib/utils/android.py b/devlib/utils/android.py index cb31e4622..5a0c6d47a 100755 --- a/devlib/utils/android.py +++ b/devlib/utils/android.py @@ -245,27 +245,6 @@ class AdbConnection(object): def name(self): return self.device - # Again, we need to handle boards where the default output format from ls is - # single column *and* boards where the default output is multi-column. - # We need to do this purely because the '-1' option causes errors on older - # versions of the ls tool in Android pre-v7. - def _setup_ls(self): - command = "shell '(ls -1); echo \"\n$?\"'" - try: - output = adb_command(self.device, command, timeout=self.timeout, adb_server=self.adb_server) - except subprocess.CalledProcessError as e: - raise HostError( - 'Failed to set up ls command on Android device. Output:\n' - + e.output) - lines = output.splitlines() - retval = lines[-1].strip() - if int(retval) == 0: - self.ls_command = 'ls -1' - else: - self.ls_command = 'ls' - logger.debug("ls command is set to {}".format(self.ls_command)) - - # pylint: disable=unused-argument def __init__(self, device=None, timeout=None, platform=None, adb_server=None): self.timeout = timeout if timeout is not None else self.default_timeout @@ -328,6 +307,25 @@ def cancel_running_command(self): # before the next one can be issued. pass + # Again, we need to handle boards where the default output format from ls is + # single column *and* boards where the default output is multi-column. + # We need to do this purely because the '-1' option causes errors on older + # versions of the ls tool in Android pre-v7. + def _setup_ls(self): + command = "shell '(ls -1); echo \"\n$?\"'" + try: + output = adb_command(self.device, command, timeout=self.timeout, adb_server=self.adb_server) + except subprocess.CalledProcessError as e: + raise HostError( + 'Failed to set up ls command on Android device. Output:\n' + + e.output) + lines = output.splitlines() + retval = lines[-1].strip() + if int(retval) == 0: + self.ls_command = 'ls -1' + else: + self.ls_command = 'ls' + logger.debug("ls command is set to {}".format(self.ls_command)) def _setup_su(self): try: