Merge "Avoid unavailable APIs in ShellUtil" into main am: 137f2d754c

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/3556284

Change-Id: I7ae1aab33a049accd408b12328afa6e9d07120e2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
index 60285a8..1db5765 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
@@ -36,6 +36,7 @@
 import android.net.wifi.WifiManager
 import android.os.Build
 import android.os.ParcelFileDescriptor
+import android.os.ParcelFileDescriptor.AutoCloseInputStream
 import android.telephony.TelephonyManager
 import android.telephony.TelephonyManager.SIM_STATE_UNKNOWN
 import android.util.Log
@@ -46,6 +47,7 @@
 import java.io.CharArrayWriter
 import java.io.File
 import java.io.FileReader
+import java.io.InputStream
 import java.io.OutputStream
 import java.io.OutputStreamWriter
 import java.io.PrintWriter
@@ -438,13 +440,44 @@
      * <p>The output will be collected immediately, and exported to a test artifact file when the
      * test ends.
      * @param cmd The command to run. Stdout of the command will be collected.
-     * @param shell The shell to run the command in.
+     * @param shell The shell to run the command in, for example "sh".
+     * @param exceptionContext An exception to write a stacktrace to the dump for context.
+     */
+    @RequiresApi(Build.VERSION_CODES.S)
+    fun collectCommandOutput(
+        cmd: String,
+        shell: String,
+        exceptionContext: Throwable? = null
+    ) = collectCommandOutput(cmd, exceptionContext) { c, outputProcessor ->
+        runCommandInShell(c, shell, outputProcessor)
+    }
+
+    /**
+     * Add the output of a command to the test data dump.
+     *
+     * <p>The output will be collected immediately, and exported to a test artifact file when the
+     * test ends.
+     *
+     * <p>Note this does not support shell pipes, redirections, or quoted arguments. See the S+
+     * overload if that is needed.
+     * @param cmd The command to run. Stdout of the command will be collected.
      * @param exceptionContext An exception to write a stacktrace to the dump for context.
      */
     fun collectCommandOutput(
         cmd: String,
-        shell: String = "sh",
         exceptionContext: Throwable? = null
+    ) = collectCommandOutput(cmd, exceptionContext) { c, outputProcessor ->
+        AutoCloseInputStream(
+            InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand(c)
+        ).use {
+            outputProcessor(it)
+        }
+    }
+
+    private fun collectCommandOutput(
+        cmd: String,
+        exceptionContext: Throwable? = null,
+        commandRunner: (String, (InputStream) -> Unit) -> Unit
     ) {
         Log.i(TAG, "Collecting '$cmd' for test artifacts")
         PrintWriter(buffer).let {
@@ -453,7 +486,7 @@
             it.flush()
         }
 
-        runCommandInShell(cmd, shell) { stdout, _ ->
+        commandRunner(cmd) { stdout ->
             stdout.copyTo(buffer)
         }
     }
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt b/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt
index fadc2ab..2b74036 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ShellUtil.kt
@@ -19,8 +19,10 @@
 package com.android.testutils
 
 import android.app.UiAutomation
+import android.os.Build
 import android.os.ParcelFileDescriptor.AutoCloseInputStream
 import android.os.ParcelFileDescriptor.AutoCloseOutputStream
+import androidx.annotation.RequiresApi
 import androidx.test.platform.app.InstrumentationRegistry
 import java.io.InputStream
 
@@ -37,18 +39,17 @@
  *                        when this function returns.
  * @return Result of [outputProcessor].
  */
+@RequiresApi(Build.VERSION_CODES.S) // executeShellCommandRw is 31+
 fun <T> runCommandInShell(
     cmd: String,
     shell: String = "sh",
-    outputProcessor: (InputStream, InputStream) -> T,
+    outputProcessor: (InputStream) -> T,
 ): T {
-    val (stdout, stdin, stderr) = InstrumentationRegistry.getInstrumentation().uiAutomation
-        .executeShellCommandRwe(shell)
+    val (stdout, stdin) = InstrumentationRegistry.getInstrumentation().uiAutomation
+        .executeShellCommandRw(shell)
     AutoCloseOutputStream(stdin).bufferedWriter().use { it.write(cmd) }
     AutoCloseInputStream(stdout).use { outStream ->
-        AutoCloseInputStream(stderr).use { errStream ->
-            return outputProcessor(outStream, errStream)
-        }
+        return outputProcessor(outStream)
     }
 }
 
@@ -57,10 +58,11 @@
  *
  * Overload of [runCommandInShell] that reads and returns stdout as String.
  */
+@RequiresApi(Build.VERSION_CODES.S)
 fun runCommandInShell(
     cmd: String,
     shell: String = "sh",
-) = runCommandInShell(cmd, shell) { stdout, _ ->
+) = runCommandInShell(cmd, shell) { stdout ->
     stdout.reader().use { it.readText() }
 }
 
@@ -70,6 +72,7 @@
  * This is generally only usable on devices on which [DeviceInfoUtils.isDebuggable] is true.
  * @see runCommandInShell
  */
+@RequiresApi(Build.VERSION_CODES.S)
 fun runCommandInRootShell(
     cmd: String
 ) = runCommandInShell(cmd, shell = "su root sh")