Add socket listener to statsd. And remove Davey atom.

+ The socket listener is behind a flag. It's disabled until we get sepolicy changes in.
+ Data parsing code is from logd, because we use the same format.

+ Removed Davey from JankTracker because it violates our new sepolicy

Test: manually
Bug: 78239479

Change-Id: Ib17729fbc362cdb13385f780e2d636a95adf9bc3
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index e0222d9..b085a09 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -66,7 +66,8 @@
     src/subscriber/IncidentdReporter.cpp \
     src/subscriber/SubscriberReporter.cpp \
     src/HashableDimensionKey.cpp \
-    src/guardrail/StatsdStats.cpp
+    src/guardrail/StatsdStats.cpp \
+    src/socket/StatsSocketListener.cpp
 
 statsd_common_c_includes := \
     $(LOCAL_PATH)/src \
@@ -96,7 +97,10 @@
     android.hardware.health@2.0 \
     android.hardware.power@1.0 \
     android.hardware.power@1.1 \
-    android.hardware.thermal@1.0
+    android.hardware.thermal@1.0 \
+    libpackagelistparser \
+    libsysutils \
+    libcutils
 
 # =========
 # statsd
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 8ce9ec7..e8904c6 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
+#define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
 #include "StatsService.h"
 #include "logd/LogReader.h"
+#include "socket/StatsSocketListener.h"
 
 #include <binder/IInterface.h>
 #include <binder/IPCThreadState.h>
@@ -35,7 +37,9 @@
 using namespace android;
 using namespace android::os::statsd;
 
-// ================================================================================
+const bool kUseLogd = false;
+const bool kUseStatsdSocket = true;
+
 /**
  * Thread function data.
  */
@@ -48,12 +52,8 @@
  */
 static void* log_reader_thread_func(void* cookie) {
     log_reader_thread_data* data = static_cast<log_reader_thread_data*>(cookie);
-
     sp<LogReader> reader = new LogReader(data->service);
 
-    // Tell StatsService that we're ready to go.
-    data->service->Startup();
-
     // Run the read loop. Never returns.
     reader->Run();
 
@@ -96,10 +96,7 @@
     return NO_ERROR;
 }
 
-// ================================================================================
 int main(int /*argc*/, char** /*argv*/) {
-    status_t err;
-
     // Set up the looper
     sp<Looper> looper(Looper::prepare(0 /* opts */));
 
@@ -118,10 +115,25 @@
     }
     service->sayHiToStatsCompanion();
 
-    // Start the log reader thread
-    err = start_log_reader_thread(service);
-    if (err != NO_ERROR) {
-        return 1;
+    service->Startup();
+
+    sp<StatsSocketListener> socketListener = new StatsSocketListener(service);
+
+    if (kUseLogd) {
+        ALOGI("using logd");
+        // Start the log reader thread
+        status_t err = start_log_reader_thread(service);
+        if (err != NO_ERROR) {
+            return 1;
+        }
+    }
+
+    if (kUseStatsdSocket) {
+        ALOGI("using statsd socket");
+        // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
+        if (socketListener->startListener(600)) {
+            exit(1);
+        }
     }
 
     // Loop forever -- the reports run on this thread in a handler, and the
diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp
new file mode 100755
index 0000000..0392d67
--- /dev/null
+++ b/cmds/statsd/src/socket/StatsSocketListener.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+#define DEBUG false  // STOPSHIP if true
+#include "Log.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
+#include <unordered_map>
+
+#include "StatsSocketListener.h"
+#include "guardrail/StatsdStats.h"
+#include "stats_log_util.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+static const int kLogMsgHeaderSize = 28;
+
+StatsSocketListener::StatsSocketListener(const sp<LogListener>& listener)
+    : SocketListener(getLogSocket(), false /*start listen*/), mListener(listener) {
+}
+
+StatsSocketListener::~StatsSocketListener() {
+}
+
+bool StatsSocketListener::onDataAvailable(SocketClient* cli) {
+    static bool name_set;
+    if (!name_set) {
+        prctl(PR_SET_NAME, "statsd.writer");
+        name_set = true;
+    }
+
+    // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
+    char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) + LOGGER_ENTRY_MAX_PAYLOAD +
+                1];
+    struct iovec iov = {buffer, sizeof(buffer) - 1};
+
+    alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
+    struct msghdr hdr = {
+            NULL, 0, &iov, 1, control, sizeof(control), 0,
+    };
+
+    int socket = cli->getSocket();
+
+    // To clear the entire buffer is secure/safe, but this contributes to 1.68%
+    // overhead under logging load. We are safe because we check counts, but
+    // still need to clear null terminator
+    // memset(buffer, 0, sizeof(buffer));
+    ssize_t n = recvmsg(socket, &hdr, 0);
+    if (n <= (ssize_t)(sizeof(android_log_header_t))) {
+        return false;
+    }
+
+    buffer[n] = 0;
+
+    struct ucred* cred = NULL;
+
+    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
+    while (cmsg != NULL) {
+        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
+            cred = (struct ucred*)CMSG_DATA(cmsg);
+            break;
+        }
+        cmsg = CMSG_NXTHDR(&hdr, cmsg);
+    }
+
+    struct ucred fake_cred;
+    if (cred == NULL) {
+        cred = &fake_cred;
+        cred->pid = 0;
+        cred->uid = DEFAULT_OVERFLOWUID;
+    }
+
+    char* ptr = ((char*)buffer) + sizeof(android_log_header_t);
+    n -= sizeof(android_log_header_t);
+
+    log_msg msg;
+
+    msg.entry.len = n;
+    msg.entry.hdr_size = kLogMsgHeaderSize;
+    msg.entry.sec = time(nullptr);
+    msg.entry.pid = cred->pid;
+    msg.entry.uid = cred->uid;
+
+    memcpy(msg.buf + kLogMsgHeaderSize, ptr, n + 1);
+    LogEvent event(msg);
+
+    // Call the listener
+    mListener->OnLogEvent(&event, false /*reconnected, N/A in statsd socket*/);
+
+    return true;
+}
+
+int StatsSocketListener::getLogSocket() {
+    static const char socketName[] = "statsdw";
+    int sock = android_get_control_socket(socketName);
+
+    if (sock < 0) {  // statsd started up in init.sh
+        sock = socket_local_server(socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_DGRAM);
+
+        int on = 1;
+        if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
+            return -1;
+        }
+    }
+    return sock;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/socket/StatsSocketListener.h b/cmds/statsd/src/socket/StatsSocketListener.h
new file mode 100644
index 0000000..73e4d33
--- /dev/null
+++ b/cmds/statsd/src/socket/StatsSocketListener.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+#pragma once
+
+#include <sysutils/SocketListener.h>
+#include <utils/RefBase.h>
+#include "logd/LogListener.h"
+
+// DEFAULT_OVERFLOWUID is defined in linux/highuid.h, which is not part of
+// the uapi headers for userspace to use.  This value is filled in on the
+// out-of-band socket credentials if the OS fails to find one available.
+// One of the causes of this is if SO_PASSCRED is set, all the packets before
+// that point will have this value.  We also use it in a fake credential if
+// no socket credentials are supplied.
+#ifndef DEFAULT_OVERFLOWUID
+#define DEFAULT_OVERFLOWUID 65534
+#endif
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class StatsSocketListener : public SocketListener, public virtual android::RefBase {
+public:
+    StatsSocketListener(const sp<LogListener>& listener);
+
+    virtual ~StatsSocketListener();
+
+protected:
+    virtual bool onDataAvailable(SocketClient* cli);
+
+private:
+    static int getLogSocket();
+    /**
+     * Who is going to get the events when they're read.
+     */
+    sp<LogListener> mListener;
+};
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
\ No newline at end of file