Cleanup devicelab framework duplicate (#59046)

* combine forwardStandardStreams

* combine exec and eval
diff --git a/dev/devicelab/lib/framework/utils.dart b/dev/devicelab/lib/framework/utils.dart
index 5fbc036..41383ca 100644
--- a/dev/devicelab/lib/framework/utils.dart
+++ b/dev/devicelab/lib/framework/utils.dart
@@ -324,8 +324,39 @@
   bool canFail = false, // as in, whether failures are ok. False means that they are fatal.
   String workingDirectory,
 }) async {
-  final Process process = await startProcess(executable, arguments, environment: environment, workingDirectory: workingDirectory);
-  await forwardStandardStreams(process);
+  return _execute(
+    executable,
+    arguments,
+    environment: environment,
+    canFail : canFail,
+    workingDirectory: workingDirectory,
+  );
+}
+
+Future<int> _execute(
+  String executable,
+  List<String> arguments, {
+  Map<String, String> environment,
+  bool canFail = false, // as in, whether failures are ok. False means that they are fatal.
+  String workingDirectory,
+  StringBuffer output, // if not null, the stdout will be written here
+  StringBuffer stderr, // if not null, the stderr will be written here
+  bool printStdout = true,
+  bool printStderr = true,
+}) async {
+  final Process process = await startProcess(
+    executable,
+    arguments,
+    environment: environment,
+    workingDirectory: workingDirectory,
+  );
+  await forwardStandardStreams(
+    process,
+    output: output,
+    stderr: stderr,
+    printStdout: printStdout,
+    printStderr: printStderr,
+    );
   final int exitCode = await process.exitCode;
 
   if (exitCode != 0 && !canFail)
@@ -335,26 +366,42 @@
 }
 
 /// Forwards standard out and standard error from [process] to this process'
-/// respective outputs.
+/// respective outputs. Also writes stdout to [output] and stderr to [stderr]
+/// if they are not null.
 ///
 /// Returns a future that completes when both out and error streams a closed.
-Future<void> forwardStandardStreams(Process process) {
+Future<void> forwardStandardStreams(
+  Process process, {
+  StringBuffer output,
+  StringBuffer stderr,
+  bool printStdout = true,
+  bool printStderr = true,
+  }) {
   final Completer<void> stdoutDone = Completer<void>();
   final Completer<void> stderrDone = Completer<void>();
   process.stdout
       .transform<String>(utf8.decoder)
       .transform<String>(const LineSplitter())
       .listen((String line) {
-        print('stdout: $line');
+        if (printStdout) {
+          print('stdout: $line');
+        }
+        output?.writeln(line);
       }, onDone: () { stdoutDone.complete(); });
   process.stderr
       .transform<String>(utf8.decoder)
       .transform<String>(const LineSplitter())
       .listen((String line) {
-        print('stderr: $line');
+        if (printStderr) {
+          print('stderr: $line');
+        }
+        stderr?.writeln(line);
       }, onDone: () { stderrDone.complete(); });
 
-  return Future.wait<void>(<Future<void>>[stdoutDone.future, stderrDone.future]);
+  return Future.wait<void>(<Future<void>>[
+    stdoutDone.future,
+    stderrDone.future,
+  ]);
 }
 
 /// Executes a command and returns its standard output as a String.
@@ -370,36 +417,18 @@
   bool printStdout = true,
   bool printStderr = true,
 }) async {
-  final Process process = await startProcess(executable, arguments, environment: environment, workingDirectory: workingDirectory);
-
   final StringBuffer output = StringBuffer();
-  final Completer<void> stdoutDone = Completer<void>();
-  final Completer<void> stderrDone = Completer<void>();
-  process.stdout
-      .transform<String>(utf8.decoder)
-      .transform<String>(const LineSplitter())
-      .listen((String line) {
-        if (printStdout) {
-          print('stdout: $line');
-        }
-        output.writeln(line);
-      }, onDone: () { stdoutDone.complete(); });
-  process.stderr
-      .transform<String>(utf8.decoder)
-      .transform<String>(const LineSplitter())
-      .listen((String line) {
-        if (printStderr) {
-          print('stderr: $line');
-        }
-        stderr?.writeln(line);
-      }, onDone: () { stderrDone.complete(); });
-
-  await Future.wait<void>(<Future<void>>[stdoutDone.future, stderrDone.future]);
-  final int exitCode = await process.exitCode;
-
-  if (exitCode != 0 && !canFail)
-    fail('Executable "$executable" failed with exit code $exitCode.');
-
+  await _execute(
+    executable,
+    arguments,
+    environment: environment,
+    canFail: canFail,
+    workingDirectory: workingDirectory,
+    output: output,
+    stderr: stderr,
+    printStdout: printStdout,
+    printStderr: printStderr,
+  );
   return output.toString().trimRight();
 }