From 0d798f1c4f9e97707ad376111d3478941a192c32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= <pierre-clement.tosi@arm.com>
Date: Tue, 14 May 2019 12:12:20 +0100
Subject: [PATCH] utils.adb_shell: Improve stability (Py3)

Move from pipes.quote (private) to shlex.quote (Py3.3+ standard).

Make tests of inputs against None (their default value) instead of based
on their truthiness.

Improve logging through quoted commands (runnable as-is, less confusing).

Make the command-building process straightforward for readability and
maintainability.
---
 devlib/utils/android.py | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/devlib/utils/android.py b/devlib/utils/android.py
index 1b1c146..dd8c5ed 100755
--- a/devlib/utils/android.py
+++ b/devlib/utils/android.py
@@ -31,7 +31,10 @@ import pexpect
 import xml.etree.ElementTree
 import zipfile
 
-from pipes import quote
+try:
+    from shlex import quote
+except ImportError:
+    from pipes import quote
 
 from devlib.exception import TargetTransientError, TargetStableError, HostError
 from devlib.utils.misc import check_output, which, ABI_MAP
@@ -422,23 +425,23 @@ def _ping(device):
 def adb_shell(device, command, timeout=None, check_exit_code=False,
               as_root=False, adb_server=None):  # NOQA
     _check_env()
-    if as_root:
-        command = 'echo {} | su'.format(quote(command))
-    device_part = []
-    if adb_server:
-        device_part = ['-H', adb_server]
-    device_part += ['-s', device] if device else []
+    parts = ['adb']
+    if adb_server is not None:
+        parts += ['-H', adb_server]
+    if device is not None:
+        parts += ['-s', device]
+    parts += ['shell',
+              command if not as_root else 'echo {} | su'.format(quote(command))]
 
+    logger.debug(' '.join(quote(part) for part in parts))
     # 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).
     # Homogenise this behaviour by running the command then echoing the exit
     # code.
-    adb_shell_command = '({}); echo \"\n$?\"'.format(command)
-    actual_command = ['adb'] + device_part + ['shell', adb_shell_command]
-    logger.debug('adb {} shell {}'.format(' '.join(device_part), command))
+    parts[-1] += ' ; echo "\n$?"'
     try:
-        raw_output, _ = check_output(actual_command, timeout, shell=False, combined_output=True)
+        raw_output, _ = check_output(parts, timeout, shell=False, combined_output=True)
     except subprocess.CalledProcessError as e:
         raise TargetStableError(str(e))