Merge "Statsd TestDrive tool: Write output to stdout. Also: Option for less verbose output." into rvc-dev
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
index 8ac251e..a97f132 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
@@ -25,6 +25,7 @@
 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
 import com.android.internal.os.StatsdConfigProto.TimeUnit;
 import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog;
 import com.android.os.StatsLog.ConfigMetricsReport;
 import com.android.os.StatsLog.ConfigMetricsReportList;
 import com.android.os.StatsLog.StatsLogReport;
@@ -78,11 +79,12 @@
 
     @VisibleForTesting
     String mDeviceSerial = null;
+    @VisibleForTesting
+    Dumper mDumper = new BasicDumper();
 
     public static void main(String[] args) {
         final Configuration configuration = new Configuration();
-
-        TestDrive testDrive = new TestDrive();
+        final TestDrive testDrive = new TestDrive();
         Utils.setUpLogger(LOGGER, false);
 
         if (!testDrive.processArgs(configuration, args,
@@ -94,7 +96,7 @@
                 configuration.createConfig(), configuration.hasPulledAtoms(),
                 configuration.hasPushedAtoms());
         if (reports != null) {
-            configuration.dumpMetrics(reports);
+            configuration.dumpMetrics(reports, testDrive.mDumper);
         }
     }
 
@@ -116,6 +118,9 @@
             if (remaining_args >= 2 && arg.equals("-one")) {
                 LOGGER.info("Creating one event metric to catch all pushed atoms.");
                 configuration.mOnePushedAtomEvent = true;
+            } else if (remaining_args >= 2 && arg.equals("-terse")) {
+                LOGGER.info("Terse output format.");
+                mDumper = new TerseDumper();
             } else if (remaining_args >= 3 && arg.equals("-p")) {
                 configuration.mAdditionalAllowedPackage = args[++first_arg];
             } else if (remaining_args >= 3 && arg.equals("-s")) {
@@ -198,12 +203,13 @@
         String mAdditionalAllowedPackage = null;
         private final Set<Long> mTrackedMetrics = new HashSet<>();
 
-        private void dumpMetrics(ConfigMetricsReportList reportList) {
+        private void dumpMetrics(ConfigMetricsReportList reportList, Dumper dumper) {
             // We may get multiple reports. Take the last one.
             ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1);
             for (StatsLogReport statsLog : report.getMetricsList()) {
                 if (isTrackedMetric(statsLog.getMetricId())) {
                     LOGGER.info(statsLog.toString());
+                    dumper.dump(statsLog);
                 }
             }
         }
@@ -341,6 +347,51 @@
         }
     }
 
+    interface Dumper {
+        void dump(StatsLogReport report);
+    }
+
+    static class BasicDumper implements Dumper {
+        @Override
+        public void dump(StatsLogReport report) {
+            System.out.println(report.toString());
+        }
+    }
+
+    static class TerseDumper extends BasicDumper {
+        @Override
+        public void dump(StatsLogReport report) {
+            if (report.hasGaugeMetrics()) {
+                dumpGaugeMetrics(report);
+            }
+            if (report.hasEventMetrics()) {
+                dumpEventMetrics(report);
+            }
+        }
+        void dumpEventMetrics(StatsLogReport report) {
+            final List<StatsLog.EventMetricData> data = report.getEventMetrics().getDataList();
+            if (data.isEmpty()) {
+                return;
+            }
+            long firstTimestampNanos = data.get(0).getElapsedTimestampNanos();
+            for (StatsLog.EventMetricData event : data) {
+                final double deltaSec = (event.getElapsedTimestampNanos() - firstTimestampNanos)
+                        / 1e9;
+                System.out.println(
+                        String.format("+%.3fs: %s", deltaSec, event.getAtom().toString()));
+            }
+        }
+        void dumpGaugeMetrics(StatsLogReport report) {
+            final List<StatsLog.GaugeMetricData> data = report.getGaugeMetrics().getDataList();
+            if (data.isEmpty()) {
+                return;
+            }
+            for (StatsLog.GaugeMetricData gauge : data) {
+                System.out.println(gauge.toString());
+            }
+        }
+    }
+
     private static String pushConfig(StatsdConfig config, String deviceSerial)
             throws IOException, InterruptedException {
         File configFile = File.createTempFile("statsdconfig", ".config");
diff --git a/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java b/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java
index 9d986e7..363fac0 100644
--- a/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java
+++ b/cmds/statsd/tools/localtools/test/com/android/statsd/shelltools/testdrive/TestDriveTest.java
@@ -41,24 +41,21 @@
     static class Expect {
         public boolean success;
         public Integer[] atoms;
-        public boolean onePushedAtomEvent;
-        public String extraPackage;
+        public boolean onePushedAtomEvent = false;
+        public String extraPackage = null;
         public String target;
+        public boolean terse = false;
 
         static Expect success(Integer... atoms) {
-            return new Expect(true, atoms, false, null,
+            return new Expect(true, atoms,
                     TARGET);
         }
-        Expect(boolean success, Integer[] atoms, boolean onePushedAtomEvent, String extraPackage,
-                String target) {
+        Expect(boolean success, Integer[] atoms, String target) {
             this.success = success;
             this.atoms = atoms;
-            this.onePushedAtomEvent = onePushedAtomEvent;
-            this.extraPackage = extraPackage;
             this.target = target;
         }
-        static final Expect FAILURE = new Expect(false, null,
-                false, null, null);
+        static final Expect FAILURE = new Expect(false, null, null);
         Expect onePushedAtomEvent() {
             this.onePushedAtomEvent = true;
             return this;
@@ -67,6 +64,10 @@
             this.extraPackage = TestDriveTest.PACKAGE;
             return this;
         }
+        Expect terse() {
+            this.terse = true;
+            return this;
+        }
     }
 
     @Parameterized.Parameter(0)
@@ -118,6 +119,10 @@
                         Expect.FAILURE},  // Two connected devices, no indication of which to use
                 new Object[]{new String[]{"-one", "244", "245"}, TARGET_ONLY, null,
                         Expect.success(244, 245).onePushedAtomEvent()},
+                new Object[]{new String[]{"-terse", "-one", "244", "245"}, TARGET_ONLY, null,
+                        Expect.success(244, 245).onePushedAtomEvent().terse()},
+                new Object[]{new String[]{"-one", "-terse", "244", "245"}, TARGET_ONLY, null,
+                        Expect.success(244, 245).onePushedAtomEvent().terse()},
                 new Object[]{new String[]{"-p", PACKAGE, "244", "245"}, TARGET_ONLY, null,
                         Expect.success(244, 245).extraPackage()},
                 new Object[]{new String[]{"-p", PACKAGE, "-one", "244", "245"}, TARGET_ONLY, null,
@@ -132,7 +137,23 @@
                         Expect.success(244, 245).extraPackage().onePushedAtomEvent()},
                 new Object[]{new String[]{"-one", "-p", PACKAGE, "-s", TARGET, "244", "245"},
                         TARGET_AND_OTHER, null,
-                        Expect.success(244, 245).extraPackage().onePushedAtomEvent()}
+                        Expect.success(244, 245).extraPackage().onePushedAtomEvent()},
+                new Object[]{new String[]{"-terse", "-one", "-p", PACKAGE, "-s", TARGET,
+                        "244", "245"},
+                        TARGET_AND_OTHER, null,
+                        Expect.success(244, 245).extraPackage().onePushedAtomEvent().terse()},
+                new Object[]{new String[]{"-one", "-terse", "-p", PACKAGE, "-s", TARGET,
+                        "244", "245"},
+                        TARGET_AND_OTHER, null,
+                        Expect.success(244, 245).extraPackage().onePushedAtomEvent().terse()},
+                new Object[]{new String[]{"-one", "-p", PACKAGE, "-terse", "-s", TARGET,
+                        "244", "245"},
+                        TARGET_AND_OTHER, null,
+                        Expect.success(244, 245).extraPackage().onePushedAtomEvent().terse()},
+                new Object[]{new String[]{"-one", "-p", PACKAGE, "-s", TARGET, "-terse",
+                        "244", "245"},
+                        TARGET_AND_OTHER, null,
+                        Expect.success(244, 245).extraPackage().onePushedAtomEvent().terse()}
         );
     }
 
@@ -162,6 +183,11 @@
             assertArrayEquals(mExpect.atoms, collectAtoms(mConfiguration));
             assertEquals(mExpect.onePushedAtomEvent, mConfiguration.mOnePushedAtomEvent);
             assertEquals(mExpect.target, mTestDrive.mDeviceSerial);
+            if (mExpect.terse) {
+                assertEquals(TestDrive.TerseDumper.class, mTestDrive.mDumper.getClass());
+            } else {
+                assertEquals(TestDrive.BasicDumper.class, mTestDrive.mDumper.getClass());
+            }
         } else {
             assertFalse(result);
         }