Add metric computation skeleton to statsd.

This cl is to let statsd understand statsd_config, and compute metrics
 defined in the config.

+ StatsLogProcessor is given a StatsdConfig (hard coded right now).
  We construct a MetricProducer for each of the metric, and the metrics
  share Condition and LogEntryMatchers

+ Added the CountMetricProducer type for CountMetric.

We can now count times of SCREEN_ON events given a config.

TODO: 1) conditions are not implemented.
      2) slicings are not implemented in CountMetric
      3) move the interaction to dropbox to a separate thread
      4) decide how the in memory metrics would be used by anomaly detection

Test: manual test.

      $ adb shell /system/bin/statsd

      $ cat config_file.dat | adb shell cmd stats config

Change-Id: I38f4059c0dc5a827c338131d4a6fa7d4cbe865db
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 280f9af..117fb5e 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -16,52 +16,74 @@
 
 #include <StatsLogProcessor.h>
 
+#include <cutils/log.h>
+#include <frameworks/base/cmds/statsd/src/stats_log.pb.h>
 #include <log/log_event_list.h>
+#include <metrics/CountMetricProducer.h>
 #include <parse_util.h>
 #include <utils/Errors.h>
 
 using namespace android;
+using std::make_unique;
+using std::unique_ptr;
+using std::vector;
 
 namespace android {
 namespace os {
 namespace statsd {
 
 StatsLogProcessor::StatsLogProcessor() : m_dropbox_writer("all-logs") {
-    // Initialize the EventTagMap, which is how we know the names of the numeric event tags.
-    // If this fails, we can't print well, but something will print.
-    m_tags = android_openEventTagMap(NULL);
-
-    // Printing format
-    m_format = android_log_format_new();
-    android_log_setPrintFormat(m_format, FORMAT_THREADTIME);
+    // hardcoded config
+    // this should be called from StatsService when it receives a statsd_config
+    UpdateConfig(0, buildFakeConfig());
 }
 
 StatsLogProcessor::~StatsLogProcessor() {
-    if (m_tags != NULL) {
-        android_closeEventTagMap(m_tags);
-    }
-    android_log_format_free(m_format);
 }
 
+StatsdConfig StatsLogProcessor::buildFakeConfig() {
+    // HACK: Hard code a test metric for counting screen on events...
+    StatsdConfig config;
+    config.set_config_id(12345L);
+
+    CountMetric* metric = config.add_count_metric();
+    metric->set_metric_id(20150717L);
+    metric->set_what("SCREEN_IS_ON");
+    metric->mutable_bucket()->set_bucket_size_millis(30 * 1000L);
+
+    LogEntryMatcher* eventMatcher = config.add_log_entry_matcher();
+    eventMatcher->set_name("SCREEN_IS_ON");
+
+    SimpleLogEntryMatcher* simpleLogEntryMatcher = eventMatcher->mutable_simple_log_entry_matcher();
+    simpleLogEntryMatcher->add_tag(2 /*SCREEN_STATE_CHANGE*/);
+    simpleLogEntryMatcher->add_key_value_matcher()->mutable_key_matcher()
+            ->set_key(1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+    simpleLogEntryMatcher->mutable_key_value_matcher(0)
+            ->set_eq_int(2/*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+    return config;
+}
+
+// TODO: what if statsd service restarts? How do we know what logs are already processed before?
 void StatsLogProcessor::OnLogEvent(const log_msg& msg) {
-    status_t err;
-    AndroidLogEntry entry;
-    char buf[1024];
+    // TODO: Use EventMetric to filter the events we want to log.
+    EventMetricData eventMetricData = parse(msg);
+    m_dropbox_writer.addEventMetricData(eventMetricData);
 
-    err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry,
-                                             m_tags, buf, sizeof(buf));
-
-    // dump all statsd logs to dropbox for now.
-    // TODO: Add filtering, aggregation, etc.
-    if (err == NO_ERROR) {
-        EventMetricData eventMetricData = parse(msg);
-        m_dropbox_writer.addEventMetricData(eventMetricData);
+    // pass the event to metrics managers.
+    for (auto& pair : mMetricsManagers) {
+        pair.second->onLogEvent(msg);
     }
 }
 
-void StatsLogProcessor::UpdateConfig(const int config_source, StatsdConfig config) {
-    m_configs[config_source] = config;
+void StatsLogProcessor::UpdateConfig(const int config_source, const StatsdConfig& config) {
+    auto it = mMetricsManagers.find(config_source);
+    if (it != mMetricsManagers.end()) {
+        it->second->finish();
+    }
+
     ALOGD("Updated configuration for source %i", config_source);
+
+    mMetricsManagers.insert({config_source, std::make_unique<MetricsManager>(config)});
 }
 
 }  // namespace statsd