Testdrive: allow multiple atoms in pulled atoms

Modifies statsd_testdrive to allow up to 100 atoms to be pulled at a
time. Uses trigger event with app breadcrumb so that the puller happens
once.

Bug: 128893770
Test: statsd_testdrive 10021 (temperature)
Change-Id: I185a7eb1b32a6b19596601dcf5a1ba7a633e4e35
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
index 91d6490..a381f9c 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/Utils.java
@@ -33,9 +33,10 @@
  */
 public class Utils {
 
-    public static final String CMD_UPDATE_CONFIG = "cmd stats config update";
     public static final String CMD_DUMP_REPORT = "cmd stats dump-report";
+    public static final String CMD_LOG_APP_BREADCRUMB = "cmd stats log-app-breadcrumb";
     public static final String CMD_REMOVE_CONFIG = "cmd stats config remove";
+    public static final String CMD_UPDATE_CONFIG = "cmd stats config update";
 
     public static final String SHELL_UID = "2000"; // Use shell, even if rooted.
 
@@ -107,6 +108,26 @@
         }
     }
 
+    /**
+     * Logs an AppBreadcrumbReported atom.
+     * @param label which label to log for the app breadcrumb atom.
+     * @param state which state to log for the app breadcrumb atom.
+     * @param logger Logger to log error messages
+     *
+     * @throws IOException
+     * @throws InterruptedException
+     */
+    public static void logAppBreadcrumb(int label, int state, Logger logger)
+            throws IOException, InterruptedException {
+        runCommand(
+                null,
+                logger,
+                "adb",
+                "shell",
+                CMD_LOG_APP_BREADCRUMB,
+                String.valueOf(label),
+                String.valueOf(state));
+    }
     public static void setUpLogger(Logger logger, boolean debug) {
         ConsoleHandler handler = new ConsoleHandler();
         handler.setFormatter(new LocalToolsFormatter());
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 3e705fd..c97f035 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
@@ -43,7 +43,10 @@
 
     private static final int METRIC_ID_BASE = 1111;
     private static final long ATOM_MATCHER_ID_BASE = 1234567;
+    private static final long APP_BREADCRUMB_MATCHER_ID = 1111111;
     private static final int PULL_ATOM_START = 10000;
+    private static final int MAX_PLATFORM_ATOM_TAG = 100000;
+    private static final int VENDOR_PULLED_ATOM_START_TAG = 150000;
     private static final long CONFIG_ID = 54321;
     private static final String[] ALLOWED_LOG_SOURCES = {
         "AID_GRAPHICS",
@@ -110,9 +113,10 @@
                                 + "be dumped after 1 min ...");
                 Thread.sleep(60_000);
             } else {
-                // wait for 2 min
-                LOGGER.info("Now wait for 2 minutes ...");
-                Thread.sleep(120_000);
+                LOGGER.info("Now wait for 1.5 minutes ...");
+                Thread.sleep(15_000);
+                Utils.logAppBreadcrumb(0, 0, LOGGER);
+                Thread.sleep(75_000);
             }
             testDrive.dumpMetrics();
         } catch (Exception e) {
@@ -156,6 +160,12 @@
             .addAllAllowedLogSource(allowedSources)
             .setHashStringsInMetricReport(false);
 
+        if (hasPulledAtom(atomIds)) {
+            builder.addAtomMatcher(
+                    createAtomMatcher(
+                            Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER, APP_BREADCRUMB_MATCHER_ID));
+        }
+
         for (int atomId : atomIds) {
             if (isPulledAtom(atomId)) {
                 builder.addAtomMatcher(createAtomMatcher(atomId, atomMatcherId));
@@ -163,8 +173,11 @@
                 gaugeMetricBuilder
                     .setId(metricId)
                     .setWhat(atomMatcherId)
+                    .setTriggerEvent(APP_BREADCRUMB_MATCHER_ID)
                     .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true).build())
-                    .setBucket(TimeUnit.ONE_MINUTE);
+                    .setBucket(TimeUnit.ONE_MINUTE)
+                    .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
+                    .setMaxNumGaugeAtomsPerBucket(100);
                 builder.addGaugeMetric(gaugeMetricBuilder.build());
             } else {
                 EventMetric.Builder eventMetricBuilder = EventMetric.newBuilder();
@@ -210,7 +223,8 @@
     }
 
     private static boolean isPulledAtom(int atomId) {
-        return atomId >= PULL_ATOM_START;
+        return atomId >= PULL_ATOM_START && atomId <= MAX_PLATFORM_ATOM_TAG
+                || atomId >= VENDOR_PULLED_ATOM_START_TAG;
     }
 
     private static boolean hasPulledAtom(Set<Integer> atoms) {