Merge "Avoid unavailable APIs in ShellUtil" into main

This commit is contained in:
Treehugger Robot 2025-03-23 19:33:44 -07:00 • committed by Gerrit Code Review
commit 137f2d754c
2 changed files with 46 additions and 10 deletions

View file

@ -36,6 +36,7 @@ import android.net.wifi.WifiInfo
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.ByteArrayOutputStream
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 @@ class ConnectivityDiagnosticsCollector : BaseMetricListener() {
* <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 @@ class ConnectivityDiagnosticsCollector : BaseMetricListener() {
it.flush()
}
runCommandInShell(cmd, shell) { stdout, _ ->
commandRunner(cmd) { stdout ->
stdout.copyTo(buffer)
}
}

View file

@ -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 @@ import java.io.InputStream
* 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 @@ fun <T> runCommandInShell(
*
* 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 @@ fun runCommandInShell(
* 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")