Read stdout and stderr in Traceur PerfettoUtils.traceStop.

In the bug referenced, the exec initiated process in traceStop appears
to hang, causing the saving trace notification to stick around
indefinitely. A common cause for this type of hang when using
RUNTIME.exec is the stdout or stderr pipe becoming full. This change
uses the AtraceUtils Logger class to constantly read from this pipes.

Bug: 137055264
Test: Built and took a trace, verified the trace saved correctly and
stderr was redirected to logcat.

Change-Id: I9187106a462fb663a566ea764a96d4763c47ae92
Merged-In: Iccd95ea73b6af2ec0f524f135d62189dc99a6d06
diff --git a/src/com/android/traceur/AtraceUtils.java b/src/com/android/traceur/AtraceUtils.java
index e5cb554..788ff9b 100644
--- a/src/com/android/traceur/AtraceUtils.java
+++ b/src/com/android/traceur/AtraceUtils.java
@@ -34,6 +34,8 @@
 import java.util.List;
 import java.util.TreeMap;
 
+import com.android.traceur.TraceUtils.Streamer;
+
 /**
  * Utility functions for calling atrace
  */
@@ -103,7 +105,7 @@
                 return false;
             }
 
-            Process ps = TraceUtils.exec("ps -AT");
+            Process ps = TraceUtils.exec("ps -AT", null, false);
 
             new Streamer("atraceDump:ps:stdout",
                     ps.getInputStream(), new FileOutputStream(outFile, true /* append */));
@@ -159,9 +161,8 @@
 
         Log.v(TAG, "Listing tags: " + cmd);
         try {
-            Process atrace = TraceUtils.exec(cmd);
+            Process atrace = TraceUtils.exec(cmd, null, false);
 
-            new Logger("atraceListCat:stderr", atrace.getErrorStream());
             BufferedReader stdout = new BufferedReader(
                     new InputStreamReader(atrace.getInputStream()));
 
@@ -182,83 +183,4 @@
             throw new RuntimeException(e);
         }
     }
-
-
-    /**
-     * Streams data from an InputStream to an OutputStream
-     */
-    private static class Streamer {
-        private boolean mDone;
-
-        Streamer(final String tag, final InputStream in, final OutputStream out) {
-            new Thread(tag) {
-                @Override
-                public void run() {
-                    int read;
-                    byte[] buf = new byte[2 << 10];
-                    try {
-                        while ((read = in.read(buf)) != -1) {
-                            out.write(buf, 0, read);
-                        }
-                    } catch (IOException e) {
-                        Log.e(TAG, "Error while streaming " + tag);
-                    } finally {
-                        try {
-                            out.close();
-                        } catch (IOException e) {
-                            // Welp.
-                        }
-                        synchronized (Streamer.this) {
-                            mDone = true;
-                            Streamer.this.notify();
-                        }
-                    }
-                }
-            }.start();
-        }
-
-        synchronized boolean isDone() {
-            return mDone;
-        }
-
-        synchronized void waitForDone() {
-            while (!isDone()) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                }
-            }
-        }
-    }
-
-    /**
-     * Streams data from an InputStream to an OutputStream
-     */
-    private static class Logger {
-
-        Logger(final String tag, final InputStream in) {
-            new Thread(tag) {
-                @Override
-                public void run() {
-                    int read;
-                    String line;
-                    BufferedReader r = new BufferedReader(new InputStreamReader(in));
-                    try {
-                        while ((line = r.readLine()) != null) {
-                            Log.e(TAG, tag + ": " + line);
-                        }
-                    } catch (IOException e) {
-                        Log.e(TAG, "Error while streaming " + tag);
-                    } finally {
-                        try {
-                            r.close();
-                        } catch (IOException e) {
-                            // Welp.
-                        }
-                    }
-                }
-            }.start();
-        }
-    }
 }
diff --git a/src/com/android/traceur/TraceUtils.java b/src/com/android/traceur/TraceUtils.java
index bb27a9f..364557e 100644
--- a/src/com/android/traceur/TraceUtils.java
+++ b/src/com/android/traceur/TraceUtils.java
@@ -21,8 +21,12 @@
 import android.os.FileUtils;
 import android.util.Log;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -105,13 +109,23 @@
     }
 
     public static Process exec(String cmd, String tmpdir) throws IOException {
+        return exec(cmd, tmpdir, true);
+    }
+
+    public static Process exec(String cmd, String tmpdir, boolean logOutput) throws IOException {
         String[] cmdarray = {"sh", "-c", cmd};
         String[] envp = {"TMPDIR=" + tmpdir};
         envp = tmpdir == null ? null : envp;
 
         Log.v(TAG, "exec: " + Arrays.toString(envp) + " " + Arrays.toString(cmdarray));
 
-        return RUNTIME.exec(cmdarray, envp);
+        Process process = RUNTIME.exec(cmdarray, envp);
+        new Logger("traceService:stderr", process.getErrorStream());
+        if (logOutput) {
+            new Logger("traceService:stdout", process.getInputStream());
+        }
+
+        return process;
     }
 
     public static String getOutputFilename() {
@@ -139,4 +153,81 @@
         }.execute();
     }
 
+    /**
+     * Streams data from an InputStream to an OutputStream
+     */
+    static class Streamer {
+        private boolean mDone;
+
+        Streamer(final String tag, final InputStream in, final OutputStream out) {
+            new Thread(tag) {
+                @Override
+                public void run() {
+                    int read;
+                    byte[] buf = new byte[2 << 10];
+                    try {
+                        while ((read = in.read(buf)) != -1) {
+                            out.write(buf, 0, read);
+                        }
+                    } catch (IOException e) {
+                        Log.e(TAG, "Error while streaming " + tag);
+                    } finally {
+                        try {
+                            out.close();
+                        } catch (IOException e) {
+                            // Welp.
+                        }
+                        synchronized (Streamer.this) {
+                            mDone = true;
+                            Streamer.this.notify();
+                        }
+                    }
+                }
+            }.start();
+        }
+
+        synchronized boolean isDone() {
+            return mDone;
+        }
+
+        synchronized void waitForDone() {
+            while (!isDone()) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+            }
+        }
+    }
+
+    /**
+     * Streams data from an InputStream to an OutputStream
+     */
+    private static class Logger {
+
+        Logger(final String tag, final InputStream in) {
+            new Thread(tag) {
+                @Override
+                public void run() {
+                    int read;
+                    String line;
+                    BufferedReader r = new BufferedReader(new InputStreamReader(in));
+                    try {
+                        while ((line = r.readLine()) != null) {
+                            Log.e(TAG, tag + ": " + line);
+                        }
+                    } catch (IOException e) {
+                        Log.e(TAG, "Error while streaming " + tag);
+                    } finally {
+                        try {
+                            r.close();
+                        } catch (IOException e) {
+                            // Welp.
+                        }
+                    }
+                }
+            }.start();
+        }
+    }
 }