Initial Contribution
diff --git a/libs/utils/LogSocket.cpp b/libs/utils/LogSocket.cpp
new file mode 100644
index 0000000..e64f794
--- /dev/null
+++ b/libs/utils/LogSocket.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+
+#ifndef HAVE_WINSOCK
+#define SOCKETLOG
+#endif
+
+#ifdef SOCKETLOG
+
+#define LOG_TAG "SOCKETLOG"
+
+#include <string.h>
+#include <cutils/log.h>
+#include "utils/LogSocket.h"
+#include "utils/logger.h"
+#include "cutils/hashmap.h"
+
+// defined in //device/data/etc/event-log-tags
+#define SOCKET_CLOSE_LOG 51000
+
+static Hashmap* statsMap = NULL;
+
+#define LOG_LIST_NUMBER 5
+
+typedef struct SocketStats {
+    int fd;
+    unsigned int send;
+    unsigned int recv;
+    unsigned int ip;
+    unsigned short port;
+    short reason;
+}SocketStats;
+
+SocketStats *get_socket_stats(int fd) {
+    if (statsMap == NULL) {
+        statsMap = hashmapCreate(8, &hashmapIntHash, &hashmapIntEquals);
+    }
+
+    SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd);
+    if (s == NULL) {
+        // LOGD("create SocketStats for fd %d", fd);
+        s = (SocketStats*) malloc(sizeof(SocketStats));
+        memset(s, 0, sizeof(SocketStats));
+        s->fd = fd;
+        hashmapPut(statsMap, &s->fd, s);
+    }
+    return s;
+}
+
+void log_socket_connect(int fd, unsigned int ip, unsigned short port) {
+    // LOGD("log_socket_connect for fd %d ip %d port%d", fd, ip, port);
+    SocketStats *s = get_socket_stats(fd);
+    s->ip = ip;
+    s->port = port;
+}
+
+void add_send_stats(int fd, int send) {
+    if (send <=0) {
+        LOGE("add_send_stats send %d", send);
+        return;
+    }
+    SocketStats *s = get_socket_stats(fd);
+    s->send += send;
+    // LOGD("add_send_stats for fd %d ip %d port%d", fd, s->ip, s->port);
+}
+
+void add_recv_stats(int fd, int recv) {
+    if (recv <=0) {
+        LOGE("add_recv_stats recv %d", recv);
+        return;
+    }
+    SocketStats *s = get_socket_stats(fd);
+    s->recv += recv;
+    // LOGD("add_recv_stats for fd %d ip %d port%d", fd, s->ip, s->port);
+}
+
+char* put_int(char* buf, int value) {
+    *buf = EVENT_TYPE_INT;
+    buf++;
+    memcpy(buf, &value, sizeof(int));
+    return buf + sizeof(int);
+}
+
+void log_socket_close(int fd, short reason) {
+    if (statsMap) {
+        SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd);
+        if (s != NULL) {
+            if (s->send != 0 || s->recv != 0) {
+                s->reason = reason;
+                // 5 int + list type need 2 bytes
+                char buf[LOG_LIST_NUMBER * 5 + 2];
+                buf[0] = EVENT_TYPE_LIST;
+                buf[1] = LOG_LIST_NUMBER;
+                char* writePos = buf + 2;
+                writePos = put_int(writePos, s->send);
+                writePos = put_int(writePos, s->recv);
+                writePos = put_int(writePos, s->ip);
+                writePos = put_int(writePos, s->port);
+                writePos = put_int(writePos, s->reason);
+                
+                android_bWriteLog(SOCKET_CLOSE_LOG, buf, sizeof(buf));
+                // LOGD("send %d recv %d reason %d", s->send, s->recv, s->reason);
+            }
+            hashmapRemove(statsMap, &s->fd);
+            free(s);
+        }
+    }
+}
+
+#else
+void add_send_stats(int fd, int send) {} 
+void add_recv_stats(int fd, int recv) {}
+void log_socket_close(int fd, short reason) {}
+void log_socket_connect(int fd, unsigned int ip, unsigned short port) {}
+#endif