Add support for dimension, and link with condition and added DurationMetric

Now we support following metrics:
  <Duration> of [app holding a wake lock], while [*this app*] is [in background] [AND] [screen is off]
  [Slice] the output by [app name, wake lock name], with bucket size [30sec]

+ Also added onDumpReport() api in MetricsManager, it can be called from client to fetch the data from
  statsd

+ Also added command line tool to dump the StatsLogReport from all metrics for debugging.

+ Synced proto from google3. with a pending cl (cr/172359050)

TODO: We need to add tons of tests to test the Metrics. I will work on it after this CL so people
can be unblocked.

I locally test the duration metric with wake lock with an app that generates StatsLog events.

Test: statsd_test

      and manual test, and run:

      adb shell cmd stats dump-report
      We have a default config, which contains a metrics to count PROCESS_START event sliced by
      package name.

Change-Id: I4838cc6cf025c143b7e84f43040703a78121fd25
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index b72e04e..87616d3 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -64,7 +64,6 @@
 // ======================================================================
 StatsService::StatsService(const sp<Looper>& handlerLooper)
     : mStatsPullerManager(),
-
       mAnomalyMonitor(new AnomalyMonitor(2))  // TODO: Put this comment somewhere better
 {
     mUidMap = new UidMap();
@@ -89,7 +88,7 @@
 
 void StatsService::init_build_type_callback(void* cookie, const char* /*name*/, const char* value,
                                             uint32_t serial) {
-    if (0 == strcmp("eng", value)) {
+    if (0 == strcmp("eng", value) || 0 == strcmp("userdebug", value)) {
         reinterpret_cast<StatsService*>(cookie)->mEngBuild = true;
     }
 }
@@ -187,10 +186,13 @@
             return cmd_print_stats_log(out, args);
         }
 
-        // adb shell cmd stats print-stats-log
         if (!args[0].compare(String8("print-uid-map"))) {
             return cmd_print_uid_map(out);
         }
+
+        if (!args[0].compare(String8("dump-report"))) {
+            return cmd_dump_report(out, err, args);
+        }
     }
 
     print_cmd_help(out);
@@ -248,7 +250,9 @@
                         }
                     }
                 } else {
-                    fprintf(err, "The config can only be set for other UIDs on eng builds.\n");
+                    fprintf(err,
+                            "The config can only be set for other UIDs on eng or userdebug "
+                            "builds.\n");
                 }
             }
 
@@ -287,6 +291,54 @@
     return UNKNOWN_ERROR;
 }
 
+status_t StatsService::cmd_dump_report(FILE* out, FILE* err, const Vector<String8>& args) {
+    if (mProcessor != nullptr) {
+        const int argCount = args.size();
+        bool good = false;
+        int uid;
+        string name;
+        if (argCount == 2) {
+            // Automatically pick the UID
+            uid = IPCThreadState::self()->getCallingUid();
+            // TODO: What if this isn't a binder call? Should we fail?
+            name.assign(args[2].c_str(), args[2].size());
+            good = true;
+        } else if (argCount == 3) {
+            // If it's a userdebug or eng build, then the shell user can
+            // impersonate other uids.
+            if (mEngBuild) {
+                const char* s = args[1].c_str();
+                if (*s != '\0') {
+                    char* end = NULL;
+                    uid = strtol(s, &end, 0);
+                    if (*end == '\0') {
+                        name.assign(args[2].c_str(), args[2].size());
+                        good = true;
+                    }
+                }
+            } else {
+                fprintf(out,
+                        "The metrics can only be dumped for other UIDs on eng or userdebug "
+                        "builds.\n");
+            }
+        }
+        if (good) {
+            mProcessor->onDumpReport(ConfigKey(uid, name));
+            // TODO: print the returned StatsLogReport to file instead of printing to logcat.
+            fprintf(out, "Dump report for Config [%d,%s]\n", uid, name.c_str());
+            fprintf(out, "See the StatsLogReport in logcat...\n");
+            return android::OK;
+        } else {
+            // If arg parsing failed, print the help text and return an error.
+            print_cmd_help(out);
+            return UNKNOWN_ERROR;
+        }
+    } else {
+        fprintf(out, "Log processor does not exist...\n");
+        return UNKNOWN_ERROR;
+    }
+}
+
 status_t StatsService::cmd_print_stats_log(FILE* out, const Vector<String8>& args) {
     long msec = 0;