Revert "Revert "Start auto-generating the stats log API.""

Test: builds successfully

This reverts commit 931945399859ab91545ba2c2a914f044092d5e2e.

Change-Id: I22bca4a32adf86040b9d72ad5b45999aba28f586
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
new file mode 100644
index 0000000..5586057
--- /dev/null
+++ b/cmds/statsd/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// ==========================================================
+// Build the library for use on the host
+// ==========================================================
+cc_library_host_shared {
+    name: "libstats_proto_host",
+    srcs: [
+        "src/stats_events.proto",
+        "src/stats_log.proto",
+        "src/statsd_config.proto",
+    ],
+
+    shared_libs: [
+        "libplatformprotos",
+    ],
+
+    proto: {
+        type: "full",
+        export_proto_headers: true,
+    },
+}
+
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 4c95007..d9c37ef 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -14,22 +14,51 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# ================
-# proto static lib
-# ================
-include $(CLEAR_VARS)
 
-LOCAL_MODULE := statsd_proto
-LOCAL_MODULE_TAGS := optional
+statsd_common_src := \
+    ../../core/java/android/os/IStatsCompanionService.aidl \
+    ../../core/java/android/os/IStatsManager.aidl \
+    src/stats_log.proto \
+    src/statsd_config.proto \
+    src/stats_events.proto \
+    src/condition/CombinationConditionTracker.cpp \
+    src/condition/condition_util.cpp \
+    src/condition/SimpleConditionTracker.cpp \
+    src/matchers/CombinationLogMatchingTracker.cpp \
+    src/matchers/matcher_util.cpp \
+    src/matchers/SimpleLogMatchingTracker.cpp \
+    src/metrics/CountAnomalyTracker.cpp \
+    src/metrics/CountMetricProducer.cpp \
+    src/metrics/MetricsManager.cpp \
+    src/metrics/metrics_manager_util.cpp \
+    src/AnomalyMonitor.cpp \
+    src/DropboxReader.cpp \
+    src/DropboxWriter.cpp \
+    src/KernelWakelockPuller.cpp \
+    src/LogEntryPrinter.cpp \
+    src/LogReader.cpp \
+    src/StatsLogProcessor.cpp \
+    src/StatsPullerManager.cpp \
+    src/StatsService.cpp \
+    src/stats_util.cpp \
+    src/UidMap.cpp
 
-LOCAL_SRC_FILES := $(call all-proto-files-under, src)
+statsd_common_c_includes := \
+    $(LOCAL_PATH)/src
 
-LOCAL_PROTOC_FLAGS :=
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite-static
+statsd_common_aidl_includes := \
+    $(LOCAL_PATH)/../../core/java
 
-include $(BUILD_STATIC_LIBRARY)
-
-STATSD_PROTO_INCLUDES := $(local-generated-sources-dir)/src/$(LOCAL_PATH)
+statsd_common_shared_libraries := \
+    libbase \
+    libbinder \
+    libcutils \
+    libincident \
+    liblog \
+    libselinux \
+    libutils \
+    libservices \
+    libandroidfw
 
 # =========
 # statsd
@@ -40,9 +69,8 @@
 LOCAL_MODULE := statsd
 
 LOCAL_SRC_FILES := \
-    ../../core/java/android/os/IStatsCompanionService.aidl \
-    ../../core/java/android/os/IStatsManager.aidl \
-    $(call all-cpp-files-under,src) \
+    $(statsd_common_src) \
+    src/main.cpp
 
 LOCAL_CFLAGS += \
     -Wall \
@@ -60,24 +88,12 @@
     LOCAL_CFLAGS += \
             -Os
 endif
+LOCAL_PROTOC_OPTIMIZE_TYPE := lite-static
 
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/../../core/java
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \
-	STATSD_PROTO_INCLUDES
+LOCAL_AIDL_INCLUDES := $(statsd_common_c_includes)
+LOCAL_C_INCLUDES += $(statsd_common_c_includes)
 
-LOCAL_STATIC_LIBRARIES := statsd_proto
-
-LOCAL_SHARED_LIBRARIES := \
-        libbase \
-        libbinder \
-        libcutils \
-        libincident \
-        liblog \
-        libselinux \
-        libutils \
-        libservices \
-        libandroidfw \
-        libprotobuf-cpp-lite \
+LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries)
 
 LOCAL_MODULE_CLASS := EXECUTABLES
 
@@ -85,6 +101,7 @@
 
 include $(BUILD_EXECUTABLE)
 
+
 # ==============
 # statsd_test
 # ==============
@@ -95,8 +112,8 @@
 LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \
-	STATSD_PROTO_INCLUDES
+LOCAL_AIDL_INCLUDES := $(statsd_common_c_includes)
+LOCAL_C_INCLUDES += $(statsd_common_c_includes)
 
 LOCAL_CFLAGS += \
     -Wall \
@@ -107,38 +124,25 @@
     -Wno-unused-parameter
 
 LOCAL_SRC_FILES := \
-    src/stats_log.proto \
-    src/statsd_config.proto \
-    ../../core/java/android/os/IStatsCompanionService.aidl \
-    ../../core/java/android/os/IStatsManager.aidl \
-    src/StatsService.cpp \
-    src/AnomalyMonitor.cpp \
-    src/stats_util.cpp \
-    src/LogEntryPrinter.cpp \
-    src/LogReader.cpp \
-    src/matchers/matcher_util.cpp \
-    src/condition/SimpleConditionTracker.cpp \
-    src/condition/CombinationConditionTracker.cpp \
-    src/matchers/SimpleLogMatchingTracker.cpp \
-    src/matchers/CombinationLogMatchingTracker.cpp \
-    src/metrics/metrics_manager_util.cpp \
-    src/metrics/CountMetricProducer.cpp \
-    src/metrics/CountAnomalyTracker.cpp \
-    src/condition/condition_util.cpp \
-    src/UidMap.cpp \
-    $(call all-cpp-files-under, tests) \
+    $(statsd_common_src) \
+    tests/indexed_priority_queue_test.cpp \
+    tests/LogReader_test.cpp \
+    tests/MetricsManager_test.cpp \
+    tests/UidMap_test.cpp \
+    tests/LogEntryMatcher_test.cpp \
+    tests/AnomalyMonitor_test.cpp \
+    tests/ConditionTracker_test.cpp
 
 LOCAL_STATIC_LIBRARIES := \
-    libgmock \
-    statsd_proto \
+    libgmock
 
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libbinder \
-    libcutils \
-    liblog \
-    libselinux \
-    libutils \
-    libprotobuf-cpp-lite \
+LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries)
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := lite
+
+statsd_common_src:=
+statsd_common_aidl_includes:=
+statsd_common_c_includes:=
 
 include $(BUILD_NATIVE_TEST)
+
diff --git a/cmds/statsd/src/LogEntryPrinter.cpp b/cmds/statsd/src/LogEntryPrinter.cpp
index 63465b0..3b6f679 100644
--- a/cmds/statsd/src/LogEntryPrinter.cpp
+++ b/cmds/statsd/src/LogEntryPrinter.cpp
@@ -20,6 +20,11 @@
 #include <log/logprint.h>
 #include <utils/Errors.h>
 
+#include "matchers/matcher_util.h"
+
+#define PRINT_WITH_LIBLOG 0
+#define PRINT_WITH_LOG_EVENT_WRAPPER 1
+
 using namespace android;
 
 namespace android {
@@ -44,16 +49,24 @@
 }
 
 void LogEntryPrinter::OnLogEvent(const log_msg& msg) {
-    status_t err;
-    AndroidLogEntry entry;
-    char buf[1024];
+    if (PRINT_WITH_LIBLOG) {
+        status_t err;
+        AndroidLogEntry entry;
+        char buf[1024];
 
-    err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry,
-                                             m_tags, buf, sizeof(buf));
-    if (err == NO_ERROR) {
-        android_log_printLogLine(m_format, m_out, &entry);
-    } else {
-        printf("log entry: %s\n", buf);
+        err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry,
+                                                 m_tags, buf, sizeof(buf));
+        if (err == NO_ERROR) {
+            android_log_printLogLine(m_format, m_out, &entry);
+        } else {
+            printf("log entry: %s\n", buf);
+            fflush(stdout);
+        }
+    }
+
+    if (PRINT_WITH_LOG_EVENT_WRAPPER) {
+        LogEventWrapper event = parseLogEvent(msg);
+        printf("event: %s\n", event.toString().c_str());
         fflush(stdout);
     }
 }
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 557c032..3308f3a 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -26,8 +26,11 @@
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "stats_util.h"
 
+#include <sstream>
+
 using std::set;
 using std::string;
+using std::ostringstream;
 using std::unordered_map;
 using std::vector;
 
@@ -35,6 +38,42 @@
 namespace os {
 namespace statsd {
 
+string LogEventWrapper::toString() const {
+    std::ostringstream result;
+    result << "{ " << timestamp_ns << " (" << tagId << ")";
+    for (int index = 1; ; index++) {
+        auto intVal = intMap.find(index);
+        auto strVal = strMap.find(index);
+        auto boolVal = boolMap.find(index);
+        auto floatVal = floatMap.find(index);
+        if (intVal != intMap.end()) {
+            result << " ";
+            result << std::to_string(index);
+            result << "->";
+            result << std::to_string(intVal->second);
+        } else if (strVal != strMap.end()) {
+            result << " ";
+            result << std::to_string(index);
+            result << "->";
+            result << strVal->second;
+        } else if (boolVal != boolMap.end()) {
+            result << " ";
+            result << std::to_string(index);
+            result << "->";
+            result << std::to_string(boolVal->second);
+        } else if (floatVal != floatMap.end()) {
+            result << " ";
+            result << std::to_string(index);
+            result << "->";
+            result << std::to_string(floatVal->second);
+        } else {
+            break;
+        }
+    }
+    result << " }";
+    return result.str();
+}
+
 LogEventWrapper parseLogEvent(log_msg msg) {
     LogEventWrapper wrapper;
     wrapper.timestamp_ns = msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec;
@@ -48,38 +87,32 @@
 
     if (context) {
         memset(&elem, 0, sizeof(elem));
-        size_t index = 0;
-        int32_t key = -1;
+        // TODO: The log is actually structured inside one list.  This is convenient
+        // because we'll be able to use it to put the attribution (WorkSource) block first
+        // without doing our own tagging scheme.  Until that change is in, just drop the
+        // list-related log elements and the order we get there is our index-keyed data
+        // structure.
+        int32_t key = 1;
         do {
             elem = android_log_read_next(context);
             switch ((int)elem.type) {
                 case EVENT_TYPE_INT:
-                    if (index % 2 == 0) {
-                        key = elem.data.int32;
-                    } else {
-                        wrapper.intMap[key] = elem.data.int32;
-                    }
-                    index++;
+                    wrapper.intMap[key] = elem.data.int32;
+                    key++;
                     break;
                 case EVENT_TYPE_FLOAT:
-                    if (index % 2 == 1) {
-                        wrapper.floatMap[key] = elem.data.float32;
-                    }
-                    index++;
+                    wrapper.floatMap[key] = elem.data.float32;
+                    key++;
                     break;
                 case EVENT_TYPE_STRING:
-                    if (index % 2 == 1) {
-                        // without explicit calling string() constructor, there will be an
-                        // additional 0 in the end of the string.
-                        wrapper.strMap[key] = string(elem.data.string);
-                    }
-                    index++;
+                    // without explicit calling string() constructor, there will be an
+                    // additional 0 in the end of the string.
+                    wrapper.strMap[key] = string(elem.data.string);
+                    key++;
                     break;
                 case EVENT_TYPE_LONG:
-                    if (index % 2 == 1) {
-                        wrapper.intMap[key] = elem.data.int64;
-                    }
-                    index++;
+                    wrapper.intMap[key] = elem.data.int64;
+                    key++;
                     break;
                 case EVENT_TYPE_LIST:
                     break;
@@ -91,10 +124,6 @@
                     elem.complete = true;
                     break;
             }
-
-            if (elem.complete) {
-                break;
-            }
         } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
 
         android_log_destroy(&context);
diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h
index 6d8e762..ac17bbe 100644
--- a/cmds/statsd/src/matchers/matcher_util.h
+++ b/cmds/statsd/src/matchers/matcher_util.h
@@ -20,6 +20,7 @@
 #include <log/log_read.h>
 #include <log/logprint.h>
 #include <set>
+#include <string>
 #include <unordered_map>
 #include <vector>
 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
@@ -36,6 +37,8 @@
     std::unordered_map<int, std::string> strMap;
     std::unordered_map<int, bool> boolMap;
     std::unordered_map<int, float> floatMap;
+
+    std::string toString() const;
 } LogEventWrapper;
 
 enum MatchingState {
diff --git a/cmds/statsd/src/stats_events.proto b/cmds/statsd/src/stats_events.proto
index 1e17895..cd00ba8 100644
--- a/cmds/statsd/src/stats_events.proto
+++ b/cmds/statsd/src/stats_events.proto
@@ -15,49 +15,116 @@
  */
 
 syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
 
+// TODO: Not the right package and class name
 package android.os.statsd;
-
 option java_package = "com.android.os";
 option java_outer_classname = "StatsEventProto";
 
+/**
+ * The master event class. This message defines all of the available
+ * raw stats log events from the Android system, also known as "atoms."
+ *
+ * This field contains a single oneof with all of the available messages.
+ * The stats-log-api-gen tool runs as part of the Android build and
+ * generates the android.util.StatsLog class, which contains the constants
+ * and methods that Android uses to log.
+ *
+ * This StatsEvent class is not actually built into the Android system.
+ * Instead, statsd on Android constructs these messages synthetically,
+ * in the format defined here and in stats_log.proto.
+ */
 message StatsEvent {
-  oneof event {
-    // Screen state change.
-    ScreenStateChange screen_state_change = 2;
-    // Process state change.
-    ProcessStateChange process_state_change = 1112;
-  }
+    oneof event {
+        ScreenStateChanged screen_state_changed = 1;
+        ProcessStateChanged process_state_changed = 2;
+        WakeLockChanged wakelock_changed = 3;
+    }
 }
 
-// Logs changes in screen state. This event is logged in
-// frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
-message ScreenStateChange {
-  // Screen state enums follow the values defined in below file.
-  // frameworks/base/core/java/android/view/Display.java
-  enum State {
-    STATE_UNKNOWN = 0;
-    STATE_OFF = 1;
-    STATE_ON = 2;
-    STATE_DOZE = 3;
-    STATE_DOZE_SUSPEND = 4;
-    STATE_VR = 5;
-  }
-  // New screen state.
-  optional State display_state = 1;
+/**
+ * A WorkSource represents the chained attribution of applications that
+ * resulted in a particular bit of work being done.
+ */
+message WorkSource {
+    // TODO
 }
 
-// Logs changes in process state. This event is logged in
-// frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
-message ProcessStateChange {
-  // Type of process event.
-  enum State {
-    START = 1;
-    CRASH = 2;
-  }
-  optional State state = 1;
+/*
+ * *****************************************************************************
+ * Below are all of the individual atoms that are logged by Android via statsd
+ * and Westworld.
+ *
+ * RULES:
+ *   - The field ids for each atom must start at 1, and count upwards by 1.
+ *     Skipping field ids is not allowed.
+ *   - These form an API, so renaming, renumbering or removing fields is
+ *     not allowed between android releases.  (This is not currently enforced,
+ *     but there will be a tool to enforce this restriction).
+ *   - The types must be built-in protocol buffer types, namely, no sub-messages
+ *     are allowed (yet).  The bytes type is also not allowed.
+ *   - The CamelCase name of the message type should match the
+ *     underscore_separated name as defined in StatsEvent.
+ *   - If an atom represents work that can be attributed to an app, there can
+ *     be exactly one WorkSource field. It must be field number 1.
+ *   - A field that is a uid should be a string field, tagged with the [xxx]
+ *     annotation. The generated code on android will be represented by UIDs,
+ *     and those UIDs will be translated in xxx to those strings.
+ *
+ * CONVENTIONS:
+ *   - Events are past tense. e.g. ScreenStateChanged, not ScreenStateChange
+ *   - If there is a UID, it goes first. Think in an object-oriented fashion.
+ * *****************************************************************************
+ */
 
-  // UID associated with the package.
-  optional int32 uid = 2;
+/**
+ * Logs when the screen state changes.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
+ */
+message ScreenStateChanged {
+    // TODO: Use the real screen state.
+    enum State {
+        STATE_UNKNOWN = 0;
+        STATE_OFF = 1;
+        STATE_ON = 2;
+        STATE_DOZE = 3;
+        STATE_DOZE_SUSPEND = 4;
+        STATE_VR = 5;
+    }
+    // New screen state.
+    optional State display_state = 1;
 }
+
+/**
+ * Logs that the state of a process state, as per the activity manager has changed.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/am/BatteryStatsService.java
+ */
+message ProcessStateChanged {
+    // TODO: Use the real (mapped) process states.
+    optional int32 uid = 1; // TODO: should be a string tagged w/ uid annotation
+
+    // The state.
+    optional int32 state = 2;
+}
+
+/**
+ * Logs that the state of a wakelock has changed.
+ *
+ * Logged from:
+ *   TODO
+ */
+message WakeLockChanged {
+    // TODO: Add attribution instead of uid.
+    optional int32 uid = 1;
+
+    // The wakelock tag (Called tag in the Java API, sometimes name elsewhere).
+    optional string tag = 2;
+
+    // TODO: Use a constant instead of boolean?
+    optional bool state = 3;
+}
+