Add statsd.

It doesn't start yet by default. When you start it manually, it sets
itself up as a binder system service and starts a thread to read the
event log.

Test: Run statsd, observe output. also run stats_test
Change-Id: If435d6a80fef3c1d957aedb61699bf5e9aae7e56
diff --git a/cmds/statsd/src/LogReader.cpp b/cmds/statsd/src/LogReader.cpp
new file mode 100644
index 0000000..e0ed646
--- /dev/null
+++ b/cmds/statsd/src/LogReader.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "LogReader.h"
+
+#include <log/log_read.h>
+
+#include <utils/Errors.h>
+
+#include <time.h>
+#include <unistd.h>
+
+using namespace android;
+using namespace std;
+
+#define SNOOZE_INITIAL_MS 100
+#define SNOOZE_MAX_MS (10 * 60 * 1000) // Ten minutes
+
+
+// ================================================================================
+LogListener::LogListener()
+{
+}
+
+LogListener::~LogListener()
+{
+}
+
+
+// ================================================================================
+LogReader::LogReader()
+{
+}
+
+LogReader::~LogReader()
+{
+}
+
+void
+LogReader::AddListener(const sp<LogListener>& listener)
+{
+    m_listeners.push_back(listener);
+}
+
+void
+LogReader::Run()
+{
+    int nextSnoozeMs = SNOOZE_INITIAL_MS;
+
+    // In an ideal world, this outer loop will only ever run one iteration, but it
+    // exists to handle crashes in logd.  The inner loop inside connect_and_read()
+    // reads from logd forever, but if that read fails, we fall out to the outer
+    // loop, do the backoff (resetting the backoff timeout if we successfully read
+    // something), and then try again.
+    while (true) {
+        // Connect and read
+        int lineCount = connect_and_read();
+
+        // Figure out how long to sleep.
+        if (lineCount > 0) {
+            // If we managed to read at least one line, reset the backoff
+            nextSnoozeMs = SNOOZE_INITIAL_MS;
+        } else {
+            // Otherwise, expontial backoff
+            nextSnoozeMs *= 1.5f;
+            if (nextSnoozeMs > 10 * 60 * 1000) {
+                // Don't wait for toooo long.
+                nextSnoozeMs = SNOOZE_MAX_MS;
+            }
+        }
+
+        // Sleep
+        timespec ts;
+        timespec rem;
+        ts.tv_sec = nextSnoozeMs / 1000;
+        ts.tv_nsec = (nextSnoozeMs % 1000) * 1000000L;
+        while (nanosleep(&ts, &rem) == -1) {
+            if (errno == EINTR) {
+                ts = rem;
+            }
+            // other errors are basically impossible
+        }
+    }
+}
+
+int
+LogReader::connect_and_read()
+{
+    int lineCount = 0;
+    status_t err;
+    logger_list* loggers;
+    logger* eventLogger;
+
+    // Prepare the logging context
+    loggers = android_logger_list_alloc(ANDROID_LOG_RDONLY,
+            /* don't stop after N lines */ 0,
+            /* no pid restriction */ 0);
+
+    // Open the buffer(s)
+    eventLogger = android_logger_open(loggers, LOG_ID_EVENTS);
+
+    // Read forever
+    if (eventLogger) {
+        while (true) {
+            log_msg msg;
+
+            // Read a message
+            err = android_logger_list_read(loggers, &msg);
+            if (err < 0) {
+                fprintf(stderr, "logcat read failure: %s\n", strerror(err));
+                break;
+            }
+
+            // Record that we read one (used above to know how to snooze).
+            lineCount++;
+
+            // Call the listeners
+            for (vector<sp<LogListener> >::iterator it = m_listeners.begin();
+                    it != m_listeners.end(); it++) {
+                (*it)->OnLogEvent(msg);
+            }
+        }
+    }
+
+    // Free the logger list and close the individual loggers
+    android_logger_list_free(loggers);
+
+    return lineCount;
+}
+