Merge "SharedBuffer: Refactor release() logic"
diff --git a/adb/Android.mk b/adb/Android.mk
index 6a2a6b1..b2a0dc4 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -52,6 +52,7 @@
     adb_utils.cpp \
     fdevent.cpp \
     sockets.cpp \
+    socket_spec.cpp \
     transport.cpp \
     transport_local.cpp \
     transport_usb.cpp \
@@ -80,12 +81,10 @@
     $(ADB_COMMON_windows_CFLAGS) \
 
 LIBADB_darwin_SRC_FILES := \
-    get_my_path_darwin.cpp \
     sysdeps_unix.cpp \
     usb_osx.cpp \
 
 LIBADB_linux_SRC_FILES := \
-    get_my_path_linux.cpp \
     sysdeps_unix.cpp \
     usb_linux.cpp \
 
@@ -111,7 +110,7 @@
 
 # Even though we're building a static library (and thus there's no link step for
 # this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -134,7 +133,7 @@
 
 # Even though we're building a static library (and thus there's no link step for
 # this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
 
 LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
 LOCAL_MULTILIB := first
@@ -154,7 +153,7 @@
     shell_service_test.cpp \
 
 LOCAL_SANITIZE := $(adb_target_sanitize)
-LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils_static libcrypto_static
+LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils libcrypto
 LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
 include $(BUILD_NATIVE_TEST)
 
@@ -198,8 +197,8 @@
 LOCAL_SHARED_LIBRARIES := libbase
 LOCAL_STATIC_LIBRARIES := \
     libadb \
-    libcrypto_utils_static \
-    libcrypto_static \
+    libcrypto_utils \
+    libcrypto \
     libcutils \
     libdiagnose_usb \
     libgmock_host \
@@ -263,8 +262,8 @@
 LOCAL_STATIC_LIBRARIES := \
     libadb \
     libbase \
-    libcrypto_utils_static \
-    libcrypto_static \
+    libcrypto_utils \
+    libcrypto \
     libdiagnose_usb \
     liblog \
 
@@ -340,8 +339,8 @@
     libsquashfs_utils \
     libcutils \
     libbase \
-    libcrypto_utils_static \
-    libcrypto_static \
+    libcrypto_utils \
+    libcrypto \
     libminijail \
     libdebuggerd_client \
 
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 725aa91..056dbef 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -34,6 +34,7 @@
 #include <vector>
 
 #include <android-base/errors.h>
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/parsenetaddress.h>
@@ -354,21 +355,13 @@
     case A_AUTH:
         if (p->msg.arg0 == ADB_AUTH_TOKEN) {
             t->connection_state = kCsUnauthorized;
-            t->key = adb_auth_nextkey(t->key);
-            if (t->key) {
-                send_auth_response(p->data, p->msg.data_length, t);
-            } else {
-                /* No more private keys to try, send the public key */
-                send_auth_publickey(t);
-            }
+            send_auth_response(p->data, p->msg.data_length, t);
         } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
-            if (adb_auth_verify(t->token, sizeof(t->token),
-                                p->data, p->msg.data_length)) {
+            if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
                 adb_auth_verified(t);
                 t->failed_auth_attempts = 0;
             } else {
-                if (t->failed_auth_attempts++ > 10)
-                    adb_sleep_ms(1000);
+                if (t->failed_auth_attempts++ > 256) adb_sleep_ms(1000);
                 send_auth_request(t);
             }
         } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
@@ -618,8 +611,7 @@
 
 #endif
 
-int launch_server(int server_port)
-{
+int launch_server(const std::string& socket_spec) {
 #if defined(_WIN32)
     /* we need to start the server in the background                    */
     /* we create a PIPE that will be used to wait for the server's "OK" */
@@ -722,9 +714,8 @@
     }
 
     WCHAR   args[64];
-    snwprintf(args, arraysize(args),
-              L"adb -P %d fork-server server --reply-fd %d", server_port,
-              ack_write_as_int);
+    snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d",
+              socket_spec.c_str(), ack_write_as_int);
 
     PROCESS_INFORMATION   pinfo;
     ZeroMemory(&pinfo, sizeof(pinfo));
@@ -851,30 +842,29 @@
         return -1;
     }
 #else /* !defined(_WIN32) */
-    char    path[PATH_MAX];
-    int     fd[2];
-
     // set up a pipe so the child can tell us when it is ready.
     // fd[0] will be parent's end, and the child will write on fd[1]
+    int fd[2];
     if (pipe(fd)) {
         fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
         return -1;
     }
-    get_my_path(path, PATH_MAX);
+
+    std::string path = android::base::GetExecutablePath();
+
     pid_t pid = fork();
-    if(pid < 0) return -1;
+    if (pid < 0) return -1;
 
     if (pid == 0) {
         // child side of the fork
 
         adb_close(fd[0]);
 
-        char str_port[30];
-        snprintf(str_port, sizeof(str_port), "%d", server_port);
         char reply_fd[30];
         snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]);
         // child process
-        int result = execl(path, "adb", "-P", str_port, "fork-server", "server", "--reply-fd", reply_fd, NULL);
+        int result = execl(path.c_str(), "adb", "-L", socket_spec.c_str(), "fork-server", "server",
+                           "--reply-fd", reply_fd, NULL);
         // this should not return
         fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
     } else  {
diff --git a/adb/adb.h b/adb/adb.h
index cd6b7bd..0b9fe5b 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -126,9 +126,8 @@
 
 void handle_packet(apacket *p, atransport *t);
 
-void get_my_path(char *s, size_t maxLen);
-int launch_server(int server_port);
-int adb_server_main(int is_daemon, int server_port, int ack_reply_fd);
+int launch_server(const std::string& socket_spec);
+int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd);
 
 /* initialize a transport object's func pointers and state */
 #if ADB_HOST
diff --git a/adb/adb_auth.cpp b/adb/adb_auth.cpp
index 215bbe6..0b07158 100644
--- a/adb/adb_auth.cpp
+++ b/adb/adb_auth.cpp
@@ -16,8 +16,9 @@
 
 #define TRACE_TAG ADB
 
-#include "sysdeps.h"
+#include "adb.h"
 #include "adb_auth.h"
+#include "transport.h"
 
 #include <errno.h>
 #include <stdio.h>
@@ -25,53 +26,28 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "adb.h"
-#include "transport.h"
-
 bool auth_required = true;
 
 void send_auth_request(atransport *t)
 {
-    D("Calling send_auth_request");
-    apacket *p;
-    int ret;
+    LOG(INFO) << "Calling send_auth_request...";
 
-    ret = adb_auth_generate_token(t->token, sizeof(t->token));
-    if (ret != sizeof(t->token)) {
-        D("Error generating token ret=%d", ret);
+    if (!adb_auth_generate_token(t->token, sizeof(t->token))) {
+        PLOG(ERROR) << "Error generating token";
         return;
     }
 
-    p = get_apacket();
-    memcpy(p->data, t->token, ret);
+    apacket* p = get_apacket();
+    memcpy(p->data, t->token, sizeof(t->token));
     p->msg.command = A_AUTH;
     p->msg.arg0 = ADB_AUTH_TOKEN;
-    p->msg.data_length = ret;
+    p->msg.data_length = sizeof(t->token);
     send_packet(p, t);
 }
 
-void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
-{
-    D("Calling send_auth_response");
-    apacket *p = get_apacket();
-    int ret;
+static void send_auth_publickey(atransport* t) {
+    LOG(INFO) << "Calling send_auth_publickey";
 
-    ret = adb_auth_sign(t->key, token, token_size, p->data);
-    if (!ret) {
-        D("Error signing the token");
-        put_apacket(p);
-        return;
-    }
-
-    p->msg.command = A_AUTH;
-    p->msg.arg0 = ADB_AUTH_SIGNATURE;
-    p->msg.data_length = ret;
-    send_packet(p, t);
-}
-
-void send_auth_publickey(atransport *t)
-{
-    D("Calling send_auth_publickey");
     std::string key = adb_auth_get_userkey();
     if (key.empty()) {
         D("Failed to get user public key");
@@ -88,7 +64,33 @@
 
     p->msg.command = A_AUTH;
     p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
-    p->msg.data_length = key.size();
+
+    // adbd expects a null-terminated string.
+    p->msg.data_length = key.size() + 1;
+    send_packet(p, t);
+}
+
+void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
+    std::shared_ptr<RSA> key = t->NextKey();
+    if (key == nullptr) {
+        // No more private keys to try, send the public key.
+        send_auth_publickey(t);
+        return;
+    }
+
+    LOG(INFO) << "Calling send_auth_response";
+    apacket* p = get_apacket();
+
+    int ret = adb_auth_sign(key.get(), token, token_size, p->data);
+    if (!ret) {
+        D("Error signing the token");
+        put_apacket(p);
+        return;
+    }
+
+    p->msg.command = A_AUTH;
+    p->msg.arg0 = ADB_AUTH_SIGNATURE;
+    p->msg.data_length = ret;
     send_packet(p, t);
 }
 
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 6363bb4..59b80d8 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -19,6 +19,11 @@
 
 #include "adb.h"
 
+#include <deque>
+#include <memory>
+
+#include <openssl/rsa.h>
+
 extern bool auth_required;
 
 int adb_auth_keygen(const char* filename);
@@ -26,7 +31,6 @@
 
 void send_auth_request(atransport *t);
 void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
-void send_auth_publickey(atransport *t);
 
 /* AUTH packets first argument */
 /* Request */
@@ -37,36 +41,25 @@
 
 #if ADB_HOST
 
-void adb_auth_init(void);
-int adb_auth_sign(void *key, const unsigned char* token, size_t token_size,
-                  unsigned char* sig);
-void *adb_auth_nextkey(void *current);
+void adb_auth_init();
+int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
 std::string adb_auth_get_userkey();
+std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
 
-static inline int adb_auth_generate_token(void *token, size_t token_size) {
-    return 0;
-}
-static inline int adb_auth_verify(void *token, size_t token_size,
-                                  void *sig, int siglen) {
-    return 0;
-}
-static inline void adb_auth_confirm_key(unsigned char *data, size_t len,
-                                        atransport *t) {}
+static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
+static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); }
+static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { abort(); }
 
 #else // !ADB_HOST
 
-static inline int adb_auth_sign(void* key, const unsigned char* token,
-                                size_t token_size, unsigned char* sig) {
-    return 0;
-}
-static inline void *adb_auth_nextkey(void *current) { return NULL; }
-static inline std::string adb_auth_get_userkey() { return ""; }
+static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); }
+static inline std::string adb_auth_get_userkey() { abort(); }
+static inline std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() { abort(); }
 
 void adbd_auth_init(void);
 void adbd_cloexec_auth_socket();
-int adb_auth_generate_token(void *token, size_t token_size);
-int adb_auth_verify(uint8_t* token, size_t token_size,
-                    uint8_t* sig, int siglen);
+bool adb_auth_generate_token(void* token, size_t token_size);
+bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len);
 void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
 
 #endif // ADB_HOST
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index 415ab8e..84ad6ef 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -16,37 +16,25 @@
 
 #define TRACE_TAG AUTH
 
-#include "sysdeps.h"
+#include "adb.h"
 #include "adb_auth.h"
+#include "fdevent.h"
+#include "sysdeps.h"
+#include "transport.h"
 
 #include <resolv.h>
 #include <stdio.h>
 #include <string.h>
 
+#include <memory>
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <crypto_utils/android_pubkey.h>
 #include <openssl/obj_mac.h>
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 
-#include <crypto_utils/android_pubkey.h>
-
-#include "cutils/list.h"
-#include "cutils/sockets.h"
-
-#include "adb.h"
-#include "fdevent.h"
-#include "transport.h"
-
-struct adb_public_key {
-    struct listnode node;
-    RSA* key;
-};
-
-static const char *key_paths[] = {
-    "/adb_keys",
-    "/data/misc/adb/adb_keys",
-    NULL
-};
-
 static fdevent listener_fde;
 static fdevent framework_fde;
 static int framework_fd = -1;
@@ -56,135 +44,71 @@
 static atransport* usb_transport;
 static bool needs_retry = false;
 
-static void read_keys(const char *file, struct listnode *list)
-{
-    FILE *f;
-    char buf[MAX_PAYLOAD_V1];
-    char *sep;
-    int ret;
+bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) {
+    static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
 
-    f = fopen(file, "re");
-    if (!f) {
-        D("Can't open '%s'", file);
-        return;
-    }
+    for (const auto& path : key_paths) {
+        if (access(path, R_OK) == 0) {
+            LOG(INFO) << "Loading keys from " << path;
 
-    while (fgets(buf, sizeof(buf), f)) {
-        auto key = reinterpret_cast<adb_public_key*>(
-            calloc(1, sizeof(adb_public_key)));
-        if (key == nullptr) {
-            D("Can't malloc key");
-            break;
-        }
+            std::string content;
+            if (!android::base::ReadFileToString(path, &content)) {
+                PLOG(ERROR) << "Couldn't read " << path;
+                continue;
+            }
 
-        sep = strpbrk(buf, " \t");
-        if (sep)
-            *sep = '\0';
+            for (const auto& line : android::base::Split(content, "\n")) {
+                // TODO: do we really have to support both ' ' and '\t'?
+                char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t");
+                if (sep) *sep = '\0';
 
-        // b64_pton requires one additional byte in the target buffer for
-        // decoding to succeed. See http://b/28035006 for details.
-        uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
-        ret = __b64_pton(buf, keybuf, sizeof(keybuf));
-        if (ret != ANDROID_PUBKEY_ENCODED_SIZE) {
-            D("%s: Invalid base64 data ret=%d", file, ret);
-            free(key);
-            continue;
-        }
+                // b64_pton requires one additional byte in the target buffer for
+                // decoding to succeed. See http://b/28035006 for details.
+                uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
+                if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
+                    LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
+                    continue;
+                }
 
-        if (!android_pubkey_decode(keybuf, ret, &key->key)) {
-            D("%s: Failed to parse key", file);
-            free(key);
-            continue;
-        }
+                RSA* key = nullptr;
+                if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
+                    LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path;
+                    continue;
+                }
 
-        list_add_tail(list, &key->node);
-    }
-
-    fclose(f);
-}
-
-static void free_keys(struct listnode *list)
-{
-    struct listnode *item;
-
-    while (!list_empty(list)) {
-        item = list_head(list);
-        list_remove(item);
-        adb_public_key* key = node_to_item(item, struct adb_public_key, node);
-        RSA_free(key->key);
-        free(key);
-    }
-}
-
-static void load_keys(struct listnode *list)
-{
-    const char* path;
-    const char** paths = key_paths;
-    struct stat buf;
-
-    list_init(list);
-
-    while ((path = *paths++)) {
-        if (!stat(path, &buf)) {
-            D("Loading keys from '%s'", path);
-            read_keys(path, list);
+                bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1);
+                RSA_free(key);
+                if (verified) return true;
+            }
         }
     }
+    return false;
 }
 
-int adb_auth_generate_token(void *token, size_t token_size)
-{
-    FILE *f;
-    int ret;
-
-    f = fopen("/dev/urandom", "re");
-    if (!f)
-        return 0;
-
-    ret = fread(token, token_size, 1, f);
-
-    fclose(f);
-    return ret * token_size;
-}
-
-int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen)
-{
-    struct listnode *item;
-    struct listnode key_list;
-    int ret = 0;
-
-    load_keys(&key_list);
-
-    list_for_each(item, &key_list) {
-        adb_public_key* key = node_to_item(item, struct adb_public_key, node);
-        ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key);
-        if (ret)
-            break;
-    }
-
-    free_keys(&key_list);
-
-    return ret;
+bool adb_auth_generate_token(void* token, size_t token_size) {
+    FILE* fp = fopen("/dev/urandom", "re");
+    if (!fp) return false;
+    bool okay = (fread(token, token_size, 1, fp) == 1);
+    fclose(fp);
+    return okay;
 }
 
 static void usb_disconnected(void* unused, atransport* t) {
-    D("USB disconnect");
+    LOG(INFO) << "USB disconnect";
     usb_transport = NULL;
     needs_retry = false;
 }
 
 static void framework_disconnected() {
-    D("Framework disconnect");
+    LOG(INFO) << "Framework disconnect";
     fdevent_remove(&framework_fde);
     framework_fd = -1;
 }
 
 static void adb_auth_event(int fd, unsigned events, void*) {
-    char response[2];
-    int ret;
-
     if (events & FDE_READ) {
-        ret = unix_read(fd, response, sizeof(response));
+        char response[2];
+        int ret = unix_read(fd, response, sizeof(response));
         if (ret <= 0) {
             framework_disconnected();
         } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
@@ -195,51 +119,41 @@
     }
 }
 
-void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
-{
-    char msg[MAX_PAYLOAD_V1];
-    int ret;
-
+void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) {
     if (!usb_transport) {
         usb_transport = t;
         t->AddDisconnect(&usb_disconnect);
     }
 
     if (framework_fd < 0) {
-        D("Client not connected");
+        LOG(ERROR) << "Client not connected";
         needs_retry = true;
         return;
     }
 
     if (key[len - 1] != '\0') {
-        D("Key must be a null-terminated string");
+        LOG(ERROR) << "Key must be a null-terminated string";
         return;
     }
 
-    ret = snprintf(msg, sizeof(msg), "PK%s", key);
-    if (ret >= (signed)sizeof(msg)) {
-        D("Key too long. ret=%d", ret);
+    char msg[MAX_PAYLOAD_V1];
+    int msg_len = snprintf(msg, sizeof(msg), "PK%s", key);
+    if (msg_len >= static_cast<int>(sizeof(msg))) {
+        LOG(ERROR) << "Key too long (" << msg_len << ")";
         return;
     }
-    D("Sending '%s'", msg);
+    LOG(DEBUG) << "Sending '" << msg << "'";
 
-    ret = unix_write(framework_fd, msg, ret);
-    if (ret < 0) {
-        D("Failed to write PK, errno=%d", errno);
+    if (unix_write(framework_fd, msg, msg_len) == -1) {
+        PLOG(ERROR) << "Failed to write PK";
         return;
     }
 }
 
 static void adb_auth_listener(int fd, unsigned events, void* data) {
-    sockaddr_storage addr;
-    socklen_t alen;
-    int s;
-
-    alen = sizeof(addr);
-
-    s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
+    int s = adb_socket_accept(fd, nullptr, nullptr);
     if (s < 0) {
-        D("Failed to accept: errno=%d", errno);
+        PLOG(ERROR) << "Failed to accept";
         return;
     }
 
@@ -261,7 +175,7 @@
 void adbd_cloexec_auth_socket() {
     int fd = android_get_control_socket("adbd");
     if (fd == -1) {
-        D("Failed to get adbd socket");
+        PLOG(ERROR) << "Failed to get adbd socket";
         return;
     }
     fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -270,12 +184,12 @@
 void adbd_auth_init(void) {
     int fd = android_get_control_socket("adbd");
     if (fd == -1) {
-        D("Failed to get adbd socket");
+        PLOG(ERROR) << "Failed to get adbd socket";
         return;
     }
 
     if (listen(fd, 4) == -1) {
-        D("Failed to listen on '%d'", fd);
+        PLOG(ERROR) << "Failed to listen on '" << fd << "'";
         return;
     }
 
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index dff874f..8366549 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -16,23 +16,24 @@
 
 #define TRACE_TAG AUTH
 
-#include "sysdeps.h"
-#include "adb_auth.h"
-#include "adb_utils.h"
-
+#include <dirent.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#if defined(__linux__)
+#include <sys/inotify.h>
+#endif
 
-#include "adb.h"
+#include <map>
+#include <mutex>
+#include <set>
+#include <string>
 
 #include <android-base/errors.h>
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <crypto_utils/android_pubkey.h>
-#include <cutils/list.h>
-
 #include <openssl/base64.h>
 #include <openssl/evp.h>
 #include <openssl/objects.h>
@@ -40,18 +41,20 @@
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 
-#define ANDROID_PATH   ".android"
-#define ADB_KEY_FILE   "adbkey"
+#include "adb.h"
+#include "adb_auth.h"
+#include "adb_utils.h"
+#include "sysdeps.h"
+#include "sysdeps/mutex.h"
 
-struct adb_private_key {
-    struct listnode node;
-    RSA *rsa;
-};
-
-static struct listnode key_list;
-
+static std::mutex& g_keys_mutex = *new std::mutex;
+static std::map<std::string, std::shared_ptr<RSA>>& g_keys =
+    *new std::map<std::string, std::shared_ptr<RSA>>;
+static std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
 
 static std::string get_user_info() {
+    LOG(INFO) << "get_user_info...";
+
     std::string hostname;
     if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
 #if !defined(_WIN32)
@@ -71,6 +74,8 @@
 }
 
 static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
+    LOG(INFO) << "write_public_keyfile...";
+
     uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
     if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
         LOG(ERROR) << "Failed to convert to public key";
@@ -99,19 +104,18 @@
     return true;
 }
 
-static int generate_key(const char *file)
-{
-    EVP_PKEY* pkey = EVP_PKEY_new();
-    BIGNUM* exponent = BN_new();
-    RSA* rsa = RSA_new();
+static int generate_key(const std::string& file) {
+    LOG(INFO) << "generate_key(" << file << ")...";
+
     mode_t old_mask;
     FILE *f = NULL;
     int ret = 0;
 
-    D("generate_key '%s'", file);
-
+    EVP_PKEY* pkey = EVP_PKEY_new();
+    BIGNUM* exponent = BN_new();
+    RSA* rsa = RSA_new();
     if (!pkey || !exponent || !rsa) {
-        D("Failed to allocate key");
+        LOG(ERROR) << "Failed to allocate key";
         goto out;
     }
 
@@ -121,9 +125,9 @@
 
     old_mask = umask(077);
 
-    f = fopen(file, "w");
+    f = fopen(file.c_str(), "w");
     if (!f) {
-        D("Failed to open '%s'", file);
+        PLOG(ERROR) << "Failed to open " << file;
         umask(old_mask);
         goto out;
     }
@@ -143,110 +147,165 @@
     ret = 1;
 
 out:
-    if (f)
-        fclose(f);
+    if (f) fclose(f);
     EVP_PKEY_free(pkey);
     RSA_free(rsa);
     BN_free(exponent);
     return ret;
 }
 
-static int read_key(const char *file, struct listnode *list)
-{
-    D("read_key '%s'", file);
+static std::string hash_key(RSA* key) {
+    unsigned char* pubkey = nullptr;
+    int len = i2d_RSA_PUBKEY(key, &pubkey);
+    if (len < 0) {
+        LOG(ERROR) << "failed to encode RSA public key";
+        return std::string();
+    }
 
-    FILE* fp = fopen(file, "r");
+    std::string result;
+    result.resize(SHA256_DIGEST_LENGTH);
+    SHA256(pubkey, len, reinterpret_cast<unsigned char*>(&result[0]));
+    OPENSSL_free(pubkey);
+    return result;
+}
+
+static bool read_key_file(const std::string& file) {
+    LOG(INFO) << "read_key_file '" << file << "'...";
+
+    std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
     if (!fp) {
-        D("Failed to open '%s': %s", file, strerror(errno));
-        return 0;
+        PLOG(ERROR) << "Failed to open '" << file << "'";
+        return false;
     }
 
-    adb_private_key* key = new adb_private_key;
-    key->rsa = RSA_new();
-
-    if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
-        D("Failed to read key");
-        fclose(fp);
-        RSA_free(key->rsa);
-        delete key;
-        return 0;
+    RSA* key = RSA_new();
+    if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
+        LOG(ERROR) << "Failed to read key";
+        RSA_free(key);
+        return false;
     }
 
-    fclose(fp);
-    list_add_tail(list, &key->node);
-    return 1;
+    std::lock_guard<std::mutex> lock(g_keys_mutex);
+    std::string fingerprint = hash_key(key);
+    if (g_keys.find(fingerprint) != g_keys.end()) {
+        LOG(INFO) << "ignoring already-loaded key: " << file;
+        RSA_free(key);
+    } else {
+        g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
+    }
+
+    return true;
 }
 
-static int get_user_keyfilepath(char *filename, size_t len)
-{
-    const std::string home = adb_get_homedir_path(true);
-    D("home '%s'", home.c_str());
+static bool read_keys(const std::string& path, bool allow_dir = true) {
+    LOG(INFO) << "read_keys '" << path << "'...";
 
-    const std::string android_dir =
-            android::base::StringPrintf("%s%c%s", home.c_str(),
-                                        OS_PATH_SEPARATOR, ANDROID_PATH);
+    struct stat st;
+    if (stat(path.c_str(), &st) != 0) {
+        PLOG(ERROR) << "failed to stat '" << path << "'";
+        return false;
+    }
 
-    struct stat buf;
-    if (stat(android_dir.c_str(), &buf)) {
-        if (adb_mkdir(android_dir.c_str(), 0750) < 0) {
-            D("Cannot mkdir '%s'", android_dir.c_str());
-            return -1;
+    if (S_ISREG(st.st_mode)) {
+        if (!android::base::EndsWith(path, ".adb_key")) {
+            LOG(INFO) << "skipping non-adb_key '" << path << "'";
+            return false;
         }
+
+        return read_key_file(path);
+    } else if (S_ISDIR(st.st_mode)) {
+        if (!allow_dir) {
+            // inotify isn't recursive. It would break expectations to load keys in nested
+            // directories but not monitor them for new keys.
+            LOG(WARNING) << "refusing to recurse into directory '" << path << "'";
+            return false;
+        }
+
+        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
+        if (!dir) {
+            PLOG(ERROR) << "failed to open directory '" << path << "'";
+            return false;
+        }
+
+        bool result = false;
+        while (struct dirent* dent = readdir(dir.get())) {
+            std::string name = dent->d_name;
+
+            // We can't use dent->d_type here because it's not available on Windows.
+            if (name == "." || name == "..") {
+                continue;
+            }
+
+            result |= read_keys((path + OS_PATH_SEPARATOR + name).c_str(), false);
+        }
+        return result;
     }
 
-    return snprintf(filename, len, "%s%c%s",
-                    android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE);
+    LOG(ERROR) << "unexpected type for '" << path << "': 0x" << std::hex << st.st_mode;
+    return false;
 }
 
-static int get_user_key(struct listnode *list)
-{
-    struct stat buf;
-    char path[PATH_MAX];
-    int ret;
+static std::string get_user_key_path() {
+    return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adbkey";
+}
 
-    ret = get_user_keyfilepath(path, sizeof(path));
-    if (ret < 0 || ret >= (signed)sizeof(path)) {
-        D("Error getting user key filename");
-        return 0;
+static bool get_user_key() {
+    std::string path = get_user_key_path();
+    if (path.empty()) {
+        PLOG(ERROR) << "Error getting user key filename";
+        return false;
     }
 
-    D("user key '%s'", path);
-
-    if (stat(path, &buf) == -1) {
+    struct stat buf;
+    if (stat(path.c_str(), &buf) == -1) {
+        LOG(INFO) << "User key '" << path << "' does not exist...";
         if (!generate_key(path)) {
-            D("Failed to generate new key");
-            return 0;
+            LOG(ERROR) << "Failed to generate new key";
+            return false;
         }
     }
 
-    return read_key(path, list);
+    return read_key_file(path);
 }
 
-static void get_vendor_keys(struct listnode* key_list) {
+static std::set<std::string> get_vendor_keys() {
     const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
     if (adb_keys_path == nullptr) {
-        return;
+        return std::set<std::string>();
     }
 
+    std::set<std::string> result;
     for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
-        if (!read_key(path.c_str(), key_list)) {
-            D("Failed to read '%s'", path.c_str());
-        }
+        result.emplace(path);
     }
+    return result;
 }
 
-int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
-                  unsigned char* sig)
-{
-    unsigned int len;
-    struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
+std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() {
+    std::deque<std::shared_ptr<RSA>> result;
 
+    // Copy all the currently known keys.
+    std::lock_guard<std::mutex> lock(g_keys_mutex);
+    for (const auto& it : g_keys) {
+        result.push_back(it.second);
+    }
+
+    // Add a sentinel to the list. Our caller uses this to mean "out of private keys,
+    // but try using the public key" (the empty deque could otherwise mean this _or_
+    // that this function hasn't been called yet to request the keys).
+    result.push_back(nullptr);
+
+    return result;
+}
+
+int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
     if (token_size != TOKEN_SIZE) {
         D("Unexpected token size %zd", token_size);
         return 0;
     }
 
-    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) {
+    unsigned int len;
+    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
         return 0;
     }
 
@@ -254,40 +313,17 @@
     return (int)len;
 }
 
-void *adb_auth_nextkey(void *current)
-{
-    struct listnode *item;
-
-    if (list_empty(&key_list))
-        return NULL;
-
-    if (!current)
-        return list_head(&key_list);
-
-    list_for_each(item, &key_list) {
-        if (item == current) {
-            /* current is the last item, we tried all the keys */
-            if (item->next == &key_list)
-                return NULL;
-            return item->next;
-        }
-    }
-
-    return NULL;
-}
-
 std::string adb_auth_get_userkey() {
-    char path[PATH_MAX];
-    int ret = get_user_keyfilepath(path, sizeof(path) - 4);
-    if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
-        D("Error getting user key filename");
+    std::string path = get_user_key_path();
+    if (path.empty()) {
+        PLOG(ERROR) << "Error getting user key filename";
         return "";
     }
-    strcat(path, ".pub");
+    path += ".pub";
 
     std::string content;
     if (!android::base::ReadFileToString(path, &content)) {
-        D("Can't load '%s'", path);
+        PLOG(ERROR) << "Can't load '" << path << "'";
         return "";
     }
     return content;
@@ -297,19 +333,92 @@
     return (generate_key(filename) == 0);
 }
 
-void adb_auth_init(void)
-{
-    int ret;
-
-    D("adb_auth_init");
-
-    list_init(&key_list);
-
-    ret = get_user_key(&key_list);
-    if (!ret) {
-        D("Failed to get user key");
+#if defined(__linux__)
+static void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
+    LOG(INFO) << "adb_auth_inotify_update called";
+    if (!(fd_event & FDE_READ)) {
         return;
     }
 
-    get_vendor_keys(&key_list);
+    char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
+    while (true) {
+        ssize_t rc = TEMP_FAILURE_RETRY(unix_read(fd, buf, sizeof(buf)));
+        if (rc == -1) {
+            if (errno == EAGAIN) {
+                LOG(INFO) << "done reading inotify fd";
+                break;
+            }
+            PLOG(FATAL) << "read of inotify event failed";
+        }
+
+        // The read potentially returned multiple events.
+        char* start = buf;
+        char* end = buf + rc;
+
+        while (start < end) {
+            inotify_event* event = reinterpret_cast<inotify_event*>(start);
+            auto root_it = g_monitored_paths.find(event->wd);
+            if (root_it == g_monitored_paths.end()) {
+                LOG(FATAL) << "observed inotify event for unmonitored path, wd = " << event->wd;
+            }
+
+            std::string path = root_it->second;
+            if (event->len > 0) {
+                path += '/';
+                path += event->name;
+            }
+
+            if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
+                if (event->mask & IN_ISDIR) {
+                    LOG(INFO) << "ignoring new directory at '" << path << "'";
+                } else {
+                    LOG(INFO) << "observed new file at '" << path << "'";
+                    read_keys(path, false);
+                }
+            } else {
+                LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
+                             << event->mask;
+            }
+
+            start += sizeof(struct inotify_event) + event->len;
+        }
+    }
+}
+
+static void adb_auth_inotify_init(const std::set<std::string>& paths) {
+    LOG(INFO) << "adb_auth_inotify_init...";
+    int infd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
+    for (const std::string& path : paths) {
+        int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
+        if (wd < 0) {
+            PLOG(ERROR) << "failed to inotify_add_watch on path '" << path;
+            continue;
+        }
+
+        g_monitored_paths[wd] = path;
+        LOG(INFO) << "watch descriptor " << wd << " registered for " << path;
+    }
+
+    fdevent* event = fdevent_create(infd, adb_auth_inotify_update, nullptr);
+    fdevent_add(event, FDE_READ);
+}
+#endif
+
+void adb_auth_init() {
+    LOG(INFO) << "adb_auth_init...";
+
+    if (!get_user_key()) {
+        LOG(ERROR) << "Failed to get user key";
+        return;
+    }
+
+    const auto& key_paths = get_vendor_keys();
+
+#if defined(__linux__)
+    adb_auth_inotify_init(key_paths);
+#endif
+
+    for (const std::string& path : key_paths) {
+        read_keys(path.c_str());
+    }
 }
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index a27dd47..919e1c1 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -37,12 +37,12 @@
 
 #include "adb_io.h"
 #include "adb_utils.h"
+#include "socket_spec.h"
 
 static TransportType __adb_transport = kTransportAny;
 static const char* __adb_serial = NULL;
 
-static int __adb_server_port = DEFAULT_ADB_PORT;
-static const char* __adb_server_name = NULL;
+static const char* __adb_server_socket_spec;
 
 void adb_set_transport(TransportType type, const char* serial)
 {
@@ -59,14 +59,11 @@
     }
 }
 
-void adb_set_tcp_specifics(int server_port)
-{
-    __adb_server_port = server_port;
-}
-
-void adb_set_tcp_name(const char* hostname)
-{
-    __adb_server_name = hostname;
+void adb_set_socket_spec(const char* socket_spec) {
+    if (__adb_server_socket_spec) {
+        LOG(FATAL) << "attempted to reinitialize adb_server_socket_spec " << socket_spec << " (was " << __adb_server_socket_spec << ")";
+    }
+    __adb_server_socket_spec = socket_spec;
 }
 
 static int switch_socket_transport(int fd, std::string* error) {
@@ -139,23 +136,12 @@
         return -1;
     }
 
-    int fd;
     std::string reason;
-    if (__adb_server_name) {
-        fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
-        if (fd == -1) {
-            *error = android::base::StringPrintf("can't connect to %s:%d: %s",
-                                                 __adb_server_name, __adb_server_port,
-                                                 reason.c_str());
-            return -2;
-        }
-    } else {
-        fd = network_loopback_client(__adb_server_port, SOCK_STREAM, &reason);
-        if (fd == -1) {
-            *error = android::base::StringPrintf("cannot connect to daemon: %s",
-                                                 reason.c_str());
-            return -2;
-        }
+    int fd = socket_spec_connect(__adb_server_socket_spec, &reason);
+    if (fd < 0) {
+        *error = android::base::StringPrintf("cannot connect to daemon at %s: %s",
+                                             __adb_server_socket_spec, reason.c_str());
+        return -2;
     }
 
     if ((memcmp(&service[0],"host",4) != 0 || service == "host:reconnect") &&
@@ -185,15 +171,14 @@
     int fd = _adb_connect("host:version", error);
 
     D("adb_connect: service %s", service.c_str());
-    if (fd == -2 && __adb_server_name) {
+    if (fd == -2 && !is_local_socket_spec(__adb_server_socket_spec)) {
         fprintf(stderr,"** Cannot start server on remote host\n");
         // error is the original network connection error
         return fd;
     } else if (fd == -2) {
-        fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
-                __adb_server_port);
+        fprintf(stdout, "* daemon not running. starting it now at %s *\n", __adb_server_socket_spec);
     start_server:
-        if (launch_server(__adb_server_port)) {
+        if (launch_server(__adb_server_socket_spec)) {
             fprintf(stderr,"* failed to start daemon *\n");
             // launch_server() has already printed detailed error info, so just
             // return a generic error string about the overall adb_connect()
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 9f9eb1f..d35d705 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -43,11 +43,9 @@
 // Get the preferred transport to connect to.
 void adb_get_transport(TransportType* _Nullable type, const char* _Nullable* _Nullable serial);
 
-// Set TCP specifics of the transport to use.
-void adb_set_tcp_specifics(int server_port);
-
-// Set TCP Hostname of the transport to use.
-void adb_set_tcp_name(const char* _Nullable hostname);
+// Set the socket specification for the adb server.
+// This function can only be called once, and the argument must live to the end of the process.
+void adb_set_socket_spec(const char* _Nonnull socket_spec);
 
 // Send commands to the current emulator instance. Will fail if there is not
 // exactly one emulator connected (or if you use -s <serial> with a <serial>
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index f54603c..18b1492 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -23,12 +23,10 @@
 #include <android-base/strings.h>
 #include <cutils/sockets.h>
 
+#include "socket_spec.h"
 #include "sysdeps.h"
 #include "transport.h"
 
-// Not static because it is used in commandline.c.
-int gListenAll = 0;
-
 // A listener is an entity which binds to a local port and, upon receiving a connection on that
 // port, creates an asocket to connect the new local connection to a specific remote service.
 //
@@ -71,10 +69,7 @@
 
 static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
     if (ev & FDE_READ) {
-        sockaddr_storage ss;
-        sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
-        socklen_t alen = sizeof(ss);
-        int fd = adb_socket_accept(_fd, addrp, &alen);
+        int fd = adb_socket_accept(_fd, nullptr, nullptr);
         if (fd < 0) return;
 
         int rcv_buf_size = CHUNK_SIZE;
@@ -96,13 +91,7 @@
     asocket *s;
 
     if (ev & FDE_READ) {
-        sockaddr_storage ss;
-        sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
-        socklen_t alen;
-        int fd;
-
-        alen = sizeof(ss);
-        fd = adb_socket_accept(_fd, addrp, &alen);
+        int fd = adb_socket_accept(_fd, nullptr, nullptr);
         if (fd < 0) {
             return;
         }
@@ -129,48 +118,6 @@
     }
 }
 
-int local_name_to_fd(alistener* listener, int* resolved_tcp_port, std::string* error) {
-    if (android::base::StartsWith(listener->local_name, "tcp:")) {
-        int requested_port = atoi(&listener->local_name[4]);
-        int sock = -1;
-        if (gListenAll > 0) {
-            sock = network_inaddr_any_server(requested_port, SOCK_STREAM, error);
-        } else {
-            sock = network_loopback_server(requested_port, SOCK_STREAM, error);
-        }
-
-        // If the caller requested port 0, update the listener name with the resolved port.
-        if (sock >= 0 && requested_port == 0) {
-            int local_port = adb_socket_get_local_port(sock);
-            if (local_port > 0) {
-                listener->local_name = android::base::StringPrintf("tcp:%d", local_port);
-                if (resolved_tcp_port != nullptr) {
-                    *resolved_tcp_port = local_port;
-                }
-            }
-        }
-
-        return sock;
-    }
-#if !defined(_WIN32)  // No Unix-domain sockets on Windows.
-    // It's nonsensical to support the "reserved" space on the adb host side.
-    if (android::base::StartsWith(listener->local_name, "local:")) {
-        return network_local_server(&listener->local_name[6], ANDROID_SOCKET_NAMESPACE_ABSTRACT,
-                                    SOCK_STREAM, error);
-    } else if (android::base::StartsWith(listener->local_name, "localabstract:")) {
-        return network_local_server(&listener->local_name[14], ANDROID_SOCKET_NAMESPACE_ABSTRACT,
-                                    SOCK_STREAM, error);
-    } else if (android::base::StartsWith(listener->local_name, "localfilesystem:")) {
-        return network_local_server(&listener->local_name[16], ANDROID_SOCKET_NAMESPACE_FILESYSTEM,
-                                    SOCK_STREAM, error);
-    }
-
-#endif
-    *error = android::base::StringPrintf("unknown local portname '%s'",
-                                         listener->local_name.c_str());
-    return -1;
-}
-
 // Write the list of current listeners (network redirections) into a string.
 std::string format_listeners() {
     std::string result;
@@ -239,11 +186,20 @@
 
     std::unique_ptr<alistener> listener(new alistener(local_name, connect_to));
 
-    listener->fd = local_name_to_fd(listener.get(), resolved_tcp_port, error);
+    int resolved = 0;
+    listener->fd = socket_spec_listen(listener->local_name, error, &resolved);
     if (listener->fd < 0) {
         return INSTALL_STATUS_CANNOT_BIND;
     }
 
+    // If the caller requested port 0, update the listener name with the resolved port.
+    if (resolved != 0) {
+        listener->local_name = android::base::StringPrintf("tcp:%d", resolved);
+        if (resolved_tcp_port) {
+            *resolved_tcp_port = resolved;
+        }
+    }
+
     close_on_exec(listener->fd);
     if (listener->connect_to == "*smartsocket*") {
         fdevent_install(&listener->fde, listener->fd, ss_listener_event_func, listener.get());
diff --git a/crash_reporter/warn_collector_test.c b/adb/adb_unique_fd.h
similarity index 66%
rename from crash_reporter/warn_collector_test.c
rename to adb/adb_unique_fd.h
index 7ebe0a8..34c1bbc 100644
--- a/crash_reporter/warn_collector_test.c
+++ b/adb/adb_unique_fd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-/*
- * Test driver for the warn_collector daemon.
- */
-#include <stdlib.h>
+#pragma once
 
-int main(int ac, char **av) {
-  int status = system("exec \"${SRC}\"/warn_collector_test.sh");
-  return status < 0 ? EXIT_FAILURE : WEXITSTATUS(status);
-}
+#include <android-base/unique_fd.h>
+
+// Helper to automatically close an FD when it goes out of scope.
+struct AdbCloser {
+    static void Close(int fd);
+};
+
+using unique_fd = android::base::unique_fd_impl<AdbCloser>;
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 31ec8af..db39ef4 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -17,6 +17,7 @@
 #define TRACE_TAG ADB
 
 #include "adb_utils.h"
+#include "adb_unique_fd.h"
 
 #include <libgen.h>
 #include <stdlib.h>
@@ -25,6 +26,7 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <vector>
 
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
@@ -41,6 +43,8 @@
 #  endif
 #  include "windows.h"
 #  include "shlobj.h"
+#else
+#include <pwd.h>
 #endif
 
 ADB_MUTEX_DEFINE(basename_lock);
@@ -263,14 +267,8 @@
     return true;
 }
 
-std::string adb_get_homedir_path(bool check_env_first) {
+std::string adb_get_homedir_path() {
 #ifdef _WIN32
-    if (check_env_first) {
-        if (const char* const home = getenv("ANDROID_SDK_HOME")) {
-            return home;
-        }
-    }
-
     WCHAR path[MAX_PATH];
     const HRESULT hr = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path);
     if (FAILED(hr)) {
@@ -286,6 +284,33 @@
     if (const char* const home = getenv("HOME")) {
         return home;
     }
+
+    struct passwd pwent;
+    struct passwd* result;
+    int pwent_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+    std::vector<char> buf(pwent_max);
+    int rc = getpwuid_r(getuid(), &pwent, buf.data(), buf.size(), &result);
+    if (rc == 0 && result) {
+        return result->pw_dir;
+    }
+
+    LOG(FATAL) << "failed to get user home directory";
     return {};
 #endif
 }
+
+std::string adb_get_android_dir_path() {
+    std::string user_dir = adb_get_homedir_path();
+    std::string android_dir = user_dir + OS_PATH_SEPARATOR + ".android";
+    struct stat buf;
+    if (stat(android_dir.c_str(), &buf) == -1) {
+        if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
+            PLOG(FATAL) << "Cannot mkdir '" << android_dir << "'";
+        }
+    }
+    return android_dir;
+}
+
+void AdbCloser::Close(int fd) {
+    adb_close(fd);
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index f6b4b26..16317e0 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -20,7 +20,6 @@
 #include <string>
 
 #include <android-base/macros.h>
-#include <android-base/unique_fd.h>
 
 void close_stdin();
 
@@ -33,10 +32,10 @@
 std::string adb_dirname(const std::string& path);
 
 // Return the user's home directory.
-// |check_env_first| - if true, on Windows check the ANDROID_SDK_HOME
-// environment variable before trying the WinAPI call (useful when looking for
-// the .android directory)
-std::string adb_get_homedir_path(bool check_env_first);
+std::string adb_get_homedir_path();
+
+// Return the adb user directory.
+std::string adb_get_android_dir_path();
 
 bool mkdirs(const std::string& path);
 
@@ -57,13 +56,4 @@
 bool forward_targets_are_valid(const std::string& source, const std::string& dest,
                                std::string* error);
 
-// Helper to automatically close an FD when it goes out of scope.
-struct AdbCloser {
-    static void Close(int fd) {
-        adb_close(fd);
-    }
-};
-
-using unique_fd = android::base::unique_fd_impl<AdbCloser>;
-
 #endif
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
index 9ed44a7..c348dd5 100644
--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -47,7 +47,7 @@
           show_progress_(show_progress),
           status_(0),
           line_() {
-        SetLineMessage();
+        SetLineMessage("generating");
     }
 
     void OnStdout(const char* buffer, int length) {
@@ -97,6 +97,7 @@
                                                           OS_PATH_SEPARATOR, dest_file_.c_str());
             }
             std::vector<const char*> srcs{src_file_.c_str()};
+            SetLineMessage("pulling");
             status_ =
                 br_->DoSyncPull(srcs, destination.c_str(), true, line_message_.c_str()) ? 0 : 1;
             if (status_ != 0) {
@@ -111,9 +112,8 @@
     }
 
   private:
-    void SetLineMessage() {
-        line_message_ =
-            android::base::StringPrintf("generating %s", adb_basename(dest_file_).c_str());
+    void SetLineMessage(const std::string& action) {
+        line_message_ = action + " " + adb_basename(dest_file_);
     }
 
     void SetSrcFile(const std::string path) {
@@ -121,7 +121,7 @@
         if (!dest_dir_.empty()) {
             // Only uses device-provided name when user passed a directory.
             dest_file_ = adb_basename(path);
-            SetLineMessage();
+            SetLineMessage("generating");
         }
     }
 
diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp
index 3cd2b6d..1129285 100644
--- a/adb/bugreport_test.cpp
+++ b/adb/bugreport_test.cpp
@@ -189,7 +189,7 @@
         .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport"};
@@ -209,7 +209,7 @@
                         WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport"};
@@ -223,7 +223,7 @@
         .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file.zip"};
@@ -239,7 +239,7 @@
                         WithArg<4>(WriteOnStdout("/bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file.zip"};
@@ -275,7 +275,7 @@
             WithArg<4>(ReturnCallbackDone())));
     // clang-format on
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file.zip"};
@@ -294,7 +294,7 @@
                         WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", td.path};
@@ -308,7 +308,7 @@
         .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
-                                true, StrEq("generating file.zip")))
+                                true, StrEq("pulling file.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", "file"};
@@ -327,7 +327,7 @@
                         WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
                         WithArg<4>(ReturnCallbackDone())));
     EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
-                                true, StrEq("generating da_bugreport.zip")))
+                                true, StrEq("pulling da_bugreport.zip")))
         .WillOnce(Return(true));
 
     const char* args[] = {"bugreport", td.path};
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 894ebd1..571c227 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -88,7 +88,7 @@
 }
 #endif
 
-int adb_server_main(int is_daemon, int server_port, int ack_reply_fd) {
+int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
 #if defined(_WIN32)
     // adb start-server starts us up with stdout and stderr hooked up to
     // anonymous pipes. When the C Runtime sees this, it makes stderr and
@@ -111,19 +111,20 @@
 
     usb_init();
     local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
-    adb_auth_init();
 
     std::string error;
-    std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
-    if (install_listener(local_name, "*smartsocket*", nullptr, 0, nullptr, &error)) {
+    if (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error)) {
         fatal("could not install *smartsocket* listener: %s", error.c_str());
     }
 
-    // Inform our parent that we are up and running.
     if (is_daemon) {
         close_stdin();
         setup_daemon_logging();
+    }
 
+    adb_auth_init();
+
+    if (is_daemon) {
 #if !defined(_WIN32)
         // Start a new session for the daemon. Do this here instead of after the fork so
         // that a ctrl-c between the "starting server" and "done starting server" messages
@@ -133,6 +134,8 @@
         }
 #endif
 
+        // Inform our parent that we are up and running.
+
         // Any error output written to stderr now goes to adb.log. We could
         // keep around a copy of the stderr fd and use that to write any errors
         // encountered by the following code, but that is probably overkill.
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index c69fe19..77c5f96 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -51,6 +51,7 @@
 #include "adb_auth.h"
 #include "adb_client.h"
 #include "adb_io.h"
+#include "adb_unique_fd.h"
 #include "adb_utils.h"
 #include "bugreport.h"
 #include "commandline.h"
@@ -100,6 +101,8 @@
         "                                 be an absolute path.\n"
         " -H                            - Name of adb server host (default: localhost)\n"
         " -P                            - Port of adb server (default: 5037)\n"
+        " -L <socket>                   - listen on socket specifier for the adb server\n"
+        "                                 (default: tcp:localhost:5037)\n"
         " devices [-l]                  - list all connected devices\n"
         "                                 ('-l' will also list device qualifiers)\n"
         " connect <host>[:<port>]       - connect to a device via TCP/IP\n"
@@ -1453,18 +1456,9 @@
     }
     // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
 
-    /* Validate and assign the server port */
-    const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
-    int server_port = DEFAULT_ADB_PORT;
-    if (server_port_str && strlen(server_port_str) > 0) {
-        server_port = strtol(server_port_str, nullptr, 0);
-        if (server_port <= 0 || server_port > 65535) {
-            fprintf(stderr,
-                    "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65536. Got \"%s\"\n",
-                    server_port_str);
-            return usage();
-        }
-    }
+    const char* server_host_str = nullptr;
+    const char* server_port_str = nullptr;
+    const char* server_socket_str = nullptr;
 
     // We need to check for -d and -e before we look at $ANDROID_SERIAL.
     const char* serial = nullptr;
@@ -1518,17 +1512,14 @@
         } else if (!strcmp(argv[0],"-a")) {
             gListenAll = 1;
         } else if (!strncmp(argv[0], "-H", 2)) {
-            const char *hostname = NULL;
             if (argv[0][2] == '\0') {
                 if (argc < 2) return usage();
-                hostname = argv[1];
+                server_host_str = argv[1];
                 argc--;
                 argv++;
             } else {
-                hostname = argv[0] + 2;
+                server_host_str = argv[0] + 2;
             }
-            adb_set_tcp_name(hostname);
-
         } else if (!strncmp(argv[0], "-P", 2)) {
             if (argv[0][2] == '\0') {
                 if (argc < 2) return usage();
@@ -1538,34 +1529,58 @@
             } else {
                 server_port_str = argv[0] + 2;
             }
-            if (strlen(server_port_str) > 0) {
-                server_port = (int) strtol(server_port_str, NULL, 0);
-                if (server_port <= 0 || server_port > 65535) {
-                    fprintf(stderr,
-                            "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
-                            server_port_str);
-                    return usage();
-                }
-            } else {
-                fprintf(stderr,
-                "adb: port number must be a positive number less than 65536. Got empty string.\n");
-                return usage();
-            }
+        } else if (!strcmp(argv[0], "-L")) {
+            if (argc < 2) return usage();
+            server_socket_str = argv[1];
+            argc--;
+            argv++;
         } else {
-                /* out of recognized modifiers and flags */
+            /* out of recognized modifiers and flags */
             break;
         }
         argc--;
         argv++;
     }
 
+    if ((server_host_str || server_port_str) && server_socket_str) {
+        fprintf(stderr, "adb: -L is incompatible with -H or -P\n");
+        exit(1);
+    }
+
+    // If -L, -H, or -P are specified, ignore environment variables.
+    // Otherwise, prefer ADB_SERVER_SOCKET over ANDROID_ADB_SERVER_ADDRESS/PORT.
+    if (!(server_host_str || server_port_str || server_socket_str)) {
+        server_socket_str = server_socket_str ? server_socket_str : getenv("ADB_SERVER_SOCKET");
+    }
+
+    if (!server_socket_str) {
+        // tcp:1234 and tcp:localhost:1234 are different with -a, so don't default to localhost
+        server_host_str = server_host_str ? server_host_str : getenv("ANDROID_ADB_SERVER_ADDRESS");
+
+        long server_port = DEFAULT_ADB_PORT;
+        server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
+
+        int rc;
+        char* temp;
+        if (server_host_str) {
+            rc = asprintf(&temp, "tcp:%s:%ld", server_host_str, server_port);
+        } else {
+            rc = asprintf(&temp, "tcp:%ld", server_port);
+        }
+        if (rc < 0) {
+            fatal("failed to allocate server socket specification");
+        }
+        server_socket_str = temp;
+    }
+
+    adb_set_socket_spec(server_socket_str);
+
     // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
     if (transport_type == kTransportAny && serial == nullptr) {
         serial = getenv("ANDROID_SERIAL");
     }
 
     adb_set_transport(transport_type, serial);
-    adb_set_tcp_specifics(server_port);
 
     if (is_server) {
         if (no_daemon || is_daemon) {
@@ -1573,9 +1588,9 @@
                 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
                 return usage();
             }
-            r = adb_server_main(is_daemon, server_port, ack_reply_fd);
+            r = adb_server_main(is_daemon, server_socket_str, ack_reply_fd);
         } else {
-            r = launch_server(server_port);
+            r = launch_server(server_socket_str);
         }
         if (r) {
             fprintf(stderr,"* could not start server *\n");
diff --git a/adb/console.cpp b/adb/console.cpp
index e9b90a5..9563eac 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -32,7 +32,7 @@
 static std::string adb_construct_auth_command() {
     static const char auth_token_filename[] = ".emulator_console_auth_token";
 
-    std::string auth_token_path = adb_get_homedir_path(false);
+    std::string auth_token_path = adb_get_homedir_path();
     auth_token_path += OS_PATH_SEPARATOR;
     auth_token_path += auth_token_filename;
 
diff --git a/adb/get_my_path_darwin.cpp b/adb/get_my_path_darwin.cpp
deleted file mode 100644
index b0c962e..0000000
--- a/adb/get_my_path_darwin.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#import <Carbon/Carbon.h>
-#include <unistd.h>
-
-#include "adb.h"
-
-void get_my_path(char *s, size_t maxLen)
-{
-    CFBundleRef mainBundle = CFBundleGetMainBundle();
-    CFURLRef executableURL = CFBundleCopyExecutableURL(mainBundle);
-    CFStringRef executablePathString = CFURLCopyFileSystemPath(executableURL, kCFURLPOSIXPathStyle);
-    CFRelease(executableURL);
-
-    CFStringGetFileSystemRepresentation(executablePathString, s, maxLen);
-    CFRelease(executablePathString);
-}
-
diff --git a/adb/get_my_path_linux.cpp b/adb/get_my_path_linux.cpp
deleted file mode 100644
index 11c0b21..0000000
--- a/adb/get_my_path_linux.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2007 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 <limits.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "adb.h"
-
-void get_my_path(char *exe, size_t maxLen)
-{
-    char proc[64];
-    snprintf(proc, sizeof proc, "/proc/%d/exe", getpid());
-    int err = readlink(proc, exe, maxLen - 1);
-    if(err > 0) {
-        exe[err] = '\0';
-    } else {
-        exe[0] = '\0';
-    }
-}
-
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index 7a44801..3135aa4 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -34,6 +34,7 @@
 
 #include "adb.h"
 #include "adb_io.h"
+#include "adb_unique_fd.h"
 #include "adb_utils.h"
 
 /* here's how these things work.
@@ -444,10 +445,7 @@
     JdwpControl* control = (JdwpControl*)_control;
 
     if (events & FDE_READ) {
-        sockaddr_storage ss;
-        sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
-        socklen_t addrlen = sizeof(ss);
-        int s = adb_socket_accept(control->listen_socket, addrp, &addrlen);
+        int s = adb_socket_accept(control->listen_socket, nullptr, nullptr);
         if (s < 0) {
             if (errno == ECONNABORTED) {
                 /* oops, the JDWP process died really quick */
diff --git a/adb/protocol.txt b/adb/protocol.txt
index 5c7c6ba..55ea87f 100644
--- a/adb/protocol.txt
+++ b/adb/protocol.txt
@@ -29,12 +29,12 @@
 32 bit words which are sent across the wire in little endian format.
 
 struct message {
-    unsigned command;       /* command identifier constant      */
-    unsigned arg0;          /* first argument                   */
-    unsigned arg1;          /* second argument                  */
-    unsigned data_length;   /* length of payload (0 is allowed) */
-    unsigned data_crc32;    /* crc32 of data payload            */
-    unsigned magic;         /* command ^ 0xffffffff             */
+    unsigned command;       /* command identifier constant (A_CNXN, ...) */
+    unsigned arg0;          /* first argument                            */
+    unsigned arg1;          /* second argument                           */
+    unsigned data_length;   /* length of payload (0 is allowed)          */
+    unsigned data_crc32;    /* crc32 of data payload                     */
+    unsigned magic;         /* command ^ 0xffffffff                      */
 };
 
 Receipt of an invalid message header, corrupt message payload, or an
@@ -55,6 +55,8 @@
 
 --- CONNECT(version, maxdata, "system-identity-string") ----------------
 
+Command constant: A_CNXN
+
 The CONNECT message establishes the presence of a remote system.
 The version is used to ensure protocol compatibility and maxdata
 declares the maximum message body size that the remote system
@@ -80,6 +82,8 @@
 
 --- AUTH(type, 0, "data") ----------------------------------------------
 
+Command constant: A_AUTH
+
 The AUTH message informs the recipient that authentication is required to
 connect to the sender. If type is TOKEN(1), data is a random token that
 the recipient can sign with a private key. The recipient replies with an
@@ -98,6 +102,8 @@
 
 --- OPEN(local-id, 0, "destination") -----------------------------------
 
+Command constant: A_OPEN
+
 The OPEN message informs the recipient that the sender has a stream
 identified by local-id that it wishes to connect to the named
 destination in the message payload.  The local-id may not be zero.
@@ -120,11 +126,13 @@
 
 --- READY(local-id, remote-id, "") -------------------------------------
 
+Command constant: A_OKAY
+
 The READY message informs the recipient that the sender's stream
 identified by local-id is ready for write messages and that it is
 connected to the recipient's stream identified by remote-id.
 
-Neither the local-id nor the remote-id may be zero. 
+Neither the local-id nor the remote-id may be zero.
 
 A READY message containing a remote-id which does not map to an open
 stream on the recipient's side is ignored.  The stream may have been
@@ -135,9 +143,10 @@
 not change on later READY messages sent to the same stream.
 
 
-
 --- WRITE(local-id, remote-id, "data") ---------------------------------
 
+Command constant: A_WRTE
+
 The WRITE message sends data to the recipient's stream identified by
 remote-id.  The payload MUST be <= maxdata in length.
 
@@ -154,6 +163,8 @@
 
 --- CLOSE(local-id, remote-id, "") -------------------------------------
 
+Command constant: A_CLSE
+
 The CLOSE message informs recipient that the connection between the
 sender's stream (local-id) and the recipient's stream (remote-id) is
 broken.  The remote-id MUST not be zero, but the local-id MAY be zero
@@ -170,12 +181,14 @@
 
 --- SYNC(online, sequence, "") -----------------------------------------
 
+Command constant: A_SYNC
+
 The SYNC message is used by the io pump to make sure that stale
 outbound messages are discarded when the connection to the remote side
 is broken.  It is only used internally to the bridge and never valid
-to send across the wire.  
+to send across the wire.
 
-* when the connection to the remote side goes offline, the io pump 
+* when the connection to the remote side goes offline, the io pump
   sends a SYNC(0, 0) and starts discarding all messages
 * when the connection to the remote side is established, the io pump
   sends a SYNC(1, token) and continues to discard messages
diff --git a/adb/services.cpp b/adb/services.cpp
index 3b212e9..2207a3e 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -49,6 +49,7 @@
 #include "remount_service.h"
 #include "services.h"
 #include "shell_service.h"
+#include "socket_spec.h"
 #include "sysdeps.h"
 #include "transport.h"
 
@@ -278,36 +279,12 @@
 int service_to_fd(const char* name, const atransport* transport) {
     int ret = -1;
 
-    if(!strncmp(name, "tcp:", 4)) {
-        int port = atoi(name + 4);
-        name = strchr(name + 4, ':');
-        if(name == 0) {
-            std::string error;
-            ret = network_loopback_client(port, SOCK_STREAM, &error);
-            if (ret >= 0)
-                disable_tcp_nagle(ret);
-        } else {
-#if ADB_HOST
-            std::string error;
-            ret = network_connect(name + 1, port, SOCK_STREAM, 0, &error);
-#else
-            return -1;
-#endif
+    if (is_socket_spec(name)) {
+        std::string error;
+        ret = socket_spec_connect(name, &error);
+        if (ret < 0) {
+            LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
         }
-#if !defined(_WIN32)   /* winsock doesn't implement unix domain sockets */
-    } else if(!strncmp(name, "local:", 6)) {
-        ret = socket_local_client(name + 6,
-                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-    } else if(!strncmp(name, "localreserved:", 14)) {
-        ret = socket_local_client(name + 14,
-                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
-    } else if(!strncmp(name, "localabstract:", 14)) {
-        ret = socket_local_client(name + 14,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-    } else if(!strncmp(name, "localfilesystem:", 16)) {
-        ret = socket_local_client(name + 16,
-                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
-#endif
 #if !ADB_HOST
     } else if(!strncmp("dev:", name, 4)) {
         ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index d83622c..01e206a 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -100,6 +100,7 @@
 #include "adb.h"
 #include "adb_io.h"
 #include "adb_trace.h"
+#include "adb_unique_fd.h"
 #include "adb_utils.h"
 #include "security_log_tags.h"
 
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
new file mode 100644
index 0000000..18e6e6d
--- /dev/null
+++ b/adb/socket_spec.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2016 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 "socket_spec.h"
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <cutils/sockets.h>
+
+#include "adb.h"
+#include "sysdeps.h"
+
+using android::base::StartsWith;
+using android::base::StringPrintf;
+
+#if defined(__linux__)
+#define ADB_LINUX 1
+#else
+#define ADB_LINUX 0
+#endif
+
+#if defined(_WIN32)
+#define ADB_WINDOWS 1
+#else
+#define ADB_WINDOWS 0
+#endif
+
+// Not static because it is used in commandline.c.
+int gListenAll = 0;
+
+struct LocalSocketType {
+    int socket_namespace;
+    bool available;
+};
+
+static auto& kLocalSocketTypes = *new std::unordered_map<std::string, LocalSocketType>({
+#if ADB_HOST
+    { "local", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } },
+#else
+    { "local", { ANDROID_SOCKET_NAMESPACE_RESERVED, !ADB_WINDOWS } },
+#endif
+
+    { "localreserved", { ANDROID_SOCKET_NAMESPACE_RESERVED, !ADB_HOST } },
+    { "localabstract", { ANDROID_SOCKET_NAMESPACE_ABSTRACT, ADB_LINUX } },
+    { "localfilesystem", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } },
+});
+
+static bool parse_tcp_spec(const std::string& spec, std::string* hostname, int* port,
+                           std::string* error) {
+    std::vector<std::string> fragments = android::base::Split(spec, ":");
+    if (fragments.size() == 1 || fragments.size() > 3) {
+        *error = StringPrintf("invalid tcp specification: '%s'", spec.c_str());
+        return false;
+    }
+
+    if (fragments[0] != "tcp") {
+        *error = StringPrintf("specification is not tcp: '%s'", spec.c_str());
+        return false;
+    }
+
+    // strtol accepts leading whitespace.
+    const std::string& port_str = fragments.back();
+    if (port_str.empty() || port_str[0] < '0' || port_str[0] > '9') {
+        *error = StringPrintf("invalid port '%s'", port_str.c_str());
+        return false;
+    }
+
+    char* parsed_end;
+    long parsed_port = strtol(port_str.c_str(), &parsed_end, 10);
+    if (*parsed_end != '\0') {
+        *error = StringPrintf("trailing chars in port: '%s'", port_str.c_str());
+        return false;
+    }
+    if (parsed_port > 65535) {
+        *error = StringPrintf("invalid port %ld", parsed_port);
+        return false;
+    }
+
+    // tcp:123 is valid, tcp::123 isn't.
+    if (fragments.size() == 2) {
+        // Empty hostname.
+        if (hostname) {
+            *hostname = "";
+        }
+    } else {
+        if (fragments[1].empty()) {
+            *error = StringPrintf("empty host in '%s'", spec.c_str());
+            return false;
+        }
+        if (hostname) {
+            *hostname = fragments[1];
+        }
+    }
+
+    if (port) {
+        *port = parsed_port;
+    }
+
+    return true;
+}
+
+static bool tcp_host_is_local(const std::string& hostname) {
+    // FIXME
+    return hostname.empty() || hostname == "localhost";
+}
+
+bool is_socket_spec(const std::string& spec) {
+    for (const auto& it : kLocalSocketTypes) {
+        std::string prefix = it.first + ":";
+        if (StartsWith(spec, prefix.c_str())) {
+            return true;
+        }
+    }
+    return StartsWith(spec, "tcp:");
+}
+
+bool is_local_socket_spec(const std::string& spec) {
+    for (const auto& it : kLocalSocketTypes) {
+        std::string prefix = it.first + ":";
+        if (StartsWith(spec, prefix.c_str())) {
+            return true;
+        }
+    }
+
+    std::string error;
+    std::string hostname;
+    if (!parse_tcp_spec(spec, &hostname, nullptr, &error)) {
+        return false;
+    }
+    return tcp_host_is_local(hostname);
+}
+
+int socket_spec_connect(const std::string& spec, std::string* error) {
+    if (StartsWith(spec, "tcp:")) {
+        std::string hostname;
+        int port;
+        if (!parse_tcp_spec(spec, &hostname, &port, error)) {
+            return -1;
+        }
+
+        int result;
+        if (tcp_host_is_local(hostname)) {
+            result = network_loopback_client(port, SOCK_STREAM, error);
+        } else {
+#if ADB_HOST
+            result = network_connect(hostname, port, SOCK_STREAM, 0, error);
+#else
+            // Disallow arbitrary connections in adbd.
+            *error = "adbd does not support arbitrary tcp connections";
+            return -1;
+#endif
+        }
+
+        if (result >= 0) {
+            disable_tcp_nagle(result);
+        }
+        return result;
+    }
+
+    for (const auto& it : kLocalSocketTypes) {
+        std::string prefix = it.first + ":";
+        if (StartsWith(spec, prefix.c_str())) {
+            if (!it.second.available) {
+                *error = StringPrintf("socket type %s is unavailable on this platform",
+                                      it.first.c_str());
+                return -1;
+            }
+
+            return network_local_client(&spec[prefix.length()], it.second.socket_namespace,
+                                        SOCK_STREAM, error);
+        }
+    }
+
+    *error = StringPrintf("unknown socket specification '%s'", spec.c_str());
+    return -1;
+}
+
+int socket_spec_listen(const std::string& spec, std::string* error, int* resolved_tcp_port) {
+    if (StartsWith(spec, "tcp:")) {
+        std::string hostname;
+        int port;
+        if (!parse_tcp_spec(spec, &hostname, &port, error)) {
+            return -1;
+        }
+
+        int result;
+        if (hostname.empty() && gListenAll) {
+            result = network_inaddr_any_server(port, SOCK_STREAM, error);
+        } else if (tcp_host_is_local(hostname)) {
+            result = network_loopback_server(port, SOCK_STREAM, error);
+        } else {
+            // TODO: Implement me.
+            *error = "listening on specified hostname currently unsupported";
+            return -1;
+        }
+
+        if (result >= 0 && port == 0 && resolved_tcp_port) {
+            *resolved_tcp_port = adb_socket_get_local_port(result);
+        }
+        return result;
+    }
+
+    for (const auto& it : kLocalSocketTypes) {
+        std::string prefix = it.first + ":";
+        if (StartsWith(spec, prefix.c_str())) {
+            if (!it.second.available) {
+                *error = StringPrintf("attempted to listen on unavailable socket type: '%s'",
+                                      spec.c_str());
+                return -1;
+            }
+
+            return network_local_server(&spec[prefix.length()], it.second.socket_namespace,
+                                        SOCK_STREAM, error);
+        }
+    }
+
+    *error = StringPrintf("unknown socket specification '%s'", spec.c_str());
+    return -1;
+}
diff --git a/adb/socket_spec.h b/adb/socket_spec.h
new file mode 100644
index 0000000..6302da5
--- /dev/null
+++ b/adb/socket_spec.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 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 <string>
+
+// Returns true if the argument starts with a plausible socket prefix.
+bool is_socket_spec(const std::string& spec);
+bool is_local_socket_spec(const std::string& spec);
+
+int socket_spec_connect(const std::string& spec, std::string* error);
+int socket_spec_listen(const std::string& spec, std::string* error,
+                       int* resolved_tcp_port = nullptr);
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index d2ce2d8..2bb01a3 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -254,10 +254,7 @@
     ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(ClientThreadFunc), nullptr,
                                   &client_thread));
 
-    struct sockaddr addr;
-    socklen_t alen;
-    alen = sizeof(addr);
-    int accept_fd = adb_socket_accept(listen_fd, &addr, &alen);
+    int accept_fd = adb_socket_accept(listen_fd, nullptr, nullptr);
     ASSERT_GE(accept_fd, 0);
     CloseRdHupSocketArg arg;
     arg.socket_fd = accept_fd;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 04df16f..8d99722 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -277,6 +277,15 @@
 int network_loopback_client(int port, int type, std::string* error);
 int network_loopback_server(int port, int type, std::string* error);
 int network_inaddr_any_server(int port, int type, std::string* error);
+
+inline int network_local_client(const char* name, int namespace_id, int type, std::string* error) {
+    abort();
+}
+
+inline int network_local_server(const char* name, int namespace_id, int type, std::string* error) {
+    abort();
+}
+
 int network_connect(const std::string& host, int port, int type, int timeout,
                     std::string* error);
 
@@ -285,6 +294,10 @@
 #undef   accept
 #define  accept  ___xxx_accept
 
+int adb_getsockname(int fd, struct sockaddr* sockaddr, socklen_t* optlen);
+#undef getsockname
+#define getsockname(...) ___xxx_getsockname(__VA__ARGS__)
+
 // Returns the local port number of a bound socket, or -1 on failure.
 int adb_socket_get_local_port(int fd);
 
@@ -634,10 +647,12 @@
   return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
 }
 
-inline int network_local_server(const char *name, int namespace_id, int type,
-                                std::string* error) {
-  return _fd_set_error_str(socket_local_server(name, namespace_id, type),
-                           error);
+inline int network_local_client(const char* name, int namespace_id, int type, std::string* error) {
+    return _fd_set_error_str(socket_local_client(name, namespace_id, type), error);
+}
+
+inline int network_local_server(const char* name, int namespace_id, int type, std::string* error) {
+    return _fd_set_error_str(socket_local_server(name, namespace_id, type), error);
 }
 
 inline int network_connect(const std::string& host, int port, int type,
@@ -828,4 +843,9 @@
 // configured to drop after 10 missed keepalives. Returns true on success.
 bool set_tcp_keepalive(int fd, int interval_sec);
 
+#if defined(_WIN32)
+// Win32 defines ERROR, which we don't need, but which conflicts with google3 logging.
+#undef ERROR
+#endif
+
 #endif /* _ADB_SYSDEPS_H */
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index ee27406..5fda27b 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -952,7 +952,7 @@
         _socket_set_errno(err);
         return -1;
     }
-    std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*> addrinfo(addrinfo_ptr, freeaddrinfo);
+    std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> addrinfo(addrinfo_ptr, freeaddrinfo);
     addrinfo_ptr = nullptr;
 
     // TODO: Try all the addresses if there's more than one? This just uses
@@ -1061,7 +1061,7 @@
         return -1;
     }
 
-    int result = getsockname(fh->fh_socket, sockaddr, optlen);
+    int result = (getsockname)(fh->fh_socket, sockaddr, optlen);
     if (result == SOCKET_ERROR) {
         const DWORD err = WSAGetLastError();
         D("adb_getsockname: setsockopt on fd %d failed: %s\n", fd,
@@ -1119,6 +1119,11 @@
     int local_port = -1;
     std::string error;
 
+    struct sockaddr_storage peer_addr = {};
+    struct sockaddr_storage client_addr = {};
+    socklen_t peer_socklen = sizeof(peer_addr);
+    socklen_t client_socklen = sizeof(client_addr);
+
     server = network_loopback_server(0, SOCK_STREAM, &error);
     if (server < 0) {
         D("adb_socketpair: failed to create server: %s", error.c_str());
@@ -1138,12 +1143,32 @@
         goto fail;
     }
 
-    accepted = adb_socket_accept(server, nullptr, nullptr);
+    // Make sure that the peer that connected to us and the client are the same.
+    accepted = adb_socket_accept(server, reinterpret_cast<sockaddr*>(&peer_addr), &peer_socklen);
     if (accepted < 0) {
         D("adb_socketpair: failed to accept: %s", strerror(errno));
         goto fail;
     }
+
+    if (adb_getsockname(client, reinterpret_cast<sockaddr*>(&client_addr), &client_socklen) != 0) {
+        D("adb_socketpair: failed to getpeername: %s", strerror(errno));
+        goto fail;
+    }
+
+    if (peer_socklen != client_socklen) {
+        D("adb_socketpair: client and peer sockaddrs have different lengths");
+        errno = EIO;
+        goto fail;
+    }
+
+    if (memcmp(&peer_addr, &client_addr, peer_socklen) != 0) {
+        D("adb_socketpair: client and peer sockaddrs don't match");
+        errno = EIO;
+        goto fail;
+    }
+
     adb_close(server);
+
     sv[0] = client;
     sv[1] = accepted;
     return 0;
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 0f1b034..cb3e0d8 100644
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -207,6 +207,28 @@
             # reading the response from the adb emu kill command (on Windows).
             self.assertEqual(0, p.returncode)
 
+    def test_connect_ipv4_ipv6(self):
+        """Ensure that `adb connect localhost:1234` will try both IPv4 and IPv6.
+
+        Bug: http://b/30313466
+        """
+        ipv4 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        ipv4.bind(('127.0.0.1', 0))
+        ipv4.listen(1)
+
+        ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+        ipv6.bind(('::1', ipv4.getsockname()[1] + 1))
+        ipv6.listen(1)
+
+        for s in (ipv4, ipv6):
+            port = s.getsockname()[1]
+            output = subprocess.check_output(
+                ['adb', 'connect', 'localhost:{}'.format(port)])
+
+            self.assertEqual(
+                output.strip(), 'connected to localhost:{}'.format(port))
+            s.close()
+
 
 def main():
     random.seed(0)
diff --git a/adb/transport.cpp b/adb/transport.cpp
index ad63a6a..3eaeb06 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -35,6 +35,7 @@
 #include <android-base/strings.h>
 
 #include "adb.h"
+#include "adb_auth.h"
 #include "adb_utils.h"
 #include "diagnose_usb.h"
 
@@ -1072,3 +1073,11 @@
         return 0;
     }
 }
+
+std::shared_ptr<RSA> atransport::NextKey() {
+    if (keys_.empty()) keys_ = adb_auth_get_private_keys();
+
+    std::shared_ptr<RSA> result = keys_[0];
+    keys_.pop_front();
+    return result;
+}
diff --git a/adb/transport.h b/adb/transport.h
index 46d472b..959681f 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -19,12 +19,16 @@
 
 #include <sys/types.h>
 
+#include <deque>
 #include <list>
+#include <memory>
 #include <string>
 #include <unordered_set>
 
 #include "adb.h"
 
+#include <openssl/rsa.h>
+
 typedef std::unordered_set<std::string> FeatureSet;
 
 const FeatureSet& supported_features();
@@ -104,7 +108,8 @@
         return type == kTransportLocal && local_port_for_emulator_ == -1;
     }
 
-    void* key = nullptr;
+    std::shared_ptr<RSA> NextKey();
+
     unsigned char token[TOKEN_SIZE] = {};
     size_t failed_auth_attempts = 0;
 
@@ -156,6 +161,8 @@
     // A list of adisconnect callbacks called when the transport is kicked.
     std::list<adisconnect*> disconnects_;
 
+    std::deque<std::shared_ptr<RSA>> keys_;
+
     DISALLOW_COPY_AND_ASSIGN(atransport);
 };
 
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index cc19785..395b893 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -202,9 +202,6 @@
 
 static void server_socket_thread(void* arg) {
     int serverfd, fd;
-    sockaddr_storage ss;
-    sockaddr *addrp = reinterpret_cast<sockaddr*>(&ss);
-    socklen_t alen;
     int port = (int) (uintptr_t) arg;
 
     adb_thread_setname("server socket");
@@ -222,9 +219,8 @@
             close_on_exec(serverfd);
         }
 
-        alen = sizeof(ss);
         D("server: trying to get new connection from %d", port);
-        fd = adb_socket_accept(serverfd, addrp, &alen);
+        fd = adb_socket_accept(serverfd, nullptr, nullptr);
         if(fd >= 0) {
             D("server: new connection on fd %d", fd);
             close_on_exec(fd);
diff --git a/base/file.cpp b/base/file.cpp
index 4e7ac82..721ab2f 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -20,14 +20,24 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
 
+#include <memory>
 #include <string>
+#include <vector>
 
 #include "android-base/macros.h"  // For TEMP_FAILURE_RETRY on Darwin.
 #include "android-base/logging.h"
 #include "android-base/utf8.h"
 #include "utils/Compat.h"
 
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
+#endif
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
 namespace android {
 namespace base {
 
@@ -171,5 +181,55 @@
   return true;
 }
 
+#if !defined(_WIN32)
+bool Readlink(const std::string& path, std::string* result) {
+  result->clear();
+
+  // Most Linux file systems (ext2 and ext4, say) limit symbolic links to
+  // 4095 bytes. Since we'll copy out into the string anyway, it doesn't
+  // waste memory to just start there. We add 1 so that we can recognize
+  // whether it actually fit (rather than being truncated to 4095).
+  std::vector<char> buf(4095 + 1);
+  while (true) {
+    ssize_t size = readlink(path.c_str(), &buf[0], buf.size());
+    // Unrecoverable error?
+    if (size == -1) return false;
+    // It fit! (If size == buf.size(), it may have been truncated.)
+    if (static_cast<size_t>(size) < buf.size()) {
+      result->assign(&buf[0], size);
+      return true;
+    }
+    // Double our buffer and try again.
+    buf.resize(buf.size() * 2);
+  }
+}
+#endif
+
+std::string GetExecutablePath() {
+#if defined(__linux__)
+  std::string path;
+  android::base::Readlink("/proc/self/exe", &path);
+  return path;
+#elif defined(__APPLE__)
+  char path[PATH_MAX + 1];
+  uint32_t path_len = sizeof(path);
+  int rc = _NSGetExecutablePath(path, &path_len);
+  if (rc < 0) {
+    std::unique_ptr<char> path_buf(new char[path_len]);
+    _NSGetExecutablePath(path_buf.get(), &path_len);
+    return path_buf.get();
+  }
+  return path;
+#elif defined(_WIN32)
+  char path[PATH_MAX + 1];
+  DWORD result = GetModuleFileName(NULL, path, sizeof(path) - 1);
+  if (result == 0 || result == sizeof(path) - 1) return "";
+  path[PATH_MAX - 1] = 0;
+  return path;
+#else
+#error unknown OS
+#endif
+}
+
 }  // namespace base
 }  // namespace android
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 17755bf..f5d6062 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -110,3 +110,33 @@
   ASSERT_FALSE(android::base::RemoveFileIfExists(td.path, &err));
   ASSERT_EQ("is not a regular or symbol link file", err);
 }
+
+TEST(file, Readlink) {
+#if !defined(_WIN32)
+  // Linux doesn't allow empty symbolic links.
+  std::string min("x");
+  // ext2 and ext4 both have PAGE_SIZE limits.
+  std::string max(static_cast<size_t>(4096 - 1), 'x');
+
+  TemporaryDir td;
+  std::string min_path{std::string(td.path) + "/" + "min"};
+  std::string max_path{std::string(td.path) + "/" + "max"};
+
+  ASSERT_EQ(0, symlink(min.c_str(), min_path.c_str()));
+  ASSERT_EQ(0, symlink(max.c_str(), max_path.c_str()));
+
+  std::string result;
+
+  result = "wrong";
+  ASSERT_TRUE(android::base::Readlink(min_path, &result));
+  ASSERT_EQ(min, result);
+
+  result = "wrong";
+  ASSERT_TRUE(android::base::Readlink(max_path, &result));
+  ASSERT_EQ(max, result);
+#endif
+}
+
+TEST(file, GetExecutablePath) {
+  ASSERT_NE("", android::base::GetExecutablePath());
+}
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index aa18ea7..5b22a65 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -43,6 +43,12 @@
 
 bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr);
 
+#if !defined(_WIN32)
+bool Readlink(const std::string& path, std::string* result);
+#endif
+
+std::string GetExecutablePath();
+
 }  // namespace base
 }  // namespace android
 
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index 66d60c9..39f4689 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -41,6 +41,7 @@
   INFO,
   WARNING,
   ERROR,
+  FATAL_WITHOUT_ABORT,
   FATAL,
 };
 
@@ -50,12 +51,15 @@
   SYSTEM,
 };
 
-typedef std::function<void(LogId, LogSeverity, const char*, const char*,
-                           unsigned int, const char*)> LogFunction;
+using LogFunction = std::function<void(LogId, LogSeverity, const char*, const char*,
+                                       unsigned int, const char*)>;
+using AbortFunction = std::function<void(const char*)>;
 
 void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
 void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
 
+void DefaultAborter(const char* abort_message);
+
 #ifdef __ANDROID__
 // We expose this even though it is the default because a user that wants to
 // override the default log buffer will have to construct this themselves.
@@ -79,15 +83,22 @@
 // The tag (or '*' for the global level) comes first, followed by a colon and a
 // letter indicating the minimum priority level we're expected to log.  This can
 // be used to reveal or conceal logs with specific tags.
-void InitLogging(char* argv[], LogFunction&& logger);
-
-// Configures logging using the default logger (logd for the device, stderr for
-// the host).
-void InitLogging(char* argv[]);
+#ifdef __ANDROID__
+#define INIT_LOGGING_DEFAULT_LOGGER LogdLogger()
+#else
+#define INIT_LOGGING_DEFAULT_LOGGER StderrLogger
+#endif
+void InitLogging(char* argv[],
+                 LogFunction&& logger = INIT_LOGGING_DEFAULT_LOGGER,
+                 AbortFunction&& aborter = DefaultAborter);
+#undef INIT_LOGGING_DEFAULT_LOGGER
 
 // Replace the current logger.
 void SetLogger(LogFunction&& logger);
 
+// Replace the current aborter.
+void SetAborter(AbortFunction&& aborter);
+
 class ErrnoRestorer {
  public:
   ErrnoRestorer()
@@ -265,7 +276,7 @@
 // MakeEagerEvaluator to infer the types of LHS and RHS.
 template <typename LHS, typename RHS>
 struct EagerEvaluator {
-  EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) {
+  constexpr EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) {
   }
   LHS lhs;
   RHS rhs;
@@ -273,7 +284,7 @@
 
 // Helper function for CHECK_xx.
 template <typename LHS, typename RHS>
-static inline EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
+constexpr EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) {
   return EagerEvaluator<LHS, RHS>(lhs, rhs);
 }
 
diff --git a/base/include/android-base/macros.h b/base/include/android-base/macros.h
index 299ec35..88bbe8a 100644
--- a/base/include/android-base/macros.h
+++ b/base/include/android-base/macros.h
@@ -41,18 +41,9 @@
 // Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
 // semantically, one should either use disallow both or neither. Try to
 // avoid these in new code.
-//
-// When building with C++11 toolchains, just use the language support
-// for explicitly deleted methods.
-#if __cplusplus >= 201103L
 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
   TypeName(const TypeName&) = delete;      \
   void operator=(const TypeName&) = delete
-#else
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&);               \
-  void operator=(const TypeName&)
-#endif
 
 // A macro to disallow all the implicit constructors, namely the
 // default constructor, copy constructor and operator= functions.
@@ -61,7 +52,7 @@
 // that wants to prevent anyone from instantiating it. This is
 // especially useful for classes containing only static methods.
 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-  TypeName();                                    \
+  TypeName() = delete;                           \
   DISALLOW_COPY_AND_ASSIGN(TypeName)
 
 // The arraysize(arr) macro returns the # of elements in an array arr.
@@ -165,10 +156,10 @@
 //  only if there are no statements on the execution path between it and the
 //  next switch label.
 //
-//  When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is
-//  expanded to [[clang::fallthrough]] attribute, which is analysed when
-//  performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough').
-//  See clang documentation on language extensions for details:
+//  When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
+//  [[clang::fallthrough]] attribute, which is analysed when performing switch
+//  labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
+//  documentation on language extensions for details:
 //  http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
 //
 //  When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
@@ -176,7 +167,7 @@
 //
 //  In either case this macro has no effect on runtime behavior and performance
 //  of code.
-#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning)
+#if defined(__clang__) && defined(__has_warning)
 #if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
 #define FALLTHROUGH_INTENDED [[clang::fallthrough]]  // NOLINT
 #endif
diff --git a/base/include/android-base/thread_annotations.h b/base/include/android-base/thread_annotations.h
index 2422102..fbb5923 100644
--- a/base/include/android-base/thread_annotations.h
+++ b/base/include/android-base/thread_annotations.h
@@ -29,6 +29,9 @@
 #define SCOPED_CAPABILITY \
       THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
 
+#define SHARED_CAPABILITY(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(shared_capability(__VA_ARGS__))
+
 #define GUARDED_BY(x) \
       THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
 
@@ -77,6 +80,27 @@
 #define RETURN_CAPABILITY(x) \
       THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
 
+#define EXCLUSIVE_LOCK_FUNCTION(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
+
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
+
+#define SHARED_LOCK_FUNCTION(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
+
+#define SHARED_TRYLOCK_FUNCTION(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
+
+#define UNLOCK_FUNCTION(...) \
+      THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
+
+#define SCOPED_LOCKABLE \
+      THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+#define LOCK_RETURNED(x) \
+      THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
 #define NO_THREAD_SAFETY_ANALYSIS \
       THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
 
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 869e60f..c323311 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -95,4 +95,14 @@
 }  // namespace base
 }  // namespace android
 
+template <typename T>
+int close(const android::base::unique_fd_impl<T>&)
+#if defined(__clang__)
+  __attribute__((__unavailable__(
+#else
+  __attribute__((__error__(
+#endif
+    "close called on unique_fd"
+  )));
+
 #endif  // ANDROID_BASE_UNIQUE_FD_H
diff --git a/base/logging.cpp b/base/logging.cpp
index 1f47a9f..6e1dd9c 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -173,6 +173,8 @@
 static auto& gLogger = *new LogFunction(StderrLogger);
 #endif
 
+static auto& gAborter = *new AbortFunction(DefaultAborter);
+
 static bool gInitialized = false;
 static LogSeverity gMinimumLogSeverity = INFO;
 static auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
@@ -188,14 +190,18 @@
 #if defined(__linux__)
 void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
                   const char* tag, const char*, unsigned int, const char* msg) {
+  // clang-format off
   static constexpr int kLogSeverityToKernelLogLevel[] = {
-    [android::base::VERBOSE] = 7, // KERN_DEBUG (there is no verbose kernel log level)
-    [android::base::DEBUG]   = 7, // KERN_DEBUG
-    [android::base::INFO]    = 6, // KERN_INFO
-    [android::base::WARNING] = 4, // KERN_WARNING
-    [android::base::ERROR]   = 3, // KERN_ERROR
-    [android::base::FATAL]   = 2, // KERN_CRIT
+      [android::base::VERBOSE] = 7,              // KERN_DEBUG (there is no verbose kernel log
+                                                 //             level)
+      [android::base::DEBUG] = 7,                // KERN_DEBUG
+      [android::base::INFO] = 6,                 // KERN_INFO
+      [android::base::WARNING] = 4,              // KERN_WARNING
+      [android::base::ERROR] = 3,                // KERN_ERROR
+      [android::base::FATAL_WITHOUT_ABORT] = 2,  // KERN_CRIT
+      [android::base::FATAL] = 2,                // KERN_CRIT
   };
+  // clang-format on
   static_assert(arraysize(kLogSeverityToKernelLogLevel) == android::base::FATAL + 1,
                 "Mismatch in size of kLogSeverityToKernelLogLevel and values in LogSeverity");
 
@@ -235,7 +241,7 @@
   char timestamp[32];
   strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
 
-  static const char log_characters[] = "VDIWEF";
+  static const char log_characters[] = "VDIWEFF";
   static_assert(arraysize(log_characters) - 1 == FATAL + 1,
                 "Mismatch in size of log_characters and values in LogSeverity");
   char severity_char = log_characters[severity];
@@ -243,6 +249,15 @@
           severity_char, timestamp, getpid(), GetThreadId(), file, line, message);
 }
 
+void DefaultAborter(const char* abort_message) {
+#ifdef __ANDROID__
+  android_set_abort_message(abort_message);
+#else
+  UNUSED(abort_message);
+#endif
+  abort();
+}
+
 
 #ifdef __ANDROID__
 LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
@@ -252,8 +267,9 @@
                             const char* file, unsigned int line,
                             const char* message) {
   static constexpr android_LogPriority kLogSeverityToAndroidLogPriority[] = {
-    ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
-    ANDROID_LOG_WARN,    ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
+      ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
+      ANDROID_LOG_WARN,    ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
+      ANDROID_LOG_FATAL,
   };
   static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
                 "Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
@@ -279,12 +295,10 @@
 }
 #endif
 
-void InitLogging(char* argv[], LogFunction&& logger) {
+void InitLogging(char* argv[], LogFunction&& logger, AbortFunction&& aborter) {
   SetLogger(std::forward<LogFunction>(logger));
-  InitLogging(argv);
-}
+  SetAborter(std::forward<AbortFunction>(aborter));
 
-void InitLogging(char* argv[]) {
   if (gInitialized) {
     return;
   }
@@ -325,12 +339,12 @@
           gMinimumLogSeverity = ERROR;
           continue;
         case 'f':
-          gMinimumLogSeverity = FATAL;
+          gMinimumLogSeverity = FATAL_WITHOUT_ABORT;
           continue;
         // liblog will even suppress FATAL if you say 's' for silent, but that's
         // crazy!
         case 's':
-          gMinimumLogSeverity = FATAL;
+          gMinimumLogSeverity = FATAL_WITHOUT_ABORT;
           continue;
       }
     }
@@ -344,6 +358,11 @@
   gLogger = std::move(logger);
 }
 
+void SetAborter(AbortFunction&& aborter) {
+  lock_guard<mutex> lock(logging_lock);
+  gAborter = std::move(aborter);
+}
+
 static const char* GetFileBasename(const char* file) {
   // We can't use basename(3) even on Unix because the Mac doesn't
   // have a non-modifying basename.
@@ -445,10 +464,7 @@
 
   // Abort if necessary.
   if (data_->GetSeverity() == FATAL) {
-#ifdef __ANDROID__
-    android_set_abort_message(msg.c_str());
-#endif
-    abort();
+    gAborter(msg.c_str());
   }
 }
 
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 3de42b7..02a9198 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -120,162 +120,233 @@
   EXPECT_FALSE(flag) << "CHECK_STREQ probably has a dangling if with no else";
 }
 
-std::string make_log_pattern(android::base::LogSeverity severity,
-                             const char* message) {
-  static const char* log_characters = "VDIWEF";
+static std::string make_log_pattern(android::base::LogSeverity severity,
+                                    const char* message) {
+  static const char log_characters[] = "VDIWEFF";
+  static_assert(arraysize(log_characters) - 1 == android::base::FATAL + 1,
+                "Mismatch in size of log_characters and values in LogSeverity");
   char log_char = log_characters[severity];
   std::string holder(__FILE__);
   return android::base::StringPrintf(
-      "%c[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+ %s:[[:digit:]]+] %s",
+      "%c \\d+-\\d+ \\d+:\\d+:\\d+ \\s*\\d+ \\s*\\d+ %s:\\d+] %s",
       log_char, basename(&holder[0]), message);
 }
 
-TEST(logging, LOG) {
-  ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
+#define CHECK_LOG_DISABLED(severity) \
+  android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+  CapturedStderr cap1; \
+  LOG(severity) << "foo bar"; \
+  ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+
+#define CHECK_LOG_ENABLED(severity) \
+  android::base::ScopedLogSeverity sls2(android::base::severity); \
+  CapturedStderr cap2; \
+  LOG(severity) << "foobar"; \
+  CheckMessage(cap2, android::base::severity, "foobar"); \
+
+static void CheckMessage(const CapturedStderr& cap,
+                         android::base::LogSeverity severity, const char* expected) {
+  std::string output;
+  ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
+  android::base::ReadFdToString(cap.fd(), &output);
 
   // We can't usefully check the output of any of these on Windows because we
   // don't have std::regex, but we can at least make sure we printed at least as
   // many characters are in the log message.
-  {
-    CapturedStderr cap;
-    LOG(WARNING) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-
-    std::string output;
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_GT(output.length(), strlen("foobar"));
+  ASSERT_GT(output.length(), strlen(expected));
+  ASSERT_NE(nullptr, strstr(output.c_str(), expected)) << output;
 
 #if !defined(_WIN32)
-    std::regex message_regex(
-        make_log_pattern(android::base::WARNING, "foobar"));
-    ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
+  std::regex message_regex(make_log_pattern(severity, expected));
+  ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
 #endif
-  }
-
-  {
-    CapturedStderr cap;
-    LOG(INFO) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-
-    std::string output;
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_GT(output.length(), strlen("foobar"));
-
-#if !defined(_WIN32)
-    std::regex message_regex(
-        make_log_pattern(android::base::INFO, "foobar"));
-    ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
-#endif
-  }
-
-  {
-    CapturedStderr cap;
-    LOG(DEBUG) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-
-    std::string output;
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_TRUE(output.empty());
-  }
-
-  {
-    android::base::ScopedLogSeverity severity(android::base::DEBUG);
-    CapturedStderr cap;
-    LOG(DEBUG) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-
-    std::string output;
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_GT(output.length(), strlen("foobar"));
-
-#if !defined(_WIN32)
-    std::regex message_regex(
-        make_log_pattern(android::base::DEBUG, "foobar"));
-    ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
-#endif
-  }
-
-  // Test whether LOG() saves and restores errno.
-  {
-    CapturedStderr cap;
-    errno = 12345;
-    LOG(INFO) << (errno = 67890);
-    EXPECT_EQ(12345, errno) << "errno was not restored";
-
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-
-    std::string output;
-    android::base::ReadFdToString(cap.fd(), &output);
-    EXPECT_NE(nullptr, strstr(output.c_str(), "67890")) << output;
-
-#if !defined(_WIN32)
-    std::regex message_regex(
-        make_log_pattern(android::base::INFO, "67890"));
-    ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
-#endif
-  }
-
-  // Test whether LOG() has a dangling if with no else.
-  {
-    CapturedStderr cap;
-
-    // Do the test two ways: once where we hypothesize that LOG()'s if
-    // will evaluate to true (when severity is high enough) and once when we
-    // expect it to evaluate to false (when severity is not high enough).
-    bool flag = false;
-    if (true)
-      LOG(INFO) << "foobar";
-    else
-      flag = true;
-
-    EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else";
-
-    flag = false;
-    if (true)
-      LOG(VERBOSE) << "foobar";
-    else
-      flag = true;
-
-    EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else";
-  }
 }
 
-TEST(logging, PLOG) {
-  {
-    CapturedStderr cap;
-    errno = ENOENT;
-    PLOG(INFO) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
+TEST(logging, LOG_FATAL) {
+  ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
+}
 
-    std::string output;
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_GT(output.length(), strlen("foobar"));
+TEST(logging, LOG_FATAL_WITHOUT_ABORT_disabled) {
+  CHECK_LOG_DISABLED(FATAL_WITHOUT_ABORT);
+}
 
-#if !defined(_WIN32)
-    std::regex message_regex(make_log_pattern(
-        android::base::INFO, "foobar: No such file or directory"));
-    ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
-#endif
-  }
+TEST(logging, LOG_FATAL_WITHOUT_ABORT_enabled) {
+  CHECK_LOG_ENABLED(FATAL_WITHOUT_ABORT);
+}
+
+TEST(logging, LOG_ERROR_disabled) {
+  CHECK_LOG_DISABLED(ERROR);
+}
+
+TEST(logging, LOG_ERROR_enabled) {
+  CHECK_LOG_ENABLED(ERROR);
+}
+
+TEST(logging, LOG_WARNING_disabled) {
+  CHECK_LOG_DISABLED(WARNING);
+}
+
+TEST(logging, LOG_WARNING_enabled) {
+  CHECK_LOG_ENABLED(WARNING);
+}
+
+TEST(logging, LOG_INFO_disabled) {
+  CHECK_LOG_DISABLED(INFO);
+}
+
+TEST(logging, LOG_INFO_enabled) {
+  CHECK_LOG_ENABLED(INFO);
+}
+
+TEST(logging, LOG_DEBUG_disabled) {
+  CHECK_LOG_DISABLED(DEBUG);
+}
+
+TEST(logging, LOG_DEBUG_enabled) {
+  CHECK_LOG_ENABLED(DEBUG);
+}
+
+TEST(logging, LOG_VERBOSE_disabled) {
+  CHECK_LOG_DISABLED(VERBOSE);
+}
+
+TEST(logging, LOG_VERBOSE_enabled) {
+  CHECK_LOG_ENABLED(VERBOSE);
+}
+
+TEST(logging, LOG_does_not_clobber_errno) {
+  CapturedStderr cap;
+  errno = 12345;
+  LOG(INFO) << (errno = 67890);
+  EXPECT_EQ(12345, errno) << "errno was not restored";
+
+  CheckMessage(cap, android::base::INFO, "67890");
+}
+
+TEST(logging, PLOG_does_not_clobber_errno) {
+  CapturedStderr cap;
+  errno = 12345;
+  PLOG(INFO) << (errno = 67890);
+  EXPECT_EQ(12345, errno) << "errno was not restored";
+
+  CheckMessage(cap, android::base::INFO, "67890");
+}
+
+TEST(logging, LOG_does_not_have_dangling_if) {
+  CapturedStderr cap; // So the logging below has no side-effects.
+
+  // Do the test two ways: once where we hypothesize that LOG()'s if
+  // will evaluate to true (when severity is high enough) and once when we
+  // expect it to evaluate to false (when severity is not high enough).
+  bool flag = false;
+  if (true)
+    LOG(INFO) << "foobar";
+  else
+    flag = true;
+
+  EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else";
+
+  flag = false;
+  if (true)
+    LOG(VERBOSE) << "foobar";
+  else
+    flag = true;
+
+  EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else";
+}
+
+#define CHECK_PLOG(severity) \
+
+#define CHECK_PLOG_DISABLED(severity) \
+  android::base::ScopedLogSeverity sls1(android::base::FATAL); \
+  CapturedStderr cap1; \
+  PLOG(severity) << "foo bar"; \
+  ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
+
+#define CHECK_PLOG_ENABLED(severity) \
+  android::base::ScopedLogSeverity sls2(android::base::severity); \
+  CapturedStderr cap2; \
+  errno = ENOENT; \
+  PLOG(severity) << "foobar"; \
+  CheckMessage(cap2, android::base::severity, "foobar: No such file or directory"); \
+
+TEST(logging, PLOG_FATAL) {
+  ASSERT_DEATH({SuppressAbortUI(); PLOG(FATAL) << "foobar";}, "foobar");
+}
+
+TEST(logging, PLOG_FATAL_WITHOUT_ABORT_disabled) {
+  CHECK_PLOG_DISABLED(FATAL_WITHOUT_ABORT);
+}
+
+TEST(logging, PLOG_FATAL_WITHOUT_ABORT_enabled) {
+  CHECK_PLOG_ENABLED(FATAL_WITHOUT_ABORT);
+}
+
+TEST(logging, PLOG_ERROR_disabled) {
+  CHECK_PLOG_DISABLED(ERROR);
+}
+
+TEST(logging, PLOG_ERROR_enabled) {
+  CHECK_PLOG_ENABLED(ERROR);
+}
+
+TEST(logging, PLOG_WARNING_disabled) {
+  CHECK_PLOG_DISABLED(WARNING);
+}
+
+TEST(logging, PLOG_WARNING_enabled) {
+  CHECK_PLOG_ENABLED(WARNING);
+}
+
+TEST(logging, PLOG_INFO_disabled) {
+  CHECK_PLOG_DISABLED(INFO);
+}
+
+TEST(logging, PLOG_INFO_enabled) {
+  CHECK_PLOG_ENABLED(INFO);
+}
+
+TEST(logging, PLOG_DEBUG_disabled) {
+  CHECK_PLOG_DISABLED(DEBUG);
+}
+
+TEST(logging, PLOG_DEBUG_enabled) {
+  CHECK_PLOG_ENABLED(DEBUG);
+}
+
+TEST(logging, PLOG_VERBOSE_disabled) {
+  CHECK_PLOG_DISABLED(VERBOSE);
+}
+
+TEST(logging, PLOG_VERBOSE_enabled) {
+  CHECK_PLOG_ENABLED(VERBOSE);
 }
 
 TEST(logging, UNIMPLEMENTED) {
+  std::string expected = android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
+
+  CapturedStderr cap;
+  errno = ENOENT;
+  UNIMPLEMENTED(ERROR);
+  CheckMessage(cap, android::base::ERROR, expected.c_str());
+}
+
+static void NoopAborter(const char* msg ATTRIBUTE_UNUSED) {
+  LOG(ERROR) << "called noop";
+}
+
+TEST(logging, LOG_FATAL_NOOP_ABORTER) {
   {
+    android::base::SetAborter(NoopAborter);
+
+    android::base::ScopedLogSeverity sls(android::base::ERROR);
     CapturedStderr cap;
-    errno = ENOENT;
-    UNIMPLEMENTED(ERROR);
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
+    LOG(FATAL) << "foobar";
+    CheckMessage(cap, android::base::FATAL, "foobar");
+    CheckMessage(cap, android::base::ERROR, "called noop");
 
-    std::string output;
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_GT(output.length(), strlen("unimplemented"));
-
-#if !defined(_WIN32)
-    std::string expected_message =
-        android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
-    std::regex message_regex(
-        make_log_pattern(android::base::ERROR, expected_message.c_str()));
-    ASSERT_TRUE(std::regex_search(output, message_regex)) << output;
-#endif
+    android::base::SetAborter(android::base::DefaultAborter);
   }
+
+  ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
 }
diff --git a/bootstat/Android.bp b/bootstat/Android.bp
new file mode 100644
index 0000000..89b4598
--- /dev/null
+++ b/bootstat/Android.bp
@@ -0,0 +1,94 @@
+//
+// Copyright (C) 2016 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.
+//
+
+bootstat_lib_src_files = [
+    "boot_event_record_store.cpp",
+    "event_log_list_builder.cpp",
+    "histogram_logger.cpp",
+    "uptime_parser.cpp",
+]
+
+cc_defaults {
+    name: "bootstat_defaults",
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+
+        // 524291 corresponds to sysui_histogram, from
+        // frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
+        "-DHISTOGRAM_LOG_TAG=524291",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+    whole_static_libs: ["libgtest_prod"],
+    // Clang is required because of C++14
+    clang: true,
+}
+
+// bootstat static library
+// -----------------------------------------------------------------------------
+cc_library_static {
+    name: "libbootstat",
+    defaults: ["bootstat_defaults"],
+    srcs: bootstat_lib_src_files,
+}
+
+// bootstat static library, debug
+// -----------------------------------------------------------------------------
+cc_library_static {
+    name: "libbootstat_debug",
+    defaults: ["bootstat_defaults"],
+    host_supported: true,
+    srcs: bootstat_lib_src_files,
+
+    target: {
+        host: {
+            cflags: ["-UNDEBUG"],
+        },
+    },
+}
+
+// bootstat binary
+// -----------------------------------------------------------------------------
+cc_binary {
+    name: "bootstat",
+    defaults: ["bootstat_defaults"],
+    static_libs: ["libbootstat"],
+    init_rc: ["bootstat.rc"],
+    srcs: ["bootstat.cpp"],
+}
+
+// Native tests
+// -----------------------------------------------------------------------------
+cc_test {
+    name: "bootstat_tests",
+    defaults: ["bootstat_defaults"],
+    host_supported: true,
+    static_libs: [
+        "libbootstat_debug",
+        "libgmock",
+    ],
+    srcs: [
+        "boot_event_record_store_test.cpp",
+        "event_log_list_builder_test.cpp",
+        "testrunner.cpp",
+    ],
+}
diff --git a/bootstat/Android.mk b/bootstat/Android.mk
deleted file mode 100644
index bdd680d..0000000
--- a/bootstat/Android.mk
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-bootstat_lib_src_files := \
-        boot_event_record_store.cpp \
-        event_log_list_builder.cpp \
-        histogram_logger.cpp \
-        uptime_parser.cpp \
-
-bootstat_src_files := \
-        bootstat.cpp \
-
-bootstat_test_src_files := \
-        boot_event_record_store_test.cpp \
-        event_log_list_builder_test.cpp \
-        testrunner.cpp \
-
-bootstat_shared_libs := \
-        libbase \
-        libcutils \
-        liblog \
-
-bootstat_cflags := \
-        -Wall \
-        -Wextra \
-        -Werror \
-
-# 524291 corresponds to sysui_histogram, from
-# frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
-bootstat_cflags += -DHISTOGRAM_LOG_TAG=524291
-
-bootstat_debug_cflags := \
-        $(bootstat_cflags) \
-        -UNDEBUG \
-
-# bootstat static library
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbootstat
-LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_SRC_FILES := $(bootstat_lib_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_STATIC_LIBRARY)
-
-# bootstat static library, debug
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbootstat_debug
-LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_SRC_FILES := $(bootstat_lib_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_STATIC_LIBRARY)
-
-# bootstat host static library, debug
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libbootstat_host_debug
-LOCAL_CFLAGS := $(bootstat_debug_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_SRC_FILES := $(bootstat_lib_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-# bootstat binary
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bootstat
-LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_STATIC_LIBRARIES := libbootstat
-LOCAL_INIT_RC := bootstat.rc
-LOCAL_SRC_FILES := $(bootstat_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_EXECUTABLE)
-
-# Native tests
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bootstat_tests
-LOCAL_CFLAGS := $(bootstat_tests_cflags)
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_STATIC_LIBRARIES := libbootstat_debug libgmock
-LOCAL_SRC_FILES := $(bootstat_test_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_NATIVE_TEST)
-
-# Host native tests
-# -----------------------------------------------------------------------------
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := bootstat_tests
-LOCAL_CFLAGS := $(bootstat_tests_cflags)
-LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
-LOCAL_STATIC_LIBRARIES := libbootstat_host_debug libgmock_host
-LOCAL_SRC_FILES := $(bootstat_test_src_files)
-# Clang is required because of C++14
-LOCAL_CLANG := true
-
-include $(BUILD_HOST_NATIVE_TEST)
diff --git a/crash_reporter/.project_alias b/crash_reporter/.project_alias
deleted file mode 100644
index 0bc3798..0000000
--- a/crash_reporter/.project_alias
+++ /dev/null
@@ -1 +0,0 @@
-crash
diff --git a/crash_reporter/99-crash-reporter.rules b/crash_reporter/99-crash-reporter.rules
deleted file mode 100644
index aea5b1c..0000000
--- a/crash_reporter/99-crash-reporter.rules
+++ /dev/null
@@ -1,6 +0,0 @@
-ACTION=="change", SUBSYSTEM=="drm", KERNEL=="card0", ENV{ERROR}=="1", RUN+="/sbin/crash_reporter --udev=KERNEL=card0:SUBSYSTEM=drm:ACTION=change"
-# For detecting cypress trackpad issue. Passing into crash_reporter SUBSYSTEM=i2c-cyapa since crash_reporter does not handle DRIVER string.
-ACTION=="change", SUBSYSTEM=="i2c", DRIVER=="cyapa", ENV{ERROR}=="1", RUN+="/sbin/crash_reporter --udev=SUBSYSTEM=i2c-cyapa:ACTION=change"
-# For detecting Atmel trackpad/touchscreen issue. Passing into crash_reporter SUBSYSTEM=i2c-atmel_mxt_ts since crash_reporter does not handle DRIVER string.
-ACTION=="change", SUBSYSTEM=="i2c", DRIVER=="atmel_mxt_ts", ENV{ERROR}=="1", RUN+="/sbin/crash_reporter --udev=SUBSYSTEM=i2c-atmel_mxt_ts:ACTION=change"
-ACTION=="add", SUBSYSTEM=="devcoredump", RUN+="/sbin/crash_reporter --udev=SUBSYSTEM=devcoredump:ACTION=add:KERNEL_NUMBER=%n"
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
deleted file mode 100644
index 4feb72a..0000000
--- a/crash_reporter/Android.mk
+++ /dev/null
@@ -1,144 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-crash_reporter_cpp_extension := .cc
-
-crash_reporter_src := crash_collector.cc \
-    kernel_collector.cc \
-    kernel_warning_collector.cc \
-    unclean_shutdown_collector.cc \
-    user_collector.cc
-
-crash_reporter_includes := external/gtest/include
-
-crash_reporter_test_src := crash_collector_test.cc \
-    crash_reporter_logs_test.cc \
-    kernel_collector_test.cc \
-    testrunner.cc \
-    unclean_shutdown_collector_test.cc \
-    user_collector_test.cc
-
-warn_collector_src := warn_collector.l
-
-# Crash reporter static library.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrash
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_C_INCLUDES := $(crash_reporter_includes)
-LOCAL_SHARED_LIBRARIES := libchrome \
-    libbinder \
-    libbrillo \
-    libcutils \
-    libmetrics \
-    libpcrecpp
-LOCAL_STATIC_LIBRARIES := libmetricscollectorservice
-LOCAL_SRC_FILES := $(crash_reporter_src)
-include $(BUILD_STATIC_LIBRARY)
-
-# Crash reporter client.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_reporter
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_C_INCLUDES := $(crash_reporter_includes)
-LOCAL_REQUIRED_MODULES := core2md \
-    crash_reporter_logs.conf \
-    crash_sender \
-    crash_server
-LOCAL_INIT_RC := crash_reporter.rc
-LOCAL_SHARED_LIBRARIES := libchrome \
-    libbinder \
-    libbrillo \
-    libcutils \
-    libmetrics \
-    libpcrecpp \
-    libutils
-LOCAL_SRC_FILES := crash_reporter.cc
-LOCAL_STATIC_LIBRARIES := libcrash \
-    libmetricscollectorservice
-include $(BUILD_EXECUTABLE)
-
-# Crash sender script.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_sender
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_REQUIRED_MODULES := curl grep periodic_scheduler
-LOCAL_SRC_FILES := crash_sender
-include $(BUILD_PREBUILT)
-
-# Warn collector client.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := warn_collector
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_SHARED_LIBRARIES := libmetrics
-LOCAL_SRC_FILES := $(warn_collector_src)
-include $(BUILD_EXECUTABLE)
-
-# /etc/os-release.d/crash_server configuration file.
-# ========================================================
-ifdef OSRELEASED_DIRECTORY
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_server
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)
-include $(BUILD_SYSTEM)/base_rules.mk
-
-# Optionally populate the BRILLO_CRASH_SERVER variable from a product
-# configuration file: brillo/crash_server.
-LOADED_BRILLO_CRASH_SERVER := $(call cfgtree-get-if-exists,brillo/crash_server)
-
-# If the crash server isn't set, use a blank value.  crash_sender
-# will log it as a configuration error.
-$(LOCAL_BUILT_MODULE): BRILLO_CRASH_SERVER ?= "$(LOADED_BRILLO_CRASH_SERVER)"
-$(LOCAL_BUILT_MODULE):
-	$(hide)mkdir -p $(dir $@)
-	echo $(BRILLO_CRASH_SERVER) > $@
-endif
-
-# Crash reporter logs conf file.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_reporter_logs.conf
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/etc
-LOCAL_SRC_FILES := crash_reporter_logs.conf
-include $(BUILD_PREBUILT)
-
-# Periodic Scheduler.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := periodic_scheduler
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_SRC_FILES := periodic_scheduler
-include $(BUILD_PREBUILT)
-
-# Crash reporter tests.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := crash_reporter_tests
-LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
-LOCAL_SHARED_LIBRARIES := libchrome \
-    libbrillo \
-    libcutils \
-    libpcrecpp
-LOCAL_SRC_FILES := $(crash_reporter_test_src)
-LOCAL_STATIC_LIBRARIES := libcrash libgmock
-include $(BUILD_NATIVE_TEST)
diff --git a/crash_reporter/OWNERS b/crash_reporter/OWNERS
deleted file mode 100644
index 96ea5b2..0000000
--- a/crash_reporter/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-vapier@chromium.org
diff --git a/crash_reporter/README.md b/crash_reporter/README.md
deleted file mode 100644
index 9ac0a86..0000000
--- a/crash_reporter/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# crash_reporter
-
-`crash_reporter` is a deamon running on the device that saves the call stack of
-crashing programs. It makes use of the
-[Breakpad](https://chromium.googlesource.com/breakpad/breakpad/) library.
-
-During a build, Breakpad symbol files are generated for all binaries.  They are
-packaged into a zip file when running `m dist`, so that a developer can upload
-them to the crash server.
-
-On a device, if the user has opted in to metrics and crash reporting, a
-Breakpad minidump is generated when an executable crashes, which is then
-uploaded to the crash server.
-
-On the crash server, it compares the minidump's signature to the symbol files
-that the developer has uploaded, and extracts and symbolizes the stack trace
-from the minidump.
-
-## SELinux policies
-
-In order to correctly generate a minidump, `crash_reporter` needs to be given
-the proper SELinux permissions for accessing the domain of the crashing
-executable.  By default, `crash_reporter` has only been given access to a select
-number of system domains, such as `metricsd`, `weave`, and `update_engine`.  If
-a developer wants their executable's crashes to be caught by `crash_reporter`,
-they will have to set their SELinux policies in their .te file to allow
-`crash_reporter` access to their domain.  This can be done through a simple
-[macro](https://android.googlesource.com/device/generic/brillo/+/master/sepolicy/te_macros):
-
-    allow_crash_reporter(domain_name)
-
-Replace *domain_name* with whatever domain is assigned to the executable in
-the `file_contexts` file.
-
-## Configuration
-
-`crash_reporter` has a few different configuration options that have to be set.
-
-- Crashes are only handled and uploaded if analytics reporting is enabled,
-  either via the weave call to set `_metrics.enableAnalyticsReporting` or by
-  manually creating the file `/data/misc/metrics/enabled` (for testing only).
-- The `BRILLO_CRASH_SERVER` make variable should be set in the `product.mk`
-  file to the URL of the crash server.  For Brillo builds, it is set
-  automatically through the product configuration.  Setting this variable will
-  populate the `/etc/os-release.d/crash_server` file on the device, which is
-  read by `crash_sender`.
-- The `BRILLO_PRODUCT_ID` make variable should be set in the `product.mk` file
-  to the product's ID.  For Brillo builds, it is set automatically through the
-  product configuration.  Setting this variable will populate the
-  `/etc/os-release.d/product_id`, which is read by `crash_sender`.
-
-## Uploading crash reports in *eng* builds
-
-By default, crash reports are only uploaded to the server for production
-*user* and *userdebug* images.  In *eng* builds, with crash reporting enabled
-the device will generate minidumps for any crashing executables but will not
-send them to the crash server.  If a developer does want to force an upload,
-they can do so by issuing the command `SECONDS_SEND_SPREAD=5 FORCE_OFFICIAL=1
-crash_sender` from an ADB shell.  This will send the report to the server, with
-the *image_type* field set to *force-official* so that these reports can be
-differentiated from normal reports.
diff --git a/crash_reporter/TEST_WARNING b/crash_reporter/TEST_WARNING
deleted file mode 100644
index 64ad2e9..0000000
--- a/crash_reporter/TEST_WARNING
+++ /dev/null
@@ -1,31 +0,0 @@
-Apr 31 25:25:25 localhost kernel: [117959.226729]  [<ffffffff810e16bf>] do_vfs_ioctl+0x469/0x4b3
-Apr 31 25:25:25 localhost kernel: [117959.226738]  [<ffffffff810d3117>] ? fsnotify_access+0x58/0x60
-Apr 31 25:25:25 localhost kernel: [117959.226747]  [<ffffffff810d3791>] ? vfs_read+0xad/0xd7
-Apr 31 25:25:25 localhost kernel: [117959.226756]  [<ffffffff810e175f>] sys_ioctl+0x56/0x7b
-Apr 31 25:25:25 localhost kernel: [117959.226765]  [<ffffffff810d37fe>] ? sys_read+0x43/0x73
-Apr 31 25:25:25 localhost kernel: [117959.226774]  [<ffffffff8146b7d2>] system_call_fastpath+0x16/0x1b
-Apr 31 25:25:25 localhost kernel: [117959.226782] ---[ end trace f16822cad7406cec ]---
-Apr 31 25:25:25 localhost kernel: [117959.231085] ------------[ cut here ]------------
-Apr 31 25:25:25 localhost kernel: [117959.231100] WARNING: at /mnt/host/source/src/third_party/kernel/files/drivers/gpu/drm/i915/intel_dp.c:351 intel_dp_check_edp+0x6b/0xb9()
-Apr 31 25:25:25 localhost kernel: [117959.231113] Hardware name: Link
-Apr 31 25:25:25 localhost kernel: [117959.231117] eDP powered off while attempting aux channel communication.
-Apr 31 25:25:25 localhost kernel: [117959.231240] Pid: 10508, comm: X Tainted: G        WC   3.4.0 #1
-Apr 31 25:25:25 localhost kernel: [117959.231247] Call Trace:
-Apr 31 25:25:25 localhost kernel: [117959.231393]  [<ffffffff810d3117>] ? fsnotify_access+0x58/0x60
-Apr 31 25:25:25 localhost kernel: [117959.231402]  [<ffffffff810d3791>] ? vfs_read+0xad/0xd7
-Apr 31 25:25:25 localhost kernel: [117959.231411]  [<ffffffff810e175f>] sys_ioctl+0x56/0x7b
-Apr 31 25:25:25 localhost kernel: [117959.231420]  [<ffffffff810d37fe>] ? sys_read+0x43/0x73
-Apr 31 25:25:25 localhost kernel: [117959.231431]  [<ffffffff8146b7d2>] system_call_fastpath+0x16/0x1b
-Apr 31 25:25:25 localhost kernel: [117959.231439] ---[ end trace f16822cad7406ced ]---
-Apr 31 25:25:25 localhost kernel: [117959.231450] ------------[ cut here ]------------
-Apr 31 25:25:25 localhost kernel: [117959.231458] BARNING: at /mnt/host/source/src/third_party/kernel/files/drivers/gpu/drm/i915/intel_dp.c:351 intel_dp_check_edp+0x6b/0xb9()
-Apr 31 25:25:25 localhost kernel: [117959.231458] ("BARNING" above is intentional)
-Apr 31 25:25:25 localhost kernel: [117959.231471] Hardware name: Link
-Apr 31 25:25:25 localhost kernel: [117959.231475] eDP powered off while attempting aux channel communication.
-Apr 31 25:25:25 localhost kernel: [117959.231482] Modules linked in: nls_iso8859_1 nls_cp437 vfat fat rfcomm i2c_dev ath9k_btcoex snd_hda_codec_hdmi snd_hda_codec_ca0132 mac80211 snd_hda_intel ath9k_common_btcoex snd_hda_codec ath9k_hw_btcoex aesni_intel cryptd snd_hwdep ath snd_pcm aes_x86_64 isl29018(C) memconsole snd_timer snd_page_alloc industrialio(C) cfg80211 rtc_cmos nm10_gpio zram(C) zsmalloc(C) lzo_decompress lzo_compress fuse nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables xt_mark option usb_wwan cdc_ether usbnet ath3k btusb bluetooth uvcvideo videobuf2_core videodev videobuf2_vmalloc videobuf2_memops joydev
-Apr 31 25:25:25 localhost kernel: [117959.231588] Pid: 10508, comm: X Tainted: G        WC   3.4.0 #1
-Apr 31 25:25:25 localhost kernel: [117959.231595] Call Trace:
-Apr 31 25:25:25 localhost kernel: [117959.231601]  [<ffffffff8102a931>] warn_slowpath_common+0x83/0x9c
-Apr 31 25:25:25 localhost kernel: [117959.231610]  [<ffffffff8102a9ed>] warn_slowpath_fmt+0x46/0x48
-Apr 31 25:25:25 localhost kernel: [117959.231620]  [<ffffffff812af495>] intel_dp_check_edp+0x6b/0xb9
-Apr 31 25:25:25 localhost kernel: [117959.231629]  [<ffffffff8102a9ed>] ? warn_slowpath_fmt+
diff --git a/crash_reporter/crash_collector.cc b/crash_reporter/crash_collector.cc
deleted file mode 100644
index 6e81c51..0000000
--- a/crash_reporter/crash_collector.cc
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (C) 2012 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 "crash_collector.h"
-
-#include <dirent.h>
-#include <fcntl.h>  // For file creation modes.
-#include <inttypes.h>
-#include <linux/limits.h>  // PATH_MAX
-#include <pwd.h>  // For struct passwd.
-#include <sys/types.h>  // for mode_t.
-#include <sys/wait.h>  // For waitpid.
-#include <unistd.h>  // For execv and fork.
-
-#include <set>
-#include <utility>
-#include <vector>
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/posix/eintr_wrapper.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/key_value_store.h>
-#include <brillo/osrelease_reader.h>
-#include <brillo/process.h>
-
-namespace {
-
-const char kCollectChromeFile[] =
-    "/mnt/stateful_partition/etc/collect_chrome_crashes";
-const char kCrashTestInProgressPath[] =
-    "/data/misc/crash_reporter/tmp/crash-test-in-progress";
-const char kDefaultLogConfig[] = "/etc/crash_reporter_logs.conf";
-const char kDefaultUserName[] = "chronos";
-const char kLeaveCoreFile[] = "/data/misc/crash_reporter/.leave_core";
-const char kShellPath[] = "/system/bin/sh";
-const char kSystemCrashPath[] = "/data/misc/crash_reporter/crash";
-const char kUploadVarPrefix[] = "upload_var_";
-const char kUploadFilePrefix[] = "upload_file_";
-
-// Product information keys in the /etc/os-release.d folder.
-static const char kBdkVersionKey[] = "bdk_version";
-static const char kProductIDKey[] = "product_id";
-static const char kProductVersionKey[] = "product_version";
-
-// Normally this path is not used.  Unfortunately, there are a few edge cases
-// where we need this.  Any process that runs as kDefaultUserName that crashes
-// is consider a "user crash".  That includes the initial Chrome browser that
-// runs the login screen.  If that blows up, there is no logged in user yet,
-// so there is no per-user dir for us to stash things in.  Instead we fallback
-// to this path as it is at least encrypted on a per-system basis.
-//
-// This also comes up when running autotests.  The GUI is sitting at the login
-// screen while tests are sshing in, changing users, and triggering crashes as
-// the user (purposefully).
-const char kFallbackUserCrashPath[] = "/home/chronos/crash";
-
-// Directory mode of the user crash spool directory.
-const mode_t kUserCrashPathMode = 0755;
-
-// Directory mode of the system crash spool directory.
-const mode_t kSystemCrashPathMode = 01755;
-
-const uid_t kRootOwner = 0;
-const uid_t kRootGroup = 0;
-
-}  // namespace
-
-// Maximum crash reports per crash spool directory.  Note that this is
-// a separate maximum from the maximum rate at which we upload these
-// diagnostics.  The higher this rate is, the more space we allow for
-// core files, minidumps, and kcrash logs, and equivalently the more
-// processor and I/O bandwidth we dedicate to handling these crashes when
-// many occur at once.  Also note that if core files are configured to
-// be left on the file system, we stop adding crashes when either the
-// number of core files or minidumps reaches this number.
-const int CrashCollector::kMaxCrashDirectorySize = 32;
-
-using base::FilePath;
-using base::StringPrintf;
-
-CrashCollector::CrashCollector()
-    : log_config_path_(kDefaultLogConfig) {
-}
-
-CrashCollector::~CrashCollector() {
-}
-
-void CrashCollector::Initialize(
-    CrashCollector::CountCrashFunction count_crash_function,
-    CrashCollector::IsFeedbackAllowedFunction is_feedback_allowed_function) {
-  CHECK(count_crash_function);
-  CHECK(is_feedback_allowed_function);
-
-  count_crash_function_ = count_crash_function;
-  is_feedback_allowed_function_ = is_feedback_allowed_function;
-}
-
-int CrashCollector::WriteNewFile(const FilePath &filename,
-                                 const char *data,
-                                 int size) {
-  int fd = HANDLE_EINTR(open(filename.value().c_str(),
-                             O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666));
-  if (fd < 0) {
-    return -1;
-  }
-
-  int rv = base::WriteFileDescriptor(fd, data, size) ? size : -1;
-  IGNORE_EINTR(close(fd));
-  return rv;
-}
-
-std::string CrashCollector::Sanitize(const std::string &name) {
-  // Make sure the sanitized name does not include any periods.
-  // The logic in crash_sender relies on this.
-  std::string result = name;
-  for (size_t i = 0; i < name.size(); ++i) {
-    if (!isalnum(result[i]) && result[i] != '_')
-      result[i] = '_';
-  }
-  return result;
-}
-
-std::string CrashCollector::FormatDumpBasename(const std::string &exec_name,
-                                               time_t timestamp,
-                                               pid_t pid) {
-  struct tm tm;
-  localtime_r(&timestamp, &tm);
-  std::string sanitized_exec_name = Sanitize(exec_name);
-  return StringPrintf("%s.%04d%02d%02d.%02d%02d%02d.%d",
-                      sanitized_exec_name.c_str(),
-                      tm.tm_year + 1900,
-                      tm.tm_mon + 1,
-                      tm.tm_mday,
-                      tm.tm_hour,
-                      tm.tm_min,
-                      tm.tm_sec,
-                      pid);
-}
-
-FilePath CrashCollector::GetCrashPath(const FilePath &crash_directory,
-                                      const std::string &basename,
-                                      const std::string &extension) {
-  return crash_directory.Append(StringPrintf("%s.%s",
-                                             basename.c_str(),
-                                             extension.c_str()));
-}
-
-FilePath CrashCollector::GetCrashDirectoryInfo(
-    mode_t *mode,
-    uid_t *directory_owner,
-    gid_t *directory_group) {
-  *mode = kSystemCrashPathMode;
-  *directory_owner = kRootOwner;
-  *directory_group = kRootGroup;
-  return FilePath(kSystemCrashPath);
-}
-
-bool CrashCollector::GetUserInfoFromName(const std::string &name,
-                                         uid_t *uid,
-                                         gid_t *gid) {
-  char storage[256];
-  struct passwd passwd_storage;
-  struct passwd *passwd_result = nullptr;
-
-  if (getpwnam_r(name.c_str(), &passwd_storage, storage, sizeof(storage),
-                 &passwd_result) != 0 || passwd_result == nullptr) {
-    LOG(ERROR) << "Cannot find user named " << name;
-    return false;
-  }
-
-  *uid = passwd_result->pw_uid;
-  *gid = passwd_result->pw_gid;
-  return true;
-}
-
-bool CrashCollector::GetCreatedCrashDirectoryByEuid(uid_t euid __unused,
-                                                    FilePath *crash_directory,
-                                                    bool *out_of_capacity) {
-  if (out_of_capacity) *out_of_capacity = false;
-
-  // For testing.
-  if (!forced_crash_directory_.empty()) {
-    *crash_directory = forced_crash_directory_;
-    return true;
-  }
-
-  mode_t directory_mode;
-  uid_t directory_owner;
-  gid_t directory_group;
-  *crash_directory =
-      GetCrashDirectoryInfo(&directory_mode,
-                            &directory_owner,
-                            &directory_group);
-
-  if (!base::PathExists(*crash_directory)) {
-    // Create the spool directory with the appropriate mode (regardless of
-    // umask) and ownership.
-    mode_t old_mask = umask(0);
-    if (mkdir(crash_directory->value().c_str(), directory_mode) < 0 ||
-        chown(crash_directory->value().c_str(),
-              directory_owner,
-              directory_group) < 0) {
-      LOG(ERROR) << "Unable to create appropriate crash directory";
-      return false;
-    }
-    umask(old_mask);
-  }
-
-  if (!base::PathExists(*crash_directory)) {
-    LOG(ERROR) << "Unable to create crash directory "
-               << crash_directory->value().c_str();
-    return false;
-  }
-
-  if (!CheckHasCapacity(*crash_directory)) {
-    if (out_of_capacity) *out_of_capacity = true;
-    LOG(ERROR) << "Directory " << crash_directory->value()
-               << " is out of capacity.";
-    return false;
-  }
-
-  return true;
-}
-
-FilePath CrashCollector::GetProcessPath(pid_t pid) {
-  return FilePath(StringPrintf("/proc/%d", pid));
-}
-
-bool CrashCollector::GetSymlinkTarget(const FilePath &symlink,
-                                      FilePath *target) {
-  ssize_t max_size = 64;
-  std::vector<char> buffer;
-
-  while (true) {
-    buffer.resize(max_size + 1);
-    ssize_t size = readlink(symlink.value().c_str(), buffer.data(), max_size);
-    if (size < 0) {
-      int saved_errno = errno;
-      LOG(ERROR) << "Readlink failed on " << symlink.value() << " with "
-                 << saved_errno;
-      return false;
-    }
-
-    buffer[size] = 0;
-    if (size == max_size) {
-      max_size *= 2;
-      if (max_size > PATH_MAX) {
-        return false;
-      }
-      continue;
-    }
-    break;
-  }
-
-  *target = FilePath(buffer.data());
-  return true;
-}
-
-bool CrashCollector::GetExecutableBaseNameFromPid(pid_t pid,
-                                                 std::string *base_name) {
-  FilePath target;
-  FilePath process_path = GetProcessPath(pid);
-  FilePath exe_path = process_path.Append("exe");
-  if (!GetSymlinkTarget(exe_path, &target)) {
-    LOG(INFO) << "GetSymlinkTarget failed - Path " << process_path.value()
-              << " DirectoryExists: "
-              << base::DirectoryExists(process_path);
-    // Try to further diagnose exe readlink failure cause.
-    struct stat buf;
-    int stat_result = stat(exe_path.value().c_str(), &buf);
-    int saved_errno = errno;
-    if (stat_result < 0) {
-      LOG(INFO) << "stat " << exe_path.value() << " failed: " << stat_result
-                << " " << saved_errno;
-    } else {
-      LOG(INFO) << "stat " << exe_path.value() << " succeeded: st_mode="
-                << buf.st_mode;
-    }
-    return false;
-  }
-  *base_name = target.BaseName().value();
-  return true;
-}
-
-// Return true if the given crash directory has not already reached
-// maximum capacity.
-bool CrashCollector::CheckHasCapacity(const FilePath &crash_directory) {
-  DIR* dir = opendir(crash_directory.value().c_str());
-  if (!dir) {
-    LOG(WARNING) << "Unable to open crash directory "
-                 << crash_directory.value();
-    return false;
-  }
-  struct dirent ent_buf;
-  struct dirent* ent;
-  bool full = false;
-  std::set<std::string> basenames;
-  while (readdir_r(dir, &ent_buf, &ent) == 0 && ent) {
-    if ((strcmp(ent->d_name, ".") == 0) ||
-        (strcmp(ent->d_name, "..") == 0))
-      continue;
-
-    std::string filename(ent->d_name);
-    size_t last_dot = filename.rfind('.');
-    std::string basename;
-    // If there is a valid looking extension, use the base part of the
-    // name.  If the only dot is the first byte (aka a dot file), treat
-    // it as unique to avoid allowing a directory full of dot files
-    // from accumulating.
-    if (last_dot != std::string::npos && last_dot != 0)
-      basename = filename.substr(0, last_dot);
-    else
-      basename = filename;
-    basenames.insert(basename);
-
-    if (basenames.size() >= static_cast<size_t>(kMaxCrashDirectorySize)) {
-      LOG(WARNING) << "Crash directory " << crash_directory.value()
-                   << " already full with " << kMaxCrashDirectorySize
-                   << " pending reports";
-      full = true;
-      break;
-    }
-  }
-  closedir(dir);
-  return !full;
-}
-
-bool CrashCollector::GetLogContents(const FilePath &config_path,
-                                    const std::string &exec_name,
-                                    const FilePath &output_file) {
-  brillo::KeyValueStore store;
-  if (!store.Load(config_path)) {
-    LOG(INFO) << "Unable to read log configuration file "
-              << config_path.value();
-    return false;
-  }
-
-  std::string command;
-  if (!store.GetString(exec_name, &command))
-    return false;
-
-  brillo::ProcessImpl diag_process;
-  diag_process.AddArg(kShellPath);
-  diag_process.AddStringOption("-c", command);
-  diag_process.RedirectOutput(output_file.value());
-
-  const int result = diag_process.Run();
-  if (result != 0) {
-    LOG(INFO) << "Log command \"" << command << "\" exited with " << result;
-    return false;
-  }
-  return true;
-}
-
-void CrashCollector::AddCrashMetaData(const std::string &key,
-                                      const std::string &value) {
-  extra_metadata_.append(StringPrintf("%s=%s\n", key.c_str(), value.c_str()));
-}
-
-void CrashCollector::AddCrashMetaUploadFile(const std::string &key,
-                                            const std::string &path) {
-  if (!path.empty())
-    AddCrashMetaData(kUploadFilePrefix + key, path);
-}
-
-void CrashCollector::AddCrashMetaUploadData(const std::string &key,
-                                            const std::string &value) {
-  if (!value.empty())
-    AddCrashMetaData(kUploadVarPrefix + key, value);
-}
-
-void CrashCollector::WriteCrashMetaData(const FilePath &meta_path,
-                                        const std::string &exec_name,
-                                        const std::string &payload_path) {
-  int64_t payload_size = -1;
-  base::GetFileSize(FilePath(payload_path), &payload_size);
-
-  brillo::OsReleaseReader reader;
-  if (!forced_osreleased_directory_.empty()) {
-    reader.LoadTestingOnly(forced_osreleased_directory_);
-  } else {
-    reader.Load();
-  }
-  std::string bdk_version = "undefined";
-  std::string product_id = "undefined";
-  std::string product_version = "undefined";
-
-  if (!reader.GetString(kBdkVersionKey, &bdk_version)) {
-    LOG(ERROR) << "Could not read " << kBdkVersionKey
-               << " from /etc/os-release.d/";
-  }
-
-  if (!reader.GetString(kProductIDKey, &product_id)) {
-    LOG(ERROR) << "Could not read " << kProductIDKey
-               << " from /etc/os-release.d/";
-  }
-
-  if (!reader.GetString(kProductVersionKey, &product_version)) {
-    LOG(ERROR) << "Could not read " << kProductVersionKey
-               << " from /etc/os-release.d/";
-  }
-
-  std::string meta_data = StringPrintf("%sexec_name=%s\n"
-                                       "payload=%s\n"
-                                       "payload_size=%" PRId64 "\n"
-                                       "%s=%s\n"
-                                       "%s=%s\n"
-                                       "%s=%s\n"
-                                       "done=1\n",
-                                       extra_metadata_.c_str(),
-                                       exec_name.c_str(),
-                                       payload_path.c_str(),
-                                       payload_size,
-                                       kBdkVersionKey,
-                                       bdk_version.c_str(),
-                                       kProductIDKey,
-                                       product_id.c_str(),
-                                       kProductVersionKey,
-                                       product_version.c_str());
-  // We must use WriteNewFile instead of base::WriteFile as we
-  // do not want to write with root access to a symlink that an attacker
-  // might have created.
-  if (WriteNewFile(meta_path, meta_data.c_str(), meta_data.size()) < 0) {
-    LOG(ERROR) << "Unable to write " << meta_path.value();
-  }
-}
-
-bool CrashCollector::IsCrashTestInProgress() {
-  return base::PathExists(FilePath(kCrashTestInProgressPath));
-}
-
-bool CrashCollector::IsDeveloperImage() {
-  // If we're testing crash reporter itself, we don't want to special-case
-  // for developer images.
-  if (IsCrashTestInProgress())
-    return false;
-  return base::PathExists(FilePath(kLeaveCoreFile));
-}
diff --git a/crash_reporter/crash_collector.h b/crash_reporter/crash_collector.h
deleted file mode 100644
index 21b9198..0000000
--- a/crash_reporter/crash_collector.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2012 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 CRASH_REPORTER_CRASH_COLLECTOR_H_
-#define CRASH_REPORTER_CRASH_COLLECTOR_H_
-
-#include <sys/stat.h>
-
-#include <map>
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-// User crash collector.
-class CrashCollector {
- public:
-  typedef void (*CountCrashFunction)();
-  typedef bool (*IsFeedbackAllowedFunction)();
-
-  CrashCollector();
-
-  virtual ~CrashCollector();
-
-  // Initialize the crash collector for detection of crashes, given a
-  // crash counting function, and metrics collection enabled oracle.
-  void Initialize(CountCrashFunction count_crash,
-                  IsFeedbackAllowedFunction is_metrics_allowed);
-
- protected:
-  friend class CrashCollectorTest;
-  FRIEND_TEST(ChromeCollectorTest, HandleCrash);
-  FRIEND_TEST(CrashCollectorTest, CheckHasCapacityCorrectBasename);
-  FRIEND_TEST(CrashCollectorTest, CheckHasCapacityStrangeNames);
-  FRIEND_TEST(CrashCollectorTest, CheckHasCapacityUsual);
-  FRIEND_TEST(CrashCollectorTest, GetCrashDirectoryInfo);
-  FRIEND_TEST(CrashCollectorTest, GetCrashPath);
-  FRIEND_TEST(CrashCollectorTest, GetLogContents);
-  FRIEND_TEST(CrashCollectorTest, ForkExecAndPipe);
-  FRIEND_TEST(CrashCollectorTest, FormatDumpBasename);
-  FRIEND_TEST(CrashCollectorTest, Initialize);
-  FRIEND_TEST(CrashCollectorTest, MetaData);
-  FRIEND_TEST(CrashCollectorTest, Sanitize);
-  FRIEND_TEST(CrashCollectorTest, WriteNewFile);
-  FRIEND_TEST(ForkExecAndPipeTest, Basic);
-  FRIEND_TEST(ForkExecAndPipeTest, NonZeroReturnValue);
-  FRIEND_TEST(ForkExecAndPipeTest, BadOutputFile);
-  FRIEND_TEST(ForkExecAndPipeTest, ExistingOutputFile);
-  FRIEND_TEST(ForkExecAndPipeTest, BadExecutable);
-  FRIEND_TEST(ForkExecAndPipeTest, StderrCaptured);
-  FRIEND_TEST(ForkExecAndPipeTest, NULLParam);
-  FRIEND_TEST(ForkExecAndPipeTest, NoParams);
-  FRIEND_TEST(ForkExecAndPipeTest, SegFaultHandling);
-
-  // Set maximum enqueued crashes in a crash directory.
-  static const int kMaxCrashDirectorySize;
-
-  // Writes |data| of |size| to |filename|, which must be a new file.
-  // If the file already exists or writing fails, return a negative value.
-  // Otherwise returns the number of bytes written.
-  int WriteNewFile(const base::FilePath &filename, const char *data, int size);
-
-  // Return a filename that has only [a-z0-1_] characters by mapping
-  // all others into '_'.
-  std::string Sanitize(const std::string &name);
-
-  // For testing, set the directory always returned by
-  // GetCreatedCrashDirectoryByEuid.
-  void ForceCrashDirectory(const base::FilePath &forced_directory) {
-    forced_crash_directory_ = forced_directory;
-  }
-
-  // For testing, set the root directory to read etc/os-release.d properties
-  // from.
-  void ForceOsReleaseDDirectory(const base::FilePath &forced_directory) {
-    forced_osreleased_directory_ = forced_directory;
-  }
-
-  base::FilePath GetCrashDirectoryInfo(mode_t *mode,
-                                       uid_t *directory_owner,
-                                       gid_t *directory_group);
-  bool GetUserInfoFromName(const std::string &name,
-                           uid_t *uid,
-                           gid_t *gid);
-
-  // Determines the crash directory for given euid, and creates the
-  // directory if necessary with appropriate permissions.  If
-  // |out_of_capacity| is not nullptr, it is set to indicate if the call
-  // failed due to not having capacity in the crash directory. Returns
-  // true whether or not directory needed to be created, false on any
-  // failure.  If the crash directory is at capacity, returns false.
-  bool GetCreatedCrashDirectoryByEuid(uid_t euid,
-                                      base::FilePath *crash_file_path,
-                                      bool *out_of_capacity);
-
-  // Format crash name based on components.
-  std::string FormatDumpBasename(const std::string &exec_name,
-                                 time_t timestamp,
-                                 pid_t pid);
-
-  // Create a file path to a file in |crash_directory| with the given
-  // |basename| and |extension|.
-  base::FilePath GetCrashPath(const base::FilePath &crash_directory,
-                              const std::string &basename,
-                              const std::string &extension);
-
-  base::FilePath GetProcessPath(pid_t pid);
-  bool GetSymlinkTarget(const base::FilePath &symlink,
-                        base::FilePath *target);
-  bool GetExecutableBaseNameFromPid(pid_t pid,
-                                    std::string *base_name);
-
-  // Check given crash directory still has remaining capacity for another
-  // crash.
-  bool CheckHasCapacity(const base::FilePath &crash_directory);
-
-  // Write a log applicable to |exec_name| to |output_file| based on the
-  // log configuration file at |config_path|.
-  bool GetLogContents(const base::FilePath &config_path,
-                      const std::string &exec_name,
-                      const base::FilePath &output_file);
-
-  // Add non-standard meta data to the crash metadata file.  Call
-  // before calling WriteCrashMetaData.  Key must not contain "=" or
-  // "\n" characters.  Value must not contain "\n" characters.
-  void AddCrashMetaData(const std::string &key, const std::string &value);
-
-  // Add a file to be uploaded to the crash reporter server. The file must
-  // persist until the crash report is sent; ideally it should live in the same
-  // place as the .meta file, so it can be cleaned up automatically.
-  void AddCrashMetaUploadFile(const std::string &key, const std::string &path);
-
-  // Add non-standard meta data to the crash metadata file.
-  // Data added though this call will be uploaded to the crash reporter server,
-  // appearing as a form field.
-  void AddCrashMetaUploadData(const std::string &key, const std::string &value);
-
-  // Write a file of metadata about crash.
-  void WriteCrashMetaData(const base::FilePath &meta_path,
-                          const std::string &exec_name,
-                          const std::string &payload_path);
-
-  // Returns true if the a crash test is currently running.
-  bool IsCrashTestInProgress();
-  // Returns true if we should consider ourselves to be running on a
-  // developer image.
-  bool IsDeveloperImage();
-
-  CountCrashFunction count_crash_function_;
-  IsFeedbackAllowedFunction is_feedback_allowed_function_;
-  std::string extra_metadata_;
-  base::FilePath forced_crash_directory_;
-  base::FilePath forced_osreleased_directory_;
-  base::FilePath log_config_path_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CrashCollector);
-};
-
-#endif  // CRASH_REPORTER_CRASH_COLLECTOR_H_
diff --git a/crash_reporter/crash_collector_test.cc b/crash_reporter/crash_collector_test.cc
deleted file mode 100644
index a386cd1..0000000
--- a/crash_reporter/crash_collector_test.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2012 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 "crash_collector_test.h"
-
-#include <unistd.h>
-#include <utility>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/syslog_logging.h>
-#include <gtest/gtest.h>
-
-#include "crash_collector.h"
-
-using base::FilePath;
-using base::StringPrintf;
-using brillo::FindLog;
-using ::testing::Invoke;
-using ::testing::Return;
-
-namespace {
-
-void CountCrash() {
-  ADD_FAILURE();
-}
-
-bool IsMetrics() {
-  ADD_FAILURE();
-  return false;
-}
-
-}  // namespace
-
-class CrashCollectorTest : public ::testing::Test {
- public:
-  void SetUp() {
-    EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(Return());
-
-    collector_.Initialize(CountCrash, IsMetrics);
-    EXPECT_TRUE(test_dir_.CreateUniqueTempDir());
-    brillo::ClearLog();
-  }
-
-  bool CheckHasCapacity();
-
- protected:
-  CrashCollectorMock collector_;
-
-  // Temporary directory used for tests.
-  base::ScopedTempDir test_dir_;
-};
-
-TEST_F(CrashCollectorTest, Initialize) {
-  ASSERT_TRUE(CountCrash == collector_.count_crash_function_);
-  ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_);
-}
-
-TEST_F(CrashCollectorTest, WriteNewFile) {
-  FilePath test_file = test_dir_.path().Append("test_new");
-  const char kBuffer[] = "buffer";
-  unsigned int numBytesWritten = collector_.WriteNewFile(
-      test_file,
-      kBuffer,
-      strlen(kBuffer));
-  EXPECT_EQ(strlen(kBuffer), numBytesWritten);
-  EXPECT_LT(collector_.WriteNewFile(test_file,
-                                    kBuffer,
-                                    strlen(kBuffer)), 0);
-}
-
-TEST_F(CrashCollectorTest, Sanitize) {
-  EXPECT_EQ("chrome", collector_.Sanitize("chrome"));
-  EXPECT_EQ("CHROME", collector_.Sanitize("CHROME"));
-  EXPECT_EQ("1chrome2", collector_.Sanitize("1chrome2"));
-  EXPECT_EQ("chrome__deleted_", collector_.Sanitize("chrome (deleted)"));
-  EXPECT_EQ("foo_bar", collector_.Sanitize("foo.bar"));
-  EXPECT_EQ("", collector_.Sanitize(""));
-  EXPECT_EQ("_", collector_.Sanitize(" "));
-}
-
-TEST_F(CrashCollectorTest, FormatDumpBasename) {
-  struct tm tm = {};
-  tm.tm_sec = 15;
-  tm.tm_min = 50;
-  tm.tm_hour = 13;
-  tm.tm_mday = 23;
-  tm.tm_mon = 4;
-  tm.tm_year = 110;
-  tm.tm_isdst = -1;
-  std::string basename =
-      collector_.FormatDumpBasename("foo", mktime(&tm), 100);
-  ASSERT_EQ("foo.20100523.135015.100", basename);
-}
-
-TEST_F(CrashCollectorTest, GetCrashPath) {
-  EXPECT_EQ("/var/spool/crash/myprog.20100101.1200.1234.core",
-            collector_.GetCrashPath(FilePath("/var/spool/crash"),
-                                    "myprog.20100101.1200.1234",
-                                    "core").value());
-  EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp",
-            collector_.GetCrashPath(FilePath("/home/chronos/user/crash"),
-                                    "chrome.20100101.1200.1234",
-                                    "dmp").value());
-}
-
-
-bool CrashCollectorTest::CheckHasCapacity() {
-  const char* kFullMessage =
-      StringPrintf("Crash directory %s already full",
-                   test_dir_.path().value().c_str()).c_str();
-  bool has_capacity = collector_.CheckHasCapacity(test_dir_.path());
-  bool has_message = FindLog(kFullMessage);
-  EXPECT_EQ(has_message, !has_capacity);
-  return has_capacity;
-}
-
-TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
-  // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
-  for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
-    base::WriteFile(test_dir_.path().Append(StringPrintf("file%d.core", i)),
-                    "", 0);
-    EXPECT_TRUE(CheckHasCapacity());
-  }
-
-  // Test an additional kMaxCrashDirectorySize - 1 meta files fit.
-  for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
-    base::WriteFile(test_dir_.path().Append(StringPrintf("file%d.meta", i)),
-                    "", 0);
-    EXPECT_TRUE(CheckHasCapacity());
-  }
-
-  // Test an additional kMaxCrashDirectorySize meta files don't fit.
-  for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
-    base::WriteFile(test_dir_.path().Append(StringPrintf("overage%d.meta", i)),
-                    "", 0);
-    EXPECT_FALSE(CheckHasCapacity());
-  }
-}
-
-TEST_F(CrashCollectorTest, CheckHasCapacityCorrectBasename) {
-  // Test kMaxCrashDirectorySize - 1 files can be added.
-  for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
-    base::WriteFile(test_dir_.path().Append(StringPrintf("file.%d.core", i)),
-                    "", 0);
-    EXPECT_TRUE(CheckHasCapacity());
-  }
-  base::WriteFile(test_dir_.path().Append("file.last.core"), "", 0);
-  EXPECT_FALSE(CheckHasCapacity());
-}
-
-TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
-  // Test many files with different extensions and same base fit.
-  for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
-    base::WriteFile(test_dir_.path().Append(StringPrintf("a.%d", i)), "", 0);
-    EXPECT_TRUE(CheckHasCapacity());
-  }
-  // Test dot files are treated as individual files.
-  for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
-    base::WriteFile(test_dir_.path().Append(StringPrintf(".file%d", i)), "", 0);
-    EXPECT_TRUE(CheckHasCapacity());
-  }
-  base::WriteFile(test_dir_.path().Append("normal.meta"), "", 0);
-  EXPECT_FALSE(CheckHasCapacity());
-}
-
-TEST_F(CrashCollectorTest, MetaData) {
-  const char kMetaFileBasename[] = "generated.meta";
-  FilePath meta_file = test_dir_.path().Append(kMetaFileBasename);
-  FilePath payload_file = test_dir_.path().Append("payload-file");
-  FilePath osreleased_directory =
-      test_dir_.path().Append("etc").Append("os-release.d");
-  ASSERT_TRUE(base::CreateDirectory(osreleased_directory));
-  collector_.ForceOsReleaseDDirectory(test_dir_.path());
-
-  std::string contents;
-  const char kPayload[] = "foo";
-  ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
-  const char kBdkVersion[] = "1";
-  ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("bdk_version"),
-                              kBdkVersion,
-                              strlen(kBdkVersion)));
-  const char kProductId[] = "baz";
-  ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("product_id"),
-                              kProductId,
-                              strlen(kProductId)));
-  const char kProductVersion[] = "1.2.3.4";
-  ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("product_version"),
-                              kProductVersion,
-                              strlen(kProductVersion)));
-  collector_.AddCrashMetaData("foo", "bar");
-  collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
-  EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
-  const std::string kExpectedMeta =
-      StringPrintf("foo=bar\n"
-          "exec_name=kernel\n"
-          "payload=%s\n"
-          "payload_size=3\n"
-          "bdk_version=1\n"
-          "product_id=baz\n"
-          "product_version=1.2.3.4\n"
-          "done=1\n",
-          test_dir_.path().Append("payload-file").value().c_str());
-  EXPECT_EQ(kExpectedMeta, contents);
-
-  // Test target of symlink is not overwritten.
-  payload_file = test_dir_.path().Append("payload2-file");
-  ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
-  FilePath meta_symlink_path = test_dir_.path().Append("symlink.meta");
-  ASSERT_EQ(0,
-            symlink(kMetaFileBasename,
-                    meta_symlink_path.value().c_str()));
-  ASSERT_TRUE(base::PathExists(meta_symlink_path));
-  brillo::ClearLog();
-  collector_.WriteCrashMetaData(meta_symlink_path,
-                                "kernel",
-                                payload_file.value());
-  // Target metadata contents should have stayed the same.
-  contents.clear();
-  EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
-  EXPECT_EQ(kExpectedMeta, contents);
-  EXPECT_TRUE(FindLog("Unable to write"));
-
-  // Test target of dangling symlink is not created.
-  base::DeleteFile(meta_file, false);
-  ASSERT_FALSE(base::PathExists(meta_file));
-  brillo::ClearLog();
-  collector_.WriteCrashMetaData(meta_symlink_path, "kernel",
-                                payload_file.value());
-  EXPECT_FALSE(base::PathExists(meta_file));
-  EXPECT_TRUE(FindLog("Unable to write"));
-}
-
-TEST_F(CrashCollectorTest, GetLogContents) {
-  FilePath config_file = test_dir_.path().Append("crash_config");
-  FilePath output_file = test_dir_.path().Append("crash_log");
-  const char kConfigContents[] =
-      "foobar=echo hello there | \\\n  sed -e \"s/there/world/\"";
-  ASSERT_TRUE(
-      base::WriteFile(config_file, kConfigContents, strlen(kConfigContents)));
-  base::DeleteFile(FilePath(output_file), false);
-  EXPECT_FALSE(collector_.GetLogContents(config_file,
-                                         "barfoo",
-                                         output_file));
-  EXPECT_FALSE(base::PathExists(output_file));
-  base::DeleteFile(FilePath(output_file), false);
-  EXPECT_TRUE(collector_.GetLogContents(config_file,
-                                        "foobar",
-                                        output_file));
-  ASSERT_TRUE(base::PathExists(output_file));
-  std::string contents;
-  EXPECT_TRUE(base::ReadFileToString(output_file, &contents));
-  EXPECT_EQ("hello world\n", contents);
-}
diff --git a/crash_reporter/crash_collector_test.h b/crash_reporter/crash_collector_test.h
deleted file mode 100644
index cfbb97b..0000000
--- a/crash_reporter/crash_collector_test.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 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 CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
-#define CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
-
-#include "crash_collector.h"
-
-#include <map>
-#include <string>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-class CrashCollectorMock : public CrashCollector {
- public:
-  MOCK_METHOD0(SetUpDBus, void());
-  MOCK_METHOD1(GetActiveUserSessions,
-               bool(std::map<std::string, std::string> *sessions));
-};
-
-#endif  // CRASH_REPORTER_CRASH_COLLECTOR_TEST_H_
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
deleted file mode 100644
index 16e70d8..0000000
--- a/crash_reporter/crash_reporter.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 2012 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 <fcntl.h>  // for open
-
-#include <string>
-#include <vector>
-
-#include <base/files/file_util.h>
-#include <base/guid.h>
-#include <base/logging.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <binder/IServiceManager.h>
-#include <brillo/flag_helper.h>
-#include <brillo/syslog_logging.h>
-#include <metrics/metrics_collector_service_client.h>
-#include <metrics/metrics_library.h>
-#include <utils/String16.h>
-
-
-#include "kernel_collector.h"
-#include "kernel_warning_collector.h"
-#include "unclean_shutdown_collector.h"
-#include "user_collector.h"
-
-#if !defined(__ANDROID__)
-#include "udev_collector.h"
-#endif
-
-static const char kCrashCounterHistogram[] = "Logging.CrashCounter";
-static const char kKernelCrashDetected[] =
-    "/data/misc/crash_reporter/run/kernel-crash-detected";
-static const char kUncleanShutdownDetected[] =
-    "/var/run/unclean-shutdown-detected";
-static const char kGUIDFileName[] = "/data/misc/crash_reporter/guid";
-
-// Enumeration of kinds of crashes to be used in the CrashCounter histogram.
-enum CrashKinds {
-  kCrashKindUncleanShutdown = 1,
-  kCrashKindUser = 2,
-  kCrashKindKernel = 3,
-  kCrashKindUdev = 4,
-  kCrashKindKernelWarning = 5,
-  kCrashKindMax
-};
-
-static MetricsLibrary s_metrics_lib;
-
-using android::brillo::metrics::IMetricsCollectorService;
-using base::FilePath;
-using base::StringPrintf;
-
-static bool IsFeedbackAllowed() {
-  return s_metrics_lib.AreMetricsEnabled();
-}
-
-static bool TouchFile(const FilePath &file_path) {
-  return base::WriteFile(file_path, "", 0) == 0;
-}
-
-static void SendCrashMetrics(CrashKinds type, const char* name) {
-  // TODO(kmixter): We can remove this histogram as part of
-  // crosbug.com/11163.
-  s_metrics_lib.SendEnumToUMA(kCrashCounterHistogram, type, kCrashKindMax);
-  s_metrics_lib.SendCrashToUMA(name);
-}
-
-static void CountKernelCrash() {
-  SendCrashMetrics(kCrashKindKernel, "kernel");
-}
-
-static void CountUdevCrash() {
-  SendCrashMetrics(kCrashKindUdev, "udevcrash");
-}
-
-static void CountUncleanShutdown() {
-  SendCrashMetrics(kCrashKindUncleanShutdown, "uncleanshutdown");
-}
-
-static void CountUserCrash() {
-  SendCrashMetrics(kCrashKindUser, "user");
-  // Tell the metrics collector about the user crash, in order to log active
-  // use time between crashes.
-  MetricsCollectorServiceClient metrics_collector_service;
-
-  if (metrics_collector_service.Init())
-    metrics_collector_service.notifyUserCrash();
-  else
-    LOG(ERROR) << "Failed to send user crash notification to metrics_collector";
-}
-
-
-static int Initialize(KernelCollector *kernel_collector,
-                      UserCollector *user_collector,
-                      UncleanShutdownCollector *unclean_shutdown_collector,
-                      const bool unclean_check,
-                      const bool clean_shutdown) {
-  CHECK(!clean_shutdown) << "Incompatible options";
-
-  // Try to read the GUID from kGUIDFileName.  If the file doesn't exist, is
-  // blank, or the read fails, generate a new GUID and write it to the file.
-  std::string guid;
-  base::FilePath filepath(kGUIDFileName);
-  if (!base::ReadFileToString(filepath, &guid) || guid.empty()) {
-    guid = base::GenerateGUID();
-    // If we can't read or write the file, log an error.  However it is not
-    // a fatal error, as the crash server will assign a random GUID based
-    // on a hash of the IP address if one is not provided in the report.
-    if (base::WriteFile(filepath, guid.c_str(), guid.size()) <= 0) {
-      LOG(ERROR) << "Could not write guid " << guid << " to file "
-                 << filepath.value();
-    }
-  }
-
-  bool was_kernel_crash = false;
-  bool was_unclean_shutdown = false;
-  kernel_collector->Enable();
-  if (kernel_collector->is_enabled()) {
-    was_kernel_crash = kernel_collector->Collect();
-  }
-
-  if (unclean_check) {
-    was_unclean_shutdown = unclean_shutdown_collector->Collect();
-  }
-
-  // Touch a file to notify the metrics daemon that a kernel
-  // crash has been detected so that it can log the time since
-  // the last kernel crash.
-  if (IsFeedbackAllowed()) {
-    if (was_kernel_crash) {
-      TouchFile(FilePath(kKernelCrashDetected));
-    } else if (was_unclean_shutdown) {
-      // We only count an unclean shutdown if it did not come with
-      // an associated kernel crash.
-      TouchFile(FilePath(kUncleanShutdownDetected));
-    }
-  }
-
-  // Must enable the unclean shutdown collector *after* collecting.
-  unclean_shutdown_collector->Enable();
-  user_collector->Enable();
-
-  return 0;
-}
-
-static int HandleUserCrash(UserCollector *user_collector,
-                           const std::string& user, const bool crash_test) {
-  // Handle a specific user space crash.
-  CHECK(!user.empty()) << "--user= must be set";
-
-  // Make it possible to test what happens when we crash while
-  // handling a crash.
-  if (crash_test) {
-    *(volatile char *)0 = 0;
-    return 0;
-  }
-
-  // Accumulate logs to help in diagnosing failures during user collection.
-  brillo::LogToString(true);
-  // Handle the crash, get the name of the process from procfs.
-  bool handled = user_collector->HandleCrash(user, nullptr);
-  brillo::LogToString(false);
-  if (!handled)
-    return 1;
-  return 0;
-}
-
-#if !defined(__ANDROID__)
-static int HandleUdevCrash(UdevCollector *udev_collector,
-                           const std::string& udev_event) {
-  // Handle a crash indicated by a udev event.
-  CHECK(!udev_event.empty()) << "--udev= must be set";
-
-  // Accumulate logs to help in diagnosing failures during user collection.
-  brillo::LogToString(true);
-  bool handled = udev_collector->HandleCrash(udev_event);
-  brillo::LogToString(false);
-  if (!handled)
-    return 1;
-  return 0;
-}
-#endif
-
-static int HandleKernelWarning(KernelWarningCollector
-                               *kernel_warning_collector) {
-  // Accumulate logs to help in diagnosing failures during collection.
-  brillo::LogToString(true);
-  bool handled = kernel_warning_collector->Collect();
-  brillo::LogToString(false);
-  if (!handled)
-    return 1;
-  return 0;
-}
-
-// Interactive/diagnostics mode for generating kernel crash signatures.
-static int GenerateKernelSignature(KernelCollector *kernel_collector,
-                                   const std::string& kernel_signature_file) {
-  std::string kcrash_contents;
-  std::string signature;
-  if (!base::ReadFileToString(FilePath(kernel_signature_file),
-                              &kcrash_contents)) {
-    fprintf(stderr, "Could not read file.\n");
-    return 1;
-  }
-  if (!kernel_collector->ComputeKernelStackSignature(
-          kcrash_contents,
-          &signature,
-          true)) {
-    fprintf(stderr, "Signature could not be generated.\n");
-    return 1;
-  }
-  printf("Kernel crash signature is \"%s\".\n", signature.c_str());
-  return 0;
-}
-
-// Ensure stdout, stdin, and stderr are open file descriptors.  If
-// they are not, any code which writes to stderr/stdout may write out
-// to files opened during execution.  In particular, when
-// crash_reporter is run by the kernel coredump pipe handler (via
-// kthread_create/kernel_execve), it will not have file table entries
-// 1 and 2 (stdout and stderr) populated.  We populate them here.
-static void OpenStandardFileDescriptors() {
-  int new_fd = -1;
-  // We open /dev/null to fill in any of the standard [0, 2] file
-  // descriptors.  We leave these open for the duration of the
-  // process.  This works because open returns the lowest numbered
-  // invalid fd.
-  do {
-    new_fd = open("/dev/null", 0);
-    CHECK_GE(new_fd, 0) << "Unable to open /dev/null";
-  } while (new_fd >= 0 && new_fd <= 2);
-  close(new_fd);
-}
-
-int main(int argc, char *argv[]) {
-  DEFINE_bool(init, false, "Initialize crash logging");
-  DEFINE_bool(clean_shutdown, false, "Signal clean shutdown");
-  DEFINE_string(generate_kernel_signature, "",
-                "Generate signature from given kcrash file");
-  DEFINE_bool(crash_test, false, "Crash test");
-  DEFINE_string(user, "", "User crash info (pid:signal:exec_name)");
-  DEFINE_bool(unclean_check, true, "Check for unclean shutdown");
-
-#if !defined(__ANDROID__)
-  DEFINE_string(udev, "", "Udev event description (type:device:subsystem)");
-#endif
-
-  DEFINE_bool(kernel_warning, false, "Report collected kernel warning");
-  DEFINE_string(pid, "", "PID of crashing process");
-  DEFINE_string(uid, "", "UID of crashing process");
-  DEFINE_string(exe, "", "Executable name of crashing process");
-  DEFINE_bool(core2md_failure, false, "Core2md failure test");
-  DEFINE_bool(directory_failure, false, "Spool directory failure test");
-  DEFINE_string(filter_in, "",
-                "Ignore all crashes but this for testing");
-
-  OpenStandardFileDescriptors();
-  FilePath my_path = base::MakeAbsoluteFilePath(FilePath(argv[0]));
-  s_metrics_lib.Init();
-  brillo::FlagHelper::Init(argc, argv, "Chromium OS Crash Reporter");
-  brillo::OpenLog(my_path.BaseName().value().c_str(), true);
-  brillo::InitLog(brillo::kLogToSyslog);
-
-  KernelCollector kernel_collector;
-  kernel_collector.Initialize(CountKernelCrash, IsFeedbackAllowed);
-  UserCollector user_collector;
-  user_collector.Initialize(CountUserCrash,
-                            my_path.value(),
-                            IsFeedbackAllowed,
-                            true,  // generate_diagnostics
-                            FLAGS_core2md_failure,
-                            FLAGS_directory_failure,
-                            FLAGS_filter_in);
-  UncleanShutdownCollector unclean_shutdown_collector;
-  unclean_shutdown_collector.Initialize(CountUncleanShutdown,
-                                        IsFeedbackAllowed);
-
-#if !defined(__ANDROID__)
-  UdevCollector udev_collector;
-  udev_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
-#endif
-
-  KernelWarningCollector kernel_warning_collector;
-  kernel_warning_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
-
-  if (FLAGS_init) {
-    return Initialize(&kernel_collector,
-                      &user_collector,
-                      &unclean_shutdown_collector,
-                      FLAGS_unclean_check,
-                      FLAGS_clean_shutdown);
-  }
-
-  if (FLAGS_clean_shutdown) {
-    unclean_shutdown_collector.Disable();
-    user_collector.Disable();
-    return 0;
-  }
-
-  if (!FLAGS_generate_kernel_signature.empty()) {
-    return GenerateKernelSignature(&kernel_collector,
-                                   FLAGS_generate_kernel_signature);
-  }
-
-#if !defined(__ANDROID__)
-  if (!FLAGS_udev.empty()) {
-    return HandleUdevCrash(&udev_collector, FLAGS_udev);
-  }
-#endif
-
-  if (FLAGS_kernel_warning) {
-    return HandleKernelWarning(&kernel_warning_collector);
-  }
-
-  return HandleUserCrash(&user_collector, FLAGS_user, FLAGS_crash_test);
-}
diff --git a/crash_reporter/crash_reporter.rc b/crash_reporter/crash_reporter.rc
deleted file mode 100644
index e6d1ec5..0000000
--- a/crash_reporter/crash_reporter.rc
+++ /dev/null
@@ -1,37 +0,0 @@
-on property:crash_reporter.coredump.enabled=1
-    write /proc/sys/kernel/core_pattern \
-          "|/system/bin/crash_reporter --user=%P:%s:%u:%g:%e"
-
-on property:crash_reporter.coredump.enabled=0
-    write /proc/sys/kernel/core_pattern "core"
-
-on post-fs-data
-    # Allow catching multiple unrelated concurrent crashes, but use a finite
-    # number to prevent infinitely recursing on crash handling.
-    write /proc/sys/kernel/core_pipe_limit 4
-
-    # Remove any previous orphaned locks.
-    rmdir /data/misc/crash_reporter/lock/crash_sender
-
-    # Remove any previous run files.
-    rm /data/misc/crash_reporter/run/kernel-crash-detected
-    rmdir /data/misc/crash_reporter/run
-
-    # Create crash directories.
-    # These directories are group-writable by root so that crash_reporter can
-    # still access them when it switches users.
-    mkdir /data/misc/crash_reporter 0770 root root
-    mkdir /data/misc/crash_reporter/crash 0770 root root
-    mkdir /data/misc/crash_reporter/lock 0700 root root
-    mkdir /data/misc/crash_reporter/log 0700 root root
-    mkdir /data/misc/crash_reporter/run 0700 root root
-    mkdir /data/misc/crash_reporter/tmp 0770 root root
-
-service crash_reporter /system/bin/crash_reporter --init
-    class late_start
-    oneshot
-
-service crash_sender /system/bin/periodic_scheduler 3600 14400 crash_sender \
-    /system/bin/crash_sender
-    class late_start
-    group system
diff --git a/crash_reporter/crash_reporter_logs.conf b/crash_reporter/crash_reporter_logs.conf
deleted file mode 100644
index 7db308c..0000000
--- a/crash_reporter/crash_reporter_logs.conf
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (C) 2012 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.
-
-# This file is parsed by chromeos::KeyValueStore. It has the format:
-#
-# <basename>=<shell command>\n
-#
-# Commands may be split across multiple lines using trailing backslashes.
-#
-# When an executable named <basename> crashes, the corresponding command is
-# executed and its standard output and standard error are attached to the crash
-# report.
-#
-# Use caution in modifying this file. Only run common Unix commands here, as
-# these commands will be run when a crash has recently occurred and we should
-# avoid running anything that might cause another crash. Similarly, these
-# commands block notification of the crash to parent processes, so commands
-# should execute quickly.
-
-update_engine=cat $(ls -1tr /var/log/update_engine | tail -5 | \
-  sed s.^./var/log/update_engine/.) | tail -c 50000
-
-# The cros_installer output is logged into the update engine log file,
-# so it is handled in the same way as update_engine.
-cros_installer=cat $(ls -1tr /var/log/update_engine | tail -5 | \
-  sed s.^./var/log/update_engine/.) | tail -c 50000
-
-# Dump the last 20 lines of the last two files in Chrome's system and user log
-# directories, along with the last 20 messages from the session manager.
-chrome=\
-  for f in $(ls -1rt /var/log/chrome/chrome_[0-9]* | tail -2) \
-    $(ls -1rt /home/chronos/u-*/log/chrome_[0-9]* 2>/dev/null | tail -2); do \
-    echo "===$f (tail)==="; \
-    tail -20 $f; \
-    echo EOF; \
-    echo; \
-  done; \
-  echo "===session_manager (tail)==="; \
-  awk '$3 ~ "^session_manager\[" { print }' /var/log/messages | tail -20; \
-  echo EOF
-
-# The following rule is used for generating additional diagnostics when
-# collection of user crashes fails.  This output should not be too large
-# as it is stored in memory.  The output format specified for 'ps' is the
-# same as with the "u" ("user-oriented") option, except it doesn't show
-# the commands' arguments (i.e. "comm" instead of "command").
-crash_reporter-user-collection=\
-  echo "===ps output==="; \
-  ps axw -o user,pid,%cpu,%mem,vsz,rss,tname,stat,start_time,bsdtime,comm | \
-    tail -c 25000; \
-  echo "===meminfo==="; \
-  cat /proc/meminfo
-
-# This rule is similar to the crash_reporter-user-collection rule, except it is
-# run for kernel errors reported through udev events.
-crash_reporter-udev-collection-change-card0-drm=\
-  for dri in /sys/kernel/debug/dri/*; do \
-    echo "===$dri/i915_error_state==="; \
-    cat $dri/i915_error_state; \
-  done
-
-# When trackpad driver cyapa detects some abnormal behavior, we collect
-# additional logs from kernel messages.
-crash_reporter-udev-collection-change--i2c-cyapa=\
-  /usr/sbin/kernel_log_collector.sh cyapa 30
-# When trackpad/touchscreen driver atmel_mxt_ts detects some abnormal behavior,
-# we collect additional logs from kernel messages.
-crash_reporter-udev-collection-change--i2c-atmel_mxt_ts=\
-  /usr/sbin/kernel_log_collector.sh atmel 30
-# When touch device noise are detected, we collect relevant logs.
-# (crosbug.com/p/16788)
-crash_reporter-udev-collection---TouchNoise=cat /var/log/touch_noise.log
-# Periodically collect touch event log for debugging (crosbug.com/p/17244)
-crash_reporter-udev-collection---TouchEvent=cat /var/log/touch_event.log
-
-# Collect the last 50 lines of /var/log/messages and /var/log/net.log for
-# intel wifi driver (iwlwifi) for debugging purpose.
-crash_reporter-udev-collection-devcoredump-iwlwifi=\
-  echo "===/var/log/messages==="; \
-  tail -n 50 /var/log/messages; \
-  echo "===/var/log/net.log==="; \
-  tail -n 50 /var/log/net.log; \
-  echo EOF
-
-# Dump the last 50 lines of the last two powerd log files -- if the job has
-# already restarted, we want to see the end of the previous instance's logs.
-powerd=\
-  for f in $(ls -1tr /var/log/power_manager/powerd.[0-9]* | tail -2); do \
-    echo "===$(basename $f) (tail)==="; \
-    tail -50 $f; \
-    echo EOF; \
-  done
-# If power_supply_info aborts (due to e.g. a bad battery), its failure message
-# could end up in various places depending on which process was running it.
-# Attach the end of powerd's log since it might've also logged the underlying
-# problem.
-power_supply_info=\
-  echo "===powerd.LATEST (tail)==="; \
-  tail -50 /var/log/power_manager/powerd.LATEST; \
-  echo EOF
-# powerd_setuid_helper gets run by powerd, so its stdout/stderr will be mixed in
-# with powerd's stdout/stderr.
-powerd_setuid_helper=\
-  echo "===powerd.OUT (tail)==="; \
-  tail -50 /var/log/powerd.out; \
-  echo EOF
-
-# The following rules are only for testing purposes.
-crash_log_test=echo hello world
-crash_log_recursion_test=sleep 1 && \
-  /usr/local/autotest/tests/crash_log_recursion_test
diff --git a/crash_reporter/crash_reporter_logs_test.cc b/crash_reporter/crash_reporter_logs_test.cc
deleted file mode 100644
index 77f5a7f..0000000
--- a/crash_reporter/crash_reporter_logs_test.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <brillo/key_value_store.h>
-#include <gtest/gtest.h>
-
-namespace {
-
-// Name of the checked-in configuration file containing log-collection commands.
-const char kConfigFile[] = "/system/etc/crash_reporter_logs.conf";
-
-// Signature name for crash_reporter user collection.
-// kConfigFile is expected to contain this entry.
-const char kUserCollectorSignature[] = "crash_reporter-user-collection";
-
-}  // namespace
-
-// Tests that the config file is parsable and that Chrome is listed.
-TEST(CrashReporterLogsTest, ReadConfig) {
-  brillo::KeyValueStore store;
-  ASSERT_TRUE(store.Load(base::FilePath(kConfigFile)));
-  std::string command;
-  EXPECT_TRUE(store.GetString(kUserCollectorSignature, &command));
-  EXPECT_FALSE(command.empty());
-}
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
deleted file mode 100755
index a430ab5..0000000
--- a/crash_reporter/crash_sender
+++ /dev/null
@@ -1,719 +0,0 @@
-#!/system/bin/sh
-
-# Copyright (C) 2010 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.
-
-set -e
-
-# Default product ID in crash report (used if GOOGLE_CRASH_* is undefined).
-BRILLO_PRODUCT=Brillo
-
-# Base directory that contains any crash reporter state files.
-CRASH_STATE_DIR="/data/misc/crash_reporter"
-
-# File containing crash_reporter's anonymized guid.
-GUID_FILE="${CRASH_STATE_DIR}/guid"
-
-# Crash sender lock in case the sender is already running.
-CRASH_SENDER_LOCK="${CRASH_STATE_DIR}/lock/crash_sender"
-
-# Path to file that indicates a crash test is currently running.
-CRASH_TEST_IN_PROGRESS_FILE="${CRASH_STATE_DIR}/tmp/crash-test-in-progress"
-
-# Set this to 1 in the environment to allow uploading crash reports
-# for unofficial versions.
-FORCE_OFFICIAL=${FORCE_OFFICIAL:-0}
-
-# Path to hardware class description.
-HWCLASS_PATH="/sys/devices/platform/chromeos_acpi/HWID"
-
-# Path to file that indicates this is a developer image.
-LEAVE_CORE_FILE="${CRASH_STATE_DIR}/.leave_core"
-
-# Path to list_proxies.
-LIST_PROXIES="list_proxies"
-
-# Maximum crashes to send per day.
-MAX_CRASH_RATE=${MAX_CRASH_RATE:-32}
-
-# File whose existence mocks crash sending.  If empty we pretend the
-# crash sending was successful, otherwise unsuccessful.
-MOCK_CRASH_SENDING="${CRASH_STATE_DIR}/tmp/mock-crash-sending"
-
-# Set this to 1 in the environment to pretend to have booted in developer
-# mode.  This is used by autotests.
-MOCK_DEVELOPER_MODE=${MOCK_DEVELOPER_MODE:-0}
-
-# Ignore PAUSE_CRASH_SENDING file if set.
-OVERRIDE_PAUSE_SENDING=${OVERRIDE_PAUSE_SENDING:-0}
-
-# File whose existence causes crash sending to be delayed (for testing).
-# Must be stateful to enable testing kernel crashes.
-PAUSE_CRASH_SENDING="${CRASH_STATE_DIR}/lock/crash_sender_paused"
-
-# Path to a directory of restricted certificates which includes
-# a certificate for the crash server.
-RESTRICTED_CERTIFICATES_PATH="/system/etc/security/cacerts"
-RESTRICTED_CERTIFICATES_PATH_GOOGLE="/system/etc/security/cacerts_google"
-
-# File whose existence implies we're running and not to start again.
-RUN_FILE="${CRASH_STATE_DIR}/run/crash_sender.pid"
-
-# Maximum time to sleep between sends.
-SECONDS_SEND_SPREAD=${SECONDS_SEND_SPREAD:-600}
-
-# Set this to 1 to allow uploading of device coredumps.
-DEVCOREDUMP_UPLOAD_FLAG_FILE="${CRASH_STATE_DIR}/device_coredump_upload_allowed"
-
-# The weave configuration file.
-WEAVE_CONF_FILE="/etc/weaved/weaved.conf"
-
-# The os-release.d folder.
-OSRELEASED_FOLDER="/etc/os-release.d"
-
-# The syslog tag for all logging we emit.
-TAG="$(basename $0)[$$]"
-
-# Directory to store timestamp files indicating the uploads in the past 24
-# hours.
-TIMESTAMPS_DIR="${CRASH_STATE_DIR}/crash_sender"
-
-# Temp directory for this process.
-TMP_DIR=""
-
-# Crash report log file.
-CRASH_LOG="${CRASH_STATE_DIR}/log/uploads.log"
-
-lecho() {
-  log -t "${TAG}" "$@"
-}
-
-lwarn() {
-  lecho -psyslog.warn "$@"
-}
-
-# Returns true if mock is enabled.
-is_mock() {
-  [ -f "${MOCK_CRASH_SENDING}" ] && return 0
-  return 1
-}
-
-is_mock_successful() {
-  local mock_in=$(cat "${MOCK_CRASH_SENDING}")
-  [ "${mock_in}" = "" ] && return 0  # empty file means success
-  return 1
-}
-
-cleanup() {
-  if [ -n "${TMP_DIR}" ]; then
-    rm -rf "${TMP_DIR}"
-  fi
-  rm -f "${RUN_FILE}"
-  if [ -n "${CRASH_SENDER_LOCK}" ]; then
-    rm -rf "${CRASH_SENDER_LOCK}"
-  fi
-  crash_done
-}
-
-crash_done() {
-  if is_mock; then
-    # For testing purposes, emit a message to log so that we
-    # know when the test has received all the messages from this run.
-    lecho "crash_sender done."
-  fi
-}
-
-is_official_image() {
-  [ ${FORCE_OFFICIAL} -ne 0 ] && return 0
-  if [ "$(getprop ro.secure)" = "1" ]; then
-    return 0
-  else
-    return 1
-  fi
-}
-
-# Returns 0 if the a crash test is currently running.  NOTE: Mirrors
-# crash_collector.cc:CrashCollector::IsCrashTestInProgress().
-is_crash_test_in_progress() {
-  [ -f "${CRASH_TEST_IN_PROGRESS_FILE}" ] && return 0
-  return 1
-}
-
-# Returns 0 if we should consider ourselves to be running on a developer
-# image.  NOTE: Mirrors crash_collector.cc:CrashCollector::IsDeveloperImage().
-is_developer_image() {
-  # If we're testing crash reporter itself, we don't want to special-case
-  # for developer images.
-  is_crash_test_in_progress && return 1
-  [ -f "${LEAVE_CORE_FILE}" ] && return 0
-  return 1
-}
-
-# Returns 0 if we should consider ourselves to be running on a test image.
-is_test_image() {
-  # If we're testing crash reporter itself, we don't want to special-case
-  # for test images.
-  is_crash_test_in_progress && return 1
-  case $(get_channel) in
-  test*) return 0;;
-  esac
-  return 1
-}
-
-# Returns 0 if the machine booted up in developer mode.
-is_developer_mode() {
-  [ ${MOCK_DEVELOPER_MODE} -ne 0 ] && return 0
-  # If we're testing crash reporter itself, we don't want to special-case
-  # for developer mode.
-  is_crash_test_in_progress && return 1
-  if [ "$(getprop ro.debuggable)" = "1" ]; then
-    return 0
-  else
-    return 1
-  fi
-}
-
-# Returns the path of the certificates directory to be used when sending
-# reports to the crash server.
-# If crash_reporter.full_certs=1, return the full certificates path.
-# Otherwise return the Google-specific certificates path.
-get_certificates_path() {
-  if [ "$(getprop crash_reporter.full_certs)" = "1" ]; then
-    echo "${RESTRICTED_CERTIFICATES_PATH}"
-  else
-    echo "${RESTRICTED_CERTIFICATES_PATH_GOOGLE}"
-  fi
-}
-
-# Return 0 if the uploading of device coredumps is allowed.
-is_device_coredump_upload_allowed() {
-  [ -f "${DEVCOREDUMP_UPLOAD_FLAG_FILE}" ] && return 0
-  return 1
-}
-
-# Generate a uniform random number in 0..max-1.
-# POSIX arithmetic expansion requires support of at least signed long integers.
-# On 32-bit systems, that may mean 32-bit signed integers, in which case the
-# 32-bit random number read from /dev/urandom may be interpreted as negative
-# when used inside an arithmetic expansion (since the high bit might be set).
-# mksh at least is known to behave this way.
-# For this case, simply take the absolute value, which will still give a
-# roughly uniform random distribution for the modulo (as we are merely ignoring
-# the high/sign bit).
-# See corresponding Arithmetic Expansion and Arithmetic Expression sections:
-# POSIX: http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_04
-# mksh: http://linux.die.net/man/1/mksh
-generate_uniform_random() {
-  local max=$1
-  local random="$(od -An -N4 -tu /dev/urandom)"
-  echo $(((random < 0 ? -random : random) % max))
-}
-
-# Check if sending a crash now does not exceed the maximum 24hr rate and
-# commit to doing so, if not.
-check_rate() {
-  mkdir -p ${TIMESTAMPS_DIR}
-  # Only consider minidumps written in the past 24 hours by removing all older.
-  find "${TIMESTAMPS_DIR}" -mindepth 1 -mtime +1 \
-      -exec rm -- '{}' ';'
-  local sends_in_24hrs=$(echo "${TIMESTAMPS_DIR}"/* | wc -w)
-  lecho "Current send rate: ${sends_in_24hrs}sends/24hrs"
-  if [ ${sends_in_24hrs} -ge ${MAX_CRASH_RATE} ]; then
-    lecho "Cannot send more crashes:"
-    lecho "  current ${sends_in_24hrs}send/24hrs >= " \
-          "max ${MAX_CRASH_RATE}send/24hrs"
-    return 1
-  fi
-  mktemp "${TIMESTAMPS_DIR}"/XXXXXX > /dev/null
-  return 0
-}
-
-# Gets the base part of a crash report file, such as name.01234.5678.9012 from
-# name.01234.5678.9012.meta or name.01234.5678.9012.log.tar.xz.  We make sure
-# "name" is sanitized in CrashCollector::Sanitize to not include any periods.
-get_base() {
-  echo "$1" | cut -d. -f-4
-}
-
-get_extension() {
-  local extension="${1##*.}"
-  local filename="${1%.*}"
-  # For gzipped file, we ignore .gz and get the real extension
-  if [ "${extension}" = "gz" ]; then
-    echo "${filename##*.}"
-  else
-    echo "${extension}"
-  fi
-}
-
-# Return which kind of report the given metadata file relates to
-get_kind() {
-  local payload="$(get_key_value "$1" "payload")"
-  if [ ! -r "${payload}" ]; then
-    lecho "Missing payload: ${payload}"
-    echo "undefined"
-    return
-  fi
-  local kind="$(get_extension "${payload}")"
-  if [ "${kind}" = "dmp" ]; then
-    echo "minidump"
-    return
-  fi
-  echo "${kind}"
-}
-
-get_key_value() {
-  local file="$1" key="$2" value
-
-  if [ -f "${file}/${key}" ]; then
-    # Get the value from a folder where each key is its own file.  The key
-    # file's entire contents is the value.
-    value=$(cat "${file}/${key}")
-  elif [ -f "${file}" ]; then
-    # Get the value from a file that has multiple key=value combinations.
-    # Return the first entry.  There shouldn't be more than one anyways.
-    # Substr at length($1) + 2 skips past the key and following = sign (awk
-    # uses 1-based indexes), but preserves embedded = characters.
-    value=$(sed -n "/^${key}[[:space:]]*=/{s:^[^=]*=::p;q}" "${file}")
-  fi
-
-  echo "${value:-undefined}"
-}
-
-get_keys() {
-  local file="$1" regex="$2"
-
-  cut -d '=' -f1 "${file}" | grep --color=never "${regex}"
-}
-
-# Return the channel name (sans "-channel" suffix).
-get_channel() {
-  getprop ro.product.channel | sed 's:-channel$::'
-}
-
-# Return the hardware class or "undefined".
-get_hardware_class() {
-  if [ -r "${HWCLASS_PATH}" ]; then
-    cat "${HWCLASS_PATH}"
-  else
-    echo "undefined"
-  fi
-}
-
-# Return the log string filtered with only JSON-safe white-listed characters.
-filter_log_string() {
-  echo "$1" | tr -cd '[:alnum:]_.\-:;'
-}
-
-send_crash() {
-  local meta_path="$1"
-  local report_payload="$(get_key_value "${meta_path}" "payload")"
-  local kind="$(get_kind "${meta_path}")"
-  local exec_name="$(get_key_value "${meta_path}" "exec_name")"
-  local url="$(get_key_value "${OSRELEASED_FOLDER}" "crash_server")"
-  local bdk_version="$(get_key_value "${meta_path}" "bdk_version")"
-  local hwclass="$(get_hardware_class)"
-  local write_payload_size="$(get_key_value "${meta_path}" "payload_size")"
-  local log="$(get_key_value "${meta_path}" "log")"
-  local sig="$(get_key_value "${meta_path}" "sig")"
-  local send_payload_size="$(stat -c "%s" "${report_payload}" 2>/dev/null)"
-  local product="$(get_key_value "${meta_path}" "product_id")"
-  local version="$(get_key_value "${meta_path}" "product_version")"
-  local upload_prefix="$(get_key_value "${meta_path}" "upload_prefix")"
-  local guid
-  local model_manifest_id="$(get_key_value "${WEAVE_CONF_FILE}" "model_id")"
-
-  # If crash_reporter.server is not set return with an error.
-  if [ -z "${url}" ]; then
-    lecho "Configuration error: crash_reporter.server not set."
-    return 1
-  fi
-
-  set -- \
-    -F "write_payload_size=${write_payload_size}" \
-    -F "send_payload_size=${send_payload_size}"
-  if [ "${sig}" != "undefined" ]; then
-    set -- "$@" \
-      -F "sig=${sig}" \
-      -F "sig2=${sig}"
-  fi
-  if [ -r "${report_payload}" ]; then
-    set -- "$@" \
-      -F "upload_file_${kind}=@${report_payload}"
-  fi
-  if [ "${log}" != "undefined" -a -r "${log}" ]; then
-    set -- "$@" \
-      -F "log=@${log}"
-  fi
-
-  if [ "${upload_prefix}" = "undefined" ]; then
-    upload_prefix=""
-  fi
-
-  # Grab any variable that begins with upload_.
-  local v
-  for k in $(get_keys "${meta_path}" "^upload_"); do
-    v="$(get_key_value "${meta_path}" "${k}")"
-    case ${k} in
-      # Product & version are handled separately.
-      upload_var_prod) ;;
-      upload_var_ver) ;;
-      upload_var_*)
-        set -- "$@" -F "${upload_prefix}${k#upload_var_}=${v}"
-        ;;
-      upload_file_*)
-        if [ -r "${v}" ]; then
-          set -- "$@" -F "${upload_prefix}${k#upload_file_}=@${v}"
-        fi
-        ;;
-    esac
-  done
-
-  # If ID or VERSION_ID is undefined, we use the default product name
-  # and bdk_version from /etc/os-release.d.
-  if [ "${product}" = "undefined" ]; then
-    product="${BRILLO_PRODUCT}"
-  fi
-  if [ "${version}" = "undefined" ]; then
-    version="${bdk_version}"
-  fi
-
-  local image_type
-  if is_test_image; then
-    image_type="test"
-  elif is_developer_image; then
-    image_type="dev"
-  elif [ ${FORCE_OFFICIAL} -ne 0 ]; then
-    image_type="force-official"
-  elif is_mock && ! is_mock_successful; then
-    image_type="mock-fail"
-  fi
-
-  local boot_mode
-  if is_developer_mode; then
-    boot_mode="dev"
-  fi
-
-  # Need to strip dashes ourselves as Chrome preserves it in the file
-  # nowadays.  This is also what the Chrome breakpad client does.
-  guid=$(tr -d '-' < "${GUID_FILE}")
-
-  local error_type="$(get_key_value "${meta_path}" "error_type")"
-  [ "${error_type}" = "undefined" ] && error_type=
-
-  lecho "Sending crash:"
-  if [ "${product}" != "${BRILLO_PRODUCT}" ]; then
-    lecho "  Sending crash report on behalf of ${product}"
-  fi
-  lecho "  Metadata: ${meta_path} (${kind})"
-  lecho "  Payload: ${report_payload}"
-  lecho "  Version: ${version}"
-  lecho "  Bdk Version: ${bdk_version}"
-  [ -n "${image_type}" ] && lecho "  Image type: ${image_type}"
-  [ -n "${boot_mode}" ] && lecho "  Boot mode: ${boot_mode}"
-  if is_mock; then
-    lecho "  Product: ${product}"
-    lecho "  URL: ${url}"
-    lecho "  HWClass: ${hwclass}"
-    lecho "  write_payload_size: ${write_payload_size}"
-    lecho "  send_payload_size: ${send_payload_size}"
-    if [ "${log}" != "undefined" ]; then
-      lecho "  log: @${log}"
-    fi
-    if [ "${sig}" != "undefined" ]; then
-      lecho "  sig: ${sig}"
-    fi
-  fi
-  lecho "  Exec name: ${exec_name}"
-  [ -n "${error_type}" ] && lecho "  Error type: ${error_type}"
-  if is_mock; then
-    if ! is_mock_successful; then
-      lecho "Mocking unsuccessful send"
-      return 1
-    fi
-    lecho "Mocking successful send"
-    return 0
-  fi
-
-  # Read in the first proxy, if any, for a given URL.  NOTE: The
-  # double-quotes are necessary due to a bug in dash with the "local"
-  # builtin command and values that have spaces in them (see
-  # "https://bugs.launchpad.net/ubuntu/+source/dash/+bug/139097").
-  if [ -f "${LIST_PROXIES}" ]; then
-    local proxy ret
-    proxy=$("${LIST_PROXIES}" --quiet "${url}")
-    ret=$?
-    if [ ${ret} -ne 0 ]; then
-      proxy=''
-      lwarn "Listing proxies failed with exit code ${ret}"
-    else
-      proxy=$(echo "${proxy}" | head -1)
-    fi
-  fi
-  # if a direct connection should be used, unset the proxy variable.
-  [ "${proxy}" = "direct://" ] && proxy=
-  local report_id="${TMP_DIR}/report_id"
-  local curl_stderr="${TMP_DIR}/curl_stderr"
-
-  set +e
-  curl "${url}" -f -v ${proxy:+--proxy "$proxy"} \
-    --capath "$(get_certificates_path)" --ciphers HIGH \
-    -F "prod=${product}" \
-    -F "ver=${version}" \
-    -F "bdk_version=${bdk_version}" \
-    -F "hwclass=${hwclass}" \
-    -F "exec_name=${exec_name}" \
-    -F "model_manifest_id=${model_manifest_id}" \
-    ${image_type:+-F "image_type=${image_type}"} \
-    ${boot_mode:+-F "boot_mode=${boot_mode}"} \
-    ${error_type:+-F "error_type=${error_type}"} \
-    -F "guid=${guid}" \
-    -o "${report_id}" \
-    "$@" \
-    2>"${curl_stderr}"
-  curl_result=$?
-  set -e
-
-  if [ ${curl_result} -eq 0 ]; then
-    local id="$(cat "${report_id}")"
-    local timestamp="$(date +%s)"
-    local filter_prod="$(filter_log_string "${product}")"
-    local filter_exec="$(filter_log_string "${exec_name}")"
-    if [ "${filter_prod}" != "${product}" ]; then
-      lwarn "Product name filtered to: ${filter_prod}."
-    fi
-    if [ "${filter_exec}" != "${exec_name}" ]; then
-      lwarn "Exec name filtered to: ${filter_exec}."
-    fi
-    printf "{'time':%s,'id':'%s','product':'%s','exec_name':'%s'}\n" \
-      "${timestamp}" "${id}" "${filter_prod}" "${filter_exec}" >> "${CRASH_LOG}"
-    lecho "Crash report receipt ID ${id}"
-  else
-    lecho "Crash sending failed with exit code ${curl_result}: " \
-      "$(cat "${curl_stderr}")"
-  fi
-
-  rm -f "${report_id}"
-
-  return ${curl_result}
-}
-
-# *.meta files always end with done=1 so we can tell if they are complete.
-is_complete_metadata() {
-  grep -q "done=1" "$1"
-}
-
-# Remove the given report path.
-remove_report() {
-  local base="${1%.*}"
-  rm -f -- "${base}".*
-}
-
-# Send all crashes from the given directory.  This applies even when we're on a
-# 3G connection (see crosbug.com/3304 for discussion).
-send_crashes() {
-  local dir="$1"
-  lecho "Sending crashes for ${dir}"
-
-  if [ ! -d "${dir}" ]; then
-    return
-  fi
-
-  # Consider any old files which still have no corresponding meta file
-  # as orphaned, and remove them.
-  for old_file in $(find "${dir}" -mindepth 1 \
-                    -mtime +1 -type f); do
-    if [ ! -e "$(get_base "${old_file}").meta" ]; then
-      lecho "Removing old orphaned file: ${old_file}."
-      rm -f -- "${old_file}"
-    fi
-  done
-
-  # Look through all metadata (*.meta) files, oldest first.  That way, the rate
-  # limit does not stall old crashes if there's a high amount of new crashes
-  # coming in.
-  # For each crash report, first evaluate conditions that might lead to its
-  # removal to honor user choice and to free disk space as soon as possible,
-  # then decide whether it should be sent right now or kept for later sending.
-  for meta_path in $(ls -1tr "${dir}"/*.meta 2>/dev/null); do
-    lecho "Considering metadata ${meta_path}."
-
-    local kind=$(get_kind "${meta_path}")
-    if [ "${kind}" != "minidump" ] && \
-       [ "${kind}" != "kcrash" ] && \
-       [ "${kind}" != "log" ] &&
-       [ "${kind}" != "devcore" ]; then
-      lecho "Unknown report kind ${kind}.  Removing report."
-      remove_report "${meta_path}"
-      continue
-    fi
-
-    if ! is_complete_metadata "${meta_path}"; then
-      # This report is incomplete, so if it's old, just remove it.
-      local old_meta=$(find "${dir}" -mindepth 1 -name \
-        $(basename "${meta_path}") -mtime +1 -type f)
-      if [ -n "${old_meta}" ]; then
-        lecho "Removing old incomplete metadata."
-        remove_report "${meta_path}"
-      else
-        lecho "Ignoring recent incomplete metadata."
-      fi
-      continue
-    fi
-
-    # Ignore device coredump if device coredump uploading is not allowed.
-    if [ "${kind}" = "devcore" ] && ! is_device_coredump_upload_allowed; then
-      lecho "Ignoring device coredump. Device coredump upload not allowed."
-      continue
-    fi
-
-    if ! is_mock && ! is_official_image; then
-      lecho "Not an official OS version.  Removing crash."
-      remove_report "${meta_path}"
-      continue
-    fi
-
-    # Remove existing crashes in case user consent has not (yet) been given or
-    # has been revoked.  This must come after the guest mode check because
-    # metrics_client always returns "not consented" in guest mode.
-    if ! metrics_client -c; then
-      lecho "Crash reporting is disabled.  Removing crash."
-      remove_report "${meta_path}"
-      continue
-    fi
-
-    # Skip report if the upload rate is exceeded.  (Don't exit right now because
-    # subsequent reports may be candidates for deletion.)
-    if ! check_rate; then
-      lecho "Sending ${meta_path} would exceed rate.  Leaving for later."
-      continue
-    fi
-
-    # The .meta file should be written *after* all to-be-uploaded files that it
-    # references.  Nevertheless, as a safeguard, a hold-off time of thirty
-    # seconds after writing the .meta file is ensured.  Also, sending of crash
-    # reports is spread out randomly by up to SECONDS_SEND_SPREAD.  Thus, for
-    # the sleep call the greater of the two delays is used.
-    local now=$(date +%s)
-    local holdoff_time=$(($(stat -c "%Y" "${meta_path}") + 30 - ${now}))
-    local spread_time=$(generate_uniform_random "${SECONDS_SEND_SPREAD}")
-    local sleep_time
-    if [ ${spread_time} -gt ${holdoff_time} ]; then
-      sleep_time="${spread_time}"
-    else
-      sleep_time="${holdoff_time}"
-    fi
-    lecho "Scheduled to send in ${sleep_time}s."
-    if ! is_mock; then
-      if ! sleep "${sleep_time}"; then
-          lecho "Sleep failed"
-          return 1
-      fi
-    fi
-
-    # Try to upload.
-    if ! send_crash "${meta_path}"; then
-      lecho "Problem sending ${meta_path}, not removing."
-      continue
-    fi
-
-    # Send was successful, now remove.
-    lecho "Successfully sent crash ${meta_path} and removing."
-    remove_report "${meta_path}"
-  done
-}
-
-usage() {
-  cat <<EOF
-Usage: crash_sender [options]
-
-Options:
- -e <var>=<val>     Set env |var| to |val| (only some vars)
-EOF
-  exit ${1:-1}
-}
-
-parseargs() {
-  # Parse the command line arguments.
-  while [ $# -gt 0 ]; do
-    case $1 in
-    -e)
-      shift
-      case $1 in
-      FORCE_OFFICIAL=*|\
-      MAX_CRASH_RATE=*|\
-      MOCK_DEVELOPER_MODE=*|\
-      OVERRIDE_PAUSE_SENDING=*|\
-      SECONDS_SEND_SPREAD=*)
-        export "$1"
-        ;;
-      *)
-        lecho "Unknown var passed to -e: $1"
-        exit 1
-        ;;
-      esac
-      ;;
-    -h)
-      usage 0
-      ;;
-    *)
-      lecho "Unknown options: $*"
-      exit 1
-      ;;
-    esac
-    shift
-  done
-}
-
-main() {
-  parseargs "$@"
-
-  if [ -e "${PAUSE_CRASH_SENDING}" ] && \
-     [ ${OVERRIDE_PAUSE_SENDING} -eq 0 ]; then
-    lecho "Exiting early due to ${PAUSE_CRASH_SENDING}."
-    exit 1
-  fi
-
-  if is_test_image; then
-    lecho "Exiting early due to test image."
-    exit 1
-  fi
-
-  # We don't perform checks on this because we have a master lock with the
-  # CRASH_SENDER_LOCK file.  This pid file is for the system to keep track
-  # (like with autotests) that we're still running.
-  echo $$ > "${RUN_FILE}"
-
-  for dependency in "$(get_certificates_path)"; do
-    if [ ! -x "${dependency}" ]; then
-      lecho "Fatal: Crash sending disabled: ${dependency} not found."
-      exit 1
-    fi
-  done
-
-  TMP_DIR="$(mktemp -d "${CRASH_STATE_DIR}/tmp/crash_sender.XXXXXX")"
-
-  # Send system-wide crashes
-  send_crashes "${CRASH_STATE_DIR}/crash"
-}
-
-trap cleanup EXIT INT TERM
-
-#TODO(http://b/23937249): Change the locking logic back to using flock.
-if ! mkdir "${CRASH_SENDER_LOCK}" 2>/dev/null; then
-  lecho "Already running; quitting."
-  crash_done
-  exit 1
-fi
-main "$@"
diff --git a/crash_reporter/dbus_bindings/org.chromium.LibCrosService.xml b/crash_reporter/dbus_bindings/org.chromium.LibCrosService.xml
deleted file mode 100644
index 64b8b84..0000000
--- a/crash_reporter/dbus_bindings/org.chromium.LibCrosService.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<node name="/org/chromium/LibCrosService"
-      xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-  <interface name="org.chromium.LibCrosServiceInterface">
-    <method name="ResolveNetworkProxy">
-      <arg name="source_url" type="s" direction="in"/>
-      <arg name="signal_interface" type="s" direction="in"/>
-      <arg name="signal_name" type="s" direction="in"/>
-      <annotation name="org.chromium.DBus.Method.Kind" value="simple"/>
-    </method>
-  </interface>
-  <interface name="org.chromium.CrashReporterLibcrosProxyResolvedInterface">
-    <signal name="ProxyResolved">
-      <arg name="source_url" type="s" direction="out"/>
-      <arg name="proxy_info" type="s" direction="out"/>
-      <arg name="error_message" type="s" direction="out"/>
-    </signal>
-  </interface>
-</node>
diff --git a/crash_reporter/init/crash-reporter.conf b/crash_reporter/init/crash-reporter.conf
deleted file mode 100644
index 19f2cdb..0000000
--- a/crash_reporter/init/crash-reporter.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description     "Initialize crash reporting services"
-author          "chromium-os-dev@chromium.org"
-
-# This job merely initializes its service and then terminates; the
-# actual checking and reporting of crash dumps is triggered by an
-# hourly cron job.
-start on starting system-services
-
-pre-start script
-  mkdir -p /var/spool
-
-  # Only allow device coredumps on a "developer system".
-  if ! is_developer_end_user; then
-    # consumer end-user - disable device coredumps, if driver exists.
-    echo 1 > /sys/class/devcoredump/disabled || true
-  fi
-end script
-
-# crash_reporter uses argv[0] as part of the command line for
-# /proc/sys/kernel/core_pattern.  That command line is invoked by
-# the kernel, and can't rely on PATH, so argv[0] must be a full
-# path; we invoke it as such here.
-exec /sbin/crash_reporter --init
diff --git a/crash_reporter/init/crash-sender.conf b/crash_reporter/init/crash-sender.conf
deleted file mode 100644
index 892186f..0000000
--- a/crash_reporter/init/crash-sender.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description     "Run the crash sender periodically"
-author          "chromium-os-dev@chromium.org"
-
-start on starting system-services
-stop on stopping system-services
-
-exec periodic_scheduler 3600 14400 crash_sender /sbin/crash_sender
diff --git a/crash_reporter/init/warn-collector.conf b/crash_reporter/init/warn-collector.conf
deleted file mode 100644
index 3be80da..0000000
--- a/crash_reporter/init/warn-collector.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-description "Runs a daemon which collects and reports kernel warnings"
-author      "chromium-os-dev@chromium.org"
-
-start on started system-services
-stop on stopping system-services
-respawn
-
-exec warn_collector
diff --git a/crash_reporter/kernel_collector.cc b/crash_reporter/kernel_collector.cc
deleted file mode 100644
index 68f2d9e..0000000
--- a/crash_reporter/kernel_collector.cc
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Copyright (C) 2012 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 "kernel_collector.h"
-
-#include <map>
-#include <sys/stat.h>
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-
-using base::FilePath;
-using base::StringPrintf;
-
-namespace {
-
-const char kDefaultKernelStackSignature[] = "kernel-UnspecifiedStackSignature";
-const char kDumpParentPath[] = "/sys/fs";
-const char kDumpPath[] = "/sys/fs/pstore";
-const char kDumpFormat[] = "dmesg-ramoops-%zu";
-const char kKernelExecName[] = "kernel";
-// Maximum number of records to examine in the kDumpPath.
-const size_t kMaxDumpRecords = 100;
-const pid_t kKernelPid = 0;
-const char kKernelSignatureKey[] = "sig";
-// Byte length of maximum human readable portion of a kernel crash signature.
-const int kMaxHumanStringLength = 40;
-const uid_t kRootUid = 0;
-// Time in seconds from the final kernel log message for a call stack
-// to count towards the signature of the kcrash.
-const int kSignatureTimestampWindow = 2;
-// Kernel log timestamp regular expression.
-const char kTimestampRegex[] = "^<.*>\\[\\s*(\\d+\\.\\d+)\\]";
-
-//
-// These regular expressions enable to us capture the PC in a backtrace.
-// The backtrace is obtained through dmesg or the kernel's preserved/kcrashmem
-// feature.
-//
-// For ARM we see:
-//   "<5>[   39.458982] PC is at write_breakme+0xd0/0x1b4"
-// For MIPS we see:
-//   "<5>[ 3378.552000] epc   : 804010f0 lkdtm_do_action+0x68/0x3f8"
-// For x86:
-//   "<0>[   37.474699] EIP: [<790ed488>] write_breakme+0x80/0x108
-//    SS:ESP 0068:e9dd3efc"
-//
-const char* const kPCRegex[] = {
-  0,
-  " PC is at ([^\\+ ]+).*",
-  " epc\\s+:\\s+\\S+\\s+([^\\+ ]+).*",  // MIPS has an exception program counter
-  " EIP: \\[<.*>\\] ([^\\+ ]+).*",  // X86 uses EIP for the program counter
-  " RIP  \\[<.*>\\] ([^\\+ ]+).*",  // X86_64 uses RIP for the program counter
-};
-
-static_assert(arraysize(kPCRegex) == KernelCollector::kArchCount,
-              "Missing Arch PC regexp");
-
-}  // namespace
-
-KernelCollector::KernelCollector()
-    : is_enabled_(false),
-      ramoops_dump_path_(kDumpPath),
-      records_(0),
-      // We expect crash dumps in the format of architecture we are built for.
-      arch_(GetCompilerArch()) {
-}
-
-KernelCollector::~KernelCollector() {
-}
-
-void KernelCollector::OverridePreservedDumpPath(const FilePath &file_path) {
-  ramoops_dump_path_ = file_path;
-}
-
-bool KernelCollector::ReadRecordToString(std::string *contents,
-                                         size_t current_record,
-                                         bool *record_found) {
-  // A record is a ramoops dump. It has an associated size of "record_size".
-  std::string record;
-  std::string captured;
-
-  // Ramoops appends a header to a crash which contains ==== followed by a
-  // timestamp. Ignore the header.
-  pcrecpp::RE record_re(
-      "====\\d+\\.\\d+\n(.*)",
-      pcrecpp::RE_Options().set_multiline(true).set_dotall(true));
-
-  pcrecpp::RE sanity_check_re("\n<\\d+>\\[\\s*(\\d+\\.\\d+)\\]");
-
-  FilePath ramoops_record;
-  GetRamoopsRecordPath(&ramoops_record, current_record);
-  if (!base::ReadFileToString(ramoops_record, &record)) {
-    LOG(ERROR) << "Unable to open " << ramoops_record.value();
-    return false;
-  }
-
-  *record_found = false;
-  if (record_re.FullMatch(record, &captured)) {
-    // Found a ramoops header, so strip the header and append the rest.
-    contents->append(captured);
-    *record_found = true;
-  } else if (sanity_check_re.PartialMatch(record.substr(0, 1024))) {
-    // pstore compression has been added since kernel 3.12. In order to
-    // decompress dmesg correctly, ramoops driver has to strip the header
-    // before handing over the record to the pstore driver, so we don't
-    // need to do it here anymore. However, the sanity check is needed because
-    // sometimes a pstore record is just a chunk of uninitialized memory which
-    // is not the result of a kernel crash. See crbug.com/443764
-    contents->append(record);
-    *record_found = true;
-  } else {
-    LOG(WARNING) << "Found invalid record at " << ramoops_record.value();
-  }
-
-  // Remove the record from pstore after it's found.
-  if (*record_found)
-    base::DeleteFile(ramoops_record, false);
-
-  return true;
-}
-
-void KernelCollector::GetRamoopsRecordPath(FilePath *path,
-                                           size_t record) {
-  // Disable error "format not a string literal, argument types not checked"
-  // because this is valid, but GNU apparently doesn't bother checking a const
-  // format string.
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wformat-nonliteral"
-  *path = ramoops_dump_path_.Append(StringPrintf(kDumpFormat, record));
-  #pragma GCC diagnostic pop
-}
-
-bool KernelCollector::LoadParameters() {
-  // Discover how many ramoops records are being exported by the driver.
-  size_t count;
-
-  for (count = 0; count < kMaxDumpRecords; ++count) {
-    FilePath ramoops_record;
-    GetRamoopsRecordPath(&ramoops_record, count);
-
-    if (!base::PathExists(ramoops_record))
-      break;
-  }
-
-  records_ = count;
-  return (records_ > 0);
-}
-
-bool KernelCollector::LoadPreservedDump(std::string *contents) {
-  // Load dumps from the preserved memory and save them in contents.
-  // Since the system is set to restart on oops we won't actually ever have
-  // multiple records (only 0 or 1), but check in case we don't restart on
-  // oops in the future.
-  bool any_records_found = false;
-  bool record_found = false;
-  // clear contents since ReadFileToString actually appends to the string.
-  contents->clear();
-
-  for (size_t i = 0; i < records_; ++i) {
-    if (!ReadRecordToString(contents, i, &record_found)) {
-      break;
-    }
-    if (record_found) {
-      any_records_found = true;
-    }
-  }
-
-  if (!any_records_found) {
-    LOG(ERROR) << "No valid records found in " << ramoops_dump_path_.value();
-    return false;
-  }
-
-  return true;
-}
-
-void KernelCollector::StripSensitiveData(std::string *kernel_dump) {
-  // Strip any data that the user might not want sent up to the crash servers.
-  // We'll read in from kernel_dump and also place our output there.
-  //
-  // At the moment, the only sensitive data we strip is MAC addresses.
-
-  // Get rid of things that look like MAC addresses, since they could possibly
-  // give information about where someone has been.  This is strings that look
-  // like this: 11:22:33:44:55:66
-  // Complications:
-  // - Within a given kernel_dump, want to be able to tell when the same MAC
-  //   was used more than once.  Thus, we'll consistently replace the first
-  //   MAC found with 00:00:00:00:00:01, the second with ...:02, etc.
-  // - ACPI commands look like MAC addresses.  We'll specifically avoid getting
-  //   rid of those.
-  std::ostringstream result;
-  std::string pre_mac_str;
-  std::string mac_str;
-  std::map<std::string, std::string> mac_map;
-  pcrecpp::StringPiece input(*kernel_dump);
-
-  // This RE will find the next MAC address and can return us the data preceding
-  // the MAC and the MAC itself.
-  pcrecpp::RE mac_re("(.*?)("
-                     "[0-9a-fA-F][0-9a-fA-F]:"
-                     "[0-9a-fA-F][0-9a-fA-F]:"
-                     "[0-9a-fA-F][0-9a-fA-F]:"
-                     "[0-9a-fA-F][0-9a-fA-F]:"
-                     "[0-9a-fA-F][0-9a-fA-F]:"
-                     "[0-9a-fA-F][0-9a-fA-F])",
-                     pcrecpp::RE_Options()
-                       .set_multiline(true)
-                       .set_dotall(true));
-
-  // This RE will identify when the 'pre_mac_str' shows that the MAC address
-  // was really an ACPI cmd.  The full string looks like this:
-  //   ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES) filtered out
-  pcrecpp::RE acpi_re("ACPI cmd ef/$",
-                      pcrecpp::RE_Options()
-                        .set_multiline(true)
-                        .set_dotall(true));
-
-  // Keep consuming, building up a result string as we go.
-  while (mac_re.Consume(&input, &pre_mac_str, &mac_str)) {
-    if (acpi_re.PartialMatch(pre_mac_str)) {
-      // We really saw an ACPI command; add to result w/ no stripping.
-      result << pre_mac_str << mac_str;
-    } else {
-      // Found a MAC address; look up in our hash for the mapping.
-      std::string replacement_mac = mac_map[mac_str];
-      if (replacement_mac == "") {
-        // It wasn't present, so build up a replacement string.
-        int mac_id = mac_map.size();
-
-        // Handle up to 2^32 unique MAC address; overkill, but doesn't hurt.
-        replacement_mac = StringPrintf("00:00:%02x:%02x:%02x:%02x",
-                                       (mac_id & 0xff000000) >> 24,
-                                       (mac_id & 0x00ff0000) >> 16,
-                                       (mac_id & 0x0000ff00) >> 8,
-                                       (mac_id & 0x000000ff));
-        mac_map[mac_str] = replacement_mac;
-      }
-
-      // Dump the string before the MAC and the fake MAC address into result.
-      result << pre_mac_str << replacement_mac;
-    }
-  }
-
-  // One last bit of data might still be in the input.
-  result << input;
-
-  // We'll just assign right back to kernel_dump.
-  *kernel_dump = result.str();
-}
-
-bool KernelCollector::DumpDirMounted() {
-  struct stat st_parent;
-  if (stat(kDumpParentPath, &st_parent)) {
-    PLOG(WARNING) << "Could not stat " << kDumpParentPath;
-    return false;
-  }
-
-  struct stat st_dump;
-  if (stat(kDumpPath, &st_dump)) {
-    PLOG(WARNING) << "Could not stat " << kDumpPath;
-    return false;
-  }
-
-  if (st_parent.st_dev == st_dump.st_dev) {
-    LOG(WARNING) << "Dump dir " << kDumpPath << " not mounted";
-    return false;
-  }
-
-  return true;
-}
-
-bool KernelCollector::Enable() {
-  if (arch_ == kArchUnknown || arch_ >= kArchCount ||
-      kPCRegex[arch_] == nullptr) {
-    LOG(WARNING) << "KernelCollector does not understand this architecture";
-    return false;
-  }
-
-  if (!DumpDirMounted()) {
-    LOG(WARNING) << "Kernel does not support crash dumping";
-    return false;
-  }
-
-  // To enable crashes, we will eventually need to set
-  // the chnv bit in BIOS, but it does not yet work.
-  LOG(INFO) << "Enabling kernel crash handling";
-  is_enabled_ = true;
-  return true;
-}
-
-// Hash a string to a number.  We define our own hash function to not
-// be dependent on a C++ library that might change.  This function
-// uses basically the same approach as tr1/functional_hash.h but with
-// a larger prime number (16127 vs 131).
-static unsigned HashString(const std::string &input) {
-  unsigned hash = 0;
-  for (size_t i = 0; i < input.length(); ++i)
-    hash = hash * 16127 + input[i];
-  return hash;
-}
-
-void KernelCollector::ProcessStackTrace(
-    pcrecpp::StringPiece kernel_dump,
-    bool print_diagnostics,
-    unsigned *hash,
-    float *last_stack_timestamp,
-    bool *is_watchdog_crash) {
-  pcrecpp::RE line_re("(.+)", pcrecpp::MULTILINE());
-  pcrecpp::RE stack_trace_start_re(std::string(kTimestampRegex) +
-        " (Call Trace|Backtrace):$");
-
-  // Match lines such as the following and grab out "function_name".
-  // The ? may or may not be present.
-  //
-  // For ARM:
-  // <4>[ 3498.731164] [<c0057220>] ? (function_name+0x20/0x2c) from
-  // [<c018062c>] (foo_bar+0xdc/0x1bc)
-  //
-  // For MIPS:
-  // <5>[ 3378.656000] [<804010f0>] lkdtm_do_action+0x68/0x3f8
-  //
-  // For X86:
-  // <4>[ 6066.849504]  [<7937bcee>] ? function_name+0x66/0x6c
-  //
-  pcrecpp::RE stack_entry_re(std::string(kTimestampRegex) +
-    "\\s+\\[<[[:xdigit:]]+>\\]"      // Matches "  [<7937bcee>]"
-    "([\\s\\?(]+)"                   // Matches " ? (" (ARM) or " ? " (X86)
-    "([^\\+ )]+)");                  // Matches until delimiter reached
-  std::string line;
-  std::string hashable;
-  std::string previous_hashable;
-  bool is_watchdog = false;
-
-  *hash = 0;
-  *last_stack_timestamp = 0;
-
-  // Find the last and second-to-last stack traces.  The latter is used when
-  // the panic is from a watchdog timeout.
-  while (line_re.FindAndConsume(&kernel_dump, &line)) {
-    std::string certainty;
-    std::string function_name;
-    if (stack_trace_start_re.PartialMatch(line, last_stack_timestamp)) {
-      if (print_diagnostics) {
-        printf("Stack trace starting.%s\n",
-               hashable.empty() ? "" : "  Saving prior trace.");
-      }
-      previous_hashable = hashable;
-      hashable.clear();
-      is_watchdog = false;
-    } else if (stack_entry_re.PartialMatch(line,
-                                           last_stack_timestamp,
-                                           &certainty,
-                                           &function_name)) {
-      bool is_certain = certainty.find('?') == std::string::npos;
-      if (print_diagnostics) {
-        printf("@%f: stack entry for %s (%s)\n",
-               *last_stack_timestamp,
-               function_name.c_str(),
-               is_certain ? "certain" : "uncertain");
-      }
-      // Do not include any uncertain (prefixed by '?') frames in our hash.
-      if (!is_certain)
-        continue;
-      if (!hashable.empty())
-        hashable.append("|");
-      if (function_name == "watchdog_timer_fn" ||
-          function_name == "watchdog") {
-        is_watchdog = true;
-      }
-      hashable.append(function_name);
-    }
-  }
-
-  // If the last stack trace contains a watchdog function we assume the panic
-  // is from the watchdog timer, and we hash the previous stack trace rather
-  // than the last one, assuming that the previous stack is that of the hung
-  // thread.
-  //
-  // In addition, if the hashable is empty (meaning all frames are uncertain,
-  // for whatever reason) also use the previous frame, as it cannot be any
-  // worse.
-  if (is_watchdog || hashable.empty()) {
-    hashable = previous_hashable;
-  }
-
-  *hash = HashString(hashable);
-  *is_watchdog_crash = is_watchdog;
-
-  if (print_diagnostics) {
-    printf("Hash based on stack trace: \"%s\" at %f.\n",
-           hashable.c_str(), *last_stack_timestamp);
-  }
-}
-
-// static
-KernelCollector::ArchKind KernelCollector::GetCompilerArch() {
-#if defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)
-  return kArchArm;
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS_FAMILY)
-  return kArchMips;
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_64)
-  return kArchX86_64;
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
-  return kArchX86;
-#else
-  return kArchUnknown;
-#endif
-}
-
-bool KernelCollector::FindCrashingFunction(
-  pcrecpp::StringPiece kernel_dump,
-  bool print_diagnostics,
-  float stack_trace_timestamp,
-  std::string *crashing_function) {
-  float timestamp = 0;
-
-  // Use the correct regex for this architecture.
-  pcrecpp::RE eip_re(std::string(kTimestampRegex) + kPCRegex[arch_],
-                     pcrecpp::MULTILINE());
-
-  while (eip_re.FindAndConsume(&kernel_dump, &timestamp, crashing_function)) {
-    if (print_diagnostics) {
-      printf("@%f: found crashing function %s\n",
-             timestamp,
-             crashing_function->c_str());
-    }
-  }
-  if (timestamp == 0) {
-    if (print_diagnostics) {
-      printf("Found no crashing function.\n");
-    }
-    return false;
-  }
-  if (stack_trace_timestamp != 0 &&
-      abs(static_cast<int>(stack_trace_timestamp - timestamp))
-        > kSignatureTimestampWindow) {
-    if (print_diagnostics) {
-      printf("Found crashing function but not within window.\n");
-    }
-    return false;
-  }
-  if (print_diagnostics) {
-    printf("Found crashing function %s\n", crashing_function->c_str());
-  }
-  return true;
-}
-
-bool KernelCollector::FindPanicMessage(pcrecpp::StringPiece kernel_dump,
-                                       bool print_diagnostics,
-                                       std::string *panic_message) {
-  // Match lines such as the following and grab out "Fatal exception"
-  // <0>[  342.841135] Kernel panic - not syncing: Fatal exception
-  pcrecpp::RE kernel_panic_re(std::string(kTimestampRegex) +
-                              " Kernel panic[^\\:]*\\:\\s*(.*)",
-                              pcrecpp::MULTILINE());
-  float timestamp = 0;
-  while (kernel_panic_re.FindAndConsume(&kernel_dump,
-                                        &timestamp,
-                                        panic_message)) {
-    if (print_diagnostics) {
-      printf("@%f: panic message %s\n",
-             timestamp,
-             panic_message->c_str());
-    }
-  }
-  if (timestamp == 0) {
-    if (print_diagnostics) {
-      printf("Found no panic message.\n");
-    }
-    return false;
-  }
-  return true;
-}
-
-bool KernelCollector::ComputeKernelStackSignature(
-    const std::string &kernel_dump,
-    std::string *kernel_signature,
-    bool print_diagnostics) {
-  unsigned stack_hash = 0;
-  float last_stack_timestamp = 0;
-  std::string human_string;
-  bool is_watchdog_crash;
-
-  ProcessStackTrace(kernel_dump,
-                    print_diagnostics,
-                    &stack_hash,
-                    &last_stack_timestamp,
-                    &is_watchdog_crash);
-
-  if (!FindCrashingFunction(kernel_dump,
-                            print_diagnostics,
-                            last_stack_timestamp,
-                            &human_string)) {
-    if (!FindPanicMessage(kernel_dump, print_diagnostics, &human_string)) {
-      if (print_diagnostics) {
-        printf("Found no human readable string, using empty string.\n");
-      }
-      human_string.clear();
-    }
-  }
-
-  if (human_string.empty() && stack_hash == 0) {
-    if (print_diagnostics) {
-      printf("Found neither a stack nor a human readable string, failing.\n");
-    }
-    return false;
-  }
-
-  human_string = human_string.substr(0, kMaxHumanStringLength);
-  *kernel_signature = StringPrintf("%s-%s%s-%08X",
-                                   kKernelExecName,
-                                   (is_watchdog_crash ? "(HANG)-" : ""),
-                                   human_string.c_str(),
-                                   stack_hash);
-  return true;
-}
-
-bool KernelCollector::Collect() {
-  std::string kernel_dump;
-  FilePath root_crash_directory;
-
-  if (!LoadParameters()) {
-    return false;
-  }
-  if (!LoadPreservedDump(&kernel_dump)) {
-    return false;
-  }
-  StripSensitiveData(&kernel_dump);
-  if (kernel_dump.empty()) {
-    return false;
-  }
-  std::string signature;
-  if (!ComputeKernelStackSignature(kernel_dump, &signature, false)) {
-    signature = kDefaultKernelStackSignature;
-  }
-
-  std::string reason = "handling";
-  bool feedback = true;
-  if (IsDeveloperImage()) {
-    reason = "developer build - always dumping";
-    feedback = true;
-  } else if (!is_feedback_allowed_function_()) {
-    reason = "ignoring - no consent";
-    feedback = false;
-  }
-
-  LOG(INFO) << "Received prior crash notification from "
-            << "kernel (signature " << signature << ") (" << reason << ")";
-
-  if (feedback) {
-    count_crash_function_();
-
-    if (!GetCreatedCrashDirectoryByEuid(kRootUid,
-                                        &root_crash_directory,
-                                        nullptr)) {
-      return true;
-    }
-
-    std::string dump_basename =
-        FormatDumpBasename(kKernelExecName, time(nullptr), kKernelPid);
-    FilePath kernel_crash_path = root_crash_directory.Append(
-        StringPrintf("%s.kcrash", dump_basename.c_str()));
-
-    // We must use WriteNewFile instead of base::WriteFile as we
-    // do not want to write with root access to a symlink that an attacker
-    // might have created.
-    if (WriteNewFile(kernel_crash_path,
-                     kernel_dump.data(),
-                     kernel_dump.length()) !=
-        static_cast<int>(kernel_dump.length())) {
-      LOG(INFO) << "Failed to write kernel dump to "
-                << kernel_crash_path.value().c_str();
-      return true;
-    }
-
-    AddCrashMetaData(kKernelSignatureKey, signature);
-    WriteCrashMetaData(
-        root_crash_directory.Append(
-            StringPrintf("%s.meta", dump_basename.c_str())),
-        kKernelExecName,
-        kernel_crash_path.value());
-
-    LOG(INFO) << "Stored kcrash to " << kernel_crash_path.value();
-  }
-
-  return true;
-}
diff --git a/crash_reporter/kernel_collector.h b/crash_reporter/kernel_collector.h
deleted file mode 100644
index 206ee26..0000000
--- a/crash_reporter/kernel_collector.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2010 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 CRASH_REPORTER_KERNEL_COLLECTOR_H_
-#define CRASH_REPORTER_KERNEL_COLLECTOR_H_
-
-#include <pcrecpp.h>
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Kernel crash collector.
-class KernelCollector : public CrashCollector {
- public:
-  // Enumeration to specify architecture type.
-  enum ArchKind {
-    kArchUnknown,
-    kArchArm,
-    kArchMips,
-    kArchX86,
-    kArchX86_64,
-
-    kArchCount  // Number of architectures.
-  };
-
-  KernelCollector();
-
-  ~KernelCollector() override;
-
-  void OverridePreservedDumpPath(const base::FilePath &file_path);
-
-  // Enable collection.
-  bool Enable();
-
-  // Returns true if the kernel collection currently enabled.
-  bool is_enabled() const { return is_enabled_; }
-
-  // Collect any preserved kernel crash dump. Returns true if there was
-  // a dump (even if there were problems storing the dump), false otherwise.
-  bool Collect();
-
-  // Compute a stack signature string from a kernel dump.
-  bool ComputeKernelStackSignature(const std::string &kernel_dump,
-                                   std::string *kernel_signature,
-                                   bool print_diagnostics);
-
-  // Set the architecture of the crash dumps we are looking at.
-  void set_arch(ArchKind arch) { arch_ = arch; }
-  ArchKind arch() const { return arch_; }
-
- private:
-  friend class KernelCollectorTest;
-  FRIEND_TEST(KernelCollectorTest, LoadPreservedDump);
-  FRIEND_TEST(KernelCollectorTest, StripSensitiveDataBasic);
-  FRIEND_TEST(KernelCollectorTest, StripSensitiveDataBulk);
-  FRIEND_TEST(KernelCollectorTest, StripSensitiveDataSample);
-  FRIEND_TEST(KernelCollectorTest, CollectOK);
-
-  virtual bool DumpDirMounted();
-
-  bool LoadPreservedDump(std::string *contents);
-  void StripSensitiveData(std::string *kernel_dump);
-
-  void GetRamoopsRecordPath(base::FilePath *path, size_t record);
-  bool LoadParameters();
-  bool HasMoreRecords();
-
-  // Read a record to string, modified from file_utils since that didn't
-  // provide a way to restrict the read length.
-  // Return value indicates (only) error state:
-  //  * false when we get an error (can't read from dump location).
-  //  * true if no error occured.
-  // Not finding a valid record is not an error state and is signaled by the
-  // record_found output parameter.
-  bool ReadRecordToString(std::string *contents,
-                          size_t current_record,
-                          bool *record_found);
-
-  void ProcessStackTrace(pcrecpp::StringPiece kernel_dump,
-                         bool print_diagnostics,
-                         unsigned *hash,
-                         float *last_stack_timestamp,
-                         bool *is_watchdog_crash);
-  bool FindCrashingFunction(pcrecpp::StringPiece kernel_dump,
-                            bool print_diagnostics,
-                            float stack_trace_timestamp,
-                            std::string *crashing_function);
-  bool FindPanicMessage(pcrecpp::StringPiece kernel_dump,
-                        bool print_diagnostics,
-                        std::string *panic_message);
-
-  // Returns the architecture kind for which we are built.
-  static ArchKind GetCompilerArch();
-
-  bool is_enabled_;
-  base::FilePath ramoops_dump_path_;
-  size_t records_;
-
-  // The architecture of kernel dump strings we are working with.
-  ArchKind arch_;
-
-  DISALLOW_COPY_AND_ASSIGN(KernelCollector);
-};
-
-#endif  // CRASH_REPORTER_KERNEL_COLLECTOR_H_
diff --git a/crash_reporter/kernel_collector_test.cc b/crash_reporter/kernel_collector_test.cc
deleted file mode 100644
index 0f6b930..0000000
--- a/crash_reporter/kernel_collector_test.cc
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Copyright (C) 2012 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 "kernel_collector_test.h"
-
-#include <unistd.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/syslog_logging.h>
-#include <gtest/gtest.h>
-
-using base::FilePath;
-using base::StringPrintf;
-using brillo::FindLog;
-using brillo::GetLog;
-
-namespace {
-
-int s_crashes = 0;
-bool s_metrics = false;
-
-void CountCrash() {
-  ++s_crashes;
-}
-
-bool IsMetrics() {
-  return s_metrics;
-}
-
-}  // namespace
-
-class KernelCollectorTest : public ::testing::Test {
- protected:
-  void WriteStringToFile(const FilePath &file_path,
-                         const char *data) {
-    unsigned int numBytesWritten =
-        base::WriteFile(file_path, data, strlen(data));
-    ASSERT_EQ(strlen(data), numBytesWritten);
-  }
-
-  void SetUpSuccessfulCollect();
-  void ComputeKernelStackSignatureCommon();
-
-  const FilePath &kcrash_file() const { return test_kcrash_; }
-  const FilePath &test_crash_directory() const { return test_crash_directory_; }
-
-  KernelCollectorMock collector_;
-
- private:
-  void SetUp() override {
-    s_crashes = 0;
-    s_metrics = true;
-
-    EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
-    collector_.Initialize(CountCrash, IsMetrics);
-    ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
-    test_kcrash_ = scoped_temp_dir_.path().Append("kcrash");
-    ASSERT_TRUE(base::CreateDirectory(test_kcrash_));
-    collector_.OverridePreservedDumpPath(test_kcrash_);
-
-    test_kcrash_ = test_kcrash_.Append("dmesg-ramoops-0");
-    ASSERT_FALSE(base::PathExists(test_kcrash_));
-
-    test_crash_directory_ = scoped_temp_dir_.path().Append("crash_directory");
-    ASSERT_TRUE(base::CreateDirectory(test_crash_directory_));
-    brillo::ClearLog();
-  }
-
-  FilePath test_kcrash_;
-  FilePath test_crash_directory_;
-  base::ScopedTempDir scoped_temp_dir_;
-};
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureBase) {
-  // Make sure the normal build architecture is detected
-  EXPECT_NE(KernelCollector::kArchUnknown, collector_.arch());
-}
-
-TEST_F(KernelCollectorTest, LoadPreservedDump) {
-  ASSERT_FALSE(base::PathExists(kcrash_file()));
-  std::string dump;
-  dump.clear();
-
-  WriteStringToFile(kcrash_file(),
-      "CrashRecordWithoutRamoopsHeader\n<6>[    0.078852]");
-  ASSERT_TRUE(collector_.LoadParameters());
-  ASSERT_TRUE(collector_.LoadPreservedDump(&dump));
-  ASSERT_EQ("CrashRecordWithoutRamoopsHeader\n<6>[    0.078852]", dump);
-
-  WriteStringToFile(kcrash_file(), "====1.1\nsomething");
-  ASSERT_TRUE(collector_.LoadParameters());
-  ASSERT_TRUE(collector_.LoadPreservedDump(&dump));
-  ASSERT_EQ("something", dump);
-
-  WriteStringToFile(kcrash_file(), "\x01\x02\xfe\xff random blob");
-  ASSERT_TRUE(collector_.LoadParameters());
-  ASSERT_FALSE(collector_.LoadPreservedDump(&dump));
-  ASSERT_EQ("", dump);
-}
-
-TEST_F(KernelCollectorTest, EnableMissingKernel) {
-  ASSERT_FALSE(collector_.Enable());
-  ASSERT_FALSE(collector_.is_enabled());
-  ASSERT_TRUE(FindLog(
-      "Kernel does not support crash dumping"));
-  ASSERT_EQ(s_crashes, 0);
-}
-
-TEST_F(KernelCollectorTest, EnableOK) {
-  WriteStringToFile(kcrash_file(), "");
-  EXPECT_CALL(collector_, DumpDirMounted()).WillOnce(::testing::Return(true));
-  ASSERT_TRUE(collector_.Enable());
-  ASSERT_TRUE(collector_.is_enabled());
-  ASSERT_TRUE(FindLog("Enabling kernel crash handling"));
-  ASSERT_EQ(s_crashes, 0);
-}
-
-TEST_F(KernelCollectorTest, StripSensitiveDataBasic) {
-  // Basic tests of StripSensitiveData...
-
-  // Make sure we work OK with a string w/ no MAC addresses.
-  const std::string kCrashWithNoMacsOrig =
-      "<7>[111566.131728] PM: Entering mem sleep\n";
-  std::string crash_with_no_macs(kCrashWithNoMacsOrig);
-  collector_.StripSensitiveData(&crash_with_no_macs);
-  EXPECT_EQ(kCrashWithNoMacsOrig, crash_with_no_macs);
-
-  // Make sure that we handle the case where there's nothing before/after the
-  // MAC address.
-  const std::string kJustAMacOrig =
-      "11:22:33:44:55:66";
-  const std::string kJustAMacStripped =
-      "00:00:00:00:00:01";
-  std::string just_a_mac(kJustAMacOrig);
-  collector_.StripSensitiveData(&just_a_mac);
-  EXPECT_EQ(kJustAMacStripped, just_a_mac);
-
-  // Test MAC addresses crammed together to make sure it gets both of them.
-  //
-  // I'm not sure that the code does ideal on these two test cases (they don't
-  // look like two MAC addresses to me), but since we don't see them I think
-  // it's OK to behave as shown here.
-  const std::string kCrammedMacs1Orig =
-      "11:22:33:44:55:66:11:22:33:44:55:66";
-  const std::string kCrammedMacs1Stripped =
-      "00:00:00:00:00:01:00:00:00:00:00:01";
-  std::string crammed_macs_1(kCrammedMacs1Orig);
-  collector_.StripSensitiveData(&crammed_macs_1);
-  EXPECT_EQ(kCrammedMacs1Stripped, crammed_macs_1);
-
-  const std::string kCrammedMacs2Orig =
-      "11:22:33:44:55:6611:22:33:44:55:66";
-  const std::string kCrammedMacs2Stripped =
-      "00:00:00:00:00:0100:00:00:00:00:01";
-  std::string crammed_macs_2(kCrammedMacs2Orig);
-  collector_.StripSensitiveData(&crammed_macs_2);
-  EXPECT_EQ(kCrammedMacs2Stripped, crammed_macs_2);
-
-  // Test case-sensitiveness (we shouldn't be case-senstive).
-  const std::string kCapsMacOrig =
-      "AA:BB:CC:DD:EE:FF";
-  const std::string kCapsMacStripped =
-      "00:00:00:00:00:01";
-  std::string caps_mac(kCapsMacOrig);
-  collector_.StripSensitiveData(&caps_mac);
-  EXPECT_EQ(kCapsMacStripped, caps_mac);
-
-  const std::string kLowerMacOrig =
-      "aa:bb:cc:dd:ee:ff";
-  const std::string kLowerMacStripped =
-      "00:00:00:00:00:01";
-  std::string lower_mac(kLowerMacOrig);
-  collector_.StripSensitiveData(&lower_mac);
-  EXPECT_EQ(kLowerMacStripped, lower_mac);
-}
-
-TEST_F(KernelCollectorTest, StripSensitiveDataBulk) {
-  // Test calling StripSensitiveData w/ lots of MAC addresses in the "log".
-
-  // Test that stripping code handles more than 256 unique MAC addresses, since
-  // that overflows past the last byte...
-  // We'll write up some code that generates 258 unique MAC addresses.  Sorta
-  // cheating since the code is very similar to the current code in
-  // StripSensitiveData(), but would catch if someone changed that later.
-  std::string lotsa_macs_orig;
-  std::string lotsa_macs_stripped;
-  int i;
-  for (i = 0; i < 258; i++) {
-    lotsa_macs_orig += StringPrintf(" 11:11:11:11:%02X:%02x",
-                                  (i & 0xff00) >> 8, i & 0x00ff);
-    lotsa_macs_stripped += StringPrintf(" 00:00:00:00:%02X:%02x",
-                                     ((i+1) & 0xff00) >> 8, (i+1) & 0x00ff);
-  }
-  std::string lotsa_macs(lotsa_macs_orig);
-  collector_.StripSensitiveData(&lotsa_macs);
-  EXPECT_EQ(lotsa_macs_stripped, lotsa_macs);
-}
-
-TEST_F(KernelCollectorTest, StripSensitiveDataSample) {
-  // Test calling StripSensitiveData w/ some actual lines from a real crash;
-  // included two MAC addresses (though replaced them with some bogusness).
-  const std::string kCrashWithMacsOrig =
-      "<6>[111567.195339] ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES)"
-        " filtered out\n"
-      "<7>[108539.540144] wlan0: authenticate with 11:22:33:44:55:66 (try 1)\n"
-      "<7>[108539.554973] wlan0: associate with 11:22:33:44:55:66 (try 1)\n"
-      "<6>[110136.587583] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
-        " QCUSBNet Ethernet Device, 99:88:77:66:55:44\n"
-      "<7>[110964.314648] wlan0: deauthenticated from 11:22:33:44:55:66"
-        " (Reason: 6)\n"
-      "<7>[110964.325057] phy0: Removed STA 11:22:33:44:55:66\n"
-      "<7>[110964.325115] phy0: Destroyed STA 11:22:33:44:55:66\n"
-      "<6>[110969.219172] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
-        " QCUSBNet Ethernet Device, 99:88:77:66:55:44\n"
-      "<7>[111566.131728] PM: Entering mem sleep\n";
-  const std::string kCrashWithMacsStripped =
-      "<6>[111567.195339] ata1.00: ACPI cmd ef/10:03:00:00:00:a0 (SET FEATURES)"
-        " filtered out\n"
-      "<7>[108539.540144] wlan0: authenticate with 00:00:00:00:00:01 (try 1)\n"
-      "<7>[108539.554973] wlan0: associate with 00:00:00:00:00:01 (try 1)\n"
-      "<6>[110136.587583] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
-        " QCUSBNet Ethernet Device, 00:00:00:00:00:02\n"
-      "<7>[110964.314648] wlan0: deauthenticated from 00:00:00:00:00:01"
-        " (Reason: 6)\n"
-      "<7>[110964.325057] phy0: Removed STA 00:00:00:00:00:01\n"
-      "<7>[110964.325115] phy0: Destroyed STA 00:00:00:00:00:01\n"
-      "<6>[110969.219172] usb0: register 'QCUSBNet2k' at usb-0000:00:1d.7-2,"
-        " QCUSBNet Ethernet Device, 00:00:00:00:00:02\n"
-      "<7>[111566.131728] PM: Entering mem sleep\n";
-  std::string crash_with_macs(kCrashWithMacsOrig);
-  collector_.StripSensitiveData(&crash_with_macs);
-  EXPECT_EQ(kCrashWithMacsStripped, crash_with_macs);
-}
-
-TEST_F(KernelCollectorTest, CollectPreservedFileMissing) {
-  ASSERT_FALSE(collector_.Collect());
-  ASSERT_FALSE(FindLog("Stored kcrash to "));
-  ASSERT_EQ(0, s_crashes);
-}
-
-void KernelCollectorTest::SetUpSuccessfulCollect() {
-  collector_.ForceCrashDirectory(test_crash_directory());
-  WriteStringToFile(kcrash_file(), "====1.1\nsomething");
-  ASSERT_EQ(0, s_crashes);
-}
-
-TEST_F(KernelCollectorTest, CollectOptedOut) {
-  SetUpSuccessfulCollect();
-  s_metrics = false;
-  ASSERT_TRUE(collector_.Collect());
-  ASSERT_TRUE(FindLog("(ignoring - no consent)"));
-  ASSERT_EQ(0, s_crashes);
-}
-
-TEST_F(KernelCollectorTest, CollectOK) {
-  SetUpSuccessfulCollect();
-  ASSERT_TRUE(collector_.Collect());
-  ASSERT_EQ(1, s_crashes);
-  ASSERT_TRUE(FindLog("(handling)"));
-  static const char kNamePrefix[] = "Stored kcrash to ";
-  std::string log = brillo::GetLog();
-  size_t pos = log.find(kNamePrefix);
-  ASSERT_NE(std::string::npos, pos)
-      << "Did not find string \"" << kNamePrefix << "\" in log: {\n"
-      << log << "}";
-  pos += strlen(kNamePrefix);
-  std::string filename = log.substr(pos, std::string::npos);
-  // Take the name up until \n
-  size_t end_pos = filename.find_first_of('\n');
-  ASSERT_NE(std::string::npos, end_pos);
-  filename = filename.substr(0, end_pos);
-  ASSERT_EQ(0U, filename.find(test_crash_directory().value()));
-  ASSERT_TRUE(base::PathExists(FilePath(filename)));
-  std::string contents;
-  ASSERT_TRUE(base::ReadFileToString(FilePath(filename), &contents));
-  ASSERT_EQ("something", contents);
-}
-
-// Perform tests which are common across architectures
-void KernelCollectorTest::ComputeKernelStackSignatureCommon() {
-  std::string signature;
-
-  const char kStackButNoPC[] =
-      "<4>[ 6066.829029]  [<790340af>] __do_softirq+0xa6/0x143\n";
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kStackButNoPC, &signature, false));
-  EXPECT_EQ("kernel--83615F0A", signature);
-
-  const char kMissingEverything[] =
-      "<4>[ 6066.829029]  [<790340af>] ? __do_softirq+0xa6/0x143\n";
-  EXPECT_FALSE(
-      collector_.ComputeKernelStackSignature(kMissingEverything,
-                                             &signature,
-                                             false));
-
-  // Long message.
-  const char kTruncatedMessage[] =
-      "<0>[   87.485611] Kernel panic - not syncing: 01234567890123456789"
-          "01234567890123456789X\n";
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kTruncatedMessage,
-                                             &signature,
-                                             false));
-  EXPECT_EQ("kernel-0123456789012345678901234567890123456789-00000000",
-            signature);
-}
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureARM) {
-  const char kBugToPanic[] =
-      "<5>[  123.412524] Modules linked in:\n"
-      "<5>[  123.412534] CPU: 0    Tainted: G        W    "
-          "(2.6.37-01030-g51cee64 #153)\n"
-      "<5>[  123.412552] PC is at write_breakme+0xd0/0x1b4\n"
-      "<5>[  123.412560] LR is at write_breakme+0xc8/0x1b4\n"
-      "<5>[  123.412569] pc : [<c0058220>]    lr : [<c005821c>]    "
-          "psr: 60000013\n"
-      "<5>[  123.412574] sp : f4e0ded8  ip : c04d104c  fp : 000e45e0\n"
-      "<5>[  123.412581] r10: 400ff000  r9 : f4e0c000  r8 : 00000004\n"
-      "<5>[  123.412589] r7 : f4e0df80  r6 : f4820c80  r5 : 00000004  "
-          "r4 : f4e0dee8\n"
-      "<5>[  123.412598] r3 : 00000000  r2 : f4e0decc  r1 : c05f88a9  "
-          "r0 : 00000039\n"
-      "<5>[  123.412608] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA "
-          "ARM  Segment user\n"
-      "<5>[  123.412617] Control: 10c53c7d  Table: 34dcc04a  DAC: 00000015\n"
-      "<0>[  123.412626] Process bash (pid: 1014, stack limit = 0xf4e0c2f8)\n"
-      "<0>[  123.412634] Stack: (0xf4e0ded8 to 0xf4e0e000)\n"
-      "<0>[  123.412641] dec0:                                              "
-          "         f4e0dee8 c0183678\n"
-      "<0>[  123.412654] dee0: 00000000 00000000 00677562 0000081f c06a6a78 "
-          "400ff000 f4e0dfb0 00000000\n"
-      "<0>[  123.412666] df00: bec7ab44 000b1719 bec7ab0c c004f498 bec7a314 "
-          "c024acc8 00000001 c018359c\n"
-      "<0>[  123.412679] df20: f4e0df34 c04d10fc f5803c80 271beb39 000e45e0 "
-          "f5803c80 c018359c c017bfe0\n"
-      "<0>[  123.412691] df40: 00000004 f4820c80 400ff000 f4e0df80 00000004 "
-          "f4e0c000 00000000 c01383e4\n"
-      "<0>[  123.412703] df60: f4820c80 400ff000 f4820c80 400ff000 00000000 "
-          "00000000 00000004 c0138578\n"
-      "<0>[  123.412715] df80: 00000000 00000000 00000004 00000000 00000004 "
-          "402f95d0 00000004 00000004\n"
-      "<0>[  123.412727] dfa0: c0054984 c00547c0 00000004 402f95d0 00000001 "
-          "400ff000 00000004 00000000\n"
-      "<0>[  123.412739] dfc0: 00000004 402f95d0 00000004 00000004 400ff000 "
-          "000c194c bec7ab58 000e45e0\n"
-      "<0>[  123.412751] dfe0: 00000000 bec7aad8 40232520 40284e9c 60000010 "
-          "00000001 00000000 00000000\n"
-      "<5>[   39.496577] Backtrace:\n"
-      "<5>[  123.412782] [<c0058220>] (__bug+0x20/0x2c) from [<c0183678>] "
-          "(write_breakme+0xdc/0x1bc)\n"
-      "<5>[  123.412798] [<c0183678>] (write_breakme+0xdc/0x1bc) from "
-          "[<c017bfe0>] (proc_reg_write+0x88/0x9c)\n";
-  std::string signature;
-
-  collector_.set_arch(KernelCollector::kArchArm);
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kBugToPanic, &signature, false));
-  EXPECT_EQ("kernel-write_breakme-97D3E92F", signature);
-
-  ComputeKernelStackSignatureCommon();
-}
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureMIPS) {
-  const char kBugToPanic[] =
-      "<5>[ 3378.472000] lkdtm: Performing direct entry BUG\n"
-      "<5>[ 3378.476000] Kernel bug detected[#1]:\n"
-      "<5>[ 3378.484000] CPU: 0 PID: 185 Comm: dash Not tainted 3.14.0 #1\n"
-      "<5>[ 3378.488000] task: 8fed5220 ti: 8ec4a000 task.ti: 8ec4a000\n"
-      "<5>[ 3378.496000] $ 0   : 00000000 804018b8 804010f0 7785b507\n"
-      "<5>[ 3378.500000] $ 4   : 8061ab64 81204478 81205b20 00000000\n"
-      "<5>[ 3378.508000] $ 8   : 80830000 20746365 72746e65 55422079\n"
-      "<5>[ 3378.512000] $12   : 8ec4be94 000000fc 00000000 00000048\n"
-      "<5>[ 3378.520000] $16   : 00000004 8ef54000 80710000 00000002\n"
-      "<5>[ 3378.528000] $20   : 7765b6d4 00000004 7fffffff 00000002\n"
-      "<5>[ 3378.532000] $24   : 00000001 803dc0dc                  \n"
-      "<5>[ 3378.540000] $28   : 8ec4a000 8ec4be20 7775438d 804018b8\n"
-      "<5>[ 3378.544000] Hi    : 00000000\n"
-      "<5>[ 3378.548000] Lo    : 49bf8080\n"
-      "<5>[ 3378.552000] epc   : 804010f0 lkdtm_do_action+0x68/0x3f8\n"
-      "<5>[ 3378.560000]     Not tainted\n"
-      "<5>[ 3378.564000] ra    : 804018b8 direct_entry+0x110/0x154\n"
-      "<5>[ 3378.568000] Status: 3100dc03 KERNEL EXL IE \n"
-      "<5>[ 3378.572000] Cause : 10800024\n"
-      "<5>[ 3378.576000] PrId  : 0001a120 (MIPS interAptiv (multi))\n"
-      "<5>[ 3378.580000] Modules linked in: uinput cfg80211 nf_conntrack_ipv6 "
-          "nf_defrag_ipv6 ip6table_filter ip6_tables pcnet32 mii fuse "
-          "ppp_async ppp_generic slhc tun\n"
-      "<5>[ 3378.600000] Process dash (pid: 185, threadinfo=8ec4a000, "
-          "task=8fed5220, tls=77632490)\n"
-      "<5>[ 3378.608000] Stack : 00000006 ffffff9c 00000000 00000000 00000000 "
-          "00000000 8083454a 00000022\n"
-      "<5>          7765baa1 00001fee 80710000 8ef54000 8ec4bf08 00000002 "
-          "7765b6d4 00000004\n"
-      "<5>          7fffffff 00000002 7775438d 805e5158 7fffffff 00000002 "
-          "00000000 7785b507\n"
-      "<5>          806a96bc 00000004 8ef54000 8ec4bf08 00000002 804018b8 "
-          "80710000 806a98bc\n"
-      "<5>          00000002 00000020 00000004 8d515600 77756450 00000004 "
-          "8ec4bf08 802377e4\n"
-      "<5>          ...\n"
-      "<5>[ 3378.652000] Call Trace:\n"
-      "<5>[ 3378.656000] [<804010f0>] lkdtm_do_action+0x68/0x3f8\n"
-      "<5>[ 3378.660000] [<804018b8>] direct_entry+0x110/0x154\n"
-      "<5>[ 3378.664000] [<802377e4>] vfs_write+0xe0/0x1bc\n"
-      "<5>[ 3378.672000] [<80237f90>] SyS_write+0x78/0xf8\n"
-      "<5>[ 3378.676000] [<80111888>] handle_sys+0x128/0x14c\n"
-      "<5>[ 3378.680000] \n"
-      "<5>[ 3378.684000] \n"
-      "<5>Code: 3c04806b  0c1793aa  248494f0 <000c000d> 3c04806b  248494fc  "
-          "0c04cc7f  2405017a  08100514 \n"
-      "<5>[ 3378.696000] ---[ end trace 75067432f24bbc93 ]---\n";
-  std::string signature;
-
-  collector_.set_arch(KernelCollector::kArchMips);
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kBugToPanic, &signature, false));
-  EXPECT_EQ("kernel-lkdtm_do_action-5E600A6B", signature);
-
-  ComputeKernelStackSignatureCommon();
-}
-
-TEST_F(KernelCollectorTest, ComputeKernelStackSignatureX86) {
-  const char kBugToPanic[] =
-      "<4>[ 6066.829029]  [<79039d16>] ? run_timer_softirq+0x165/0x1e6\n"
-      "<4>[ 6066.829029]  [<790340af>] ignore_old_stack+0xa6/0x143\n"
-      "<0>[ 6066.829029] EIP: [<b82d7c15>] ieee80211_stop_tx_ba_session+"
-          "0xa3/0xb5 [mac80211] SS:ESP 0068:7951febc\n"
-      "<0>[ 6066.829029] CR2: 00000000323038a7\n"
-      "<4>[ 6066.845422] ---[ end trace 12b058bb46c43500 ]---\n"
-      "<0>[ 6066.845747] Kernel panic - not syncing: Fatal exception "
-          "in interrupt\n"
-      "<0>[ 6066.846902] Call Trace:\n"
-      "<4>[ 6066.846902]  [<7937a07b>] ? printk+0x14/0x19\n"
-      "<4>[ 6066.949779]  [<79379fc1>] panic+0x3e/0xe4\n"
-      "<4>[ 6066.949971]  [<7937c5c5>] oops_end+0x73/0x81\n"
-      "<4>[ 6066.950208]  [<7901b260>] no_context+0x10d/0x117\n";
-  std::string signature;
-
-  collector_.set_arch(KernelCollector::kArchX86);
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kBugToPanic, &signature, false));
-  EXPECT_EQ("kernel-ieee80211_stop_tx_ba_session-DE253569", signature);
-
-  const char kPCButNoStack[] =
-      "<0>[ 6066.829029] EIP: [<b82d7c15>] ieee80211_stop_tx_ba_session+";
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kPCButNoStack, &signature, false));
-  EXPECT_EQ("kernel-ieee80211_stop_tx_ba_session-00000000", signature);
-
-  const char kBreakmeBug[] =
-      "<4>[  180.492137]  [<790970c6>] ? handle_mm_fault+0x67f/0x96d\n"
-      "<4>[  180.492137]  [<790dcdfe>] ? proc_reg_write+0x5f/0x73\n"
-      "<4>[  180.492137]  [<790e2224>] ? write_breakme+0x0/0x108\n"
-      "<4>[  180.492137]  [<790dcd9f>] ? proc_reg_write+0x0/0x73\n"
-      "<4>[  180.492137]  [<790ac0aa>] vfs_write+0x85/0xe4\n"
-      "<0>[  180.492137] Code: c6 44 05 b2 00 89 d8 e8 0c ef 09 00 85 c0 75 "
-      "0b c7 00 00 00 00 00 e9 8e 00 00 00 ba e6 75 4b 79 89 d8 e8 f1 ee 09 "
-      "00 85 c0 75 04 <0f> 0b eb fe ba 58 47 49 79 89 d8 e8 dd ee 09 00 85 "
-      "c0 75 0a 68\n"
-      "<0>[  180.492137] EIP: [<790e22a4>] write_breakme+0x80/0x108 SS:ESP "
-          "0068:aa3e9efc\n"
-      "<4>[  180.501800] ---[ end trace 2a6b72965e1b1523 ]---\n"
-      "<0>[  180.502026] Kernel panic - not syncing: Fatal exception\n"
-      "<4>[  180.502026] Call Trace:\n"
-      "<4>[  180.502806]  [<79379aba>] ? printk+0x14/0x1a\n"
-      "<4>[  180.503033]  [<79379a00>] panic+0x3e/0xe4\n"
-      "<4>[  180.503287]  [<7937c005>] oops_end+0x73/0x81\n"
-      "<4>[  180.503520]  [<790055dd>] die+0x58/0x5e\n"
-      "<4>[  180.503538]  [<7937b96c>] do_trap+0x8e/0xa7\n"
-      "<4>[  180.503555]  [<79003d70>] ? do_invalid_op+0x0/0x80\n";
-
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kBreakmeBug, &signature, false));
-  EXPECT_EQ("kernel-write_breakme-122AB3CD", signature);
-
-  const char kPCLineTooOld[] =
-      "<4>[  174.492137]  [<790970c6>] ignored_function+0x67f/0x96d\n"
-      "<4>[  175.492137]  [<790970c6>] ignored_function2+0x67f/0x96d\n"
-      "<0>[  174.492137] EIP: [<790e22a4>] write_breakme+0x80/0x108 SS:ESP "
-          "0068:aa3e9efc\n"
-      "<4>[  180.501800] ---[ end trace 2a6b72965e1b1523 ]---\n"
-      "<4>[  180.502026] Call Trace:\n"
-      "<0>[  180.502026] Kernel panic - not syncing: Fatal exception\n"
-      "<4>[  180.502806]  [<79379aba>] printk+0x14/0x1a\n";
-
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kPCLineTooOld, &signature, false));
-  EXPECT_EQ("kernel-Fatal exception-ED4C84FE", signature);
-
-  // Panic without EIP line.
-  const char kExamplePanicOnly[] =
-      "<0>[   87.485611] Kernel panic - not syncing: Testing panic\n"
-      "<4>[   87.485630] Pid: 2825, comm: bash Tainted: G         "
-          "C 2.6.32.23+drm33.10 #1\n"
-      "<4>[   87.485639] Call Trace:\n"
-      "<4>[   87.485660]  [<8133f71d>] ? printk+0x14/0x17\n"
-      "<4>[   87.485674]  [<8133f663>] panic+0x3e/0xe4\n"
-      "<4>[   87.485689]  [<810d062e>] write_breakme+0xaa/0x124\n";
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kExamplePanicOnly,
-                                             &signature,
-                                             false));
-  EXPECT_EQ("kernel-Testing panic-E0FC3552", signature);
-
-  // Panic from hung task.
-  const char kHungTaskBreakMe[] =
-      "<3>[  720.459157] INFO: task bash:2287 blocked blah blah\n"
-      "<5>[  720.459282] Call Trace:\n"
-      "<5>[  720.459307]  [<810a457b>] ? __dentry_open+0x186/0x23e\n"
-      "<5>[  720.459323]  [<810b9c71>] ? mntput_no_expire+0x29/0xe2\n"
-      "<5>[  720.459336]  [<810b9d48>] ? mntput+0x1e/0x20\n"
-      "<5>[  720.459350]  [<810ad135>] ? path_put+0x1a/0x1d\n"
-      "<5>[  720.459366]  [<8137cacc>] schedule+0x4d/0x4f\n"
-      "<5>[  720.459379]  [<8137ccfb>] schedule_timeout+0x26/0xaf\n"
-      "<5>[  720.459394]  [<8102127e>] ? should_resched+0xd/0x27\n"
-      "<5>[  720.459409]  [<81174d1f>] ? _copy_from_user+0x3c/0x50\n"
-      "<5>[  720.459423]  [<8137cd9e>] "
-      "schedule_timeout_uninterruptible+0x1a/0x1c\n"
-      "<5>[  720.459438]  [<810dee63>] write_breakme+0xb3/0x178\n"
-      "<5>[  720.459453]  [<810dedb0>] ? meminfo_proc_show+0x2f2/0x2f2\n"
-      "<5>[  720.459467]  [<810d94ae>] proc_reg_write+0x6d/0x87\n"
-      "<5>[  720.459481]  [<810d9441>] ? proc_reg_poll+0x76/0x76\n"
-      "<5>[  720.459493]  [<810a5e9e>] vfs_write+0x79/0xa5\n"
-      "<5>[  720.459505]  [<810a6011>] sys_write+0x40/0x65\n"
-      "<5>[  720.459519]  [<8137e677>] sysenter_do_call+0x12/0x26\n"
-      "<0>[  720.459530] Kernel panic - not syncing: hung_task: blocked tasks\n"
-      "<5>[  720.459768] Pid: 31, comm: khungtaskd Tainted: "
-      "G         C  3.0.8 #1\n"
-      "<5>[  720.459998] Call Trace:\n"
-      "<5>[  720.460140]  [<81378a35>] panic+0x53/0x14a\n"
-      "<5>[  720.460312]  [<8105f875>] watchdog+0x15b/0x1a0\n"
-      "<5>[  720.460495]  [<8105f71a>] ? hung_task_panic+0x16/0x16\n"
-      "<5>[  720.460693]  [<81043af3>] kthread+0x67/0x6c\n"
-      "<5>[  720.460862]  [<81043a8c>] ? __init_kthread_worker+0x2d/0x2d\n"
-      "<5>[  720.461106]  [<8137eb9e>] kernel_thread_helper+0x6/0x10\n";
-
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kHungTaskBreakMe,
-                                             &signature,
-                                             false));
-
-  EXPECT_EQ("kernel-(HANG)-hung_task: blocked tasks-600B37EA", signature);
-
-  // Panic with all question marks in the last stack trace.
-  const char kUncertainStackTrace[] =
-      "<0>[56279.689669] ------------[ cut here ]------------\n"
-      "<2>[56279.689677] kernel BUG at /build/x86-alex/tmp/portage/"
-      "sys-kernel/chromeos-kernel-0.0.1-r516/work/chromeos-kernel-0.0.1/"
-      "kernel/timer.c:844!\n"
-      "<0>[56279.689683] invalid opcode: 0000 [#1] SMP \n"
-      "<0>[56279.689688] last sysfs file: /sys/power/state\n"
-      "<5>[56279.689692] Modules linked in: nls_iso8859_1 nls_cp437 vfat fat "
-      "gobi usbnet tsl2583(C) industrialio(C) snd_hda_codec_realtek "
-      "snd_hda_intel i2c_dev snd_hda_codec snd_hwdep qcserial snd_pcm usb_wwan "
-      "i2c_i801 snd_timer nm10_gpio snd_page_alloc rtc_cmos fuse "
-      "nf_conntrack_ipv6 nf_defrag_ipv6 uvcvideo videodev ip6table_filter "
-      "ath9k ip6_tables ipv6 mac80211 ath9k_common ath9k_hw ath cfg80211 "
-      "xt_mark\n"
-      "<5>[56279.689731] \n"
-      "<5>[56279.689738] Pid: 24607, comm: powerd_suspend Tainted: G        "
-      "WC  2.6.38.3+ #1 SAMSUNG ELECTRONICS CO., LTD. Alex/G100          \n"
-      "<5>[56279.689748] EIP: 0060:[<8103e3ea>] EFLAGS: 00210286 CPU: 3\n"
-      "<5>[56279.689758] EIP is at add_timer+0xd/0x1b\n"
-      "<5>[56279.689762] EAX: f5e00684 EBX: f5e003c0 ECX: 00000002 EDX: "
-      "00200246\n"
-      "<5>[56279.689767] ESI: f5e003c0 EDI: d28bc03c EBP: d2be5e40 ESP: "
-      "d2be5e40\n"
-      "<5>[56279.689772]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068\n"
-      "<0>[56279.689778] Process powerd_suspend (pid: 24607, ti=d2be4000 "
-      "task=f5dc9b60 task.ti=d2be4000)\n"
-      "<0>[56279.689782] Stack:\n"
-      "<5>[56279.689785]  d2be5e4c f8dccced f4ac02c0 d2be5e70 f8ddc752 "
-      "f5e003c0 f4ac0458 f4ac092c\n"
-      "<5>[56279.689797]  f4ac043c f4ac02c0 f4ac0000 f4ac007c d2be5e7c "
-      "f8dd4a33 f4ac0164 d2be5e94\n"
-      "<5>[56279.689809]  f87e0304 f69ff0cc f4ac0164 f87e02a4 f4ac0164 "
-      "d2be5eb0 81248968 00000000\n"
-      "<0>[56279.689821] Call Trace:\n"
-      "<5>[56279.689840]  [<f8dccced>] ieee80211_sta_restart+0x25/0x8c "
-      "[mac80211]\n"
-      "<5>[56279.689854]  [<f8ddc752>] ieee80211_reconfig+0x2e9/0x339 "
-      "[mac80211]\n"
-      "<5>[56279.689869]  [<f8dd4a33>] ieee80211_aes_cmac+0x182d/0x184e "
-      "[mac80211]\n"
-      "<5>[56279.689883]  [<f87e0304>] cfg80211_get_dev_from_info+0x29b/0x2c0 "
-      "[cfg80211]\n"
-      "<5>[56279.689895]  [<f87e02a4>] ? "
-      "cfg80211_get_dev_from_info+0x23b/0x2c0 [cfg80211]\n"
-      "<5>[56279.689904]  [<81248968>] legacy_resume+0x25/0x5d\n"
-      "<5>[56279.689910]  [<812490ae>] device_resume+0xdd/0x110\n"
-      "<5>[56279.689917]  [<812491c2>] dpm_resume_end+0xe1/0x271\n"
-      "<5>[56279.689925]  [<81060481>] suspend_devices_and_enter+0x18b/0x1de\n"
-      "<5>[56279.689932]  [<810605ba>] enter_state+0xe6/0x132\n"
-      "<5>[56279.689939]  [<8105fd4b>] state_store+0x91/0x9d\n"
-      "<5>[56279.689945]  [<8105fcba>] ? state_store+0x0/0x9d\n"
-      "<5>[56279.689953]  [<81178fb1>] kobj_attr_store+0x16/0x22\n"
-      "<5>[56279.689961]  [<810eea5e>] sysfs_write_file+0xc1/0xec\n"
-      "<5>[56279.689969]  [<810af443>] vfs_write+0x8f/0x101\n"
-      "<5>[56279.689975]  [<810ee99d>] ? sysfs_write_file+0x0/0xec\n"
-      "<5>[56279.689982]  [<810af556>] sys_write+0x40/0x65\n"
-      "<5>[56279.689989]  [<81002d57>] sysenter_do_call+0x12/0x26\n"
-      "<0>[56279.689993] Code: c1 d3 e2 4a 89 55 f4 f7 d2 21 f2 6a 00 31 c9 89 "
-      "d8 e8 6e fd ff ff 5a 8d 65 f8 5b 5e 5d c3 55 89 e5 3e 8d 74 26 00 83 38 "
-      "00 74 04 <0f> 0b eb fe 8b 50 08 e8 6f ff ff ff 5d c3 55 89 e5 3e 8d 74 "
-      "26 \n"
-      "<0>[56279.690009] EIP: [<8103e3ea>] add_timer+0xd/0x1b SS:ESP "
-      "0068:d2be5e40\n"
-      "<4>[56279.690113] ---[ end trace b71141bb67c6032a ]---\n"
-      "<7>[56279.694069] wlan0: deauthenticated from 00:00:00:00:00:01 "
-      "(Reason: 6)\n"
-      "<0>[56279.703465] Kernel panic - not syncing: Fatal exception\n"
-      "<5>[56279.703471] Pid: 24607, comm: powerd_suspend Tainted: G      D "
-      "WC  2.6.38.3+ #1\n"
-      "<5>[56279.703475] Call Trace:\n"
-      "<5>[56279.703483]  [<8136648c>] ? panic+0x55/0x152\n"
-      "<5>[56279.703491]  [<810057fa>] ? oops_end+0x73/0x81\n"
-      "<5>[56279.703497]  [<81005a44>] ? die+0xed/0xf5\n"
-      "<5>[56279.703503]  [<810033cb>] ? do_trap+0x7a/0x80\n"
-      "<5>[56279.703509]  [<8100369b>] ? do_invalid_op+0x0/0x80\n"
-      "<5>[56279.703515]  [<81003711>] ? do_invalid_op+0x76/0x80\n"
-      "<5>[56279.703522]  [<8103e3ea>] ? add_timer+0xd/0x1b\n"
-      "<5>[56279.703529]  [<81025e23>] ? check_preempt_curr+0x2e/0x69\n"
-      "<5>[56279.703536]  [<8102ef28>] ? ttwu_post_activation+0x5a/0x11b\n"
-      "<5>[56279.703543]  [<8102fa8d>] ? try_to_wake_up+0x213/0x21d\n"
-      "<5>[56279.703550]  [<81368b7f>] ? error_code+0x67/0x6c\n"
-      "<5>[56279.703557]  [<8103e3ea>] ? add_timer+0xd/0x1b\n"
-      "<5>[56279.703577]  [<f8dccced>] ? ieee80211_sta_restart+0x25/0x8c "
-      "[mac80211]\n"
-      "<5>[56279.703591]  [<f8ddc752>] ? ieee80211_reconfig+0x2e9/0x339 "
-      "[mac80211]\n"
-      "<5>[56279.703605]  [<f8dd4a33>] ? ieee80211_aes_cmac+0x182d/0x184e "
-      "[mac80211]\n"
-      "<5>[56279.703618]  [<f87e0304>] ? "
-      "cfg80211_get_dev_from_info+0x29b/0x2c0 [cfg80211]\n"
-      "<5>[56279.703630]  [<f87e02a4>] ? "
-      "cfg80211_get_dev_from_info+0x23b/0x2c0 [cfg80211]\n"
-      "<5>[56279.703637]  [<81248968>] ? legacy_resume+0x25/0x5d\n"
-      "<5>[56279.703643]  [<812490ae>] ? device_resume+0xdd/0x110\n"
-      "<5>[56279.703649]  [<812491c2>] ? dpm_resume_end+0xe1/0x271\n"
-      "<5>[56279.703657]  [<81060481>] ? "
-      "suspend_devices_and_enter+0x18b/0x1de\n"
-      "<5>[56279.703663]  [<810605ba>] ? enter_state+0xe6/0x132\n"
-      "<5>[56279.703670]  [<8105fd4b>] ? state_store+0x91/0x9d\n"
-      "<5>[56279.703676]  [<8105fcba>] ? state_store+0x0/0x9d\n"
-      "<5>[56279.703683]  [<81178fb1>] ? kobj_attr_store+0x16/0x22\n"
-      "<5>[56279.703690]  [<810eea5e>] ? sysfs_write_file+0xc1/0xec\n"
-      "<5>[56279.703697]  [<810af443>] ? vfs_write+0x8f/0x101\n"
-      "<5>[56279.703703]  [<810ee99d>] ? sysfs_write_file+0x0/0xec\n"
-      "<5>[56279.703709]  [<810af556>] ? sys_write+0x40/0x65\n"
-      "<5>[56279.703716]  [<81002d57>] ? sysenter_do_call+0x12/0x26\n";
-
-  EXPECT_TRUE(
-      collector_.ComputeKernelStackSignature(kUncertainStackTrace,
-                                             &signature,
-                                             false));
-  // The first trace contains only uncertain entries and its hash is 00000000,
-  // so, if we used that, the signature would be kernel-add_timer-00000000.
-  // Instead we use the second-to-last trace for the hash.
-  EXPECT_EQ("kernel-add_timer-B5178878", signature);
-
-  ComputeKernelStackSignatureCommon();
-}
diff --git a/crash_reporter/kernel_collector_test.h b/crash_reporter/kernel_collector_test.h
deleted file mode 100644
index f689e7d..0000000
--- a/crash_reporter/kernel_collector_test.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2014 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 CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
-#define CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
-
-#include "kernel_collector.h"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-class KernelCollectorMock : public KernelCollector {
- public:
-  MOCK_METHOD0(DumpDirMounted, bool());
-  MOCK_METHOD0(SetUpDBus, void());
-};
-
-#endif  // CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
diff --git a/crash_reporter/kernel_log_collector.sh b/crash_reporter/kernel_log_collector.sh
deleted file mode 100644
index 82512c2..0000000
--- a/crash_reporter/kernel_log_collector.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-
-# Copyright (C) 2013 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.
-
-# Usage example: "kernel_log_collector.sh XXX YYY"
-# This script searches logs in the /var/log/messages which have the keyword XXX.
-# And only those logs which are within the last YYY seconds of the latest log
-# that has the keyword XXX are printed.
-
-# Kernel log has the possible formats:
-# 2013-06-14T16:31:40.514513-07:00 localhost kernel: [    2.682472] MSG MSG ...
-# 2013-06-19T20:38:58.661826+00:00 localhost kernel: [    1.668092] MSG MSG ...
-
-search_key=$1
-time_duration=$2
-msg_pattern="^[0-9-]*T[0-9:.+-]* localhost kernel"
-
-die() {
-  echo "kernel_log_collector: $*" >&2
-  exit 1
-}
-
-get_timestamp() {
-  timestamp="$(echo $1 | cut -d " " -f 1)"
-  timestamp="$(date -d "${timestamp}" +%s)" || exit $?
-  echo "${timestamp}"
-}
-
-last_line=$(grep "${msg_pattern}" /var/log/messages | grep -- "${search_key}" | tail -n 1)
-
-if [ -n "${last_line}" ]; then
-  if ! allowed_timestamp=$(get_timestamp "${last_line}"); then
-    die "coule not get timestamp from: ${last_line}"
-  fi
-  : $(( allowed_timestamp -= ${time_duration} ))
-  grep "${msg_pattern}" /var/log/messages | grep -- "${search_key}" | while read line; do
-    if ! timestamp=$(get_timestamp "${line}"); then
-      die "could not get timestamp from: ${line}"
-    fi
-    if [ ${timestamp} -gt ${allowed_timestamp} ]; then
-      echo "${line}"
-    fi
-  done
-fi
-
-echo "END-OF-LOG"
-
diff --git a/crash_reporter/kernel_warning_collector.cc b/crash_reporter/kernel_warning_collector.cc
deleted file mode 100644
index e28e8fd..0000000
--- a/crash_reporter/kernel_warning_collector.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2012 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 "kernel_warning_collector.h"
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-
-namespace {
-const char kExecName[] = "kernel-warning";
-const char kKernelWarningSignatureKey[] = "sig";
-const char kKernelWarningPath[] = "/var/run/kwarn/warning";
-const pid_t kKernelPid = 0;
-const uid_t kRootUid = 0;
-}  // namespace
-
-using base::FilePath;
-using base::StringPrintf;
-
-KernelWarningCollector::KernelWarningCollector() {
-}
-
-KernelWarningCollector::~KernelWarningCollector() {
-}
-
-bool KernelWarningCollector::LoadKernelWarning(std::string *content,
-                                               std::string *signature) {
-  FilePath kernel_warning_path(kKernelWarningPath);
-  if (!base::ReadFileToString(kernel_warning_path, content)) {
-    LOG(ERROR) << "Could not open " << kKernelWarningPath;
-    return false;
-  }
-  // The signature is in the first line.
-  std::string::size_type end_position = content->find('\n');
-  if (end_position == std::string::npos) {
-    LOG(ERROR) << "unexpected kernel warning format";
-    return false;
-  }
-  *signature = content->substr(0, end_position);
-  return true;
-}
-
-bool KernelWarningCollector::Collect() {
-  std::string reason = "normal collection";
-  bool feedback = true;
-  if (IsDeveloperImage()) {
-    reason = "always collect from developer builds";
-    feedback = true;
-  } else if (!is_feedback_allowed_function_()) {
-    reason = "no user consent";
-    feedback = false;
-  }
-
-  LOG(INFO) << "Processing kernel warning: " << reason;
-
-  if (!feedback) {
-    return true;
-  }
-
-  std::string kernel_warning;
-  std::string warning_signature;
-  if (!LoadKernelWarning(&kernel_warning, &warning_signature)) {
-    return true;
-  }
-
-  FilePath root_crash_directory;
-  if (!GetCreatedCrashDirectoryByEuid(kRootUid, &root_crash_directory,
-                                      nullptr)) {
-    return true;
-  }
-
-  std::string dump_basename =
-      FormatDumpBasename(kExecName, time(nullptr), kKernelPid);
-  FilePath kernel_crash_path = root_crash_directory.Append(
-      StringPrintf("%s.kcrash", dump_basename.c_str()));
-
-  // We must use WriteNewFile instead of base::WriteFile as we
-  // do not want to write with root access to a symlink that an attacker
-  // might have created.
-  if (WriteNewFile(kernel_crash_path,
-                   kernel_warning.data(),
-                   kernel_warning.length()) !=
-      static_cast<int>(kernel_warning.length())) {
-    LOG(INFO) << "Failed to write kernel warning to "
-              << kernel_crash_path.value().c_str();
-    return true;
-  }
-
-  AddCrashMetaData(kKernelWarningSignatureKey, warning_signature);
-  WriteCrashMetaData(
-      root_crash_directory.Append(
-          StringPrintf("%s.meta", dump_basename.c_str())),
-    kExecName, kernel_crash_path.value());
-
-  LOG(INFO) << "Stored kernel warning into " << kernel_crash_path.value();
-  return true;
-}
diff --git a/crash_reporter/kernel_warning_collector.h b/crash_reporter/kernel_warning_collector.h
deleted file mode 100644
index 5ccb780..0000000
--- a/crash_reporter/kernel_warning_collector.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2013 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 CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
-#define CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
-
-#include <string>
-
-#include <base/macros.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Kernel warning collector.
-class KernelWarningCollector : public CrashCollector {
- public:
-  KernelWarningCollector();
-
-  ~KernelWarningCollector() override;
-
-  // Collects warning.
-  bool Collect();
-
- private:
-  friend class KernelWarningCollectorTest;
-  FRIEND_TEST(KernelWarningCollectorTest, CollectOK);
-
-  // Reads the full content of the kernel warn dump and its signature.
-  bool LoadKernelWarning(std::string *content, std::string *signature);
-
-  DISALLOW_COPY_AND_ASSIGN(KernelWarningCollector);
-};
-
-#endif  // CRASH_REPORTER_KERNEL_WARNING_COLLECTOR_H_
diff --git a/crash_reporter/list_proxies.cc b/crash_reporter/list_proxies.cc
deleted file mode 100644
index 3374b5f..0000000
--- a/crash_reporter/list_proxies.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2011 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 <sysexits.h>
-#include <unistd.h>  // for isatty()
-
-#include <string>
-#include <vector>
-
-#include <base/cancelable_callback.h>
-#include <base/command_line.h>
-#include <base/files/file_util.h>
-#include <base/memory/weak_ptr.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_tokenizer.h>
-#include <base/strings/string_util.h>
-#include <base/values.h>
-#include <brillo/daemons/dbus_daemon.h>
-#include <brillo/syslog_logging.h>
-
-#include "libcrosservice/dbus-proxies.h"
-
-using std::unique_ptr;
-
-namespace {
-
-const char kLibCrosProxyResolvedSignalInterface[] =
-    "org.chromium.CrashReporterLibcrosProxyResolvedInterface";
-const char kLibCrosProxyResolvedName[] = "ProxyResolved";
-const char kLibCrosServiceName[] = "org.chromium.LibCrosService";
-const char kNoProxy[] = "direct://";
-
-const int kTimeoutDefaultSeconds = 5;
-
-const char kHelp[] = "help";
-const char kQuiet[] = "quiet";
-const char kTimeout[] = "timeout";
-const char kVerbose[] = "verbose";
-// Help message to show when the --help command line switch is specified.
-const char kHelpMessage[] =
-    "Chromium OS Crash helper: proxy lister\n"
-    "\n"
-    "Available Switches:\n"
-    "  --quiet      Only print the proxies\n"
-    "  --verbose    Print additional messages even when not run from a TTY\n"
-    "  --timeout=N  Set timeout for browser resolving proxies (default is 5)\n"
-    "  --help       Show this help.\n";
-
-// Copied from src/update_engine/chrome_browser_proxy_resolver.cc
-// Parses the browser's answer for resolved proxies.  It returns a
-// list of strings, each of which is a resolved proxy.
-std::vector<std::string> ParseProxyString(const std::string& input) {
-  std::vector<std::string> ret;
-  // Some of this code taken from
-  // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_server.cc and
-  // http://src.chromium.org/svn/trunk/src/net/proxy/proxy_list.cc
-  base::StringTokenizer entry_tok(input, ";");
-  while (entry_tok.GetNext()) {
-    std::string token = entry_tok.token();
-    base::TrimWhitespaceASCII(token, base::TRIM_ALL, &token);
-
-    // Start by finding the first space (if any).
-    std::string::iterator space;
-    for (space = token.begin(); space != token.end(); ++space) {
-      if (base::IsAsciiWhitespace(*space)) {
-        break;
-      }
-    }
-
-    std::string scheme = base::ToLowerASCII(std::string(token.begin(), space));
-    // Chrome uses "socks" to mean socks4 and "proxy" to mean http.
-    if (scheme == "socks")
-      scheme += "4";
-    else if (scheme == "proxy")
-      scheme = "http";
-    else if (scheme != "https" &&
-             scheme != "socks4" &&
-             scheme != "socks5" &&
-             scheme != "direct")
-      continue;  // Invalid proxy scheme
-
-    std::string host_and_port = std::string(space, token.end());
-    base::TrimWhitespaceASCII(host_and_port, base::TRIM_ALL, &host_and_port);
-    if (scheme != "direct" && host_and_port.empty())
-      continue;  // Must supply host/port when non-direct proxy used.
-    ret.push_back(scheme + "://" + host_and_port);
-  }
-  if (ret.empty() || *ret.rbegin() != kNoProxy)
-    ret.push_back(kNoProxy);
-  return ret;
-}
-
-// A class for interfacing with Chrome to resolve proxies for a given source
-// url.  The class is initialized with the given source url to check, the
-// signal interface and name that Chrome will reply to, and how long to wait
-// for the resolve request to timeout.  Once initialized, the Run() function
-// must be called, which blocks on the D-Bus call to Chrome.  The call returns
-// after either the timeout or the proxy has been resolved.  The resolved
-// proxies can then be accessed through the proxies() function.
-class ProxyResolver : public brillo::DBusDaemon {
- public:
-  ProxyResolver(const std::string& source_url,
-                const std::string& signal_interface,
-                const std::string& signal_name,
-                base::TimeDelta timeout)
-      : source_url_(source_url),
-        signal_interface_(signal_interface),
-        signal_name_(signal_name),
-        timeout_(timeout),
-        weak_ptr_factory_(this),
-        timeout_callback_(base::Bind(&ProxyResolver::HandleBrowserTimeout,
-                                     weak_ptr_factory_.GetWeakPtr())) {}
-
-  ~ProxyResolver() override {}
-
-  const std::vector<std::string>& proxies() {
-    return proxies_;
-  }
-
-  int Run() override {
-    // Add task for if the browser proxy call times out.
-    base::MessageLoop::current()->PostDelayedTask(
-        FROM_HERE,
-        timeout_callback_.callback(),
-        timeout_);
-
-    return brillo::DBusDaemon::Run();
-  }
-
- protected:
-  // If the browser times out, quit the run loop.
-  void HandleBrowserTimeout() {
-    LOG(ERROR) << "Timeout while waiting for browser to resolve proxy";
-    Quit();
-  }
-
-  // If the signal handler connects successfully, call the browser's
-  // ResolveNetworkProxy D-Bus method.  Otherwise, don't do anything and let
-  // the timeout task quit the run loop.
-  void HandleDBusSignalConnected(const std::string& interface,
-                                 const std::string& signal,
-                                 bool success) {
-    if (!success) {
-      LOG(ERROR) << "Could not connect to signal " << interface << "."
-                 << signal;
-      timeout_callback_.Cancel();
-      Quit();
-      return;
-    }
-
-    brillo::ErrorPtr error;
-    call_proxy_->ResolveNetworkProxy(source_url_,
-                                     signal_interface_,
-                                     signal_name_,
-                                     &error);
-
-    if (error) {
-      LOG(ERROR) << "Call to ResolveNetworkProxy failed: "
-                 << error->GetMessage();
-      timeout_callback_.Cancel();
-      Quit();
-    }
-  }
-
-  // Handle incoming ProxyResolved signal.
-  void HandleProxyResolvedSignal(const std::string& source_url,
-                                 const std::string& proxy_info,
-                                 const std::string& error_message) {
-    timeout_callback_.Cancel();
-    proxies_ = ParseProxyString(proxy_info);
-    LOG(INFO) << "Found proxies via browser signal: "
-              << base::JoinString(proxies_, "x");
-
-    Quit();
-  }
-
-  int OnInit() override {
-    int return_code = brillo::DBusDaemon::OnInit();
-    if (return_code != EX_OK)
-      return return_code;
-
-    // Initialize D-Bus proxies.
-    call_proxy_.reset(
-        new org::chromium::LibCrosServiceInterfaceProxy(bus_,
-                                                        kLibCrosServiceName));
-    signal_proxy_.reset(
-        new org::chromium::CrashReporterLibcrosProxyResolvedInterfaceProxy(
-            bus_,
-            kLibCrosServiceName));
-
-    // Set up the D-Bus signal handler.
-    // TODO(crbug.com/446115): Update ResolveNetworkProxy call to use an
-    //     asynchronous return value rather than a return signal.
-    signal_proxy_->RegisterProxyResolvedSignalHandler(
-        base::Bind(&ProxyResolver::HandleProxyResolvedSignal,
-                   weak_ptr_factory_.GetWeakPtr()),
-        base::Bind(&ProxyResolver::HandleDBusSignalConnected,
-                   weak_ptr_factory_.GetWeakPtr()));
-
-    return EX_OK;
-  }
-
- private:
-  unique_ptr<org::chromium::LibCrosServiceInterfaceProxy> call_proxy_;
-  unique_ptr<org::chromium::CrashReporterLibcrosProxyResolvedInterfaceProxy>
-      signal_proxy_;
-
-  const std::string source_url_;
-  const std::string signal_interface_;
-  const std::string signal_name_;
-  base::TimeDelta timeout_;
-
-  std::vector<std::string> proxies_;
-  base::WeakPtrFactory<ProxyResolver> weak_ptr_factory_;
-
-  base::CancelableClosure timeout_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProxyResolver);
-};
-
-static bool ShowBrowserProxies(std::string url, base::TimeDelta timeout) {
-  // Initialize and run the proxy resolver to watch for signals.
-  ProxyResolver resolver(url,
-                         kLibCrosProxyResolvedSignalInterface,
-                         kLibCrosProxyResolvedName,
-                         timeout);
-  resolver.Run();
-
-  std::vector<std::string> proxies = resolver.proxies();
-
-  // If proxies is empty, then the timeout was reached waiting for the proxy
-  // resolved signal.  If no proxies are defined, proxies will be populated
-  // with "direct://".
-  if (proxies.empty())
-    return false;
-
-  for (const auto& proxy : proxies) {
-    printf("%s\n", proxy.c_str());
-  }
-  return true;
-}
-
-}  // namespace
-
-int main(int argc, char *argv[]) {
-  base::CommandLine::Init(argc, argv);
-  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
-
-  if (cl->HasSwitch(kHelp)) {
-    LOG(INFO) << kHelpMessage;
-    return 0;
-  }
-
-  bool quiet = cl->HasSwitch(kQuiet);
-  bool verbose = cl->HasSwitch(kVerbose);
-
-  int timeout = kTimeoutDefaultSeconds;
-  std::string str_timeout = cl->GetSwitchValueASCII(kTimeout);
-  if (!str_timeout.empty() && !base::StringToInt(str_timeout, &timeout)) {
-    LOG(ERROR) << "Invalid timeout value: " << str_timeout;
-    return 1;
-  }
-
-  // Default to logging to syslog.
-  int init_flags = brillo::kLogToSyslog;
-  // Log to stderr if a TTY (and "-quiet" wasn't passed), or if "-verbose"
-  // was passed.
-
-  if ((!quiet && isatty(STDERR_FILENO)) || verbose)
-    init_flags |= brillo::kLogToStderr;
-  brillo::InitLog(init_flags);
-
-  std::string url;
-  base::CommandLine::StringVector urls = cl->GetArgs();
-  if (!urls.empty()) {
-    url = urls[0];
-    LOG(INFO) << "Resolving proxies for URL: " << url;
-  } else {
-    LOG(INFO) << "Resolving proxies without URL";
-  }
-
-  if (!ShowBrowserProxies(url, base::TimeDelta::FromSeconds(timeout))) {
-    LOG(ERROR) << "Error resolving proxies via the browser";
-    LOG(INFO) << "Assuming direct proxy";
-    printf("%s\n", kNoProxy);
-  }
-
-  return 0;
-}
diff --git a/crash_reporter/periodic_scheduler b/crash_reporter/periodic_scheduler
deleted file mode 100755
index 5408da7..0000000
--- a/crash_reporter/periodic_scheduler
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/system/bin/sh
-
-# Copyright (C) 2014 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.
-
-# Run tasks periodically.
-# Usage: $0 <delay_seconds> <timeout_seconds> <task_name> <task_binary>
-#
-# Executes task <task_name> by running <task_binary> every <delay_seconds>.
-
-set -e -u
-
-SCRIPT_NAME="$(basename "$0")"
-CHECK_DELAY=300  # Check every 5 minutes.
-KILL_DELAY=10    # How long to let the job clean up after a timeout.
-# Let the unittests override.
-: ${SPOOL_DIR:=/data/misc/crash_reporter/spool/cron-lite}
-
-loginfo() {
-  log -p i -t "${SCRIPT_NAME}" "$@"
-}
-
-trap "loginfo 'exiting'" EXIT
-
-check_and_fix_spool_paths() {
-  # Avoid weird spool paths if possible.
-  rm -f "$(dirname "${SPOOL_DIR}")" "${SPOOL_DIR}" 2>/dev/null || :
-  mkdir -p "${SPOOL_DIR}"
-  if [ ! -O "${SPOOL_DIR}" -o ! -d "${SPOOL_DIR}" ]; then
-    loginfo "Spool directory is damaged. Aborting!"
-    exit 1
-  fi
-}
-
-main() {
-  local delay="$1"
-  local timeout="$2"
-  local name="$3"
-  local spool_file="${SPOOL_DIR}/${name}"
-  shift 3
-
-  [ -z "${delay}" ] && exit 1
-  [ -z "${timeout}" ] && exit 1
-  [ -z "${name}" ] && exit 1
-  [ $# -eq 0 ] && exit 1
-  check_and_fix_spool_paths
-
-  while true; do
-    # Allow the sleep to be killed manually without terminating the handler.
-    # Send stderr to /dev/null to suppress the shell's "Terminated" message.
-    sleep $(( CHECK_DELAY + KILL_DELAY )) 2>/dev/null || true
-
-    [ ! -e "${spool_file}" ] && touch "${spool_file}"
-
-    local last_rotation="$(stat -c "%Y" "${spool_file}" 2>/dev/null || echo 0)"
-    local now="$(date +%s)"
-    local time_diff=$((now - last_rotation))
-
-    if [ ${time_diff} -gt ${delay} ]; then
-      rm "${spool_file}" || true
-      touch "${spool_file}"
-      loginfo "${name}: running $*"
-      timeout -k ${KILL_DELAY} ${timeout} "$@" || true
-      loginfo "${name}: job completed"
-    fi
-  done
-}
-
-main "$@"
diff --git a/crash_reporter/testrunner.cc b/crash_reporter/testrunner.cc
deleted file mode 100644
index 744cf10..0000000
--- a/crash_reporter/testrunner.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-#include <brillo/test_helpers.h>
-#include <gtest/gtest.h>
-
-int main(int argc, char** argv) {
-  SetUpTests(&argc, argv, true);
-  return RUN_ALL_TESTS();
-}
diff --git a/crash_reporter/udev_collector.cc b/crash_reporter/udev_collector.cc
deleted file mode 100644
index 1e018db..0000000
--- a/crash_reporter/udev_collector.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2012 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 "udev_collector.h"
-
-#include <map>
-#include <utility>
-#include <vector>
-
-#include <base/files/file_enumerator.h>
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/process.h>
-
-using base::FilePath;
-
-namespace {
-
-const char kCollectUdevSignature[] = "crash_reporter-udev-collection";
-const char kGzipPath[] = "/bin/gzip";
-const char kUdevExecName[] = "udev";
-const char kUdevSignatureKey[] = "sig";
-const char kUdevSubsystemDevCoredump[] = "devcoredump";
-const char kDefaultDevCoredumpDirectory[] = "/sys/class/devcoredump";
-const char kDevCoredumpFilePrefixFormat[] = "devcoredump_%s";
-
-}  // namespace
-
-UdevCollector::UdevCollector()
-    : dev_coredump_directory_(kDefaultDevCoredumpDirectory) {}
-
-UdevCollector::~UdevCollector() {}
-
-bool UdevCollector::HandleCrash(const std::string &udev_event) {
-  if (IsDeveloperImage()) {
-    LOG(INFO) << "developer image - collect udev crash info.";
-  } else if (is_feedback_allowed_function_()) {
-    LOG(INFO) << "Consent given - collect udev crash info.";
-  } else {
-    LOG(INFO) << "Ignoring - Non-developer image and no consent given.";
-    return false;
-  }
-
-  // Process the udev event string.
-  // First get all the key-value pairs.
-  std::vector<std::pair<std::string, std::string>> udev_event_keyval;
-  base::SplitStringIntoKeyValuePairs(udev_event, '=', ':', &udev_event_keyval);
-  std::vector<std::pair<std::string, std::string>>::const_iterator iter;
-  std::map<std::string, std::string> udev_event_map;
-  for (iter = udev_event_keyval.begin();
-       iter != udev_event_keyval.end();
-       ++iter) {
-    udev_event_map[iter->first] = iter->second;
-  }
-
-  // Make sure the crash directory exists, or create it if it doesn't.
-  FilePath crash_directory;
-  if (!GetCreatedCrashDirectoryByEuid(0, &crash_directory, nullptr)) {
-    LOG(ERROR) << "Could not get crash directory.";
-    return false;
-  }
-
-  if (udev_event_map["SUBSYSTEM"] == kUdevSubsystemDevCoredump) {
-    int instance_number;
-    if (!base::StringToInt(udev_event_map["KERNEL_NUMBER"], &instance_number)) {
-      LOG(ERROR) << "Invalid kernel number: "
-                 << udev_event_map["KERNEL_NUMBER"];
-      return false;
-    }
-    return ProcessDevCoredump(crash_directory, instance_number);
-  }
-
-  return ProcessUdevCrashLogs(crash_directory,
-                              udev_event_map["ACTION"],
-                              udev_event_map["KERNEL"],
-                              udev_event_map["SUBSYSTEM"]);
-}
-
-bool UdevCollector::ProcessUdevCrashLogs(const FilePath& crash_directory,
-                                         const std::string& action,
-                                         const std::string& kernel,
-                                         const std::string& subsystem) {
-  // Construct the basename string for crash_reporter_logs.conf:
-  //   "crash_reporter-udev-collection-[action]-[name]-[subsystem]"
-  // If a udev field is not provided, "" is used in its place, e.g.:
-  //   "crash_reporter-udev-collection-[action]--[subsystem]"
-  // Hence, "" is used as a wildcard name string.
-  // TODO(sque, crosbug.com/32238): Implement wildcard checking.
-  std::string basename = action + "-" + kernel + "-" + subsystem;
-  std::string udev_log_name = std::string(kCollectUdevSignature) + '-' +
-                              basename;
-
-  // Create the destination path.
-  std::string log_file_name =
-      FormatDumpBasename(basename, time(nullptr), 0);
-  FilePath crash_path = GetCrashPath(crash_directory, log_file_name, "log");
-
-  // Handle the crash.
-  bool result = GetLogContents(log_config_path_, udev_log_name, crash_path);
-  if (!result) {
-    LOG(ERROR) << "Error reading udev log info " << udev_log_name;
-    return false;
-  }
-
-  // Compress the output using gzip.
-  brillo::ProcessImpl gzip_process;
-  gzip_process.AddArg(kGzipPath);
-  gzip_process.AddArg(crash_path.value());
-  int process_result = gzip_process.Run();
-  FilePath crash_path_zipped = FilePath(crash_path.value() + ".gz");
-  // If the zip file was not created, use the uncompressed file.
-  if (process_result != 0 || !base::PathExists(crash_path_zipped))
-    LOG(ERROR) << "Could not create zip file " << crash_path_zipped.value();
-  else
-    crash_path = crash_path_zipped;
-
-  std::string exec_name = std::string(kUdevExecName) + "-" + subsystem;
-  AddCrashMetaData(kUdevSignatureKey, udev_log_name);
-  WriteCrashMetaData(GetCrashPath(crash_directory, log_file_name, "meta"),
-                     exec_name, crash_path.value());
-  return true;
-}
-
-bool UdevCollector::ProcessDevCoredump(const FilePath& crash_directory,
-                                       int instance_number) {
-  FilePath coredump_path =
-      FilePath(base::StringPrintf("%s/devcd%d/data",
-                                  dev_coredump_directory_.c_str(),
-                                  instance_number));
-  if (!base::PathExists(coredump_path)) {
-    LOG(ERROR) << "Device coredump file " << coredump_path.value()
-               << " does not exist";
-    return false;
-  }
-
-  // Add coredump file to the crash directory.
-  if (!AppendDevCoredump(crash_directory, coredump_path, instance_number)) {
-    ClearDevCoredump(coredump_path);
-    return false;
-  }
-
-  // Clear the coredump data to allow generation of future device coredumps
-  // without having to wait for the 5-minutes timeout.
-  return ClearDevCoredump(coredump_path);
-}
-
-bool UdevCollector::AppendDevCoredump(const FilePath& crash_directory,
-                                      const FilePath& coredump_path,
-                                      int instance_number) {
-  // Retrieve the driver name of the failing device.
-  std::string driver_name = GetFailingDeviceDriverName(instance_number);
-  if (driver_name.empty()) {
-    LOG(ERROR) << "Failed to obtain driver name for instance: "
-               << instance_number;
-    return false;
-  }
-
-  std::string coredump_prefix =
-      base::StringPrintf(kDevCoredumpFilePrefixFormat, driver_name.c_str());
-
-  std::string dump_basename = FormatDumpBasename(coredump_prefix,
-                                                 time(nullptr),
-                                                 instance_number);
-  FilePath core_path = GetCrashPath(crash_directory, dump_basename, "devcore");
-  FilePath log_path = GetCrashPath(crash_directory, dump_basename, "log");
-  FilePath meta_path = GetCrashPath(crash_directory, dump_basename, "meta");
-
-  // Collect coredump data.
-  if (!base::CopyFile(coredump_path, core_path)) {
-    LOG(ERROR) << "Failed to copy device coredumpm file from "
-               << coredump_path.value() << " to " << core_path.value();
-    return false;
-  }
-
-  // Collect additional logs if one is specified in the config file.
-  std::string udev_log_name = std::string(kCollectUdevSignature) + '-' +
-      kUdevSubsystemDevCoredump + '-' + driver_name;
-  bool result = GetLogContents(log_config_path_, udev_log_name, log_path);
-  if (result) {
-    AddCrashMetaUploadFile("logs", log_path.value());
-  }
-
-  WriteCrashMetaData(meta_path, coredump_prefix, core_path.value());
-
-  return true;
-}
-
-bool UdevCollector::ClearDevCoredump(const FilePath& coredump_path) {
-  if (!base::WriteFile(coredump_path, "0", 1)) {
-    LOG(ERROR) << "Failed to delete the coredump data file "
-               << coredump_path.value();
-    return false;
-  }
-  return true;
-}
-
-std::string UdevCollector::GetFailingDeviceDriverName(int instance_number) {
-  FilePath failing_uevent_path =
-      FilePath(base::StringPrintf("%s/devcd%d/failing_device/uevent",
-                                  dev_coredump_directory_.c_str(),
-                                  instance_number));
-  if (!base::PathExists(failing_uevent_path)) {
-    LOG(ERROR) << "Failing uevent path " << failing_uevent_path.value()
-               << " does not exist";
-    return "";
-  }
-
-  std::string uevent_content;
-  if (!base::ReadFileToString(failing_uevent_path, &uevent_content)) {
-    LOG(ERROR) << "Failed to read uevent file " << failing_uevent_path.value();
-    return "";
-  }
-
-  // Parse uevent file contents as key-value pairs.
-  std::vector<std::pair<std::string, std::string>> uevent_keyval;
-  base::SplitStringIntoKeyValuePairs(uevent_content, '=', '\n', &uevent_keyval);
-  std::vector<std::pair<std::string, std::string>>::const_iterator iter;
-  for (iter = uevent_keyval.begin();
-       iter != uevent_keyval.end();
-       ++iter) {
-    if (iter->first == "DRIVER") {
-      return iter->second;
-    }
-  }
-
-  return "";
-}
diff --git a/crash_reporter/udev_collector.h b/crash_reporter/udev_collector.h
deleted file mode 100644
index e267b75..0000000
--- a/crash_reporter/udev_collector.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2012 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 CRASH_REPORTER_UDEV_COLLECTOR_H_
-#define CRASH_REPORTER_UDEV_COLLECTOR_H_
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Udev crash collector.
-class UdevCollector : public CrashCollector {
- public:
-  UdevCollector();
-
-  ~UdevCollector() override;
-
-  // The udev event string should be formatted as follows:
-  //   "ACTION=[action]:KERNEL=[name]:SUBSYSTEM=[subsystem]"
-  // The values don't have to be in any particular order. One or more of them
-  // could be omitted, in which case it would be treated as a wildcard (*).
-  bool HandleCrash(const std::string& udev_event);
-
- protected:
-  std::string dev_coredump_directory_;
-
- private:
-  friend class UdevCollectorTest;
-
-  // Process udev crash logs, collecting log files according to the config
-  // file (crash_reporter_logs.conf).
-  bool ProcessUdevCrashLogs(const base::FilePath& crash_directory,
-                            const std::string& action,
-                            const std::string& kernel,
-                            const std::string& subsystem);
-  // Process device coredump, collecting device coredump file.
-  // |instance_number| is the kernel number of the virtual device for the device
-  // coredump instance.
-  bool ProcessDevCoredump(const base::FilePath& crash_directory,
-                          int instance_number);
-  // Copy device coredump file to crash directory, and perform necessary
-  // coredump file management.
-  bool AppendDevCoredump(const base::FilePath& crash_directory,
-                         const base::FilePath& coredump_path,
-                         int instance_number);
-  // Clear the device coredump file by performing a dummy write to it.
-  bool ClearDevCoredump(const base::FilePath& coredump_path);
-  // Return the driver name of the device that generates the coredump.
-  std::string GetFailingDeviceDriverName(int instance_number);
-
-  // Mutator for unit testing.
-  void set_log_config_path(const std::string& path) {
-    log_config_path_ = base::FilePath(path);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(UdevCollector);
-};
-
-#endif  // CRASH_REPORTER_UDEV_COLLECTOR_H_
diff --git a/crash_reporter/udev_collector_test.cc b/crash_reporter/udev_collector_test.cc
deleted file mode 100644
index 5474f48..0000000
--- a/crash_reporter/udev_collector_test.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2012 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 <base/files/file_enumerator.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/syslog_logging.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "udev_collector.h"
-
-using base::FilePath;
-
-namespace {
-
-// Dummy log config file name.
-const char kLogConfigFileName[] = "log_config_file";
-
-// Dummy directory for storing device coredumps.
-const char kDevCoredumpDirectory[] = "devcoredump";
-
-// A bunch of random rules to put into the dummy log config file.
-const char kLogConfigFileContents[] =
-    "crash_reporter-udev-collection-change-card0-drm=echo change card0 drm\n"
-    "crash_reporter-udev-collection-add-state0-cpu=echo change state0 cpu\n"
-    "crash_reporter-udev-collection-devcoredump-iwlwifi=echo devcoredump\n"
-    "cros_installer=echo not for udev";
-
-const char kCrashLogFilePattern[] = "*.log.gz";
-const char kDevCoredumpFilePattern[] = "*.devcore";
-
-// Dummy content for device coredump data file.
-const char kDevCoredumpDataContents[] = "coredump";
-
-// Content for failing device's uevent file.
-const char kFailingDeviceUeventContents[] = "DRIVER=iwlwifi\n";
-
-void CountCrash() {}
-
-bool s_consent_given = true;
-
-bool IsMetrics() {
-  return s_consent_given;
-}
-
-// Returns the number of files found in the given path that matches the
-// specified file name pattern.
-int GetNumFiles(const FilePath& path, const std::string& file_pattern) {
-  base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
-                                  file_pattern);
-  int num_files = 0;
-  for (FilePath file_path = enumerator.Next();
-       !file_path.value().empty();
-       file_path = enumerator.Next()) {
-    num_files++;
-  }
-  return num_files;
-}
-
-}  // namespace
-
-class UdevCollectorMock : public UdevCollector {
- public:
-  MOCK_METHOD0(SetUpDBus, void());
-};
-
-class UdevCollectorTest : public ::testing::Test {
- protected:
-  base::ScopedTempDir temp_dir_generator_;
-
-  void HandleCrash(const std::string &udev_event) {
-    collector_.HandleCrash(udev_event);
-  }
-
-  void GenerateDevCoredump(const std::string& device_name) {
-    // Generate coredump data file.
-    ASSERT_TRUE(CreateDirectory(
-        FilePath(base::StringPrintf("%s/%s",
-                                    collector_.dev_coredump_directory_.c_str(),
-                                    device_name.c_str()))));
-    FilePath data_path =
-        FilePath(base::StringPrintf("%s/%s/data",
-                                    collector_.dev_coredump_directory_.c_str(),
-                                    device_name.c_str()));
-    ASSERT_EQ(strlen(kDevCoredumpDataContents),
-              base::WriteFile(data_path,
-                              kDevCoredumpDataContents,
-                              strlen(kDevCoredumpDataContents)));
-    // Generate uevent file for failing device.
-    ASSERT_TRUE(CreateDirectory(
-        FilePath(base::StringPrintf("%s/%s/failing_device",
-                                    collector_.dev_coredump_directory_.c_str(),
-                                    device_name.c_str()))));
-    FilePath uevent_path =
-        FilePath(base::StringPrintf("%s/%s/failing_device/uevent",
-                                    collector_.dev_coredump_directory_.c_str(),
-                                    device_name.c_str()));
-    ASSERT_EQ(strlen(kFailingDeviceUeventContents),
-              base::WriteFile(uevent_path,
-                              kFailingDeviceUeventContents,
-                              strlen(kFailingDeviceUeventContents)));
-  }
-
- private:
-  void SetUp() override {
-    s_consent_given = true;
-
-    EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
-    collector_.Initialize(CountCrash, IsMetrics);
-
-    ASSERT_TRUE(temp_dir_generator_.CreateUniqueTempDir());
-
-    FilePath log_config_path =
-        temp_dir_generator_.path().Append(kLogConfigFileName);
-    collector_.log_config_path_ = log_config_path;
-    collector_.ForceCrashDirectory(temp_dir_generator_.path());
-
-    FilePath dev_coredump_path =
-        temp_dir_generator_.path().Append(kDevCoredumpDirectory);
-    collector_.dev_coredump_directory_ = dev_coredump_path.value();
-
-    // Write to a dummy log config file.
-    ASSERT_EQ(strlen(kLogConfigFileContents),
-              base::WriteFile(log_config_path,
-                              kLogConfigFileContents,
-                              strlen(kLogConfigFileContents)));
-
-    brillo::ClearLog();
-  }
-
-  UdevCollectorMock collector_;
-};
-
-TEST_F(UdevCollectorTest, TestNoConsent) {
-  s_consent_given = false;
-  HandleCrash("ACTION=change:KERNEL=card0:SUBSYSTEM=drm");
-  EXPECT_EQ(0, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
-}
-
-TEST_F(UdevCollectorTest, TestNoMatch) {
-  // No rule should match this.
-  HandleCrash("ACTION=change:KERNEL=foo:SUBSYSTEM=bar");
-  EXPECT_EQ(0, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
-}
-
-TEST_F(UdevCollectorTest, TestMatches) {
-  // Try multiple udev events in sequence.  The number of log files generated
-  // should increase.
-  HandleCrash("ACTION=change:KERNEL=card0:SUBSYSTEM=drm");
-  EXPECT_EQ(1, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
-  HandleCrash("ACTION=add:KERNEL=state0:SUBSYSTEM=cpu");
-  EXPECT_EQ(2, GetNumFiles(temp_dir_generator_.path(), kCrashLogFilePattern));
-}
-
-TEST_F(UdevCollectorTest, TestDevCoredump) {
-  GenerateDevCoredump("devcd0");
-  HandleCrash("ACTION=add:KERNEL_NUMBER=0:SUBSYSTEM=devcoredump");
-  EXPECT_EQ(1, GetNumFiles(temp_dir_generator_.path(),
-                           kDevCoredumpFilePattern));
-  GenerateDevCoredump("devcd1");
-  HandleCrash("ACTION=add:KERNEL_NUMBER=1:SUBSYSTEM=devcoredump");
-  EXPECT_EQ(2, GetNumFiles(temp_dir_generator_.path(),
-                           kDevCoredumpFilePattern));
-}
-
-// TODO(sque, crosbug.com/32238) - test wildcard cases, multiple identical udev
-// events.
diff --git a/crash_reporter/unclean_shutdown_collector.cc b/crash_reporter/unclean_shutdown_collector.cc
deleted file mode 100644
index 8a092ec..0000000
--- a/crash_reporter/unclean_shutdown_collector.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010 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 "unclean_shutdown_collector.h"
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-
-static const char kUncleanShutdownFile[] =
-    "/var/lib/crash_reporter/pending_clean_shutdown";
-
-// Files created by power manager used for crash reporting.
-static const char kPowerdTracePath[] = "/var/lib/power_manager";
-// Presence of this file indicates that the system was suspended
-static const char kPowerdSuspended[] = "powerd_suspended";
-
-using base::FilePath;
-
-UncleanShutdownCollector::UncleanShutdownCollector()
-    : unclean_shutdown_file_(kUncleanShutdownFile),
-      powerd_trace_path_(kPowerdTracePath),
-      powerd_suspended_file_(powerd_trace_path_.Append(kPowerdSuspended)) {
-}
-
-UncleanShutdownCollector::~UncleanShutdownCollector() {
-}
-
-bool UncleanShutdownCollector::Enable() {
-  FilePath file_path(unclean_shutdown_file_);
-  base::CreateDirectory(file_path.DirName());
-  if (base::WriteFile(file_path, "", 0) != 0) {
-    LOG(ERROR) << "Unable to create shutdown check file";
-    return false;
-  }
-  return true;
-}
-
-bool UncleanShutdownCollector::DeleteUncleanShutdownFiles() {
-  if (!base::DeleteFile(FilePath(unclean_shutdown_file_), false)) {
-    LOG(ERROR) << "Failed to delete unclean shutdown file "
-               << unclean_shutdown_file_;
-    return false;
-  }
-  // Delete power manager state file if it exists.
-  base::DeleteFile(powerd_suspended_file_, false);
-  return true;
-}
-
-bool UncleanShutdownCollector::Collect() {
-  FilePath unclean_file_path(unclean_shutdown_file_);
-  if (!base::PathExists(unclean_file_path)) {
-    return false;
-  }
-  LOG(WARNING) << "Last shutdown was not clean";
-  if (DeadBatteryCausedUncleanShutdown()) {
-    DeleteUncleanShutdownFiles();
-    return false;
-  }
-  DeleteUncleanShutdownFiles();
-
-  if (is_feedback_allowed_function_()) {
-    count_crash_function_();
-  }
-  return true;
-}
-
-bool UncleanShutdownCollector::Disable() {
-  LOG(INFO) << "Clean shutdown signalled";
-  return DeleteUncleanShutdownFiles();
-}
-
-bool UncleanShutdownCollector::DeadBatteryCausedUncleanShutdown() {
-  // Check for case of battery running out while suspended.
-  if (base::PathExists(powerd_suspended_file_)) {
-    LOG(INFO) << "Unclean shutdown occurred while suspended. Not counting "
-              << "toward unclean shutdown statistic.";
-    return true;
-  }
-  return false;
-}
diff --git a/crash_reporter/unclean_shutdown_collector.h b/crash_reporter/unclean_shutdown_collector.h
deleted file mode 100644
index 5bc9968..0000000
--- a/crash_reporter/unclean_shutdown_collector.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010 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 CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
-#define CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-// Unclean shutdown collector.
-class UncleanShutdownCollector : public CrashCollector {
- public:
-  UncleanShutdownCollector();
-  ~UncleanShutdownCollector() override;
-
-  // Enable collection - signal that a boot has started.
-  bool Enable();
-
-  // Collect if there is was an unclean shutdown. Returns true if
-  // there was, false otherwise.
-  bool Collect();
-
-  // Disable collection - signal that the system has been shutdown cleanly.
-  bool Disable();
-
- private:
-  friend class UncleanShutdownCollectorTest;
-  FRIEND_TEST(UncleanShutdownCollectorTest, EnableCannotWrite);
-  FRIEND_TEST(UncleanShutdownCollectorTest, CollectDeadBatterySuspended);
-
-  bool DeleteUncleanShutdownFiles();
-
-  // Check for unclean shutdown due to battery running out by analyzing powerd
-  // trace files.
-  bool DeadBatteryCausedUncleanShutdown();
-
-  const char *unclean_shutdown_file_;
-  base::FilePath powerd_trace_path_;
-  base::FilePath powerd_suspended_file_;
-
-  DISALLOW_COPY_AND_ASSIGN(UncleanShutdownCollector);
-};
-
-#endif  // CRASH_REPORTER_UNCLEAN_SHUTDOWN_COLLECTOR_H_
diff --git a/crash_reporter/unclean_shutdown_collector_test.cc b/crash_reporter/unclean_shutdown_collector_test.cc
deleted file mode 100644
index 36372ae..0000000
--- a/crash_reporter/unclean_shutdown_collector_test.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2010 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 "unclean_shutdown_collector.h"
-
-#include <unistd.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_util.h>
-#include <brillo/syslog_logging.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-using base::FilePath;
-using ::brillo::FindLog;
-
-namespace {
-
-int s_crashes = 0;
-bool s_metrics = true;
-
-void CountCrash() {
-  ++s_crashes;
-}
-
-bool IsMetrics() {
-  return s_metrics;
-}
-
-}  // namespace
-
-class UncleanShutdownCollectorMock : public UncleanShutdownCollector {
- public:
-  MOCK_METHOD0(SetUpDBus, void());
-};
-
-class UncleanShutdownCollectorTest : public ::testing::Test {
-  void SetUp() {
-    s_crashes = 0;
-
-    EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
-    collector_.Initialize(CountCrash,
-                          IsMetrics);
-
-    EXPECT_TRUE(test_dir_.CreateUniqueTempDir());
-
-    test_directory_ = test_dir_.path().Append("test");
-    test_unclean_ = test_dir_.path().Append("test/unclean");
-
-    collector_.unclean_shutdown_file_ = test_unclean_.value().c_str();
-    base::DeleteFile(test_unclean_, true);
-    // Set up an alternate power manager state file as well
-    collector_.powerd_suspended_file_ =
-        test_dir_.path().Append("test/suspended");
-    brillo::ClearLog();
-  }
-
- protected:
-  void WriteStringToFile(const FilePath &file_path,
-                         const char *data) {
-    unsigned int numBytesWritten =
-        base::WriteFile(file_path, data, strlen(data));
-    ASSERT_EQ(strlen(data), numBytesWritten);
-  }
-
-  UncleanShutdownCollectorMock collector_;
-
-  // Temporary directory used for tests.
-  base::ScopedTempDir test_dir_;
-  FilePath test_directory_;
-  FilePath test_unclean_;
-};
-
-TEST_F(UncleanShutdownCollectorTest, EnableWithoutParent) {
-  ASSERT_TRUE(collector_.Enable());
-  ASSERT_TRUE(base::PathExists(test_unclean_));
-}
-
-TEST_F(UncleanShutdownCollectorTest, EnableWithParent) {
-  mkdir(test_directory_.value().c_str(), 0777);
-  ASSERT_TRUE(collector_.Enable());
-  ASSERT_TRUE(base::PathExists(test_unclean_));
-}
-
-TEST_F(UncleanShutdownCollectorTest, EnableCannotWrite) {
-  collector_.unclean_shutdown_file_ = "/bad/path";
-  ASSERT_FALSE(collector_.Enable());
-  ASSERT_TRUE(FindLog("Unable to create shutdown check file"));
-}
-
-TEST_F(UncleanShutdownCollectorTest, CollectTrue) {
-  ASSERT_TRUE(collector_.Enable());
-  ASSERT_TRUE(base::PathExists(test_unclean_));
-  ASSERT_TRUE(collector_.Collect());
-  ASSERT_FALSE(base::PathExists(test_unclean_));
-  ASSERT_EQ(1, s_crashes);
-  ASSERT_TRUE(FindLog("Last shutdown was not clean"));
-}
-
-TEST_F(UncleanShutdownCollectorTest, CollectFalse) {
-  ASSERT_FALSE(collector_.Collect());
-  ASSERT_EQ(0, s_crashes);
-}
-
-TEST_F(UncleanShutdownCollectorTest, CollectDeadBatterySuspended) {
-  ASSERT_TRUE(collector_.Enable());
-  ASSERT_TRUE(base::PathExists(test_unclean_));
-  base::WriteFile(collector_.powerd_suspended_file_, "", 0);
-  ASSERT_FALSE(collector_.Collect());
-  ASSERT_FALSE(base::PathExists(test_unclean_));
-  ASSERT_FALSE(base::PathExists(collector_.powerd_suspended_file_));
-  ASSERT_EQ(0, s_crashes);
-  ASSERT_TRUE(FindLog("Unclean shutdown occurred while suspended."));
-}
-
-TEST_F(UncleanShutdownCollectorTest, Disable) {
-  ASSERT_TRUE(collector_.Enable());
-  ASSERT_TRUE(base::PathExists(test_unclean_));
-  ASSERT_TRUE(collector_.Disable());
-  ASSERT_FALSE(base::PathExists(test_unclean_));
-  ASSERT_FALSE(collector_.Collect());
-}
-
-TEST_F(UncleanShutdownCollectorTest, DisableWhenNotEnabled) {
-  ASSERT_TRUE(collector_.Disable());
-}
-
-TEST_F(UncleanShutdownCollectorTest, CantDisable) {
-  mkdir(test_directory_.value().c_str(), 0700);
-  if (mkdir(test_unclean_.value().c_str(), 0700)) {
-    ASSERT_EQ(EEXIST, errno)
-        << "Error while creating directory '" << test_unclean_.value()
-        << "': " << strerror(errno);
-  }
-  ASSERT_EQ(0, base::WriteFile(test_unclean_.Append("foo"), "", 0))
-      << "Error while creating empty file '"
-      << test_unclean_.Append("foo").value() << "': " << strerror(errno);
-  ASSERT_FALSE(collector_.Disable());
-  rmdir(test_unclean_.value().c_str());
-}
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
deleted file mode 100644
index 48b64e9..0000000
--- a/crash_reporter/user_collector.cc
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright (C) 2012 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 "user_collector.h"
-
-#include <elf.h>
-#include <fcntl.h>
-#include <grp.h>  // For struct group.
-#include <pcrecpp.h>
-#include <pwd.h>  // For struct passwd.
-#include <stdint.h>
-#include <sys/cdefs.h>  // For __WORDSIZE
-#include <sys/fsuid.h>
-#include <sys/types.h>  // For getpwuid_r, getgrnam_r, WEXITSTATUS.
-#include <unistd.h>  // For setgroups
-
-#include <iostream>  // For std::oct
-#include <string>
-#include <vector>
-
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/posix/eintr_wrapper.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/process.h>
-#include <brillo/syslog_logging.h>
-#include <cutils/properties.h>
-#include <private/android_filesystem_config.h>
-
-static const char kCollectionErrorSignature[] =
-    "crash_reporter-user-collection";
-static const char kCorePatternProperty[] = "crash_reporter.coredump.enabled";
-static const char kCoreToMinidumpConverterPath[] = "/system/bin/core2md";
-
-static const char kStatePrefix[] = "State:\t";
-
-static const char kCoreTempFolder[] = "/data/misc/crash_reporter/tmp";
-
-// Define an otherwise invalid value that represents an unknown UID and GID.
-static const uid_t kUnknownUid = -1;
-static const gid_t kUnknownGid = -1;
-
-const char *UserCollector::kUserId = "Uid:\t";
-const char *UserCollector::kGroupId = "Gid:\t";
-
-
-using base::FilePath;
-using base::StringPrintf;
-
-UserCollector::UserCollector()
-    : generate_diagnostics_(false),
-      initialized_(false) {
-}
-
-void UserCollector::Initialize(
-    UserCollector::CountCrashFunction count_crash_function,
-    const std::string &our_path,
-    UserCollector::IsFeedbackAllowedFunction is_feedback_allowed_function,
-    bool generate_diagnostics,
-    bool core2md_failure,
-    bool directory_failure,
-    const std::string &filter_in) {
-  CrashCollector::Initialize(count_crash_function,
-                             is_feedback_allowed_function);
-  our_path_ = our_path;
-  initialized_ = true;
-  generate_diagnostics_ = generate_diagnostics;
-  core2md_failure_ = core2md_failure;
-  directory_failure_ = directory_failure;
-  filter_in_ = filter_in;
-
-  gid_t groups[] = { AID_ROOT, AID_SYSTEM, AID_DBUS, AID_READPROC };
-  if (setgroups(arraysize(groups), groups) != 0) {
-    PLOG(FATAL) << "Unable to set groups to root, system, dbus, and readproc";
-  }
-}
-
-UserCollector::~UserCollector() {
-}
-
-std::string UserCollector::GetErrorTypeSignature(ErrorType error_type) const {
-  switch (error_type) {
-    case kErrorSystemIssue:
-      return "system-issue";
-    case kErrorReadCoreData:
-      return "read-core-data";
-    case kErrorUnusableProcFiles:
-      return "unusable-proc-files";
-    case kErrorInvalidCoreFile:
-      return "invalid-core-file";
-    case kErrorUnsupported32BitCoreFile:
-      return "unsupported-32bit-core-file";
-    case kErrorCore2MinidumpConversion:
-      return "core2md-conversion";
-    default:
-      return "";
-  }
-}
-
-bool UserCollector::SetUpInternal(bool enabled) {
-  CHECK(initialized_);
-  LOG(INFO) << (enabled ? "Enabling" : "Disabling") << " user crash handling";
-
-  property_set(kCorePatternProperty, enabled ? "1" : "0");
-
-  return true;
-}
-
-bool UserCollector::GetFirstLineWithPrefix(
-    const std::vector<std::string> &lines,
-    const char *prefix, std::string *line) {
-  std::vector<std::string>::const_iterator line_iterator;
-  for (line_iterator = lines.begin(); line_iterator != lines.end();
-       ++line_iterator) {
-    if (line_iterator->find(prefix) == 0) {
-      *line = *line_iterator;
-      return true;
-    }
-  }
-  return false;
-}
-
-bool UserCollector::GetIdFromStatus(
-    const char *prefix, IdKind kind,
-    const std::vector<std::string> &status_lines, int *id) {
-  // From fs/proc/array.c:task_state(), this file contains:
-  // \nUid:\t<uid>\t<euid>\t<suid>\t<fsuid>\n
-  std::string id_line;
-  if (!GetFirstLineWithPrefix(status_lines, prefix, &id_line)) {
-    return false;
-  }
-  std::string id_substring = id_line.substr(strlen(prefix), std::string::npos);
-  std::vector<std::string> ids = base::SplitString(
-      id_substring, "\t", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-  if (ids.size() != kIdMax || kind < 0 || kind >= kIdMax) {
-    return false;
-  }
-  const char *number = ids[kind].c_str();
-  char *end_number = nullptr;
-  *id = strtol(number, &end_number, 10);
-  if (*end_number != '\0') {
-    return false;
-  }
-  return true;
-}
-
-bool UserCollector::GetStateFromStatus(
-    const std::vector<std::string> &status_lines, std::string *state) {
-  std::string state_line;
-  if (!GetFirstLineWithPrefix(status_lines, kStatePrefix, &state_line)) {
-    return false;
-  }
-  *state = state_line.substr(strlen(kStatePrefix), std::string::npos);
-  return true;
-}
-
-void UserCollector::EnqueueCollectionErrorLog(pid_t pid,
-                                              ErrorType error_type,
-                                              const std::string &exec) {
-  FilePath crash_path;
-  LOG(INFO) << "Writing conversion problems as separate crash report.";
-  if (!GetCreatedCrashDirectoryByEuid(0, &crash_path, nullptr)) {
-    LOG(ERROR) << "Could not even get log directory; out of space?";
-    return;
-  }
-  AddCrashMetaData("sig", kCollectionErrorSignature);
-  AddCrashMetaData("error_type", GetErrorTypeSignature(error_type));
-  std::string dump_basename = FormatDumpBasename(exec, time(nullptr), pid);
-  std::string error_log = brillo::GetLog();
-  FilePath diag_log_path = GetCrashPath(crash_path, dump_basename, "diaglog");
-  if (GetLogContents(FilePath(log_config_path_), kCollectionErrorSignature,
-                     diag_log_path)) {
-    // We load the contents of diag_log into memory and append it to
-    // the error log.  We cannot just append to files because we need
-    // to always create new files to prevent attack.
-    std::string diag_log_contents;
-    base::ReadFileToString(diag_log_path, &diag_log_contents);
-    error_log.append(diag_log_contents);
-    base::DeleteFile(diag_log_path, false);
-  }
-  FilePath log_path = GetCrashPath(crash_path, dump_basename, "log");
-  FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta");
-  // We must use WriteNewFile instead of base::WriteFile as we do
-  // not want to write with root access to a symlink that an attacker
-  // might have created.
-  if (WriteNewFile(log_path, error_log.data(), error_log.length()) < 0) {
-    LOG(ERROR) << "Error writing new file " << log_path.value();
-    return;
-  }
-  WriteCrashMetaData(meta_path, exec, log_path.value());
-}
-
-bool UserCollector::CopyOffProcFiles(pid_t pid,
-                                     const FilePath &container_dir) {
-  if (!base::CreateDirectory(container_dir)) {
-    PLOG(ERROR) << "Could not create " << container_dir.value();
-    return false;
-  }
-  int dir_mask = base::FILE_PERMISSION_READ_BY_USER
-                 | base::FILE_PERMISSION_WRITE_BY_USER
-                 | base::FILE_PERMISSION_EXECUTE_BY_USER
-                 | base::FILE_PERMISSION_READ_BY_GROUP
-                 | base::FILE_PERMISSION_WRITE_BY_GROUP;
-  if (!base::SetPosixFilePermissions(container_dir,
-                                     base::FILE_PERMISSION_MASK & dir_mask)) {
-    PLOG(ERROR) << "Could not set permissions for " << container_dir.value()
-                << " to " << std::oct
-                << (base::FILE_PERMISSION_MASK & dir_mask);
-    return false;
-  }
-  FilePath process_path = GetProcessPath(pid);
-  if (!base::PathExists(process_path)) {
-    LOG(ERROR) << "Path " << process_path.value() << " does not exist";
-    return false;
-  }
-  static const char *proc_files[] = {
-    "auxv",
-    "cmdline",
-    "environ",
-    "maps",
-    "status"
-  };
-  for (unsigned i = 0; i < arraysize(proc_files); ++i) {
-    if (!base::CopyFile(process_path.Append(proc_files[i]),
-                        container_dir.Append(proc_files[i]))) {
-      LOG(ERROR) << "Could not copy " << proc_files[i] << " file";
-      return false;
-    }
-  }
-  return true;
-}
-
-bool UserCollector::ValidateProcFiles(const FilePath &container_dir) const {
-  // Check if the maps file is empty, which could be due to the crashed
-  // process being reaped by the kernel before finishing a core dump.
-  int64_t file_size = 0;
-  if (!base::GetFileSize(container_dir.Append("maps"), &file_size)) {
-    LOG(ERROR) << "Could not get the size of maps file";
-    return false;
-  }
-  if (file_size == 0) {
-    LOG(ERROR) << "maps file is empty";
-    return false;
-  }
-  return true;
-}
-
-UserCollector::ErrorType UserCollector::ValidateCoreFile(
-    const FilePath &core_path) const {
-  int fd = HANDLE_EINTR(open(core_path.value().c_str(), O_RDONLY));
-  if (fd < 0) {
-    PLOG(ERROR) << "Could not open core file " << core_path.value();
-    return kErrorInvalidCoreFile;
-  }
-
-  char e_ident[EI_NIDENT];
-  bool read_ok = base::ReadFromFD(fd, e_ident, sizeof(e_ident));
-  IGNORE_EINTR(close(fd));
-  if (!read_ok) {
-    LOG(ERROR) << "Could not read header of core file";
-    return kErrorInvalidCoreFile;
-  }
-
-  if (e_ident[EI_MAG0] != ELFMAG0 || e_ident[EI_MAG1] != ELFMAG1 ||
-      e_ident[EI_MAG2] != ELFMAG2 || e_ident[EI_MAG3] != ELFMAG3) {
-    LOG(ERROR) << "Invalid core file";
-    return kErrorInvalidCoreFile;
-  }
-
-#if __WORDSIZE == 64
-  // TODO(benchan, mkrebs): Remove this check once core2md can
-  // handles both 32-bit and 64-bit ELF on a 64-bit platform.
-  if (e_ident[EI_CLASS] == ELFCLASS32) {
-    LOG(ERROR) << "Conversion of 32-bit core file on 64-bit platform is "
-               << "currently not supported";
-    return kErrorUnsupported32BitCoreFile;
-  }
-#endif
-
-  return kErrorNone;
-}
-
-bool UserCollector::GetCreatedCrashDirectory(pid_t pid, uid_t supplied_ruid,
-                                             FilePath *crash_file_path,
-                                             bool *out_of_capacity) {
-  FilePath process_path = GetProcessPath(pid);
-  std::string status;
-  if (directory_failure_) {
-    LOG(ERROR) << "Purposefully failing to create spool directory";
-    return false;
-  }
-
-  uid_t uid;
-  if (base::ReadFileToString(process_path.Append("status"), &status)) {
-    std::vector<std::string> status_lines = base::SplitString(
-        status, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
-    std::string process_state;
-    if (!GetStateFromStatus(status_lines, &process_state)) {
-      LOG(ERROR) << "Could not find process state in status file";
-      return false;
-    }
-    LOG(INFO) << "State of crashed process [" << pid << "]: " << process_state;
-
-    // Get effective UID of crashing process.
-    int id;
-    if (!GetIdFromStatus(kUserId, kIdEffective, status_lines, &id)) {
-      LOG(ERROR) << "Could not find euid in status file";
-      return false;
-    }
-    uid = id;
-  } else if (supplied_ruid != kUnknownUid) {
-    LOG(INFO) << "Using supplied UID " << supplied_ruid
-              << " for crashed process [" << pid
-              << "] due to error reading status file";
-    uid = supplied_ruid;
-  } else {
-    LOG(ERROR) << "Could not read status file and kernel did not supply UID";
-    LOG(INFO) << "Path " << process_path.value() << " DirectoryExists: "
-              << base::DirectoryExists(process_path);
-    return false;
-  }
-
-  if (!GetCreatedCrashDirectoryByEuid(uid, crash_file_path, out_of_capacity)) {
-    LOG(ERROR) << "Could not create crash directory";
-    return false;
-  }
-  return true;
-}
-
-bool UserCollector::CopyStdinToCoreFile(const FilePath &core_path) {
-  // Copy off all stdin to a core file.
-  FilePath stdin_path("/proc/self/fd/0");
-  if (base::CopyFile(stdin_path, core_path)) {
-    return true;
-  }
-
-  PLOG(ERROR) << "Could not write core file";
-  // If the file system was full, make sure we remove any remnants.
-  base::DeleteFile(core_path, false);
-  return false;
-}
-
-bool UserCollector::RunCoreToMinidump(const FilePath &core_path,
-                                      const FilePath &procfs_directory,
-                                      const FilePath &minidump_path,
-                                      const FilePath &temp_directory) {
-  FilePath output_path = temp_directory.Append("output");
-  brillo::ProcessImpl core2md;
-  core2md.RedirectOutput(output_path.value());
-  core2md.AddArg(kCoreToMinidumpConverterPath);
-  core2md.AddArg(core_path.value());
-  core2md.AddArg(procfs_directory.value());
-
-  if (!core2md_failure_) {
-    core2md.AddArg(minidump_path.value());
-  } else {
-    // To test how core2md errors are propagaged, cause an error
-    // by forgetting a required argument.
-  }
-
-  int errorlevel = core2md.Run();
-
-  std::string output;
-  base::ReadFileToString(output_path, &output);
-  if (errorlevel != 0) {
-    LOG(ERROR) << "Problem during " << kCoreToMinidumpConverterPath
-               << " [result=" << errorlevel << "]: " << output;
-    return false;
-  }
-
-  if (!base::PathExists(minidump_path)) {
-    LOG(ERROR) << "Minidump file " << minidump_path.value()
-               << " was not created";
-    return false;
-  }
-  return true;
-}
-
-UserCollector::ErrorType UserCollector::ConvertCoreToMinidump(
-    pid_t pid,
-    const FilePath &container_dir,
-    const FilePath &core_path,
-    const FilePath &minidump_path) {
-  // If proc files are unuable, we continue to read the core file from stdin,
-  // but only skip the core-to-minidump conversion, so that we may still use
-  // the core file for debugging.
-  bool proc_files_usable =
-      CopyOffProcFiles(pid, container_dir) && ValidateProcFiles(container_dir);
-
-  // Switch back to the original UID/GID.
-  gid_t rgid, egid, sgid;
-  if (getresgid(&rgid, &egid, &sgid) != 0) {
-    PLOG(FATAL) << "Unable to read saved gid";
-  }
-  if (setresgid(sgid, sgid, -1) != 0) {
-    PLOG(FATAL) << "Unable to set real group ID back to saved gid";
-  } else {
-    if (getresgid(&rgid, &egid, &sgid) != 0) {
-      // If the groups cannot be read at this point, the rgid variable will
-      // contain the previously read group ID from before changing it.  This
-      // will cause the chown call below to set the incorrect group for
-      // non-root crashes.  But do not treat this as a fatal error, so that
-      // the rest of the collection will continue for potential manual
-      // collection by a developer.
-      PLOG(ERROR) << "Unable to read real group ID after setting it";
-    }
-  }
-
-  uid_t ruid, euid, suid;
-  if (getresuid(&ruid, &euid, &suid) != 0) {
-    PLOG(FATAL) << "Unable to read saved uid";
-  }
-  if (setresuid(suid, suid, -1) != 0) {
-    PLOG(FATAL) << "Unable to set real user ID back to saved uid";
-  } else {
-    if (getresuid(&ruid, &euid, &suid) != 0) {
-      // If the user ID cannot be read at this point, the ruid variable will
-      // contain the previously read user ID from before changing it.  This
-      // will cause the chown call below to set the incorrect user for
-      // non-root crashes.  But do not treat this as a fatal error, so that
-      // the rest of the collection will continue for potential manual
-      // collection by a developer.
-      PLOG(ERROR) << "Unable to read real user ID after setting it";
-    }
-  }
-
-  if (!CopyStdinToCoreFile(core_path)) {
-    return kErrorReadCoreData;
-  }
-
-  if (!proc_files_usable) {
-    LOG(INFO) << "Skipped converting core file to minidump due to "
-              << "unusable proc files";
-    return kErrorUnusableProcFiles;
-  }
-
-  ErrorType error = ValidateCoreFile(core_path);
-  if (error != kErrorNone) {
-    return error;
-  }
-
-  // Chown the temp container directory back to the original user/group that
-  // crash_reporter is run as, so that additional files can be written to
-  // the temp folder.
-  if (chown(container_dir.value().c_str(), ruid, rgid) < 0) {
-    PLOG(ERROR) << "Could not set owner for " << container_dir.value();
-  }
-
-  if (!RunCoreToMinidump(core_path,
-                         container_dir,  // procfs directory
-                         minidump_path,
-                         container_dir)) {  // temporary directory
-    return kErrorCore2MinidumpConversion;
-  }
-
-  LOG(INFO) << "Stored minidump to " << minidump_path.value();
-  return kErrorNone;
-}
-
-UserCollector::ErrorType UserCollector::ConvertAndEnqueueCrash(
-    pid_t pid, const std::string &exec, uid_t supplied_ruid,
-    bool *out_of_capacity) {
-  FilePath crash_path;
-  if (!GetCreatedCrashDirectory(pid, supplied_ruid, &crash_path,
-      out_of_capacity)) {
-    LOG(ERROR) << "Unable to find/create process-specific crash path";
-    return kErrorSystemIssue;
-  }
-
-  // Directory like /tmp/crash_reporter/1234 which contains the
-  // procfs entries and other temporary files used during conversion.
-  FilePath container_dir(StringPrintf("%s/%d", kCoreTempFolder, pid));
-  // Delete a pre-existing directory from crash reporter that may have
-  // been left around for diagnostics from a failed conversion attempt.
-  // If we don't, existing files can cause forking to fail.
-  base::DeleteFile(container_dir, true);
-  std::string dump_basename = FormatDumpBasename(exec, time(nullptr), pid);
-  FilePath core_path = GetCrashPath(crash_path, dump_basename, "core");
-  FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta");
-  FilePath minidump_path = GetCrashPath(crash_path, dump_basename, "dmp");
-  FilePath log_path = GetCrashPath(crash_path, dump_basename, "log");
-
-  if (GetLogContents(FilePath(log_config_path_), exec, log_path))
-    AddCrashMetaData("log", log_path.value());
-
-  ErrorType error_type =
-      ConvertCoreToMinidump(pid, container_dir, core_path, minidump_path);
-  if (error_type != kErrorNone) {
-    LOG(INFO) << "Leaving core file at " << core_path.value()
-              << " due to conversion error";
-    return error_type;
-  }
-
-  // Here we commit to sending this file.  We must not return false
-  // after this point or we will generate a log report as well as a
-  // crash report.
-  WriteCrashMetaData(meta_path,
-                     exec,
-                     minidump_path.value());
-
-  if (!IsDeveloperImage()) {
-    base::DeleteFile(core_path, false);
-  } else {
-    LOG(INFO) << "Leaving core file at " << core_path.value()
-              << " due to developer image";
-  }
-
-  base::DeleteFile(container_dir, true);
-  return kErrorNone;
-}
-
-bool UserCollector::ParseCrashAttributes(const std::string &crash_attributes,
-                                         pid_t *pid, int *signal, uid_t *uid,
-                                         gid_t *gid,
-                                         std::string *kernel_supplied_name) {
-  pcrecpp::RE re("(\\d+):(\\d+):(\\d+):(\\d+):(.*)");
-  if (re.FullMatch(crash_attributes, pid, signal, uid, gid,
-                   kernel_supplied_name))
-    return true;
-
-  LOG(INFO) << "Falling back to parsing crash attributes '"
-            << crash_attributes << "' without UID and GID";
-  pcrecpp::RE re_without_uid("(\\d+):(\\d+):(.*)");
-  *uid = kUnknownUid;
-  *gid = kUnknownGid;
-  return re_without_uid.FullMatch(crash_attributes, pid, signal,
-      kernel_supplied_name);
-}
-
-bool UserCollector::ShouldDump(bool has_owner_consent,
-                               bool is_developer,
-                               std::string *reason) {
-  reason->clear();
-
-  // For developer builds, we always want to keep the crash reports unless
-  // we're testing the crash facilities themselves.  This overrides
-  // feedback.  Crash sending still obeys consent.
-  if (is_developer) {
-    *reason = "developer build - not testing - always dumping";
-    return true;
-  }
-
-  if (!has_owner_consent) {
-    *reason = "ignoring - no consent";
-    return false;
-  }
-
-  *reason = "handling";
-  return true;
-}
-
-bool UserCollector::HandleCrash(const std::string &crash_attributes,
-                                const char *force_exec) {
-  CHECK(initialized_);
-  pid_t pid = 0;
-  int signal = 0;
-  uid_t supplied_ruid = kUnknownUid;
-  gid_t supplied_rgid = kUnknownGid;
-  std::string kernel_supplied_name;
-
-  if (!ParseCrashAttributes(crash_attributes, &pid, &signal, &supplied_ruid,
-                            &supplied_rgid, &kernel_supplied_name)) {
-    LOG(ERROR) << "Invalid parameter: --user=" <<  crash_attributes;
-    return false;
-  }
-
-  // Switch to the group and user that ran the crashing binary in order to
-  // access their /proc files.  Do not set suid/sgid, so that we can switch
-  // back after copying the necessary files.
-  if (setresgid(supplied_rgid, supplied_rgid, -1) != 0) {
-    PLOG(FATAL) << "Unable to set real group ID to access process files";
-  }
-  if (setresuid(supplied_ruid, supplied_ruid, -1) != 0) {
-    PLOG(FATAL) << "Unable to set real user ID to access process files";
-  }
-
-  std::string exec;
-  if (force_exec) {
-    exec.assign(force_exec);
-  } else if (!GetExecutableBaseNameFromPid(pid, &exec)) {
-    // If we cannot find the exec name, use the kernel supplied name.
-    // We don't always use the kernel's since it truncates the name to
-    // 16 characters.
-    exec = StringPrintf("supplied_%s", kernel_supplied_name.c_str());
-  }
-
-  // Allow us to test the crash reporting mechanism successfully even if
-  // other parts of the system crash.
-  if (!filter_in_.empty() &&
-      (filter_in_ == "none" ||
-       filter_in_ != exec)) {
-    // We use a different format message to make it more obvious in tests
-    // which crashes are test generated and which are real.
-    LOG(WARNING) << "Ignoring crash from " << exec << "[" << pid << "] while "
-                 << "filter_in=" << filter_in_ << ".";
-    return true;
-  }
-
-  std::string reason;
-  bool dump = ShouldDump(is_feedback_allowed_function_(),
-                         IsDeveloperImage(),
-                         &reason);
-
-  LOG(WARNING) << "Received crash notification for " << exec << "[" << pid
-               << "] sig " << signal << ", user " << supplied_ruid
-               << " (" << reason << ")";
-
-  if (dump) {
-    count_crash_function_();
-
-    if (generate_diagnostics_) {
-      bool out_of_capacity = false;
-      ErrorType error_type =
-          ConvertAndEnqueueCrash(pid, exec, supplied_ruid, &out_of_capacity);
-      if (error_type != kErrorNone) {
-        if (!out_of_capacity)
-          EnqueueCollectionErrorLog(pid, error_type, exec);
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
diff --git a/crash_reporter/user_collector.h b/crash_reporter/user_collector.h
deleted file mode 100644
index 7261ed4..0000000
--- a/crash_reporter/user_collector.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2010 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 CRASH_REPORTER_USER_COLLECTOR_H_
-#define CRASH_REPORTER_USER_COLLECTOR_H_
-
-#include <string>
-#include <vector>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-#include "crash_collector.h"
-
-class SystemLogging;
-
-// User crash collector.
-class UserCollector : public CrashCollector {
- public:
-  UserCollector();
-
-  // Initialize the user crash collector for detection of crashes,
-  // given a crash counting function, the path to this executable,
-  // metrics collection enabled oracle, and system logger facility.
-  // Crash detection/reporting is not enabled until Enable is called.
-  // |generate_diagnostics| is used to indicate whether or not to try
-  // to generate a minidump from crashes.
-  void Initialize(CountCrashFunction count_crash,
-                  const std::string &our_path,
-                  IsFeedbackAllowedFunction is_metrics_allowed,
-                  bool generate_diagnostics,
-                  bool core2md_failure,
-                  bool directory_failure,
-                  const std::string &filter_in);
-
-  ~UserCollector() override;
-
-  // Enable collection.
-  bool Enable() { return SetUpInternal(true); }
-
-  // Disable collection.
-  bool Disable() { return SetUpInternal(false); }
-
-  // Handle a specific user crash.  Returns true on success.
-  bool HandleCrash(const std::string &crash_attributes,
-                   const char *force_exec);
-
- private:
-  friend class UserCollectorTest;
-  FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPath);
-  FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPid);
-  FRIEND_TEST(UserCollectorTest, CopyOffProcFilesOK);
-  FRIEND_TEST(UserCollectorTest, GetExecutableBaseNameFromPid);
-  FRIEND_TEST(UserCollectorTest, GetFirstLineWithPrefix);
-  FRIEND_TEST(UserCollectorTest, GetIdFromStatus);
-  FRIEND_TEST(UserCollectorTest, GetStateFromStatus);
-  FRIEND_TEST(UserCollectorTest, GetProcessPath);
-  FRIEND_TEST(UserCollectorTest, GetSymlinkTarget);
-  FRIEND_TEST(UserCollectorTest, GetUserInfoFromName);
-  FRIEND_TEST(UserCollectorTest, ParseCrashAttributes);
-  FRIEND_TEST(UserCollectorTest, ShouldDumpChromeOverridesDeveloperImage);
-  FRIEND_TEST(UserCollectorTest, ShouldDumpDeveloperImageOverridesConsent);
-  FRIEND_TEST(UserCollectorTest, ShouldDumpUseConsentProductionImage);
-  FRIEND_TEST(UserCollectorTest, ValidateProcFiles);
-  FRIEND_TEST(UserCollectorTest, ValidateCoreFile);
-
-  // Enumeration to pass to GetIdFromStatus.  Must match the order
-  // that the kernel lists IDs in the status file.
-  enum IdKind {
-    kIdReal = 0,  // uid and gid
-    kIdEffective = 1,  // euid and egid
-    kIdSet = 2,  // suid and sgid
-    kIdFileSystem = 3,  // fsuid and fsgid
-    kIdMax
-  };
-
-  enum ErrorType {
-    kErrorNone,
-    kErrorSystemIssue,
-    kErrorReadCoreData,
-    kErrorUnusableProcFiles,
-    kErrorInvalidCoreFile,
-    kErrorUnsupported32BitCoreFile,
-    kErrorCore2MinidumpConversion,
-  };
-
-  static const int kForkProblem = 255;
-
-  // Returns an error type signature for a given |error_type| value,
-  // which is reported to the crash server along with the
-  // crash_reporter-user-collection signature.
-  std::string GetErrorTypeSignature(ErrorType error_type) const;
-
-  bool SetUpInternal(bool enabled);
-
-  // Returns, via |line|, the first line in |lines| that starts with |prefix|.
-  // Returns true if a line is found, or false otherwise.
-  bool GetFirstLineWithPrefix(const std::vector<std::string> &lines,
-                              const char *prefix, std::string *line);
-
-  // Returns the identifier of |kind|, via |id|, found in |status_lines| on
-  // the line starting with |prefix|. |status_lines| contains the lines in
-  // the status file. Returns true if the identifier can be determined.
-  bool GetIdFromStatus(const char *prefix,
-                       IdKind kind,
-                       const std::vector<std::string> &status_lines,
-                       int *id);
-
-  // Returns the process state, via |state|, found in |status_lines|, which
-  // contains the lines in the status file. Returns true if the process state
-  // can be determined.
-  bool GetStateFromStatus(const std::vector<std::string> &status_lines,
-                          std::string *state);
-
-  void LogCollectionError(const std::string &error_message);
-  void EnqueueCollectionErrorLog(pid_t pid, ErrorType error_type,
-                                 const std::string &exec_name);
-
-  bool CopyOffProcFiles(pid_t pid, const base::FilePath &container_dir);
-
-  // Validates the proc files at |container_dir| and returns true if they
-  // are usable for the core-to-minidump conversion later. For instance, if
-  // a process is reaped by the kernel before the copying of its proc files
-  // takes place, some proc files like /proc/<pid>/maps may contain nothing
-  // and thus become unusable.
-  bool ValidateProcFiles(const base::FilePath &container_dir) const;
-
-  // Validates the core file at |core_path| and returns kErrorNone if
-  // the file contains the ELF magic bytes and an ELF class that matches the
-  // platform (i.e. 32-bit ELF on a 32-bit platform or 64-bit ELF on a 64-bit
-  // platform), which is due to the limitation in core2md. It returns an error
-  // type otherwise.
-  ErrorType ValidateCoreFile(const base::FilePath &core_path) const;
-
-  // Determines the crash directory for given pid based on pid's owner,
-  // and creates the directory if necessary with appropriate permissions.
-  // Returns true whether or not directory needed to be created, false on
-  // any failure.
-  bool GetCreatedCrashDirectory(pid_t pid, uid_t supplied_ruid,
-                                base::FilePath *crash_file_path,
-                                bool *out_of_capacity);
-  bool CopyStdinToCoreFile(const base::FilePath &core_path);
-  bool RunCoreToMinidump(const base::FilePath &core_path,
-                         const base::FilePath &procfs_directory,
-                         const base::FilePath &minidump_path,
-                         const base::FilePath &temp_directory);
-  ErrorType ConvertCoreToMinidump(pid_t pid,
-                                  const base::FilePath &container_dir,
-                                  const base::FilePath &core_path,
-                                  const base::FilePath &minidump_path);
-  ErrorType ConvertAndEnqueueCrash(pid_t pid, const std::string &exec_name,
-                                   uid_t supplied_ruid, bool *out_of_capacity);
-  bool ParseCrashAttributes(const std::string &crash_attributes,
-                            pid_t *pid, int *signal, uid_t *uid, gid_t *gid,
-                            std::string *kernel_supplied_name);
-
-  bool ShouldDump(bool has_owner_consent,
-                  bool is_developer,
-                  std::string *reason);
-
-  bool generate_diagnostics_;
-  std::string our_path_;
-  bool initialized_;
-
-  bool core2md_failure_;
-  bool directory_failure_;
-  std::string filter_in_;
-
-  static const char *kUserId;
-  static const char *kGroupId;
-
-  DISALLOW_COPY_AND_ASSIGN(UserCollector);
-};
-
-#endif  // CRASH_REPORTER_USER_COLLECTOR_H_
diff --git a/crash_reporter/user_collector_test.cc b/crash_reporter/user_collector_test.cc
deleted file mode 100644
index 16a5cd5..0000000
--- a/crash_reporter/user_collector_test.cc
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * Copyright (C) 2012 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 "user_collector.h"
-
-#include <elf.h>
-#include <sys/cdefs.h>  // For __WORDSIZE
-#include <unistd.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_split.h>
-#include <brillo/syslog_logging.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-using base::FilePath;
-using brillo::FindLog;
-
-namespace {
-
-int s_crashes = 0;
-bool s_metrics = false;
-
-const char kFilePath[] = "/my/path";
-
-void CountCrash() {
-  ++s_crashes;
-}
-
-bool IsMetrics() {
-  return s_metrics;
-}
-
-}  // namespace
-
-class UserCollectorMock : public UserCollector {
- public:
-  MOCK_METHOD0(SetUpDBus, void());
-};
-
-class UserCollectorTest : public ::testing::Test {
-  void SetUp() {
-    s_crashes = 0;
-
-    EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
-
-    collector_.Initialize(CountCrash,
-                          kFilePath,
-                          IsMetrics,
-                          false,
-                          false,
-                          false,
-                          "");
-
-    EXPECT_TRUE(test_dir_.CreateUniqueTempDir());
-
-    mkdir(test_dir_.path().Append("test").value().c_str(), 0777);
-    pid_ = getpid();
-    brillo::ClearLog();
-  }
-
- protected:
-  void ExpectFileEquals(const char *golden,
-                        const FilePath &file_path) {
-    std::string contents;
-    EXPECT_TRUE(base::ReadFileToString(file_path, &contents));
-    EXPECT_EQ(golden, contents);
-  }
-
-  std::vector<std::string> SplitLines(const std::string &lines) const {
-    return base::SplitString(lines, "\n", base::TRIM_WHITESPACE,
-                             base::SPLIT_WANT_ALL);
-  }
-
-  UserCollectorMock collector_;
-  pid_t pid_;
-  base::ScopedTempDir test_dir_;
-};
-
-TEST_F(UserCollectorTest, ParseCrashAttributes) {
-  pid_t pid;
-  int signal;
-  uid_t uid;
-  gid_t gid;
-  std::string exec_name;
-  EXPECT_TRUE(collector_.ParseCrashAttributes("123456:11:1000:2000:foobar",
-      &pid, &signal, &uid, &gid, &exec_name));
-  EXPECT_EQ(123456, pid);
-  EXPECT_EQ(11, signal);
-  EXPECT_EQ(1000U, uid);
-  EXPECT_EQ(2000U, gid);
-  EXPECT_EQ("foobar", exec_name);
-  EXPECT_TRUE(collector_.ParseCrashAttributes("4321:6:barfoo",
-      &pid, &signal, &uid, &gid, &exec_name));
-  EXPECT_EQ(4321, pid);
-  EXPECT_EQ(6, signal);
-  EXPECT_EQ(-1U, uid);
-  EXPECT_EQ(-1U, gid);
-  EXPECT_EQ("barfoo", exec_name);
-
-  EXPECT_FALSE(collector_.ParseCrashAttributes("123456:11",
-      &pid, &signal, &uid, &gid, &exec_name));
-
-  EXPECT_TRUE(collector_.ParseCrashAttributes("123456:11:exec:extra",
-      &pid, &signal, &uid, &gid, &exec_name));
-  EXPECT_EQ("exec:extra", exec_name);
-
-  EXPECT_FALSE(collector_.ParseCrashAttributes("12345p:11:foobar",
-      &pid, &signal, &uid, &gid, &exec_name));
-
-  EXPECT_FALSE(collector_.ParseCrashAttributes("123456:1 :foobar",
-      &pid, &signal, &uid, &gid, &exec_name));
-
-  EXPECT_FALSE(collector_.ParseCrashAttributes("123456::foobar",
-      &pid, &signal, &uid, &gid, &exec_name));
-}
-
-TEST_F(UserCollectorTest, ShouldDumpDeveloperImageOverridesConsent) {
-  std::string reason;
-  EXPECT_TRUE(collector_.ShouldDump(false, true, &reason));
-  EXPECT_EQ("developer build - not testing - always dumping", reason);
-
-  // When running a crash test, behave as normal.
-  EXPECT_FALSE(collector_.ShouldDump(false, false, &reason));
-  EXPECT_EQ("ignoring - no consent", reason);
-}
-
-TEST_F(UserCollectorTest, ShouldDumpUseConsentProductionImage) {
-  std::string result;
-  EXPECT_FALSE(collector_.ShouldDump(false, false, &result));
-  EXPECT_EQ("ignoring - no consent", result);
-
-  EXPECT_TRUE(collector_.ShouldDump(true, false, &result));
-  EXPECT_EQ("handling", result);
-}
-
-TEST_F(UserCollectorTest, HandleCrashWithoutConsent) {
-  s_metrics = false;
-  collector_.HandleCrash("20:10:ignored", "foobar");
-  EXPECT_TRUE(FindLog(
-      "Received crash notification for foobar[20] sig 10"));
-  ASSERT_EQ(s_crashes, 0);
-}
-
-TEST_F(UserCollectorTest, HandleNonChromeCrashWithConsent) {
-  s_metrics = true;
-  collector_.HandleCrash("5:2:ignored", "chromeos-wm");
-  EXPECT_TRUE(FindLog(
-      "Received crash notification for chromeos-wm[5] sig 2"));
-  ASSERT_EQ(s_crashes, 1);
-}
-
-TEST_F(UserCollectorTest, GetProcessPath) {
-  FilePath path = collector_.GetProcessPath(100);
-  ASSERT_EQ("/proc/100", path.value());
-}
-
-TEST_F(UserCollectorTest, GetSymlinkTarget) {
-  FilePath result;
-  ASSERT_FALSE(collector_.GetSymlinkTarget(FilePath("/does_not_exist"),
-                                           &result));
-  ASSERT_TRUE(FindLog(
-      "Readlink failed on /does_not_exist with 2"));
-  std::string long_link = test_dir_.path().value();
-  for (int i = 0; i < 50; ++i)
-    long_link += "0123456789";
-  long_link += "/gold";
-
-  for (size_t len = 1; len <= long_link.size(); ++len) {
-    std::string this_link;
-    static const char* kLink =
-        test_dir_.path().Append("test/this_link").value().c_str();
-    this_link.assign(long_link.c_str(), len);
-    ASSERT_EQ(len, this_link.size());
-    ASSERT_EQ(0, symlink(this_link.c_str(), kLink));
-    ASSERT_TRUE(collector_.GetSymlinkTarget(FilePath(kLink), &result));
-    ASSERT_EQ(this_link, result.value());
-    unlink(kLink);
-  }
-}
-
-TEST_F(UserCollectorTest, GetExecutableBaseNameFromPid) {
-  std::string base_name;
-  EXPECT_FALSE(collector_.GetExecutableBaseNameFromPid(0, &base_name));
-  EXPECT_TRUE(FindLog(
-      "Readlink failed on /proc/0/exe with 2"));
-  EXPECT_TRUE(FindLog(
-      "GetSymlinkTarget failed - Path /proc/0 DirectoryExists: 0"));
-  EXPECT_TRUE(FindLog("stat /proc/0/exe failed: -1 2"));
-
-  brillo::ClearLog();
-  pid_t my_pid = getpid();
-  EXPECT_TRUE(collector_.GetExecutableBaseNameFromPid(my_pid, &base_name));
-  EXPECT_FALSE(FindLog("Readlink failed"));
-  EXPECT_EQ("crash_reporter_tests", base_name);
-}
-
-TEST_F(UserCollectorTest, GetFirstLineWithPrefix) {
-  std::vector<std::string> lines;
-  std::string line;
-
-  EXPECT_FALSE(collector_.GetFirstLineWithPrefix(lines, "Name:", &line));
-  EXPECT_EQ("", line);
-
-  lines.push_back("Name:\tls");
-  lines.push_back("State:\tR (running)");
-  lines.push_back(" Foo:\t1000");
-
-  line.clear();
-  EXPECT_TRUE(collector_.GetFirstLineWithPrefix(lines, "Name:", &line));
-  EXPECT_EQ(lines[0], line);
-
-  line.clear();
-  EXPECT_TRUE(collector_.GetFirstLineWithPrefix(lines, "State:", &line));
-  EXPECT_EQ(lines[1], line);
-
-  line.clear();
-  EXPECT_FALSE(collector_.GetFirstLineWithPrefix(lines, "Foo:", &line));
-  EXPECT_EQ("", line);
-
-  line.clear();
-  EXPECT_TRUE(collector_.GetFirstLineWithPrefix(lines, " Foo:", &line));
-  EXPECT_EQ(lines[2], line);
-
-  line.clear();
-  EXPECT_FALSE(collector_.GetFirstLineWithPrefix(lines, "Bar:", &line));
-  EXPECT_EQ("", line);
-}
-
-TEST_F(UserCollectorTest, GetIdFromStatus) {
-  int id = 1;
-  EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                          UserCollector::kIdEffective,
-                                          SplitLines("nothing here"),
-                                          &id));
-  EXPECT_EQ(id, 1);
-
-  // Not enough parameters.
-  EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                          UserCollector::kIdReal,
-                                          SplitLines("line 1\nUid:\t1\n"),
-                                          &id));
-
-  const std::vector<std::string> valid_contents =
-      SplitLines("\nUid:\t1\t2\t3\t4\nGid:\t5\t6\t7\t8\n");
-  EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                         UserCollector::kIdReal,
-                                         valid_contents,
-                                         &id));
-  EXPECT_EQ(1, id);
-
-  EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                         UserCollector::kIdEffective,
-                                         valid_contents,
-                                         &id));
-  EXPECT_EQ(2, id);
-
-  EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                         UserCollector::kIdFileSystem,
-                                         valid_contents,
-                                         &id));
-  EXPECT_EQ(4, id);
-
-  EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kGroupId,
-                                         UserCollector::kIdEffective,
-                                         valid_contents,
-                                         &id));
-  EXPECT_EQ(6, id);
-
-  EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kGroupId,
-                                         UserCollector::kIdSet,
-                                         valid_contents,
-                                         &id));
-  EXPECT_EQ(7, id);
-
-  EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kGroupId,
-                                          UserCollector::IdKind(5),
-                                          valid_contents,
-                                          &id));
-  EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kGroupId,
-                                          UserCollector::IdKind(-1),
-                                          valid_contents,
-                                          &id));
-
-  // Fail if junk after number
-  EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                          UserCollector::kIdReal,
-                                          SplitLines("Uid:\t1f\t2\t3\t4\n"),
-                                          &id));
-  EXPECT_TRUE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                         UserCollector::kIdReal,
-                                         SplitLines("Uid:\t1\t2\t3\t4\n"),
-                                         &id));
-  EXPECT_EQ(1, id);
-
-  // Fail if more than 4 numbers.
-  EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,
-                                          UserCollector::kIdReal,
-                                          SplitLines("Uid:\t1\t2\t3\t4\t5\n"),
-                                          &id));
-}
-
-TEST_F(UserCollectorTest, GetStateFromStatus) {
-  std::string state;
-  EXPECT_FALSE(collector_.GetStateFromStatus(SplitLines("nothing here"),
-                                             &state));
-  EXPECT_EQ("", state);
-
-  EXPECT_TRUE(collector_.GetStateFromStatus(SplitLines("State:\tR (running)"),
-                                            &state));
-  EXPECT_EQ("R (running)", state);
-
-  EXPECT_TRUE(collector_.GetStateFromStatus(
-      SplitLines("Name:\tls\nState:\tZ (zombie)\n"), &state));
-  EXPECT_EQ("Z (zombie)", state);
-}
-
-TEST_F(UserCollectorTest, GetUserInfoFromName) {
-  gid_t gid = 100;
-  uid_t uid = 100;
-  EXPECT_TRUE(collector_.GetUserInfoFromName("root", &uid, &gid));
-  EXPECT_EQ(0U, uid);
-  EXPECT_EQ(0U, gid);
-}
-
-TEST_F(UserCollectorTest, CopyOffProcFilesBadPath) {
-  // Try a path that is not writable.
-  ASSERT_FALSE(collector_.CopyOffProcFiles(pid_, FilePath("/bad/path")));
-  EXPECT_TRUE(FindLog("Could not create /bad/path"));
-}
-
-TEST_F(UserCollectorTest, CopyOffProcFilesBadPid) {
-  FilePath container_path(test_dir_.path().Append("test/container"));
-  ASSERT_FALSE(collector_.CopyOffProcFiles(0, container_path));
-  EXPECT_TRUE(FindLog("Path /proc/0 does not exist"));
-}
-
-TEST_F(UserCollectorTest, CopyOffProcFilesOK) {
-  FilePath container_path(test_dir_.path().Append("test/container"));
-  ASSERT_TRUE(collector_.CopyOffProcFiles(pid_, container_path));
-  EXPECT_FALSE(FindLog("Could not copy"));
-  static struct {
-    const char *name;
-    bool exists;
-  } expectations[] = {
-    { "auxv", true },
-    { "cmdline", true },
-    { "environ", true },
-    { "maps", true },
-    { "mem", false },
-    { "mounts", false },
-    { "sched", false },
-    { "status", true }
-  };
-  for (unsigned i = 0; i < sizeof(expectations)/sizeof(expectations[0]); ++i) {
-    EXPECT_EQ(expectations[i].exists,
-              base::PathExists(
-                  container_path.Append(expectations[i].name)));
-  }
-}
-
-TEST_F(UserCollectorTest, ValidateProcFiles) {
-  FilePath container_dir = test_dir_.path();
-
-  // maps file not exists (i.e. GetFileSize fails)
-  EXPECT_FALSE(collector_.ValidateProcFiles(container_dir));
-
-  // maps file is empty
-  FilePath maps_file = container_dir.Append("maps");
-  ASSERT_EQ(0, base::WriteFile(maps_file, nullptr, 0));
-  ASSERT_TRUE(base::PathExists(maps_file));
-  EXPECT_FALSE(collector_.ValidateProcFiles(container_dir));
-
-  // maps file is not empty
-  const char data[] = "test data";
-  unsigned int numBytesWritten =
-      base::WriteFile(maps_file, data, sizeof(data));
-  ASSERT_EQ(sizeof(data), numBytesWritten);
-  ASSERT_TRUE(base::PathExists(maps_file));
-  EXPECT_TRUE(collector_.ValidateProcFiles(container_dir));
-}
-
-TEST_F(UserCollectorTest, ValidateCoreFile) {
-  FilePath container_dir = test_dir_.path();
-  FilePath core_file = container_dir.Append("core");
-
-  // Core file does not exist
-  EXPECT_EQ(UserCollector::kErrorInvalidCoreFile,
-            collector_.ValidateCoreFile(core_file));
-  char e_ident[EI_NIDENT];
-  e_ident[EI_MAG0] = ELFMAG0;
-  e_ident[EI_MAG1] = ELFMAG1;
-  e_ident[EI_MAG2] = ELFMAG2;
-  e_ident[EI_MAG3] = ELFMAG3;
-#if __WORDSIZE == 32
-  e_ident[EI_CLASS] = ELFCLASS32;
-#elif __WORDSIZE == 64
-  e_ident[EI_CLASS] = ELFCLASS64;
-#else
-#error Unknown/unsupported value of __WORDSIZE.
-#endif
-
-  // Core file has the expected header
-  ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident)));
-  EXPECT_EQ(UserCollector::kErrorNone,
-            collector_.ValidateCoreFile(core_file));
-
-#if __WORDSIZE == 64
-  // 32-bit core file on 64-bit platform
-  e_ident[EI_CLASS] = ELFCLASS32;
-  ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident)));
-  EXPECT_EQ(UserCollector::kErrorUnsupported32BitCoreFile,
-            collector_.ValidateCoreFile(core_file));
-  e_ident[EI_CLASS] = ELFCLASS64;
-#endif
-
-  // Invalid core files
-  ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident) - 1));
-  EXPECT_EQ(UserCollector::kErrorInvalidCoreFile,
-            collector_.ValidateCoreFile(core_file));
-
-  e_ident[EI_MAG0] = 0;
-  ASSERT_TRUE(base::WriteFile(core_file, e_ident, sizeof(e_ident)));
-  EXPECT_EQ(UserCollector::kErrorInvalidCoreFile,
-            collector_.ValidateCoreFile(core_file));
-}
diff --git a/crash_reporter/warn_collector.l b/crash_reporter/warn_collector.l
deleted file mode 100644
index 70ab25c..0000000
--- a/crash_reporter/warn_collector.l
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- *
- * This flex program reads /var/log/messages as it grows and saves kernel
- * warnings to files.  It keeps track of warnings it has seen (based on
- * file/line only, ignoring differences in the stack trace), and reports only
- * the first warning of each kind, but maintains a count of all warnings by
- * using their hashes as buckets in a UMA sparse histogram.  It also invokes
- * the crash collector, which collects the warnings and prepares them for later
- * shipment to the crash server.
- */
-
-%option noyywrap
-
-%{
-#include <fcntl.h>
-#include <inttypes.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <sys/inotify.h>
-#include <sys/select.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "metrics/c_metrics_library.h"
-
-int WarnStart(void);
-void WarnEnd(void);
-void WarnInput(char *buf, yy_size_t *result, size_t max_size);
-
-#define YY_INPUT(buf, result, max_size) WarnInput(buf, &result, max_size)
-
-%}
-
-/* Define a few useful regular expressions. */
-
-D               [0-9]
-PREFIX          .*" kernel: [ "*{D}+"."{D}+"]"
-CUT_HERE        {PREFIX}" ------------[ cut here".*
-WARNING         {PREFIX}" WARNING: at "
-END_TRACE       {PREFIX}" ---[ end trace".*
-
-/* Use exclusive start conditions. */
-%x PRE_WARN WARN
-
-%%
- /* The scanner itself. */
-
-^{CUT_HERE}\n{WARNING}          BEGIN(PRE_WARN);
-.|\n                            /* ignore all other input in state 0 */
-<PRE_WARN>[^ ]+.[^ ]+\n         if (WarnStart()) {
-                                  /* yytext is
-                                     "file:line func+offset/offset()\n" */
-                                  BEGIN(WARN); ECHO;
-                                } else {
-                                  BEGIN(0);
-                                }
-
- /* Assume the warning ends at the "end trace" line */
-<WARN>^{END_TRACE}\n            ECHO; BEGIN(0); WarnEnd();
-<WARN>^.*\n                     ECHO;
-
-%%
-
-#define HASH_BITMAP_SIZE        (1 << 15)  /* size in bits */
-#define HASH_BITMAP_MASK        (HASH_BITMAP_SIZE - 1)
-
-const char warn_hist_name[] = "Platform.KernelWarningHashes";
-uint32_t hash_bitmap[HASH_BITMAP_SIZE / 32];
-CMetricsLibrary metrics_library;
-
-const char *prog_name;          /* the name of this program */
-int yyin_fd;                    /* instead of FILE *yyin to avoid buffering */
-int i_fd;                       /* for inotify, to detect file changes */
-int testing;                    /* 1 if running test */
-int filter;                     /* 1 when using as filter (for development) */
-int fifo;                       /* 1 when reading from fifo (for devel) */
-int draining;                   /* 1 when draining renamed log file */
-
-const char *msg_path = "/var/log/messages";
-const char warn_dump_dir[]  = "/var/run/kwarn";
-const char *warn_dump_path = "/var/run/kwarn/warning";
-const char *crash_reporter_command;
-
-__attribute__((__format__(__printf__, 1, 2)))
-static void Die(const char *format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  fprintf(stderr, "%s: ", prog_name);
-  vfprintf(stderr, format, ap);
-  exit(1);
-}
-
-static void RunCrashReporter(void) {
-  int status = system(crash_reporter_command);
-  if (status != 0)
-    Die("%s exited with status %d\n", crash_reporter_command, status);
-}
-
-static uint32_t StringHash(const char *string) {
-  uint32_t hash = 0;
-  while (*string != '\0') {
-    hash = (hash << 5) + hash + *string++;
-  }
-  return hash;
-}
-
-/* We expect only a handful of different warnings per boot session, so the
- * probability of a collision is very low, and statistically it won't matter
- * (unless warnings with the same hash also happens in tandem, which is even
- * rarer).
- */
-static int HashSeen(uint32_t hash) {
-  int word_index = (hash & HASH_BITMAP_MASK) / 32;
-  int bit_index = (hash & HASH_BITMAP_MASK) % 32;
-  return hash_bitmap[word_index] & 1 << bit_index;
-}
-
-static void SetHashSeen(uint32_t hash) {
-  int word_index = (hash & HASH_BITMAP_MASK) / 32;
-  int bit_index = (hash & HASH_BITMAP_MASK) % 32;
-  hash_bitmap[word_index] |= 1 << bit_index;
-}
-
-#pragma GCC diagnostic ignored "-Wwrite-strings"
-int WarnStart(void) {
-  uint32_t hash;
-  char *spacep;
-
-  if (filter)
-    return 1;
-
-  hash = StringHash(yytext);
-  if (!(testing || fifo || filter)) {
-    CMetricsLibrarySendSparseToUMA(metrics_library, warn_hist_name, (int) hash);
-  }
-  if (HashSeen(hash))
-    return 0;
-  SetHashSeen(hash);
-
-  yyout = fopen(warn_dump_path, "w");
-  if (yyout == NULL)
-    Die("fopen %s failed: %s\n", warn_dump_path, strerror(errno));
-  spacep = strchr(yytext, ' ');
-  if (spacep == NULL || spacep[1] == '\0')
-    spacep = "unknown-function";
-  fprintf(yyout, "%08x-%s\n", hash, spacep + 1);
-  return 1;
-}
-
-void WarnEnd(void) {
-  if (filter)
-    return;
-  fclose(yyout);
-  yyout = stdout;               /* for debugging */
-  RunCrashReporter();
-}
-
-static void WarnOpenInput(const char *path) {
-  yyin_fd = open(path, O_RDONLY);
-  if (yyin_fd < 0)
-    Die("could not open %s: %s\n", path, strerror(errno));
-  if (!fifo) {
-    /* Go directly to the end of the file.  We don't want to parse the same
-     * warnings multiple times on reboot/restart.  We might miss some
-     * warnings, but so be it---it's too hard to keep track reliably of the
-     * last parsed position in the syslog.
-     */
-    if (lseek(yyin_fd, 0, SEEK_END) < 0)
-      Die("could not lseek %s: %s\n", path, strerror(errno));
-    /* Set up notification of file growth and rename. */
-    i_fd = inotify_init();
-    if (i_fd < 0)
-      Die("inotify_init: %s\n", strerror(errno));
-    if (inotify_add_watch(i_fd, path, IN_MODIFY | IN_MOVE_SELF) < 0)
-      Die("inotify_add_watch: %s\n", strerror(errno));
-  }
-}
-
-/* We replace the default YY_INPUT() for the following reasons:
- *
- * 1.  We want to read data as soon as it becomes available, but the default
- * YY_INPUT() uses buffered I/O.
- *
- * 2.  We want to block on end of input and wait for the file to grow.
- *
- * 3.  We want to detect log rotation, and reopen the input file as needed.
- */
-void WarnInput(char *buf, yy_size_t *result, size_t max_size) {
-  while (1) {
-    ssize_t ret = read(yyin_fd, buf, max_size);
-    if (ret < 0)
-      Die("read: %s", strerror(errno));
-    *result = ret;
-    if (*result > 0 || fifo || filter)
-      return;
-    if (draining) {
-      /* Assume we're done with this log, and move to next
-       * log.  Rsyslogd may keep writing to the old log file
-       * for a while, but we don't care since we don't have
-       * to be exact.
-       */
-      close(yyin_fd);
-      if (YYSTATE == WARN) {
-        /* Be conservative in case we lose the warn
-         * terminator during the switch---or we may
-         * collect personally identifiable information.
-         */
-        WarnEnd();
-      }
-      BEGIN(0);        /* see above comment */
-      sleep(1);        /* avoid race with log rotator */
-      WarnOpenInput(msg_path);
-      draining = 0;
-      continue;
-    }
-    /* Nothing left to read, so we must wait. */
-    struct inotify_event event;
-    while (1) {
-      int n = read(i_fd, &event, sizeof(event));
-      if (n <= 0) {
-        if (errno == EINTR)
-          continue;
-        else
-          Die("inotify: %s\n", strerror(errno));
-      } else
-        break;
-    }
-    if (event.mask & IN_MOVE_SELF) {
-      /* The file has been renamed.  Before switching
-       * to the new one, we process any remaining
-       * content of this file.
-       */
-      draining = 1;
-    }
-  }
-}
-
-int main(int argc, char **argv) {
-  int result;
-  struct passwd *user;
-  prog_name = argv[0];
-
-  if (argc == 2 && strcmp(argv[1], "--test") == 0)
-    testing = 1;
-  else if (argc == 2 && strcmp(argv[1], "--filter") == 0)
-    filter = 1;
-  else if (argc == 2 && strcmp(argv[1], "--fifo") == 0) {
-    fifo = 1;
-  } else if (argc != 1) {
-    fprintf(stderr,
-            "usage: %s [single-flag]\n"
-            "flags (for testing only):\n"
-            "--fifo\tinput is fifo \"fifo\", output is stdout\n"
-            "--filter\tinput is stdin, output is stdout\n"
-            "--test\trun self-test\n",
-            prog_name);
-    exit(1);
-  }
-
-  metrics_library = CMetricsLibraryNew();
-  CMetricsLibraryInit(metrics_library);
-
-  crash_reporter_command = testing ?
-    "./warn_collector_test_reporter.sh" :
-    "/sbin/crash_reporter --kernel_warning";
-
-  /* When filtering with --filter (for development) use stdin for input.
-   * Otherwise read input from a file or a fifo.
-   */
-  yyin_fd = fileno(stdin);
-  if (testing) {
-    msg_path = "messages";
-    warn_dump_path = "warning";
-  }
-  if (fifo) {
-    msg_path = "fifo";
-  }
-  if (!filter) {
-    WarnOpenInput(msg_path);
-  }
-
-  /* Create directory for dump file.  Still need to be root here. */
-  unlink(warn_dump_path);
-  if (!testing && !fifo && !filter) {
-    rmdir(warn_dump_dir);
-    result = mkdir(warn_dump_dir, 0755);
-    if (result < 0)
-      Die("could not create %s: %s\n",
-          warn_dump_dir, strerror(errno));
-  }
-
-  if (0) {
-    /* TODO(semenzato): put this back in once we decide it's safe
-     * to make /var/spool/crash rwxrwxrwx root, or use a different
-     * owner and setuid for the crash reporter as well.
-     */
-
-    /* Get low privilege uid, gid. */
-    user = getpwnam("chronos");
-    if (user == NULL)
-      Die("getpwnam failed\n");
-
-    /* Change dump directory ownership. */
-    if (chown(warn_dump_dir, user->pw_uid, user->pw_gid) < 0)
-      Die("chown: %s\n", strerror(errno));
-
-    /* Drop privileges. */
-    if (setuid(user->pw_uid) < 0) {
-      Die("setuid: %s\n", strerror(errno));
-    }
-  }
-
-  /* Go! */
-  return yylex();
-}
-
-/* Flex should really know not to generate these functions.
- */
-void UnusedFunctionWarningSuppressor(void) {
-  yyunput(0, 0);
-}
diff --git a/crash_reporter/warn_collector_test.sh b/crash_reporter/warn_collector_test.sh
deleted file mode 100755
index a5af16c..0000000
--- a/crash_reporter/warn_collector_test.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#! /bin/bash
-
-# Copyright (C) 2013 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.
-
-# Test for warn_collector.  Run the warn collector in the background, emulate
-# the kernel by appending lines to the log file "messages", and observe the log
-# of the (fake) crash reporter each time is run by the warn collector daemon.
-
-set -e
-
-fail() {
-  printf '[ FAIL ] %b\n' "$*"
-  exit 1
-}
-
-if [[ -z ${SYSROOT} ]]; then
-  fail "SYSROOT must be set for this test to work"
-fi
-: ${OUT:=${PWD}}
-cd "${OUT}"
-PATH=${OUT}:${PATH}
-TESTLOG="${OUT}/warn-test-log"
-
-echo "Testing: $(which warn_collector)"
-
-cleanup() {
-  # Kill daemon (if started) on exit
-  kill %
-}
-
-check_log() {
-  local n_expected=$1
-  if [[ ! -f ${TESTLOG} ]]; then
-    fail "${TESTLOG} was not created"
-  fi
-  if [[ $(wc -l < "${TESTLOG}") -ne ${n_expected} ]]; then
-    fail "expected ${n_expected} lines in ${TESTLOG}, found this instead:
-$(<"${TESTLOG}")"
-  fi
-  if egrep -qv '^[0-9a-f]{8}' "${TESTLOG}"; then
-    fail "found bad lines in ${TESTLOG}:
-$(<"${TESTLOG}")"
-  fi
-}
-
-rm -f "${TESTLOG}"
-cp "${SRC}/warn_collector_test_reporter.sh" .
-cp "${SRC}/TEST_WARNING" .
-cp TEST_WARNING messages
-
-# Start the collector daemon.  With the --test option, the daemon reads input
-# from ./messages, writes the warning into ./warning, and invokes
-# ./warn_collector_test_reporter.sh to report the warning.
-warn_collector --test &
-trap cleanup EXIT
-
-# After a while, check that the first warning has been collected.
-sleep 1
-check_log 1
-
-# Add the same warning to messages, verify that it is NOT collected
-cat TEST_WARNING >> messages
-sleep 1
-check_log 1
-
-# Add a slightly different warning to messages, check that it is collected.
-sed s/intel_dp.c/intel_xx.c/ < TEST_WARNING >> messages
-sleep 1
-check_log 2
-
-# Emulate log rotation, add a warning, and check.
-mv messages messages.1
-sed s/intel_dp.c/intel_xy.c/ < TEST_WARNING > messages
-sleep 2
-check_log 3
-
-# Success!
-exit 0
diff --git a/crash_reporter/warn_collector_test_reporter.sh b/crash_reporter/warn_collector_test_reporter.sh
deleted file mode 100755
index b6096ed..0000000
--- a/crash_reporter/warn_collector_test_reporter.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#! /bin/sh
-
-# Copyright (C) 2013 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.
-
-# Replacement for the crash reporter, for testing.  Log the first line of the
-# "warning" file, which by convention contains the warning hash, and remove the
-# file.
-
-set -e
-
-exec 1>> warn-test-log
-exec 2>> warn-test-log
-
-head -1 warning
-rm warning
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 8a63f3f..f0131b8 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -9,6 +9,12 @@
     "-Os",
   ],
 
+  target: {
+    android64: {
+      cflags: ["-DTARGET_IS_64_BIT"],
+    },
+  },
+
   local_include_dirs: ["include"],
   export_include_dirs: ["include"],
 
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 44e92fe..cf37701 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -129,6 +129,9 @@
       signal_name = "SIGSTKFLT";
       break;
 #endif
+    case SIGSYS:
+      signal_name = "SIGSYS";
+      break;
     case SIGTRAP:
       signal_name = "SIGTRAP";
       break;
@@ -185,7 +188,7 @@
   return result;
 }
 
-static void send_debuggerd_packet(siginfo_t* info) {
+static void send_debuggerd_packet() {
   // Mutex to prevent multiple crashing threads from trying to talk
   // to debuggerd at the same time.
   static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -222,7 +225,6 @@
     msg.abort_msg_address = reinterpret_cast<uintptr_t>(g_callbacks.get_abort_message());
   }
 
-  msg.original_si_code = (info != nullptr) ? info->si_code : 0;
   ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
   if (ret == sizeof(msg)) {
     char debuggerd_ack;
@@ -254,7 +256,7 @@
 
   log_signal_summary(signal_number, info);
 
-  send_debuggerd_packet(info);
+  send_debuggerd_packet();
 
   // We need to return from the signal handler so that debuggerd can dump the
   // thread that crashed, but returning here does not guarantee that the signal
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index c352aeb..8f08c08 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -51,6 +51,8 @@
 
 #include <private/android_filesystem_config.h>
 
+#include <debuggerd/client.h>
+
 #include "backtrace.h"
 #include "getevent.h"
 #include "signal_sender.h"
@@ -70,7 +72,6 @@
   pid_t pid, tid;
   uid_t uid, gid;
   uintptr_t abort_msg_address;
-  int32_t original_si_code;
 };
 
 static void wait_for_user_action(const debugger_request_t& request) {
@@ -202,8 +203,6 @@
   }
 
   ALOGV("reading tid");
-  fcntl(fd, F_SETFL, O_NONBLOCK);
-
   pollfd pollfds[1];
   pollfds[0].fd = fd;
   pollfds[0].events = POLLIN;
@@ -232,7 +231,6 @@
   out_request->uid = cr.uid;
   out_request->gid = cr.gid;
   out_request->abort_msg_address = msg.abort_msg_address;
-  out_request->original_si_code = msg.original_si_code;
 
   if (msg.action == DEBUGGER_ACTION_CRASH) {
     // Ensure that the tid reported by the crashing process is valid.
@@ -487,9 +485,10 @@
     return false;
   }
 
-  int total_sleep_time_usec = 0;
   while (true) {
-    int signal = wait_for_signal(request.tid, &total_sleep_time_usec);
+    // wait_for_signal waits for forever, but the watchdog process will kill us
+    // if it takes too long.
+    int signal = wait_for_signal(request.tid);
     switch (signal) {
       case -1:
         ALOGE("debuggerd: timed out waiting for signal");
@@ -498,8 +497,8 @@
       case SIGSTOP:
         if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
           ALOGV("debuggerd: stopped -- dumping to tombstone");
-          engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
-                            request.original_si_code, request.abort_msg_address, amfd_data);
+          engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+                            request.abort_msg_address, amfd_data);
         } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
           ALOGV("debuggerd: stopped -- dumping to fd");
           dump_backtrace(fd, backtrace_map, request.pid, request.tid, siblings, nullptr);
@@ -525,8 +524,8 @@
       case SIGTRAP:
         ALOGV("stopped -- fatal signal\n");
         *crash_signal = signal;
-        engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
-                          request.original_si_code, request.abort_msg_address, amfd_data);
+        engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+                          request.abort_msg_address, amfd_data);
         break;
 
       default:
@@ -873,12 +872,8 @@
   ALOGI("debuggerd: starting\n");
 
   for (;;) {
-    sockaddr_storage ss;
-    sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
-    socklen_t alen = sizeof(ss);
-
     ALOGV("waiting for connection\n");
-    int fd = accept4(s, addrp, &alen, SOCK_CLOEXEC);
+    int fd = accept4(s, nullptr, nullptr, SOCK_CLOEXEC | SOCK_NONBLOCK);
     if (fd == -1) {
       ALOGE("accept failed: %s\n", strerror(errno));
       continue;
diff --git a/debuggerd/include/debuggerd/client.h b/debuggerd/include/debuggerd/client.h
index 41b7b3a..8225c73 100644
--- a/debuggerd/include/debuggerd/client.h
+++ b/debuggerd/include/debuggerd/client.h
@@ -44,7 +44,6 @@
   int32_t action;
   pid_t tid;
   uint64_t abort_msg_address;
-  int32_t original_si_code;
 } debugger_msg_t;
 
 // These callbacks are called in a signal handler, and thus must be async signal safe.
diff --git a/debuggerd/test/tombstone_test.cpp b/debuggerd/test/tombstone_test.cpp
index 58d640e..5ee07cd 100644
--- a/debuggerd/test/tombstone_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -595,7 +595,7 @@
   si.si_signo = 0;
   ptrace_set_fake_getsiginfo(si);
 
-  dump_signal_info(&log_, 123, SIGSEGV, 10);
+  dump_signal_info(&log_, 123);
 
   std::string tombstone_contents;
   ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index dfdf29c..e663920 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -56,8 +56,13 @@
 #define TOMBSTONE_DIR   "/data/tombstones"
 #define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")
 
-static bool signal_has_si_addr(int sig) {
-  switch (sig) {
+static bool signal_has_si_addr(int si_signo, int si_code) {
+  // Manually sent signals won't have si_addr.
+  if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) {
+    return false;
+  }
+
+  switch (si_signo) {
     case SIGBUS:
     case SIGFPE:
     case SIGILL:
@@ -80,6 +85,7 @@
     case SIGSTKFLT: return "SIGSTKFLT";
 #endif
     case SIGSTOP: return "SIGSTOP";
+    case SIGSYS: return "SIGSYS";
     case SIGTRAP: return "SIGTRAP";
     default: return "?";
   }
@@ -131,13 +137,26 @@
 #if defined(SEGV_BNDERR)
         case SEGV_BNDERR: return "SEGV_BNDERR";
 #endif
+#if defined(SEGV_PKUERR)
+        case SEGV_PKUERR: return "SEGV_PKUERR";
+#endif
       }
-#if defined(SEGV_BNDERR)
+#if defined(SEGV_PKUERR)
+      static_assert(NSIGSEGV == SEGV_PKUERR, "missing SEGV_* si_code");
+#elif defined(SEGV_BNDERR)
       static_assert(NSIGSEGV == SEGV_BNDERR, "missing SEGV_* si_code");
 #else
       static_assert(NSIGSEGV == SEGV_ACCERR, "missing SEGV_* si_code");
 #endif
       break;
+#if defined(SYS_SECCOMP) // Our glibc is too old, and we build this for the host too.
+    case SIGSYS:
+      switch (code) {
+        case SYS_SECCOMP: return "SYS_SECCOMP";
+      }
+      static_assert(NSIGSYS == SYS_SECCOMP, "missing SYS_* si_code");
+      break;
+#endif
     case SIGTRAP:
       switch (code) {
         case TRAP_BRKPT: return "TRAP_BRKPT";
@@ -176,7 +195,7 @@
   _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
 }
 
-static void dump_signal_info(log_t* log, pid_t tid, int signal, int si_code) {
+static void dump_signal_info(log_t* log, pid_t tid) {
   siginfo_t si;
   memset(&si, 0, sizeof(si));
   if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si) == -1) {
@@ -184,18 +203,15 @@
     return;
   }
 
-  // bionic has to re-raise some signals, which overwrites the si_code with SI_TKILL.
-  si.si_code = si_code;
-
   char addr_desc[32]; // ", fault addr 0x1234"
-  if (signal_has_si_addr(signal)) {
+  if (signal_has_si_addr(si.si_signo, si.si_code)) {
     snprintf(addr_desc, sizeof(addr_desc), "%p", si.si_addr);
   } else {
     snprintf(addr_desc, sizeof(addr_desc), "--------");
   }
 
-  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n",
-       signal, get_signame(signal), si.si_code, get_sigcode(signal, si.si_code), addr_desc);
+  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", si.si_signo,
+       get_signame(si.si_signo), si.si_code, get_sigcode(si.si_signo, si.si_code), addr_desc);
 }
 
 static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
@@ -362,7 +378,7 @@
   siginfo_t si;
   memset(&si, 0, sizeof(si));
   if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si) != -1) {
-    print_fault_address_marker = signal_has_si_addr(si.si_signo);
+    print_fault_address_marker = signal_has_si_addr(si.si_signo, si.si_code);
     addr = reinterpret_cast<uintptr_t>(si.si_addr);
   } else {
     ALOGE("Cannot get siginfo for %d: %s\n", tid, strerror(errno));
@@ -445,17 +461,14 @@
   }
 }
 
-static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map, int signal,
-                        int si_code, uintptr_t abort_msg_address, bool primary_thread) {
+static void dump_thread(log_t* log, pid_t pid, pid_t tid, BacktraceMap* map,
+                        uintptr_t abort_msg_address, bool primary_thread) {
   log->current_tid = tid;
   if (!primary_thread) {
     _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
   }
   dump_thread_info(log, pid, tid);
-
-  if (signal) {
-    dump_signal_info(log, tid, signal, si_code);
-  }
+  dump_signal_info(log, tid);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
   if (primary_thread) {
@@ -545,6 +558,10 @@
     if (!hdr_size) {
       hdr_size = sizeof(log_entry.entry_v1);
     }
+    if ((hdr_size < sizeof(log_entry.entry_v1)) ||
+        (hdr_size > sizeof(log_entry.entry))) {
+      continue;
+    }
     char* msg = reinterpret_cast<char*>(log_entry.buf) + hdr_size;
 
     char timeBuf[32];
@@ -606,8 +623,7 @@
 
 // Dumps all information about the specified pid to the tombstone.
 static void dump_crash(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid,
-                       const std::set<pid_t>& siblings, int signal, int si_code,
-                       uintptr_t abort_msg_address) {
+                       const std::set<pid_t>& siblings, uintptr_t abort_msg_address) {
   // don't copy log messages to tombstone unless this is a dev device
   char value[PROPERTY_VALUE_MAX];
   property_get("ro.debuggable", value, "0");
@@ -616,14 +632,14 @@
   _LOG(log, logtype::HEADER,
        "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
   dump_header_info(log);
-  dump_thread(log, pid, tid, map, signal, si_code, abort_msg_address, true);
+  dump_thread(log, pid, tid, map, abort_msg_address, true);
   if (want_logs) {
     dump_logs(log, pid, 5);
   }
 
   if (!siblings.empty()) {
     for (pid_t sibling : siblings) {
-      dump_thread(log, pid, sibling, map, 0, 0, 0, false);
+      dump_thread(log, pid, sibling, map, 0, false);
     }
   }
 
@@ -686,8 +702,8 @@
 }
 
 void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
-                       const std::set<pid_t>& siblings, int signal, int original_si_code,
-                       uintptr_t abort_msg_address, std::string* amfd_data) {
+                       const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
+                       std::string* amfd_data) {
   log_t log;
   log.current_tid = tid;
   log.crashed_tid = tid;
@@ -699,5 +715,5 @@
 
   log.tfd = tombstone_fd;
   log.amfd_data = amfd_data;
-  dump_crash(&log, map, pid, tid, siblings, signal, original_si_code, abort_msg_address);
+  dump_crash(&log, map, pid, tid, siblings, abort_msg_address);
 }
diff --git a/debuggerd/tombstone.h b/debuggerd/tombstone.h
index 487d950..e1c39c5 100644
--- a/debuggerd/tombstone.h
+++ b/debuggerd/tombstone.h
@@ -33,7 +33,7 @@
 
 /* Creates a tombstone file and writes the crash dump to it. */
 void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
-                       const std::set<pid_t>& siblings, int signal, int original_si_code,
-                       uintptr_t abort_msg_address, std::string* amfd_data);
+                       const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
+                       std::string* amfd_data);
 
 #endif // _DEBUGGERD_TOMBSTONE_H
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index bd06095..7fabf69 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -31,9 +31,6 @@
 #include <backtrace/Backtrace.h>
 #include <log/log.h>
 
-constexpr int SLEEP_TIME_USEC = 50000;          // 0.05 seconds
-constexpr int MAX_TOTAL_SLEEP_USEC = 10000000;  // 10 seconds
-
 // Whitelist output desired in the logcat output.
 bool is_allowed_in_logcat(enum logtype ltype) {
   if ((ltype == HEADER)
@@ -74,10 +71,10 @@
   }
 }
 
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
+int wait_for_signal(pid_t tid) {
   while (true) {
     int status;
-    pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG));
+    pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL));
     if (n == -1) {
       ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno));
       return -1;
@@ -91,14 +88,6 @@
         return -1;
       }
     }
-
-    if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) {
-      ALOGE("timed out waiting for stop signal: tid=%d", tid);
-      return -1;
-    }
-
-    usleep(SLEEP_TIME_USEC);
-    *total_sleep_time_usec += SLEEP_TIME_USEC;
   }
 }
 
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index cd01188..d820f0f 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -77,7 +77,7 @@
 void _LOG(log_t* log, logtype ltype, const char *fmt, ...)
         __attribute__ ((format(printf, 3, 4)));
 
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
+int wait_for_signal(pid_t tid);
 
 void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...);
 
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 1b4ecbe..7112d1d 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -43,22 +43,22 @@
 
 LOCAL_CFLAGS += -DFASTBOOT_REVISION='"$(fastboot_version)"'
 
-LOCAL_SRC_FILES_linux := usb_linux.cpp util_linux.cpp
+LOCAL_SRC_FILES_linux := usb_linux.cpp
 LOCAL_STATIC_LIBRARIES_linux := libselinux
 
-LOCAL_SRC_FILES_darwin := usb_osx.cpp util_osx.cpp
+LOCAL_SRC_FILES_darwin := usb_osx.cpp
 LOCAL_STATIC_LIBRARIES_darwin := libselinux
 LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
 LOCAL_CFLAGS_darwin := -Wno-unused-parameter
 
-LOCAL_SRC_FILES_windows := usb_windows.cpp util_windows.cpp
+LOCAL_SRC_FILES_windows := usb_windows.cpp
 LOCAL_STATIC_LIBRARIES_windows := AdbWinApi
 LOCAL_REQUIRED_MODULES_windows := AdbWinApi
 LOCAL_LDLIBS_windows := -lws2_32
 LOCAL_C_INCLUDES_windows := development/host/windows/usb/api
 
 LOCAL_STATIC_LIBRARIES := \
-    libziparchive-host \
+    libziparchive \
     libext4_utils_host \
     libsparse_host \
     libutils \
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 314ed42..987ba83 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -47,6 +47,7 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
 #include <android-base/parsenetaddress.h>
@@ -115,16 +116,15 @@
 };
 
 static std::string find_item_given_name(const char* img_name, const char* product) {
-    char *dir;
-
     if(product) {
-        std::string path = get_my_path();
+        std::string path = android::base::GetExecutablePath();
+        path.erase(path.find_last_of('/'));
         return android::base::StringPrintf("%s/../../../target/product/%s/%s",
                                            path.c_str(), product, img_name);
     }
 
-    dir = getenv("ANDROID_PRODUCT_OUT");
-    if((dir == 0) || (dir[0] == 0)) {
+    char *dir = getenv("ANDROID_PRODUCT_OUT");
+    if (dir == nullptr || dir[0] == '\0') {
         die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
     }
 
@@ -134,7 +134,7 @@
 std::string find_item(const char* item, const char* product) {
     const char *fn;
 
-    if(!strcmp(item,"boot")) {
+    if (!strcmp(item,"boot")) {
         fn = "boot.img";
     } else if(!strcmp(item,"recovery")) {
         fn = "recovery.img";
@@ -397,9 +397,8 @@
             "  -a, --set-active[=<slot>]                Sets the active slot. If no slot is\n"
             "                                           provided, this will default to the value\n"
             "                                           given by --slot. If slots are not\n"
-            "                                           supported, this sets the current slot\n"
-            "                                           to be active. This will run after all\n"
-            "                                           non-reboot commands.\n"
+            "                                           supported, this does nothing. This will\n"
+            "                                           run after all non-reboot commands.\n"
             "  --skip-secondary                         Will not flash secondary slots when\n"
             "                                           performing a flashall or update. This\n"
             "                                           will preserve data on other slots.\n"
@@ -599,6 +598,7 @@
     ZipEntry zip_entry;
     if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
         fprintf(stderr, "archive does not contain '%s'\n", entry_name);
+        fclose(fp);
         return -1;
     }
 
@@ -606,10 +606,12 @@
     int error = ExtractEntryToFile(zip, &zip_entry, fd);
     if (error != 0) {
         fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error));
+        fclose(fp);
         return -1;
     }
 
     lseek(fd, 0, SEEK_SET);
+    // TODO: We're leaking 'fp' here.
     return fd;
 }
 
@@ -1139,17 +1141,14 @@
     }
 }
 
-static void do_send_signature(const char* filename) {
-    if (android::base::EndsWith(filename, ".img") == false) {
-        return;
-    }
+static void do_send_signature(const std::string& fn) {
+    std::size_t extension_loc = fn.find(".img");
+    if (extension_loc == std::string::npos) return;
 
-    std::string sig_path = filename;
-    sig_path.erase(sig_path.size() - 4);
-    sig_path += ".sig";
+    std::string fs_sig = fn.substr(0, extension_loc) + ".sig";
 
     int64_t sz;
-    void* data = load_file(sig_path, &sz);
+    void* data = load_file(fs_sig.c_str(), &sz);
     if (data == nullptr) return;
 
     fb_queue_download("signature", data, sz);
@@ -1198,7 +1197,7 @@
         fastboot_buffer buf;
         if (!load_buf(transport, fname.c_str(), &buf)) {
             if (images[i].is_optional) continue;
-            die("could not load %s\n", images[i].img_name);
+            die("could not load '%s': %s\n", images[i].img_name, strerror(errno));
         }
 
         auto flashall = [&](const std::string &partition) {
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index c2ea551..6699b6a 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -72,8 +72,6 @@
 char *mkmsg(const char *fmt, ...);
 __attribute__((__noreturn__)) void die(const char *fmt, ...);
 
-std::string get_my_path();
-
 /* Current product */
 extern char cur_product[FB_RESPONSE_SZ + 1];
 
diff --git a/fastboot/util_linux.cpp b/fastboot/util_linux.cpp
deleted file mode 100644
index 2c6aedb..0000000
--- a/fastboot/util_linux.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "fastboot.h"
-
-#include <unistd.h>
-#include <limits.h>
-
-#include <android-base/stringprintf.h>
-
-std::string get_my_path() {
-    std::string proc = android::base::StringPrintf("/proc/%d/exe", getpid());
-    char path[PATH_MAX + 1];
-    int rc = readlink(proc.c_str(), path, sizeof(path) - 1);
-    if (rc == -1) return "";
-    path[rc] = '\0';
-    return path;
-}
diff --git a/fastboot/util_osx.cpp b/fastboot/util_osx.cpp
deleted file mode 100644
index 4bae7c4..0000000
--- a/fastboot/util_osx.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "fastboot.h"
-
-#import <Carbon/Carbon.h>
-#include <unistd.h>
-
-std::string get_my_path() {
-    CFBundleRef mainBundle = CFBundleGetMainBundle();
-    CFURLRef executableURL = CFBundleCopyExecutableURL(mainBundle);
-    CFStringRef executablePathString = CFURLCopyFileSystemPath(executableURL, kCFURLPOSIXPathStyle);
-    CFRelease(executableURL);
-
-    char path[PATH_MAX + 1];
-    CFStringGetFileSystemRepresentation(executablePathString, path, sizeof(PATH_MAX)-1);
-    CFRelease(executablePathString);
-
-    return path;
-}
diff --git a/fastboot/util_windows.cpp b/fastboot/util_windows.cpp
deleted file mode 100644
index 3b22c55..0000000
--- a/fastboot/util_windows.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "fastboot.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include <windows.h>
-
-std::string get_my_path() {
-    char path[PATH_MAX + 1];
-
-    DWORD result = GetModuleFileName(NULL, path, sizeof(path) - 1);
-    if (result == 0 || result == sizeof(path) - 1) return "";
-    path[PATH_MAX - 1] = 0;
-
-    return path;
-}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 7da3ca4..d6b699b 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -7,8 +7,8 @@
     libfec \
     libfec_rs \
     libbase \
-    libcrypto_utils_static \
-    libcrypto_static \
+    libcrypto_utils \
+    libcrypto \
     libext4_utils_static \
     libsquashfs_utils \
     libselinux
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index ab52512..b11ce75 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -486,7 +486,7 @@
  * first successful mount.
  * Returns -1 on error, and  FS_MGR_MNTALL_* otherwise.
  */
-int fs_mgr_mount_all(struct fstab *fstab)
+int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
 {
     int i = 0;
     int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
@@ -500,8 +500,10 @@
     }
 
     for (i = 0; i < fstab->num_entries; i++) {
-        /* Don't mount entries that are managed by vold */
-        if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) {
+        /* Don't mount entries that are managed by vold or not for the mount mode*/
+        if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
+             ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) ||
+             ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i]))) {
             continue;
         }
 
@@ -898,3 +900,22 @@
 
     return 0;
 }
+
+int fs_mgr_early_setup_verity(struct fstab_rec *fstab_rec)
+{
+    if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+        int rc = fs_mgr_setup_verity(fstab_rec);
+        if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+            INFO("Verity disabled");
+            return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
+        } else if (rc == FS_MGR_SETUP_VERITY_SUCCESS) {
+            return FS_MGR_EARLY_SETUP_VERITY_SUCCESS;
+        } else {
+            return FS_MGR_EARLY_SETUP_VERITY_FAIL;
+        }
+    } else if (device_is_secure()) {
+        ERROR("Verity must be enabled for early mounted partitions on secured devices.\n");
+        return FS_MGR_EARLY_SETUP_VERITY_FAIL;
+    }
+    return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
+}
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 45adb34..f03b2dd 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -78,6 +78,7 @@
     { "formattable", MF_FORMATTABLE },
     { "slotselect",  MF_SLOTSELECT },
     { "nofail",      MF_NOFAIL },
+    { "latemount",   MF_LATEMOUNT },
     { "defaults",    0 },
     { 0,             0 },
 };
@@ -241,9 +242,8 @@
     return f;
 }
 
-struct fstab *fs_mgr_read_fstab(const char *fstab_path)
+struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
 {
-    FILE *fstab_file;
     int cnt, entries;
     ssize_t len;
     size_t alloc_len = 0;
@@ -255,12 +255,6 @@
 #define FS_OPTIONS_LEN 1024
     char tmp_fs_options[FS_OPTIONS_LEN];
 
-    fstab_file = fopen(fstab_path, "r");
-    if (!fstab_file) {
-        ERROR("Cannot open file %s\n", fstab_path);
-        return 0;
-    }
-
     entries = 0;
     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
         /* if the last character is a newline, shorten the string by 1 byte */
@@ -286,7 +280,6 @@
     /* Allocate and init the fstab structure */
     fstab = calloc(1, sizeof(struct fstab));
     fstab->num_entries = entries;
-    fstab->fstab_filename = strdup(fstab_path);
     fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
 
     fseek(fstab_file, 0, SEEK_SET);
@@ -370,18 +363,34 @@
         ERROR("Error updating for slotselect\n");
         goto err;
     }
-    fclose(fstab_file);
     free(line);
     return fstab;
 
 err:
-    fclose(fstab_file);
     free(line);
     if (fstab)
         fs_mgr_free_fstab(fstab);
     return NULL;
 }
 
+struct fstab *fs_mgr_read_fstab(const char *fstab_path)
+{
+    FILE *fstab_file;
+    struct fstab *fstab;
+
+    fstab_file = fopen(fstab_path, "r");
+    if (!fstab_file) {
+        ERROR("Cannot open file %s\n", fstab_path);
+        return NULL;
+    }
+    fstab = fs_mgr_read_fstab_file(fstab_file);
+    if (fstab) {
+        fstab->fstab_filename = strdup(fstab_path);
+    }
+    fclose(fstab_file);
+    return fstab;
+}
+
 void fs_mgr_free_fstab(struct fstab *fstab)
 {
     int i;
@@ -545,3 +554,8 @@
 {
     return fstab->fs_mgr_flags & MF_NOFAIL;
 }
+
+int fs_mgr_is_latemount(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_LATEMOUNT;
+}
diff --git a/fs_mgr/fs_mgr_main.c b/fs_mgr/fs_mgr_main.c
index b3f131e..33a7496 100644
--- a/fs_mgr/fs_mgr_main.c
+++ b/fs_mgr/fs_mgr_main.c
@@ -95,7 +95,7 @@
     fstab = fs_mgr_read_fstab(fstab_file);
 
     if (a_flag) {
-        return fs_mgr_mount_all(fstab);
+        return fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT);
     } else if (n_flag) {
         return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0);
     } else if (u_flag) {
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 46975f1..6d9492b 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -48,7 +48,7 @@
  *
  *   <fs_mgr_options> is a comma separated list of flags that control the operation of
  *                     the fs_mgr program.  The list includes "wait", which will wait till
- *                     the <source> file exists, and "check", which requests that the fs_mgr 
+ *                     the <source> file exists, and "check", which requests that the fs_mgr
  *                     run an fscheck program on the <source> before mounting the filesystem.
  *                     If check is specifed on a read-only filesystem, it is ignored.
  *                     Also, "encryptable" means that filesystem can be encrypted.
@@ -83,6 +83,7 @@
 #define MF_FORMATTABLE  0x4000
 #define MF_SLOTSELECT   0x8000
 #define MF_FORCEFDEORFBE 0x10000
+#define MF_LATEMOUNT    0x20000
 #define MF_NOFAIL       0x40000
 
 #define DM_BUF_SIZE 4096
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 031b042..7fe6763 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -341,17 +341,6 @@
     return 0;
 }
 
-static int test_access(char *device) {
-    int tries = 25;
-    while (tries--) {
-        if (!access(device, F_OK) || errno != ENOENT) {
-            return 0;
-        }
-        usleep(40 * 1000);
-    }
-    return -1;
-}
-
 static int check_verity_restart(const char *fname)
 {
     char buffer[VERITY_KMSG_BUFSIZE + 1];
@@ -1042,11 +1031,6 @@
     fstab->blk_device = verity_blk_name;
     verity_blk_name = 0;
 
-    // make sure we've set everything up properly
-    if (test_access(fstab->blk_device) < 0) {
-        goto out;
-    }
-
     retval = FS_MGR_SETUP_VERITY_SUCCESS;
 
 out:
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 6f2548d..b43847c 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -17,6 +17,7 @@
 #ifndef __CORE_FS_MGR_H
 #define __CORE_FS_MGR_H
 
+#include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <linux/dm-ioctl.h>
@@ -41,6 +42,13 @@
     VERITY_MODE_DEFAULT = VERITY_MODE_RESTART
 };
 
+// Mount modes
+enum mount_mode {
+    MOUNT_MODE_DEFAULT = 0,
+    MOUNT_MODE_EARLY = 1,
+    MOUNT_MODE_LATE = 2
+};
+
 /*
  * The entries must be kept in the same order as they were seen in the fstab.
  * Unless explicitly requested, a lookup on mount point should always
@@ -73,6 +81,7 @@
 typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
         const char *mount_point, int mode, int status);
 
+struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file);
 struct fstab *fs_mgr_read_fstab(const char *fstab_path);
 void fs_mgr_free_fstab(struct fstab *fstab);
 
@@ -83,7 +92,7 @@
 #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTED 1
 #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0
 #define FS_MGR_MNTALL_FAIL (-1)
-int fs_mgr_mount_all(struct fstab *fstab);
+int fs_mgr_mount_all(struct fstab *fstab, int mount_mode);
 
 #define FS_MGR_DOMNT_FAILED (-1)
 #define FS_MGR_DOMNT_BUSY (-2)
@@ -111,10 +120,16 @@
 int fs_mgr_is_notrim(struct fstab_rec *fstab);
 int fs_mgr_is_formattable(struct fstab_rec *fstab);
 int fs_mgr_is_nofail(struct fstab_rec *fstab);
+int fs_mgr_is_latemount(struct fstab_rec *fstab);
 int fs_mgr_swapon_all(struct fstab *fstab);
 
 int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
 
+#define FS_MGR_EARLY_SETUP_VERITY_NO_VERITY -2
+#define FS_MGR_EARLY_SETUP_VERITY_FAIL -1
+#define FS_MGR_EARLY_SETUP_VERITY_SUCCESS 0
+int fs_mgr_early_setup_verity(struct fstab_rec *fstab);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 612885b..857bcb2 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -257,13 +257,13 @@
 
 static int draw_text(const char *str, int x, int y)
 {
-    int str_len_px = gr_measure(str);
+    int str_len_px = gr_measure(gr_sys_font(), str);
 
     if (x < 0)
         x = (gr_fb_width() - str_len_px) / 2;
     if (y < 0)
         y = (gr_fb_height() - char_height) / 2;
-    gr_text(x, y, str, 0);
+    gr_text(gr_sys_font(), x, y, str, 0);
 
     return y + char_height;
 }
@@ -364,7 +364,7 @@
         }
 
         gr_init();
-        gr_font_size(&char_width, &char_height);
+        gr_font_size(gr_sys_font(), &char_width, &char_height);
 
 #ifndef CHARGER_DISABLE_INIT_BLANK
         gr_fb_blank(true);
diff --git a/include/android/log.h b/include/android/log.h
index 2956e6e..a4973b2 100644
--- a/include/android/log.h
+++ b/include/android/log.h
@@ -89,6 +89,11 @@
 } android_LogPriority;
 
 /*
+ * Release any logger resources (a new log write will immediately re-acquire)
+ */
+void __android_log_close();
+
+/*
  * Send a simple string to the log.
  */
 int __android_log_write(int prio, const char *tag, const char *text);
diff --git a/include/cutils/ashmem.h b/include/cutils/ashmem.h
index acedf73..d80caa6 100644
--- a/include/cutils/ashmem.h
+++ b/include/cutils/ashmem.h
@@ -20,6 +20,7 @@
 extern "C" {
 #endif
 
+int ashmem_valid(int fd);
 int ashmem_create_region(const char *name, size_t size);
 int ashmem_set_prot_region(int fd, int prot);
 int ashmem_pin_region(int fd, size_t offset, size_t len);
diff --git a/include/cutils/process_name.h b/include/cutils/process_name.h
deleted file mode 100644
index 1e72e5c..0000000
--- a/include/cutils/process_name.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Gives the current process a name.
- */
-
-#ifndef __PROCESS_NAME_H
-#define __PROCESS_NAME_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Sets the current process name.
- *
- * Warning: This leaks a string every time you call it. Use judiciously!
- */
-void set_process_name(const char* process_name);
-
-/** Gets the current process name. */
-const char* get_process_name(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __PROCESS_NAME_H */ 
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index c9790ad..19313af 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -70,7 +70,8 @@
 #define ATRACE_TAG_PACKAGE_MANAGER  (1<<18)
 #define ATRACE_TAG_SYSTEM_SERVER    (1<<19)
 #define ATRACE_TAG_DATABASE         (1<<20)
-#define ATRACE_TAG_LAST             ATRACE_TAG_DATABASE
+#define ATRACE_TAG_NETWORK          (1<<21)
+#define ATRACE_TAG_LAST             ATRACE_TAG_NETWORK
 
 // Reserved for initialization.
 #define ATRACE_TAG_NOT_READY        (1ULL<<63)
diff --git a/include/log/logger.h b/include/log/logger.h
index 60d47a2..256fdd1 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -143,7 +143,14 @@
     }
     char *msg()
     {
-        return entry.hdr_size ? (char *) buf + entry.hdr_size : entry_v1.msg;
+        unsigned short hdr_size = entry.hdr_size;
+        if (!hdr_size) {
+            hdr_size = sizeof(entry_v1);
+        }
+        if ((hdr_size < sizeof(entry_v1)) || (hdr_size > sizeof(entry))) {
+            return NULL;
+        }
+        return (char *) buf + hdr_size;
     }
     unsigned int len()
     {
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
index 18049cd..2137069 100644
--- a/include/sysutils/FrameworkListener.h
+++ b/include/sysutils/FrameworkListener.h
@@ -32,6 +32,7 @@
     int mCommandCount;
     bool mWithSeq;
     FrameworkCommandCollection *mCommands;
+    bool mSkipToNextNullByte;
 
 public:
     FrameworkListener(const char *socketName);
diff --git a/include/utils/Mutex.h b/include/utils/Mutex.h
index 8c4683c..d106185 100644
--- a/include/utils/Mutex.h
+++ b/include/utils/Mutex.h
@@ -64,13 +64,18 @@
     status_t    tryLock();
 
 #if defined(__ANDROID__)
-    // lock the mutex, but don't wait longer than timeoutMilliseconds.
+    // Lock the mutex, but don't wait longer than timeoutNs (relative time).
     // Returns 0 on success, TIMED_OUT for failure due to timeout expiration.
     //
     // OSX doesn't have pthread_mutex_timedlock() or equivalent. To keep
     // capabilities consistent across host OSes, this method is only available
     // when building Android binaries.
-    status_t    timedLock(nsecs_t timeoutMilliseconds);
+    //
+    // FIXME?: pthread_mutex_timedlock is based on CLOCK_REALTIME,
+    // which is subject to NTP adjustments, and includes time during suspend,
+    // so a timeout may occur even though no processes could run.
+    // Not holding a partial wakelock may lead to a system suspend.
+    status_t    timedLock(nsecs_t timeoutNs);
 #endif
 
     // Manages the mutex automatically. It'll be locked when Autolock is
@@ -134,6 +139,7 @@
 }
 #if defined(__ANDROID__)
 inline status_t Mutex::timedLock(nsecs_t timeoutNs) {
+    timeoutNs += systemTime(SYSTEM_TIME_REALTIME);
     const struct timespec ts = {
         /* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000),
         /* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000),
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index 950dbd0..3c318c4 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -14,6 +14,159 @@
  * limitations under the License.
  */
 
+
+// SOME COMMENTS ABOUT USAGE:
+
+// This provides primarily wp<> weak pointer types and RefBase, which work
+// together with sp<> from <StrongPointer.h>.
+
+// sp<> (and wp<>) are a type of smart pointer that use a well defined protocol
+// to operate. As long as the object they are templated with implements that
+// protocol, these smart pointers work. In several places the platform
+// instantiates sp<> with non-RefBase objects; the two are not tied to each
+// other.
+
+// RefBase is such an implementation and it supports strong pointers, weak
+// pointers and some magic features for the binder.
+
+// So, when using RefBase objects, you have the ability to use strong and weak
+// pointers through sp<> and wp<>.
+
+// Normally, when the last strong pointer goes away, the object is destroyed,
+// i.e. it's destructor is called. HOWEVER, parts of its associated memory is not
+// freed until the last weak pointer is released.
+
+// Weak pointers are essentially "safe" pointers. They are always safe to
+// access through promote(). They may return nullptr if the object was
+// destroyed because it ran out of strong pointers. This makes them good candidates
+// for keys in a cache for instance.
+
+// Weak pointers remain valid for comparison purposes even after the underlying
+// object has been destroyed. Even if object A is destroyed and its memory reused
+// for B, A remaining weak pointer to A will not compare equal to one to B.
+// This again makes them attractive for use as keys.
+
+// How is this supposed / intended to be used?
+
+// Our recommendation is to use strong references (sp<>) when there is an
+// ownership relation. e.g. when an object "owns" another one, use a strong
+// ref. And of course use strong refs as arguments of functions (it's extremely
+// rare that a function will take a wp<>).
+
+// Typically a newly allocated object will immediately be used to initialize
+// a strong pointer, which may then be used to construct or assign to other
+// strong and weak pointers.
+
+// Use weak references when there are no ownership relation. e.g. the keys in a
+// cache (you cannot use plain pointers because there is no safe way to acquire
+// a strong reference from a vanilla pointer).
+
+// This implies that two objects should never (or very rarely) have sp<> on
+// each other, because they can't both own each other.
+
+
+// Caveats with reference counting
+
+// Obviously, circular strong references are a big problem; this creates leaks
+// and it's hard to debug -- except it's in fact really easy because RefBase has
+// tons of debugging code for that. It can basically tell you exactly where the
+// leak is.
+
+// Another problem has to do with destructors with side effects. You must
+// assume that the destructor of reference counted objects can be called AT ANY
+// TIME. For instance code as simple as this:
+
+// void setStuff(const sp<Stuff>& stuff) {
+//   std::lock_guard<std::mutex> lock(mMutex);
+//   mStuff = stuff;
+// }
+
+// is very dangerous. This code WILL deadlock one day or another.
+
+// What isn't obvious is that ~Stuff() can be called as a result of the
+// assignment. And it gets called with the lock held. First of all, the lock is
+// protecting mStuff, not ~Stuff(). Secondly, if ~Stuff() uses its own internal
+// mutex, now you have mutex ordering issues.  Even worse, if ~Stuff() is
+// virtual, now you're calling into "user" code (potentially), by that, I mean,
+// code you didn't even write.
+
+// A correct way to write this code is something like:
+
+// void setStuff(const sp<Stuff>& stuff) {
+//   std::unique_lock<std::mutex> lock(mMutex);
+//   sp<Stuff> hold = mStuff;
+//   mStuff = stuff;
+//   lock.unlock();
+// }
+
+// More importantly, reference counted objects should do as little work as
+// possible in their destructor, or at least be mindful that their destructor
+// could be called from very weird and unintended places.
+
+// Other more specific restrictions for wp<> and sp<>:
+
+// Do not construct a strong pointer to "this" in an object's constructor.
+// The onFirstRef() callback would be made on an incompletely constructed
+// object.
+// Construction of a weak pointer to "this" in an object's constructor is also
+// discouraged. But the implementation was recently changed so that, in the
+// absence of extendObjectLifetime() calls, weak pointers no longer impact
+// object lifetime, and hence this no longer risks premature deallocation,
+// and hence usually works correctly.
+
+// Such strong or weak pointers can be safely created in the RefBase onFirstRef()
+// callback.
+
+// Use of wp::unsafe_get() for any purpose other than debugging is almost
+// always wrong.  Unless you somehow know that there is a longer-lived sp<> to
+// the same object, it may well return a pointer to a deallocated object that
+// has since been reallocated for a different purpose. (And if you know there
+// is a longer-lived sp<>, why not use an sp<> directly?) A wp<> should only be
+// dereferenced by using promote().
+
+// Any object inheriting from RefBase should always be destroyed as the result
+// of a reference count decrement, not via any other means.  Such objects
+// should never be stack allocated, or appear directly as data members in other
+// objects. Objects inheriting from RefBase should have their strong reference
+// count incremented as soon as possible after construction. Usually this
+// will be done via construction of an sp<> to the object, but may instead
+// involve other means of calling RefBase::incStrong().
+// Explicitly deleting or otherwise destroying a RefBase object with outstanding
+// wp<> or sp<> pointers to it will result in an abort or heap corruption.
+
+// It is particularly important not to mix sp<> and direct storage management
+// since the sp from raw pointer constructor is implicit. Thus if a RefBase-
+// -derived object of type T is managed without ever incrementing its strong
+// count, and accidentally passed to f(sp<T>), a strong pointer to the object
+// will be temporarily constructed and destroyed, prematurely deallocating the
+// object, and resulting in heap corruption. None of this would be easily
+// visible in the source.
+
+// Extra Features:
+
+// RefBase::extendObjectLifetime() can be used to prevent destruction of the
+// object while there are still weak references. This is really special purpose
+// functionality to support Binder.
+
+// Wp::promote(), implemented via the attemptIncStrong() member function, is
+// used to try to convert a weak pointer back to a strong pointer.  It's the
+// normal way to try to access the fields of an object referenced only through
+// a wp<>.  Binder code also sometimes uses attemptIncStrong() directly.
+
+// RefBase provides a number of additional callbacks for certain reference count
+// events, as well as some debugging facilities.
+
+// Debugging support can be enabled by turning on DEBUG_REFS in RefBase.cpp.
+// Otherwise little checking is provided.
+
+// Thread safety:
+
+// Like std::shared_ptr, sp<> and wp<> allow concurrent accesses to DIFFERENT
+// sp<> and wp<> instances that happen to refer to the same underlying object.
+// They do NOT support concurrent access (where at least one access is a write)
+// to THE SAME sp<> or wp<>.  In effect, their thread-safety properties are
+// exactly like those of T*, NOT atomic<T*>.
+
 #ifndef ANDROID_REF_BASE_H
 #define ANDROID_REF_BASE_H
 
@@ -142,9 +295,19 @@
         FIRST_INC_STRONG = 0x0001
     };
     
+    // Invoked after creation of initial strong pointer/reference.
     virtual void            onFirstRef();
+    // Invoked when either the last strong reference goes away, or we need to undo
+    // the effect of an unnecessary onIncStrongAttempted.
     virtual void            onLastStrongRef(const void* id);
+    // Only called in OBJECT_LIFETIME_WEAK case.  Returns true if OK to promote to
+    // strong reference. May have side effects if it returns true.
+    // The first flags argument is always FIRST_INC_STRONG.
+    // TODO: Remove initial flag argument.
     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
+    // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
+    // kind goes away.  Unused.
+    // TODO: Remove.
     virtual void            onLastWeakRef(const void* id);
 
 private:
diff --git a/init/Android.mk b/init/Android.mk
index 36a5713..98bf12d 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -95,8 +95,8 @@
     libc \
     libselinux \
     liblog \
-    libcrypto_utils_static \
-    libcrypto_static \
+    libcrypto_utils \
+    libcrypto \
     libc++_static \
     libdl \
     libsparse_static \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 055723f..d25e4a8 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -465,9 +465,9 @@
  *
  * start_index: index of the first path in the args list
  */
-static void import_late(const std::vector<std::string>& args, size_t start_index) {
+static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) {
     Parser& parser = Parser::GetInstance();
-    if (args.size() <= start_index) {
+    if (end_index <= start_index) {
         // Use the default set if no path is given
         static const std::vector<std::string> init_directories = {
             "/system/etc/init",
@@ -479,21 +479,19 @@
             parser.ParseConfig(dir);
         }
     } else {
-        for (size_t i = start_index; i < args.size(); ++i) {
+        for (size_t i = start_index; i < end_index; ++i) {
             parser.ParseConfig(args[i]);
         }
     }
 }
 
-/* mount_all <fstab> [ <path> ]*
+/* mount_fstab
  *
- * This function might request a reboot, in which case it will
- * not return.
+ *  Call fs_mgr_mount_all() to mount the given fstab
  */
-static int do_mount_all(const std::vector<std::string>& args) {
+static int mount_fstab(const char* fstabfile, int mount_mode) {
     int ret = -1;
 
-    const char* fstabfile = args[1].c_str();
     /*
      * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
      * do the call in the child to provide protection to the main init
@@ -523,7 +521,7 @@
         android::base::ScopedLogSeverity info(android::base::INFO);
 
         struct fstab* fstab = fs_mgr_read_fstab(fstabfile);
-        int child_ret = fs_mgr_mount_all(fstab);
+        int child_ret = fs_mgr_mount_all(fstab, mount_mode);
         fs_mgr_free_fstab(fstab);
         if (child_ret == -1) {
             PLOG(ERROR) << "fs_mgr_mount_all returned an error";
@@ -533,28 +531,38 @@
         /* fork failed, return an error */
         return -1;
     }
+    return ret;
+}
 
-    /* Paths of .rc files are specified at the 2nd argument and beyond */
-    import_late(args, 2);
-
-    if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
+/* Queue event based on fs_mgr return code.
+ *
+ * code: return code of fs_mgr_mount_all
+ *
+ * This function might request a reboot, in which case it will
+ * not return.
+ *
+ * return code is processed based on input code
+ */
+static int queue_fs_event(int code) {
+    int ret = code;
+    if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
         ActionManager::GetInstance().QueueEventTrigger("encrypt");
-    } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
+    } else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
         property_set("ro.crypto.state", "encrypted");
         property_set("ro.crypto.type", "block");
         ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
-    } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
+    } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
         property_set("ro.crypto.state", "unencrypted");
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-    } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
+    } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
         property_set("ro.crypto.state", "unsupported");
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-    } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
+    } else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
         /* Setup a wipe via recovery, and reboot into recovery */
         PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
         ret = wipe_data_via_recovery("wipe_data_via_recovery");
         /* If reboot worked, there is no return. */
-    } else if (ret == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
+    } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
         if (e4crypt_install_keyring()) {
             return -1;
         }
@@ -564,14 +572,55 @@
         // Although encrypted, we have device key, so we do not need to
         // do anything different from the nonencrypted case.
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-    } else if (ret > 0) {
-        PLOG(ERROR) << "fs_mgr_mount_all returned unexpected error " << ret;
+    } else if (code > 0) {
+        PLOG(ERROR) << "fs_mgr_mount_all returned unexpected error " << code;
     }
     /* else ... < 0: error */
 
     return ret;
 }
 
+/* mount_all <fstab> [ <path> ]* [--<options>]*
+ *
+ * This function might request a reboot, in which case it will
+ * not return.
+ */
+static int do_mount_all(const std::vector<std::string>& args) {
+    std::size_t na = 0;
+    bool import_rc = true;
+    bool queue_event = true;
+    int mount_mode = MOUNT_MODE_DEFAULT;
+    const char* fstabfile = args[1].c_str();
+    std::size_t path_arg_end = args.size();
+
+    for (na = args.size() - 1; na > 1; --na) {
+        if (args[na] == "--early") {
+             path_arg_end = na;
+             queue_event = false;
+             mount_mode = MOUNT_MODE_EARLY;
+        } else if (args[na] == "--late") {
+            path_arg_end = na;
+            import_rc = false;
+            mount_mode = MOUNT_MODE_LATE;
+        }
+    }
+
+    int ret =  mount_fstab(fstabfile, mount_mode);
+
+    if (import_rc) {
+        /* Paths of .rc files are specified at the 2nd argument and beyond */
+        import_late(args, 2, path_arg_end);
+    }
+
+    if (queue_event) {
+        /* queue_fs_event will queue event based on mount_fstab return code
+         * and return processed return code*/
+        ret = queue_fs_event(ret);
+    }
+
+    return ret;
+}
+
 static int do_swapon_all(const std::vector<std::string>& args) {
     struct fstab *fstab;
     int ret;
diff --git a/init/devices.cpp b/init/devices.cpp
index 373177e..bad04ae 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
+#include <dirent.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <fnmatch.h>
+#include <libgen.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
 #include <string.h>
-
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
 #include <sys/un.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
 #include <linux/netlink.h>
 
 #include <memory>
@@ -39,11 +41,10 @@
 #include <selinux/avc.h>
 
 #include <private/android_filesystem_config.h>
-#include <sys/time.h>
-#include <sys/wait.h>
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <cutils/list.h>
 #include <cutils/uevent.h>
 
@@ -540,30 +541,49 @@
     return links;
 }
 
+static void make_link_init(const char* oldpath, const char* newpath) {
+  const char* slash = strrchr(newpath, '/');
+  if (!slash) return;
+
+  if (mkdir_recursive(dirname(newpath), 0755)) {
+    PLOG(ERROR) << "Failed to create directory " << dirname(newpath);
+  }
+
+  if (symlink(oldpath, newpath) && errno != EEXIST) {
+    PLOG(ERROR) << "Failed to symlink " << oldpath << " to " << newpath;
+  }
+}
+
+static void remove_link(const char* oldpath, const char* newpath) {
+  std::string path;
+  if (android::base::Readlink(newpath, &path) && path == oldpath) unlink(newpath);
+}
+
 static void handle_device(const char *action, const char *devpath,
         const char *path, int block, int major, int minor, char **links)
 {
-    int i;
-
     if(!strcmp(action, "add")) {
         make_device(devpath, path, block, major, minor, (const char **)links);
         if (links) {
-            for (i = 0; links[i]; i++)
+            for (int i = 0; links[i]; i++) {
                 make_link_init(devpath, links[i]);
+            }
         }
     }
 
     if(!strcmp(action, "remove")) {
         if (links) {
-            for (i = 0; links[i]; i++)
+            for (int i = 0; links[i]; i++) {
                 remove_link(devpath, links[i]);
+            }
         }
         unlink(devpath);
     }
 
     if (links) {
-        for (i = 0; links[i]; i++)
+        for (int i = 0; links[i]; i++) {
             free(links[i]);
+        }
         free(links);
     }
 }
@@ -601,14 +621,17 @@
     return name;
 }
 
+#define DEVPATH_LEN 96
+#define MAX_DEV_NAME 64
+
 static void handle_block_device_event(struct uevent *uevent)
 {
     const char *base = "/dev/block/";
     const char *name;
-    char devpath[96];
+    char devpath[DEVPATH_LEN];
     char **links = NULL;
 
-    name = parse_device_name(uevent, 64);
+    name = parse_device_name(uevent, MAX_DEV_NAME);
     if (!name)
         return;
 
@@ -622,8 +645,6 @@
             uevent->major, uevent->minor, links);
 }
 
-#define DEVPATH_LEN 96
-
 static bool assemble_devpath(char *devpath, const char *dirname,
         const char *devname)
 {
@@ -657,7 +678,7 @@
     char devpath[DEVPATH_LEN] = {0};
     char **links = NULL;
 
-    name = parse_device_name(uevent, 64);
+    name = parse_device_name(uevent, MAX_DEV_NAME);
     if (!name)
         return;
 
@@ -900,7 +921,8 @@
 }
 
 #define UEVENT_MSG_LEN  2048
-void handle_device_fd()
+
+static inline void handle_device_fd_with(void (handle_uevent)(struct uevent*))
 {
     char msg[UEVENT_MSG_LEN+2];
     int n;
@@ -913,21 +935,28 @@
 
         struct uevent uevent;
         parse_event(msg, &uevent);
-
-        if (selinux_status_updated() > 0) {
-            struct selabel_handle *sehandle2;
-            sehandle2 = selinux_android_file_context_handle();
-            if (sehandle2) {
-                selabel_close(sehandle);
-                sehandle = sehandle2;
-            }
-        }
-
-        handle_device_event(&uevent);
-        handle_firmware_event(&uevent);
+        handle_uevent(&uevent);
     }
 }
 
+void handle_device_fd()
+{
+    handle_device_fd_with(
+        [](struct uevent *uevent) {
+            if (selinux_status_updated() > 0) {
+                struct selabel_handle *sehandle2;
+                sehandle2 = selinux_android_file_context_handle();
+                if (sehandle2) {
+                    selabel_close(sehandle);
+                    sehandle = sehandle2;
+                }
+            }
+
+            handle_device_event(uevent);
+            handle_firmware_event(uevent);
+        });
+}
+
 /* Coldboot walks parts of the /sys tree and pokes the uevent files
 ** to cause the kernel to regenerate device add events that happened
 ** before init's device manager was started
@@ -979,6 +1008,65 @@
     }
 }
 
+static void early_uevent_handler(struct uevent *uevent, const char *base, bool is_block)
+{
+    const char *name;
+    char devpath[DEVPATH_LEN];
+
+    if (is_block && strncmp(uevent->subsystem, "block", 5))
+        return;
+
+    name = parse_device_name(uevent, MAX_DEV_NAME);
+    if (!name) {
+        LOG(ERROR) << "Failed to parse dev name from uevent: " << uevent->action
+                   << " " << uevent->partition_name << " " << uevent->partition_num
+                   << " " << uevent->major << ":" << uevent->minor;
+        return;
+    }
+
+    snprintf(devpath, sizeof(devpath), "%s%s", base, name);
+    make_dir(base, 0755);
+
+    dev_t dev = makedev(uevent->major, uevent->minor);
+    mode_t mode = 0600 | (is_block ? S_IFBLK : S_IFCHR);
+    mknod(devpath, mode, dev);
+}
+
+void early_create_dev(const std::string& syspath, early_device_type dev_type)
+{
+    android::base::unique_fd dfd(open(syspath.c_str(), O_RDONLY));
+    if (dfd < 0) {
+        LOG(ERROR) << "Failed to open " << syspath;
+        return;
+    }
+
+    android::base::unique_fd fd(openat(dfd, "uevent", O_WRONLY));
+    if (fd < 0) {
+        LOG(ERROR) << "Failed to open " << syspath << "/uevent";
+        return;
+    }
+
+    fcntl(device_fd, F_SETFL, O_NONBLOCK);
+
+    write(fd, "add\n", 4);
+    handle_device_fd_with(dev_type == EARLY_BLOCK_DEV ?
+        [](struct uevent *uevent) {
+            early_uevent_handler(uevent, "/dev/block/", true);
+        } :
+        [](struct uevent *uevent) {
+            early_uevent_handler(uevent, "/dev/", false);
+        });
+}
+
+int early_device_socket_open() {
+    device_fd = uevent_open_socket(256*1024, true);
+    return device_fd < 0;
+}
+
+void early_device_socket_close() {
+    close(device_fd);
+}
+
 void device_init() {
     sehandle = selinux_android_file_context_handle();
     selinux_status_open(true);
diff --git a/init/devices.h b/init/devices.h
index 6cb0a77..8e9ab7d 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -21,6 +21,13 @@
 
 extern void handle_device_fd();
 extern void device_init(void);
+
+enum early_device_type { EARLY_BLOCK_DEV, EARLY_CHAR_DEV };
+
+extern int early_device_socket_open();
+extern void early_device_socket_close();
+extern void early_create_dev(const std::string& syspath, early_device_type dev_type);
+
 extern int add_dev_perms(const char *name, const char *attr,
                          mode_t perm, unsigned int uid,
                          unsigned int gid, unsigned short prefix,
diff --git a/init/init.cpp b/init/init.cpp
index 29e8cbb..7a0e114 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -55,6 +55,7 @@
 #include "action.h"
 #include "bootchart.h"
 #include "devices.h"
+#include "fs_mgr.h"
 #include "import_parser.h"
 #include "init.h"
 #include "init_parser.h"
@@ -450,9 +451,6 @@
 }
 
 static void process_kernel_cmdline() {
-    // Don't expose the raw commandline to unprivileged processes.
-    chmod("/proc/cmdline", 0440);
-
     // The first pass does the common stuff, and finds if we are in qemu.
     // The second pass is only necessary for qemu to export all kernel params
     // as properties.
@@ -563,6 +561,104 @@
     }
 }
 
+/* Returns a new path consisting of base_path and the file name in reference_path. */
+static std::string get_path(const std::string& base_path, const std::string& reference_path) {
+    std::string::size_type pos = reference_path.rfind('/');
+    if (pos == std::string::npos) {
+        return base_path + '/' + reference_path;
+    } else {
+        return base_path + reference_path.substr(pos);
+    }
+}
+
+/* Imports the fstab info from cmdline. */
+static std::string import_cmdline_fstab() {
+    std::string prefix, fstab, fstab_full;
+
+    import_kernel_cmdline(false,
+        [&](const std::string& key, const std::string& value, bool in_qemu __attribute__((__unused__))) {
+            if (key == "android.early.prefix") {
+                prefix = value;
+            } else if (key == "android.early.fstab") {
+                fstab = value;
+            }
+        });
+    if (!fstab.empty()) {
+        // Convert "mmcblk0p09+/odm+ext4+ro+verify" to "mmcblk0p09 /odm ext4 ro verify"
+        std::replace(fstab.begin(), fstab.end(), '+', ' ');
+        for (const auto& entry : android::base::Split(fstab, "\n")) {
+            fstab_full += prefix + entry + '\n';
+        }
+    }
+    return fstab_full;
+}
+
+/* Early mount vendor and ODM partitions. The fstab info is read from kernel cmdline. */
+static void early_mount() {
+    std::string fstab_string = import_cmdline_fstab();
+    if (fstab_string.empty()) {
+        LOG(INFO) << "Failed to load vendor fstab from kernel cmdline";
+        return;
+    }
+    FILE *fstab_file = fmemopen((void *)fstab_string.c_str(), fstab_string.length(), "r");
+    if (!fstab_file) {
+        PLOG(ERROR) << "Failed to open fstab string as FILE";
+        return;
+    }
+    std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_file(fstab_file), fs_mgr_free_fstab);
+    fclose(fstab_file);
+    if (!fstab) {
+        LOG(ERROR) << "Failed to parse fstab string: " << fstab_string;
+        return;
+    }
+    LOG(INFO) << "Loaded vendor fstab from cmdline";
+
+    if (early_device_socket_open()) {
+        LOG(ERROR) << "Failed to open device uevent socket";
+        return;
+    }
+
+    /* Create /dev/device-mapper for dm-verity */
+    early_create_dev("/sys/devices/virtual/misc/device-mapper", EARLY_CHAR_DEV);
+
+    for (int i = 0; i < fstab->num_entries; ++i) {
+        struct fstab_rec *rec = &fstab->recs[i];
+        std::string mount_point = rec->mount_point;
+        std::string syspath = rec->blk_device;
+
+        if (mount_point != "/vendor" && mount_point != "/odm")
+            continue;
+
+        /* Create mount target under /dev/block/ from sysfs via uevent */
+        LOG(INFO) << "Mounting " << mount_point << " from " << syspath << "...";
+        char *devpath = strdup(get_path("/dev/block", syspath).c_str());
+        if (!devpath) {
+            PLOG(ERROR) << "Failed to strdup dev path in early mount " << syspath;
+            continue;
+        }
+        rec->blk_device = devpath;
+        early_create_dev(syspath, EARLY_BLOCK_DEV);
+
+        int rc = fs_mgr_early_setup_verity(rec);
+        if (rc == FS_MGR_EARLY_SETUP_VERITY_SUCCESS) {
+            /* Mount target is changed to /dev/block/dm-<n>; initiate its creation from sysfs counterpart */
+            early_create_dev(get_path("/sys/devices/virtual/block", rec->blk_device), EARLY_BLOCK_DEV);
+        } else if (rc == FS_MGR_EARLY_SETUP_VERITY_FAIL) {
+            LOG(ERROR) << "Failed to set up dm-verity on " << rec->blk_device;
+            continue;
+        } else { /* FS_MGR_EARLY_SETUP_VERITY_NO_VERITY */
+            LOG(INFO) << "dm-verity disabled on debuggable device; mount directly on " << rec->blk_device;
+        }
+
+        mkdir(mount_point.c_str(), 0755);
+        rc = mount(rec->blk_device, mount_point.c_str(), rec->fs_type, rec->flags, rec->fs_options);
+        if (rc) {
+            PLOG(ERROR) << "Failed to mount on " << rec->blk_device;
+        }
+    }
+    early_device_socket_close();
+}
+
 int main(int argc, char** argv) {
     if (!strcmp(basename(argv[0]), "ueventd")) {
         return ueventd_main(argc, argv);
@@ -579,6 +675,9 @@
 
     bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
 
+    // Don't expose the raw commandline to unprivileged processes.
+    chmod("/proc/cmdline", 0440);
+
     // Get the basic filesystem setup we need put together in the initramdisk
     // on / and then we'll let the rc file figure out the rest.
     if (is_first_stage) {
@@ -591,6 +690,7 @@
         mount("sysfs", "/sys", "sysfs", 0, NULL);
         mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
         mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
+        early_mount();
     }
 
     // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
@@ -643,6 +743,8 @@
     restorecon("/dev/__properties__");
     restorecon("/property_contexts");
     restorecon_recursive("/sys");
+    restorecon_recursive("/dev/block");
+    restorecon("/dev/device-mapper");
 
     epoll_fd = epoll_create1(EPOLL_CLOEXEC);
     if (epoll_fd == -1) {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index e2e1b16..9e13733 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -227,32 +227,29 @@
 static void handle_property_set_fd()
 {
     prop_msg msg;
-    int s;
     int r;
-    struct ucred cr;
-    struct sockaddr_un addr;
-    socklen_t addr_size = sizeof(addr);
-    socklen_t cr_size = sizeof(cr);
     char * source_ctx = NULL;
-    struct pollfd ufds[1];
-    const int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
-    int nr;
 
-    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
+    int s = accept(property_set_fd, nullptr, nullptr);
+    if (s == -1) {
         return;
     }
 
     /* Check socket options here */
+    struct ucred cr;
+    socklen_t cr_size = sizeof(cr);
     if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
         close(s);
         PLOG(ERROR) << "Unable to receive socket options";
         return;
     }
 
+    static constexpr int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
+    struct pollfd ufds[1];
     ufds[0].fd = s;
     ufds[0].events = POLLIN;
     ufds[0].revents = 0;
-    nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
+    int nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
     if (nr == 0) {
         LOG(ERROR) << "sys_prop: timeout waiting for uid " << cr.uid << " to send property message.";
         close(s);
diff --git a/init/readme.txt b/init/readme.txt
index 25b53ec..77e5de2 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -1,4 +1,3 @@
-
 Android Init Language
 ---------------------
 
@@ -78,6 +77,14 @@
 conflict resolution when multiple services are added to the system, as
 each one will go into a separate file.
 
+There are two options "early" and "late" in mount_all command
+which can be set after optional paths. With "--early" set, the
+init executable will skip mounting entries with "latemount" flag
+and triggering fs encryption state event. With "--late" set,
+init executable will only mount entries with "latemount" flag but skip
+importing rc files. By default, no option is set, and mount_all will
+mount_all will process all entries in the given fstab.
+
 Actions
 -------
 Actions are named sequences of commands.  Actions have a trigger which
@@ -188,6 +195,14 @@
   Scheduling priority of the service process. This value has to be in range
   -20 to 19. Default priority is 0. Priority is set via setpriority().
 
+namespace <pid|mnt>
+  Enter a new PID or mount namespace when forking the service.
+
+oom_score_adjust <value>
+   Sets the child's /proc/self/oom_score_adj to the specified value,
+   which must range from -1000 to 1000.
+
+
 Triggers
 --------
 Triggers are strings which can be used to match certain kinds of
@@ -304,10 +319,11 @@
    owned by the root user and root group. If provided, the mode, owner and group
    will be updated if the directory exists already.
 
-mount_all <fstab> [ <path> ]*
+mount_all <fstab> [ <path> ]* [--<option>]
    Calls fs_mgr_mount_all on the given fs_mgr-format fstab and imports .rc files
-   at the specified paths (e.g., on the partitions just mounted). Refer to the
-   section of "Init .rc Files" for detail.
+   at the specified paths (e.g., on the partitions just mounted) with optional
+   options "early" and "late".
+   Refer to the section of "Init .rc Files" for detail.
 
 mount <type> <device> <dir> [ <flag> ]* [<options>]
    Attempt to mount the named device at the directory <dir>
diff --git a/init/service.cpp b/init/service.cpp
index 32aafd6..1caf7c6 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -163,7 +163,7 @@
     : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0),
       time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), namespace_flags_(0),
       seclabel_(""), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
-      priority_(0), args_(args) {
+      priority_(0), oom_score_adjust_(-1000), args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -176,7 +176,7 @@
       time_started_(0), time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid),
       supp_gids_(supp_gids), namespace_flags_(namespace_flags),
       seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
-      priority_(0), args_(args) {
+      priority_(0), oom_score_adjust_(-1000), args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -419,6 +419,18 @@
     return true;
 }
 
+bool Service::ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err) {
+    oom_score_adjust_ = std::stol(args[1], 0, 10);
+
+    if (oom_score_adjust_ < -1000 || oom_score_adjust_ > 1000) {
+        *err = "oom_score_adjust value must be in range -1000 - +1000";
+        return false;
+    }
+
+    return true;
+}
+
+
 bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) {
     seclabel_ = args[1];
     return true;
@@ -476,6 +488,8 @@
         {"keycodes",    {1,     kMax, &Service::ParseKeycodes}},
         {"oneshot",     {0,     0,    &Service::ParseOneshot}},
         {"onrestart",   {1,     kMax, &Service::ParseOnrestart}},
+        {"oom_score_adjust",
+                        {1,     1,    &Service::ParseOomScoreAdjust}},
         {"namespace",   {1,     2,    &Service::ParseNamespace}},
         {"seclabel",    {1,     1,    &Service::ParseSeclabel}},
         {"setenv",      {2,     2,    &Service::ParseSetenv}},
@@ -611,6 +625,14 @@
         return false;
     }
 
+    if (oom_score_adjust_ != -1000) {
+        std::string oom_str = StringPrintf("%d", oom_score_adjust_);
+        std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
+        if (!WriteStringToFile(oom_str, oom_file)) {
+            PLOG(ERROR) << "couldn't write oom_score_adj: " << strerror(errno);
+        }
+    }
+
     time_started_ = gettime();
     pid_ = pid;
     flags_ |= SVC_RUNNING;
diff --git a/init/service.h b/init/service.h
index fb03a07..4a3412c 100644
--- a/init/service.h
+++ b/init/service.h
@@ -126,6 +126,7 @@
     bool ParseKeycodes(const std::vector<std::string>& args, std::string* err);
     bool ParseOneshot(const std::vector<std::string>& args, std::string* err);
     bool ParseOnrestart(const std::vector<std::string>& args, std::string* err);
+    bool ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err);
     bool ParseNamespace(const std::vector<std::string>& args, std::string* err);
     bool ParseSeclabel(const std::vector<std::string>& args, std::string* err);
     bool ParseSetenv(const std::vector<std::string>& args, std::string* err);
@@ -165,6 +166,8 @@
     int ioprio_pri_;
     int priority_;
 
+    int oom_score_adjust_;
+
     std::vector<std::string> args_;
 };
 
diff --git a/init/util.cpp b/init/util.cpp
index c1750d2..660a66f 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -270,40 +270,6 @@
     }
 }
 
-void make_link_init(const char *oldpath, const char *newpath)
-{
-    int ret;
-    char buf[256];
-    const char *slash;
-    int width;
-
-    slash = strrchr(newpath, '/');
-    if (!slash)
-        return;
-    width = slash - newpath;
-    if (width <= 0 || width > (int)sizeof(buf) - 1)
-        return;
-    memcpy(buf, newpath, width);
-    buf[width] = 0;
-    ret = mkdir_recursive(buf, 0755);
-    if (ret) PLOG(ERROR) << "Failed to create directory " << buf;
-
-    ret = symlink(oldpath, newpath);
-    if (ret && errno != EEXIST) PLOG(ERROR) << "Failed to symlink " << oldpath << " to " << newpath;
-}
-
-void remove_link(const char *oldpath, const char *newpath)
-{
-    char path[256];
-    ssize_t ret;
-    ret = readlink(newpath, path, sizeof(path) - 1);
-    if (ret <= 0)
-        return;
-    path[ret] = 0;
-    if (!strcmp(path, oldpath))
-        unlink(newpath);
-}
-
 int wait_for_file(const char *filename, int timeout)
 {
     struct stat info;
diff --git a/init/util.h b/init/util.h
index 29d0497..b83b9a0 100644
--- a/init/util.h
+++ b/init/util.h
@@ -51,8 +51,6 @@
 
 int mkdir_recursive(const char *pathname, mode_t mode);
 void sanitize(char *p);
-void make_link_init(const char *oldpath, const char *newpath);
-void remove_link(const char *oldpath, const char *newpath);
 int wait_for_file(const char *filename, int timeout);
 void import_kernel_cmdline(bool in_qemu,
                            const std::function<void(const std::string&, const std::string&, bool)>&);
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 9bb113a..56a3970 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -67,7 +67,7 @@
 libbacktrace_offline_static_libraries_host := \
 	libbacktrace \
 	libunwind \
-	libziparchive-host \
+	libziparchive \
 	libz \
 	libbase \
 	liblog \
@@ -129,7 +129,7 @@
 	libz \
 
 backtrace_test_static_libraries_host := \
-	libziparchive-host \
+	libziparchive \
 	libz \
 	libutils \
 	libLLVMObject \
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
new file mode 100644
index 0000000..ca7bd31
--- /dev/null
+++ b/libcrypto_utils/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2016 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.
+//
+
+cc_library {
+    name: "libcrypto_utils",
+    host_supported: true,
+    srcs: [
+        "android_pubkey.c",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-std=c99",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    shared_libs: ["libcrypto"],
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+}
diff --git a/libcrypto_utils/Android.mk b/libcrypto_utils/Android.mk
deleted file mode 100644
index b6d2204..0000000
--- a/libcrypto_utils/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := libcrypto
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := libcrypto
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils_static
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libcrypto
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils_static
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libcrypto_static
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 4f26034..8624d13 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -42,7 +42,6 @@
         "load_file.c",
         "native_handle.c",
         "open_memstream.c",
-        "process_name.c",
         "record_stream.c",
         "sched_policy.c",
         "sockets.cpp",
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index 4a07d66..09fa09a 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -85,7 +85,7 @@
 }
 
 /* Make sure file descriptor references ashmem, negative number means false */
-static int __ashmem_is_ashmem(int fd)
+static int __ashmem_is_ashmem(int fd, int fatal)
 {
     dev_t rdev;
     struct stat st;
@@ -117,22 +117,29 @@
         }
     }
 
-    if (rdev) {
-        LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d",
-          fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
-          S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP,
-          major(rdev), minor(rdev));
-    } else {
-        LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o",
-          fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
-          S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP);
+    if (fatal) {
+        if (rdev) {
+            LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d",
+              fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
+              S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP,
+              major(rdev), minor(rdev));
+        } else {
+            LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o",
+              fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
+              S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP);
+        }
+        /* NOTREACHED */
     }
-    /* NOTREACHED */
 
     errno = ENOTTY;
     return -1;
 }
 
+int ashmem_valid(int fd)
+{
+    return __ashmem_is_ashmem(fd, 0) >= 0;
+}
+
 /*
  * ashmem_create_region - creates a new ashmem region and returns the file
  * descriptor, or <0 on error
@@ -175,7 +182,7 @@
 
 int ashmem_set_prot_region(int fd, int prot)
 {
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
@@ -187,7 +194,7 @@
 {
     struct ashmem_pin pin = { offset, len };
 
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
@@ -199,7 +206,7 @@
 {
     struct ashmem_pin pin = { offset, len };
 
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
@@ -209,7 +216,7 @@
 
 int ashmem_get_size_region(int fd)
 {
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
diff --git a/libcutils/process_name.c b/libcutils/process_name.c
deleted file mode 100644
index 5d28b6f..0000000
--- a/libcutils/process_name.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.
- */
-
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#if defined(__linux__)
-#include <sys/prctl.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cutils/process_name.h>
-#if defined(__ANDROID__)
-#include <cutils/properties.h>
-#endif
-
-#define PROCESS_NAME_DEVICE "/sys/qemu_trace/process_name"
-
-static const char* process_name = "unknown";
-#if defined(__ANDROID__)
-static int running_in_emulator = -1;
-#endif
-
-void set_process_name(const char* new_name) {
-#if defined(__ANDROID__)
-    char  propBuf[PROPERTY_VALUE_MAX];
-#endif
-
-    if (new_name == NULL) {
-        return;
-    }
-
-    // We never free the old name. Someone else could be using it.
-    int len = strlen(new_name);
-    char* copy = (char*) malloc(len + 1);
-    strcpy(copy, new_name);
-    process_name = (const char*) copy;
-
-#if defined(__linux__)
-    if (len < 16) {
-        prctl(PR_SET_NAME, (unsigned long) new_name, 0, 0, 0);
-    } else {
-        prctl(PR_SET_NAME, (unsigned long) new_name + len - 15, 0, 0, 0);
-    }
-#endif
-
-#if defined(__ANDROID__)
-    // If we know we are not running in the emulator, then return.
-    if (running_in_emulator == 0) {
-        return;
-    }
-
-    // If the "running_in_emulator" variable has not been initialized,
-    // then do it now.
-    if (running_in_emulator == -1) {
-        property_get("ro.kernel.qemu", propBuf, "");
-        if (propBuf[0] == '1') {
-            running_in_emulator = 1;
-        } else {
-            running_in_emulator = 0;
-            return;
-        }
-    }
-
-    // If the emulator was started with the "-trace file" command line option
-    // then we want to record the process name in the trace even if we are
-    // not currently tracing instructions (so that we will know the process
-    // name when we do start tracing instructions).  We do not need to execute
-    // this code if we are just running in the emulator without the "-trace"
-    // command line option, but we don't know that here and this function
-    // isn't called frequently enough to bother optimizing that case.
-    int fd = open(PROCESS_NAME_DEVICE, O_RDWR);
-    if (fd < 0)
-        return;
-    write(fd, process_name, strlen(process_name) + 1);
-    close(fd);
-#endif
-}
-
-const char* get_process_name(void) {
-    return process_name;
-}
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 0a8346b..cba800f 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -52,6 +52,7 @@
 static pthread_once_t the_once = PTHREAD_ONCE_INIT;
 
 static int __sys_supports_schedgroups = -1;
+static int __sys_supports_timerslack = -1;
 
 // File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error.
 static int bg_cgroup_fd = -1;
@@ -107,7 +108,7 @@
 
 static void __initialize(void) {
     char* filename;
-    if (!access("/dev/cpuctl/tasks", F_OK)) {
+    if (!access("/dev/cpuctl/tasks", W_OK)) {
         __sys_supports_schedgroups = 1;
 
         filename = "/dev/cpuctl/tasks";
@@ -126,7 +127,7 @@
     }
 
 #ifdef USE_CPUSETS
-    if (!access("/dev/cpuset/tasks", F_OK)) {
+    if (!access("/dev/cpuset/tasks", W_OK)) {
 
         filename = "/dev/cpuset/foreground/tasks";
         fg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
@@ -147,6 +148,10 @@
 #endif
     }
 #endif
+
+    char buf[64];
+    snprintf(buf, sizeof(buf), "/proc/%d/timerslack_ns", getpid());
+    __sys_supports_timerslack = !access(buf, W_OK);
 }
 
 /*
@@ -437,8 +442,10 @@
                            &param);
     }
 
-    set_timerslack_ns(tid, policy == SP_BACKGROUND ?
+    if (__sys_supports_timerslack) {
+        set_timerslack_ns(tid, policy == SP_BACKGROUND ?
                                TIMER_SLACK_BG : TIMER_SLACK_FG);
+    }
 
     return 0;
 }
diff --git a/libcutils/socket_network_client_unix.c b/libcutils/socket_network_client_unix.c
index 3300b8f..46818d6 100644
--- a/libcutils/socket_network_client_unix.c
+++ b/libcutils/socket_network_client_unix.c
@@ -59,64 +59,63 @@
         return -1;
     }
 
-    // TODO: try all the addresses if there's more than one?
-    int family = addrs[0].ai_family;
-    int protocol = addrs[0].ai_protocol;
-    socklen_t addr_len = addrs[0].ai_addrlen;
-    struct sockaddr_storage addr;
-    memcpy(&addr, addrs[0].ai_addr, addr_len);
+    int result = -1;
+    for (struct addrinfo* addr = addrs; addr != NULL; addr = addr->ai_next) {
+        // The Mac doesn't have SOCK_NONBLOCK.
+        int s = socket(addr->ai_family, type, addr->ai_protocol);
+        if (s == -1 || toggle_O_NONBLOCK(s) == -1) return -1;
+
+        int rc = connect(s, addr->ai_addr, addr->ai_addrlen);
+        if (rc == 0) {
+            result = toggle_O_NONBLOCK(s);
+            break;
+        } else if (rc == -1 && errno != EINPROGRESS) {
+            close(s);
+            continue;
+        }
+
+        fd_set r_set;
+        FD_ZERO(&r_set);
+        FD_SET(s, &r_set);
+        fd_set w_set = r_set;
+
+        struct timeval ts;
+        ts.tv_sec = timeout;
+        ts.tv_usec = 0;
+        if ((rc = select(s + 1, &r_set, &w_set, NULL, (timeout != 0) ? &ts : NULL)) == -1) {
+            close(s);
+            break;
+        }
+        if (rc == 0) {  // we had a timeout
+            errno = ETIMEDOUT;
+            close(s);
+            break;
+        }
+
+        int error = 0;
+        socklen_t len = sizeof(error);
+        if (FD_ISSET(s, &r_set) || FD_ISSET(s, &w_set)) {
+            if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+                close(s);
+                break;
+            }
+        } else {
+            close(s);
+            break;
+        }
+
+        if (error) {  // check if we had a socket error
+            // TODO: Update the timeout.
+            errno = error;
+            close(s);
+            continue;
+        }
+
+        result = toggle_O_NONBLOCK(s);
+    }
 
     freeaddrinfo(addrs);
-
-    // The Mac doesn't have SOCK_NONBLOCK.
-    int s = socket(family, type, protocol);
-    if (s == -1 || toggle_O_NONBLOCK(s) == -1) return -1;
-
-    int rc = connect(s, (const struct sockaddr*) &addr, addr_len);
-    if (rc == 0) {
-        return toggle_O_NONBLOCK(s);
-    } else if (rc == -1 && errno != EINPROGRESS) {
-        close(s);
-        return -1;
-    }
-
-    fd_set r_set;
-    FD_ZERO(&r_set);
-    FD_SET(s, &r_set);
-    fd_set w_set = r_set;
-
-    struct timeval ts;
-    ts.tv_sec = timeout;
-    ts.tv_usec = 0;
-    if ((rc = select(s + 1, &r_set, &w_set, NULL, (timeout != 0) ? &ts : NULL)) == -1) {
-        close(s);
-        return -1;
-    }
-    if (rc == 0) {   // we had a timeout
-        errno = ETIMEDOUT;
-        close(s);
-        return -1;
-    }
-
-    int error = 0;
-    socklen_t len = sizeof(error);
-    if (FD_ISSET(s, &r_set) || FD_ISSET(s, &w_set)) {
-        if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-            close(s);
-            return -1;
-        }
-    } else {
-        close(s);
-        return -1;
-    }
-
-    if (error) {  // check if we had a socket error
-        errno = error;
-        close(s);
-        return -1;
-    }
-
-    return toggle_O_NONBLOCK(s);
+    return result;
 }
 
 int socket_network_client(const char* host, int port, int type) {
diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.c
index 3cb04cf..345f0d3 100644
--- a/liblog/event_tag_map.c
+++ b/liblog/event_tag_map.c
@@ -99,6 +99,9 @@
     if (processFile(newTagMap) != 0)
         goto fail;
 
+    if (fd >= 0)
+      close(fd);
+
     return newTagMap;
 
 fail:
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.c
index 059f170..ed82902 100644
--- a/liblog/logd_writer.c
+++ b/liblog/logd_writer.c
@@ -67,12 +67,9 @@
     int i, ret = 0;
 
     if (logdLoggerWrite.context.sock < 0) {
-        i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+        i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
         if (i < 0) {
             ret = -errno;
-        } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) {
-            ret = -errno;
-            close(i);
         } else {
             struct sockaddr_un un;
             memset(&un, 0, sizeof(struct sockaddr_un));
diff --git a/liblog/logger_read.c b/liblog/logger_read.c
index 00157b7..0d55453 100644
--- a/liblog/logger_read.c
+++ b/liblog/logger_read.c
@@ -367,6 +367,10 @@
     if (log_msg->entry_v2.hdr_size == 0) {
         log_msg->entry_v2.hdr_size = sizeof(struct logger_entry);
     }
+    if ((log_msg->entry_v2.hdr_size < sizeof(log_msg->entry_v1)) ||
+            (log_msg->entry_v2.hdr_size > sizeof(log_msg->entry))) {
+        return -EINVAL;
+    }
 
     /* len validation */
     if (ret <= log_msg->entry_v2.hdr_size) {
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index b802ed7..c7b5a84 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -132,6 +132,41 @@
     }
     return kLogNotAvailable;
 }
+/*
+ * Release any logger resources. A new log write will immediately re-acquire.
+ */
+LIBLOG_ABI_PUBLIC void __android_log_close()
+{
+    struct android_log_transport_write *transport;
+
+    __android_log_lock();
+
+    write_to_log = __write_to_log_init;
+
+    /*
+     * Threads that are actively writing at this point are not held back
+     * by a lock and are at risk of dropping the messages with a return code
+     * -EBADF. Prefer to return error code than add the overhead of a lock to
+     * each log writing call to guarantee delivery. In addition, anyone
+     * calling this is doing so to release the logging resources and shut down,
+     * for them to do so with outstanding log requests in other threads is a
+     * disengenuous use of this function.
+     */
+
+    write_transport_for_each(transport, &__android_log_persist_write) {
+        if (transport->close) {
+            (*transport->close)();
+        }
+    }
+
+    write_transport_for_each(transport, &__android_log_transport_write) {
+        if (transport->close) {
+            (*transport->close)();
+        }
+    }
+
+    __android_log_unlock();
+}
 
 /* log_init_lock assumed */
 static int __write_to_log_initialize()
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 59bd479..e21a9c4 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -496,6 +496,11 @@
     char *msg = buf->msg;
     struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
     if (buf2->hdr_size) {
+        if ((buf2->hdr_size < sizeof(((struct log_msg *)NULL)->entry_v1)) ||
+                (buf2->hdr_size > sizeof(((struct log_msg *)NULL)->entry))) {
+            fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
+            return -1;
+        }
         msg = ((char *)buf2) + buf2->hdr_size;
         if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
             entry->uid = ((struct logger_entry_v4 *)buf)->uid;
@@ -775,6 +780,11 @@
     eventData = (const unsigned char*) buf->msg;
     struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
     if (buf2->hdr_size) {
+        if ((buf2->hdr_size < sizeof(((struct log_msg *)NULL)->entry_v1)) ||
+                (buf2->hdr_size > sizeof(((struct log_msg *)NULL)->entry))) {
+            fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
+            return -1;
+        }
         eventData = ((unsigned char *)buf2) + buf2->hdr_size;
         if ((buf2->hdr_size >= sizeof(struct logger_entry_v3)) &&
                 (((struct logger_entry_v3 *)buf)->lid == LOG_ID_SECURITY)) {
diff --git a/liblog/pmsg_reader.c b/liblog/pmsg_reader.c
index a4eec65..679c159 100644
--- a/liblog/pmsg_reader.c
+++ b/liblog/pmsg_reader.c
@@ -343,6 +343,10 @@
         char *msg = (char *)&transp.logMsg + hdr_size;
         char *split = NULL;
 
+        if ((hdr_size < sizeof(transp.logMsg.entry_v1)) ||
+                (hdr_size > sizeof(transp.logMsg.entry))) {
+            continue;
+        }
         /* Check for invalid sequence number */
         if ((transp.logMsg.entry.nsec % ANDROID_LOG_PMSG_FILE_SEQUENCE) ||
                 ((transp.logMsg.entry.nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.c
index 944feba..b338dca 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.c
@@ -31,6 +31,8 @@
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
+#include <sys/system_properties.h>
+
 #include "config_write.h"
 #include "log_portability.h"
 #include "logger.h"
@@ -51,8 +53,25 @@
     .write = pmsgWrite,
 };
 
+static bool pmsgShouldUse = false;
+
+// Only use pmsg on eng builds
+static bool pmsgIsEng() {
+    char buf[PROP_VALUE_MAX];
+
+    if (__system_property_get("ro.build.type", buf) == 0) {
+        return false;
+    }
+
+    if (!strncmp(buf, "eng", sizeof("eng"))) {
+        return true;
+    }
+    return false;
+}
+
 static int pmsgOpen()
 {
+    pmsgShouldUse = pmsgIsEng();
     if (pmsgLoggerWrite.context.fd < 0) {
         pmsgLoggerWrite.context.fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
     }
@@ -75,7 +94,7 @@
     }
     if ((logId != LOG_ID_SECURITY) &&
             (logId != LOG_ID_EVENTS) &&
-            !__android_log_is_debuggable()) {
+            (!pmsgShouldUse || !__android_log_is_debuggable())) {
         return -EINVAL;
     }
     if (pmsgLoggerWrite.context.fd < 0) {
@@ -105,7 +124,7 @@
     size_t i, payloadSize;
     ssize_t ret;
 
-    if ((logId == LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
+    if ((logId == LOG_ID_EVENTS) && (!pmsgShouldUse || !__android_log_is_debuggable())) {
         if (vec[0].iov_len < 4) {
             return -EINVAL;
         }
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 1b66a56..f4e3089 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -542,7 +542,7 @@
 
             char* eventData = log_msg.msg();
 
-            if (eventData[4] != EVENT_TYPE_LONG) {
+            if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
                 continue;
             }
             log_time tx(eventData + 4 + 1);
@@ -622,7 +622,7 @@
 
             char* eventData = log_msg.msg();
 
-            if (eventData[4] != EVENT_TYPE_LONG) {
+            if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
                 continue;
             }
             log_time tx(eventData + 4 + 1);
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index df2c766..b3b44e3 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -132,12 +132,17 @@
     ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
         LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
+    // Check that we can close and reopen the logger
     log_time ts(CLOCK_MONOTONIC);
-
     ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+    __android_log_close();
+
+    log_time ts1(CLOCK_MONOTONIC);
+    ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
     usleep(1000000);
 
     int count = 0;
+    int second_count = 0;
 
     for (;;) {
         log_msg log_msg;
@@ -154,17 +159,20 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
         log_time tx(eventData + 4 + 1);
         if (ts == tx) {
             ++count;
+        } else if (ts1 == tx) {
+            ++second_count;
         }
     }
 
     EXPECT_EQ(1, count);
+    EXPECT_EQ(1, second_count);
 
     android_logger_list_close(logger_list);
 }
@@ -227,7 +235,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_STRING) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_STRING)) {
             continue;
         }
 
@@ -506,7 +514,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
@@ -637,7 +645,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
@@ -788,7 +796,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
@@ -990,9 +998,9 @@
             continue;
         }
 
-        char *data = log_msg.msg() + 1;
+        char *data = log_msg.msg();
 
-        if (strcmp(data, tag)) {
+        if (!data || strcmp(++data, tag)) {
             continue;
         }
 
@@ -1107,9 +1115,9 @@
             continue;
         }
 
-        char *data = log_msg.msg() + 1;
+        char *data = log_msg.msg();
 
-        if (strcmp(data, tag)) {
+        if (!data || strcmp(++data, tag)) {
             continue;
         }
 
@@ -1606,6 +1614,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1687,6 +1698,10 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
+
         char *original = eventData;
 
         // Tag
@@ -1774,6 +1789,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1817,6 +1835,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1904,6 +1925,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1961,6 +1985,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -2449,16 +2476,19 @@
         android_log_format_free(logformat);
 
         // test buffer reading API
-        snprintf(msgBuf, sizeof(msgBuf), "I/[%d]", get4LE(eventData));
-        print_barrier();
-        fprintf(stderr, "%-10s(%5u): ", msgBuf, pid);
-        memset(msgBuf, 0, sizeof(msgBuf));
-        int buffer_to_string = android_log_buffer_to_string(
-            eventData + sizeof(uint32_t),
-            log_msg.entry.len - sizeof(uint32_t),
-            msgBuf, sizeof(msgBuf));
-        fprintf(stderr, "%s\n", msgBuf);
-        print_barrier();
+        int buffer_to_string = -1;
+        if (eventData) {
+            snprintf(msgBuf, sizeof(msgBuf), "I/[%d]", get4LE(eventData));
+            print_barrier();
+            fprintf(stderr, "%-10s(%5u): ", msgBuf, pid);
+            memset(msgBuf, 0, sizeof(msgBuf));
+            buffer_to_string = android_log_buffer_to_string(
+                eventData + sizeof(uint32_t),
+                log_msg.entry.len - sizeof(uint32_t),
+                msgBuf, sizeof(msgBuf));
+            fprintf(stderr, "%s\n", msgBuf);
+            print_barrier();
+        }
         EXPECT_EQ(0, buffer_to_string);
         EXPECT_EQ(strlen(expected_string), strlen(msgBuf));
         EXPECT_EQ(0, strcmp(expected_string, msgBuf));
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
new file mode 100644
index 0000000..85bc421
--- /dev/null
+++ b/libmemunreachable/Android.bp
@@ -0,0 +1,80 @@
+cc_defaults {
+    name: "libmemunreachable_defaults",
+
+    cflags: [
+        "-std=c++14",
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    clang: true,
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+}
+
+cc_library_shared {
+    name: "libmemunreachable",
+    defaults: ["libmemunreachable_defaults"],
+    srcs: [
+        "Allocator.cpp",
+        "HeapWalker.cpp",
+        "LeakFolding.cpp",
+        "LeakPipe.cpp",
+        "LineBuffer.cpp",
+        "MemUnreachable.cpp",
+        "ProcessMappings.cpp",
+        "PtracerThread.cpp",
+        "ThreadCapture.cpp",
+    ],
+
+    static_libs: [
+        "libc_malloc_debug_backtrace",
+        "libc_logging",
+    ],
+    // Only need this for arm since libc++ uses its own unwind code that
+    // doesn't mix with the other default unwind code.
+    arch: {
+        arm: {
+            static_libs: ["libunwind_llvm"],
+        },
+    },
+    export_include_dirs: ["include"],
+    local_include_dirs: ["include"],
+}
+
+cc_test {
+    name: "memunreachable_test",
+    defaults: ["libmemunreachable_defaults"],
+    host_supported: true,
+    srcs: [
+        "tests/Allocator_test.cpp",
+        "tests/HeapWalker_test.cpp",
+        "tests/LeakFolding_test.cpp",
+    ],
+
+    target: {
+        android: {
+            srcs: [
+                "tests/DisableMalloc_test.cpp",
+                "tests/MemUnreachable_test.cpp",
+                "tests/ThreadCapture_test.cpp",
+            ],
+            shared_libs: [
+                "libmemunreachable",
+            ],
+        },
+        host: {
+            srcs: [
+                "Allocator.cpp",
+                "HeapWalker.cpp",
+                "LeakFolding.cpp",
+                "tests/HostMallocStub.cpp",
+            ],
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/libmemunreachable/Android.mk b/libmemunreachable/Android.mk
deleted file mode 100644
index 7b66d44..0000000
--- a/libmemunreachable/Android.mk
+++ /dev/null
@@ -1,65 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-memunreachable_srcs := \
-   Allocator.cpp \
-   HeapWalker.cpp \
-   LeakFolding.cpp \
-   LeakPipe.cpp \
-   LineBuffer.cpp \
-   MemUnreachable.cpp \
-   ProcessMappings.cpp \
-   PtracerThread.cpp \
-   ThreadCapture.cpp \
-
-memunreachable_test_srcs := \
-   tests/Allocator_test.cpp \
-   tests/DisableMalloc_test.cpp \
-   tests/HeapWalker_test.cpp \
-   tests/LeakFolding_test.cpp \
-   tests/MemUnreachable_test.cpp \
-   tests/ThreadCapture_test.cpp \
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libmemunreachable
-LOCAL_SRC_FILES := $(memunreachable_srcs)
-LOCAL_CFLAGS := -std=c++14 -Wall -Wextra -Werror
-LOCAL_SHARED_LIBRARIES := libbase liblog
-LOCAL_STATIC_LIBRARIES := libc_malloc_debug_backtrace libc_logging
-# Only need this for arm since libc++ uses its own unwind code that
-# doesn't mix with the other default unwind code.
-LOCAL_STATIC_LIBRARIES_arm := libunwind_llvm
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CLANG := true
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := memunreachable_test
-LOCAL_SRC_FILES := $(memunreachable_test_srcs)
-LOCAL_CFLAGS := -std=c++14 -Wall -Wextra -Werror
-LOCAL_CLANG := true
-LOCAL_SHARED_LIBRARIES := libmemunreachable libbase liblog
-
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := memunreachable_test
-LOCAL_SRC_FILES := \
-   Allocator.cpp \
-   HeapWalker.cpp  \
-   LeakFolding.cpp \
-   tests/Allocator_test.cpp \
-   tests/HeapWalker_test.cpp \
-   tests/HostMallocStub.cpp \
-   tests/LeakFolding_test.cpp \
-
-LOCAL_CFLAGS := -std=c++14 -Wall -Wextra -Werror
-LOCAL_CLANG := true
-LOCAL_SHARED_LIBRARIES := libbase liblog
-LOCAL_MODULE_HOST_OS := linux
-
-include $(BUILD_HOST_NATIVE_TEST)
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk
index ce7c3ba..2150279 100644
--- a/libnetutils/Android.mk
+++ b/libnetutils/Android.mk
@@ -19,10 +19,3 @@
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 
 include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dhcptool.c
-LOCAL_SHARED_LIBRARIES := libnetutils
-LOCAL_MODULE := dhcptool
-LOCAL_MODULE_TAGS := debug
-include $(BUILD_EXECUTABLE)
diff --git a/libnetutils/dhcptool.c b/libnetutils/dhcptool.c
deleted file mode 100644
index d23afd3..0000000
--- a/libnetutils/dhcptool.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#include <err.h>
-#include <errno.h>
-#include <error.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include <netutils/ifc.h>
-
-extern int do_dhcp(char*);
-
-int main(int argc, char* argv[]) {
-  if (argc != 2) {
-    error(EXIT_FAILURE, 0, "usage: %s INTERFACE", argv[0]);
-  }
-
-  char* interface = argv[1];
-  if (ifc_init()) {
-    err(errno, "dhcptool %s: ifc_init failed", interface);
-    ifc_close();
-    return EXIT_FAILURE;
-  }
-
-  int rc = do_dhcp(interface);
-  if (rc) {
-    err(errno, "dhcptool %s: do_dhcp failed", interface);
-  }
-
-  ifc_close();
-
-  return rc ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 4b498c1..ae38519 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -23,7 +23,6 @@
 #include <sys/mman.h>
 
 #include <cutils/ashmem.h>
-#include <cutils/atomic.h>
 #define LOG_TAG "CodeCache"
 #include <cutils/log.h>
 
@@ -101,7 +100,7 @@
 }
 
 Assembly::Assembly(size_t size)
-    : mCount(1), mSize(0)
+    : mCount(0), mSize(0)
 {
     mBase = (uint32_t*)mspace_malloc(getMspace(), size);
     LOG_ALWAYS_FATAL_IF(mBase == NULL,
@@ -117,12 +116,12 @@
 
 void Assembly::incStrong(const void*) const
 {
-    android_atomic_inc(&mCount);
+    mCount.fetch_add(1, std::memory_order_relaxed);
 }
 
 void Assembly::decStrong(const void*) const
 {
-    if (android_atomic_dec(&mCount) == 1) {
+    if (mCount.fetch_sub(1, std::memory_order_acq_rel) == 1) {
         delete this;
     }
 }
diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h
index c0e0684..9326453 100644
--- a/libpixelflinger/codeflinger/CodeCache.h
+++ b/libpixelflinger/codeflinger/CodeCache.h
@@ -19,6 +19,7 @@
 #ifndef ANDROID_CODECACHE_H
 #define ANDROID_CODECACHE_H
 
+#include <atomic>
 #include <stdint.h>
 #include <pthread.h>
 #include <sys/types.h>
@@ -69,7 +70,7 @@
     typedef void    weakref_type;
 
 private:
-    mutable int32_t     mCount;
+    mutable std::atomic<int32_t>     mCount;
             uint32_t*   mBase;
             size_t      mSize;
 };
diff --git a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
index 5f58797..63642c4 100644
--- a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
+++ b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
@@ -34,7 +34,6 @@
 
 #include <sys/mman.h>
 #include <cutils/ashmem.h>
-#include <cutils/atomic.h>
 
 #define __STDC_FORMAT_MACROS
 #include <inttypes.h>
diff --git a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
index b680b60..e8c4626 100644
--- a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
+++ b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
@@ -34,7 +34,6 @@
 
 #include <sys/mman.h>
 #include <cutils/ashmem.h>
-#include <cutils/atomic.h>
 #include <cutils/log.h>
 
 #define __STDC_FORMAT_MACROS
diff --git a/libsync/Android.bp b/libsync/Android.bp
new file mode 100644
index 0000000..4948aa5
--- /dev/null
+++ b/libsync/Android.bp
@@ -0,0 +1,42 @@
+cc_defaults {
+    name: "libsync_defaults",
+    srcs: ["sync.c"],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    cflags: ["-Werror"],
+}
+
+cc_library_shared {
+    name: "libsync",
+    defaults: ["libsync_defaults"],
+}
+
+// libsync_recovery is only intended for the recovery binary.
+// Future versions of the kernel WILL require an updated libsync, and will break
+// anything statically linked against the current libsync.
+cc_library_static {
+    name: "libsync_recovery",
+    defaults: ["libsync_defaults"],
+}
+
+cc_test {
+    name: "sync_test",
+    defaults: ["libsync_defaults"],
+    gtest: false,
+    srcs: ["sync_test.c"],
+}
+
+cc_test {
+    name: "sync-unit-tests",
+    shared_libs: ["libsync"],
+    srcs: ["tests/sync_test.cpp"],
+    cflags: [
+        "-g",
+        "-Wall",
+        "-Werror",
+        "-std=gnu++11",
+        "-Wno-missing-field-initializers",
+        "-Wno-sign-compare",
+    ],
+    clang: true,
+}
diff --git a/libsync/Android.mk b/libsync/Android.mk
deleted file mode 100644
index f407bd1..0000000
--- a/libsync/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := sync.c
-LOCAL_MODULE := libsync
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_SHARED_LIBRARY)
-
-# libsync_recovery is only intended for the recovery binary.
-# Future versions of the kernel WILL require an updated libsync, and will break
-# anything statically linked against the current libsync.
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := sync.c
-LOCAL_MODULE := libsync_recovery
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := sync.c sync_test.c
-LOCAL_MODULE := sync_test
-LOCAL_MODULE_TAGS := optional tests
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_EXECUTABLE)
diff --git a/libsync/sync.c b/libsync/sync.c
index d73bb11..169dc36 100644
--- a/libsync/sync.c
+++ b/libsync/sync.c
@@ -21,13 +21,27 @@
 #include <stdint.h>
 #include <string.h>
 
-#include <linux/sync.h>
 #include <linux/sw_sync.h>
 
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <sync/sync.h>
+
+// The sync code is undergoing a major change. Add enough in to get
+// everything to compile wih the latest uapi headers.
+struct sync_merge_data {
+  int32_t fd2;
+  char name[32];
+  int32_t fence;
+};
+
+#define SYNC_IOC_MAGIC '>'
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_fence_info_data)
+
 int sync_wait(int fd, int timeout)
 {
     __s32 to = timeout;
diff --git a/libsync/tests/Android.mk b/libsync/tests/Android.mk
deleted file mode 100644
index 8137c7a..0000000
--- a/libsync/tests/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright 2014 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_MODULE := sync-unit-tests
-LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers -Wno-sign-compare
-LOCAL_SHARED_LIBRARIES += libsync
-LOCAL_STATIC_LIBRARIES += libgtest_main
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
-LOCAL_SRC_FILES := \
-    sync_test.cpp
-include $(BUILD_NATIVE_TEST)
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index e7b3dd6..579ead9 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -49,6 +49,7 @@
     errorRate = 0;
     mCommandCount = 0;
     mWithSeq = withSeq;
+    mSkipToNextNullByte = false;
 }
 
 bool FrameworkListener::onDataAvailable(SocketClient *c) {
@@ -59,10 +60,15 @@
     if (len < 0) {
         SLOGE("read() failed (%s)", strerror(errno));
         return false;
-    } else if (!len)
+    } else if (!len) {
         return false;
-   if(buffer[len-1] != '\0')
+    } else if (buffer[len-1] != '\0') {
         SLOGW("String is not zero-terminated");
+        android_errorWriteLog(0x534e4554, "29831647");
+        c->sendMsg(500, "Command too large for buffer", false);
+        mSkipToNextNullByte = true;
+        return false;
+    }
 
     int offset = 0;
     int i;
@@ -70,11 +76,16 @@
     for (i = 0; i < len; i++) {
         if (buffer[i] == '\0') {
             /* IMPORTANT: dispatchCommand() expects a zero-terminated string */
-            dispatchCommand(c, buffer + offset);
+            if (mSkipToNextNullByte) {
+                mSkipToNextNullByte = false;
+            } else {
+                dispatchCommand(c, buffer + offset);
+            }
             offset = i + 1;
         }
     }
 
+    mSkipToNextNullByte = false;
     return true;
 }
 
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 4d602a6..608abae 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -199,16 +199,7 @@
             continue;
         }
         if (mListen && FD_ISSET(mSock, &read_fds)) {
-            sockaddr_storage ss;
-            sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
-            socklen_t alen;
-            int c;
-
-            do {
-                alen = sizeof(ss);
-                c = accept4(mSock, addrp, &alen, SOCK_CLOEXEC);
-                SLOGV("%s got %d from accept", mSocketName, c);
-            } while (c < 0 && errno == EINTR);
+            int c = TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC));
             if (c < 0) {
                 SLOGE("accept failed (%s)", strerror(errno));
                 sleep(1);
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 952c992..254cd8d 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -84,6 +84,7 @@
 
 Looper::~Looper() {
     close(mWakeEventFd);
+    mWakeEventFd = -1;
     if (mEpollFd >= 0) {
         close(mEpollFd);
     }
@@ -413,7 +414,8 @@
     ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
     if (nWrite != sizeof(uint64_t)) {
         if (errno != EAGAIN) {
-            ALOGW("Could not write wake signal: %s", strerror(errno));
+            LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s",
+                    mWakeEventFd, strerror(errno));
         }
     }
 }
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index d4d7d7e..fee9984 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -56,37 +56,44 @@
 
 namespace android {
 
-// Usage, invariants, etc:
+// Observations, invariants, etc:
 
-// It is normally OK just to keep weak pointers to an object.  The object will
-// be deallocated by decWeak when the last weak reference disappears.
-// Once a a strong reference has been created, the object will disappear once
-// the last strong reference does (decStrong).
-// AttemptIncStrong will succeed if the object has a strong reference, or if it
-// has a weak reference and has never had a strong reference.
-// AttemptIncWeak really does succeed only if there is already a WEAK
-// reference, and thus may fail when attemptIncStrong would succeed.
+// By default, obects are destroyed when the last strong reference disappears
+// or, if the object never had a strong reference, when the last weak reference
+// disappears.
+//
 // OBJECT_LIFETIME_WEAK changes this behavior to retain the object
 // unconditionally until the last reference of either kind disappears.  The
 // client ensures that the extendObjectLifetime call happens before the dec
 // call that would otherwise have deallocated the object, or before an
 // attemptIncStrong call that might rely on it.  We do not worry about
 // concurrent changes to the object lifetime.
+//
+// AttemptIncStrong will succeed if the object has a strong reference, or if it
+// has a weak reference and has never had a strong reference.
+// AttemptIncWeak really does succeed only if there is already a WEAK
+// reference, and thus may fail when attemptIncStrong would succeed.
+//
 // mStrong is the strong reference count.  mWeak is the weak reference count.
 // Between calls, and ignoring memory ordering effects, mWeak includes strong
 // references, and is thus >= mStrong.
 //
+// A weakref_impl holds all the information, including both reference counts,
+// required to perform wp<> operations.  Thus these can continue to be performed
+// after the RefBase object has been destroyed.
+//
 // A weakref_impl is allocated as the value of mRefs in a RefBase object on
 // construction.
-// In the OBJECT_LIFETIME_STRONG case, it is deallocated in the RefBase
-// destructor iff the strong reference count was never incremented. The
-// destructor can be invoked either from decStrong, or from decWeak if there
-// was never a strong reference. If the reference count had been incremented,
-// it is deallocated directly in decWeak, and hence still lives as long as
-// the last weak reference.
-// In the OBJECT_LIFETIME_WEAK case, it is always deallocated from the RefBase
-// destructor, which is always invoked by decWeak. DecStrong explicitly avoids
-// the deletion in this case.
+// In the OBJECT_LIFETIME_STRONG case, it is normally deallocated in decWeak,
+// and hence lives as long as the last weak reference. (It can also be
+// deallocated in the RefBase destructor iff the strong reference count was
+// never incremented and the weak count is zero, e.g.  if the RefBase object is
+// explicitly destroyed without decrementing the strong count.  This should be
+// avoided.) In this case, the RefBase destructor should be invoked from
+// decStrong.
+// In the OBJECT_LIFETIME_WEAK case, the weakref_impl is always deallocated in
+// the RefBase destructor, which is always invoked by decWeak. DecStrong
+// explicitly avoids the deletion in this case.
 //
 // Memory ordering:
 // The client must ensure that every inc() call, together with all other
@@ -120,6 +127,19 @@
 
 #define INITIAL_STRONG_VALUE (1<<28)
 
+#define MAX_COUNT 0xfffff
+
+// Test whether the argument is a clearly invalid strong reference count.
+// Used only for error checking on the value before an atomic decrement.
+// Intended to be very cheap.
+// Note that we cannot just check for excess decrements by comparing to zero
+// since the object would be deallocated before that.
+#define BAD_STRONG(c) \
+        ((c) == 0 || ((c) & (~(MAX_COUNT | INITIAL_STRONG_VALUE))) != 0)
+
+// Same for weak counts.
+#define BAD_WEAK(c) ((c) == 0 || ((c) & (~MAX_COUNT)) != 0)
+
 // ---------------------------------------------------------------------------
 
 class RefBase::weakref_impl : public RefBase::weakref_type
@@ -415,15 +435,15 @@
 #if PRINT_REFS
     ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
 #endif
-    ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
+    LOG_ALWAYS_FATAL_IF(BAD_STRONG(c), "decStrong() called on %p too many times",
+            refs);
     if (c == 1) {
         std::atomic_thread_fence(std::memory_order_acquire);
         refs->mBase->onLastStrongRef(id);
         int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
         if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
             delete this;
-            // Since mStrong had been incremented, the destructor did not
-            // delete refs.
+            // The destructor does not delete refs in this case.
         }
     }
     // Note that even with only strong reference operations, the thread
@@ -486,7 +506,8 @@
     weakref_impl* const impl = static_cast<weakref_impl*>(this);
     impl->removeWeakRef(id);
     const int32_t c = impl->mWeak.fetch_sub(1, std::memory_order_release);
-    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
+    LOG_ALWAYS_FATAL_IF(BAD_WEAK(c), "decWeak called on %p too many times",
+            this);
     if (c != 1) return;
     atomic_thread_fence(std::memory_order_acquire);
 
@@ -494,13 +515,19 @@
     if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
         // This is the regular lifetime case. The object is destroyed
         // when the last strong reference goes away. Since weakref_impl
-        // outlive the object, it is not destroyed in the dtor, and
+        // outlives the object, it is not destroyed in the dtor, and
         // we'll have to do it here.
         if (impl->mStrong.load(std::memory_order_relaxed)
                 == INITIAL_STRONG_VALUE) {
-            // Special case: we never had a strong reference, so we need to
-            // destroy the object now.
-            delete impl->mBase;
+            // Decrementing a weak count to zero when object never had a strong
+            // reference.  We assume it acquired a weak reference early, e.g.
+            // in the constructor, and will eventually be properly destroyed,
+            // usually via incrementing and decrementing the strong count.
+            // Thus we no longer do anything here.  We log this case, since it
+            // seems to be extremely rare, and should not normally occur. We
+            // used to deallocate mBase here, so this may now indicate a leak.
+            ALOGW("RefBase: Object at %p lost last weak reference "
+                    "before it had a strong reference", impl->mBase);
         } else {
             // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
             delete impl;
@@ -669,24 +696,28 @@
 
 RefBase::~RefBase()
 {
-    if (mRefs->mStrong.load(std::memory_order_relaxed)
-            == INITIAL_STRONG_VALUE) {
-        // we never acquired a strong (and/or weak) reference on this object.
-        delete mRefs;
-    } else {
-        // life-time of this object is extended to WEAK, in
-        // which case weakref_impl doesn't out-live the object and we
-        // can free it now.
-        int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
-        if ((flags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
-            // It's possible that the weak count is not 0 if the object
-            // re-acquired a weak reference in its destructor
-            if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
-                delete mRefs;
-            }
+    int32_t flags = mRefs->mFlags.load(std::memory_order_relaxed);
+    // Life-time of this object is extended to WEAK, in
+    // which case weakref_impl doesn't out-live the object and we
+    // can free it now.
+    if ((flags & OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
+        // It's possible that the weak count is not 0 if the object
+        // re-acquired a weak reference in its destructor
+        if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
+            delete mRefs;
         }
+    } else if (mRefs->mStrong.load(std::memory_order_relaxed)
+            == INITIAL_STRONG_VALUE) {
+        // We never acquired a strong reference on this object.
+        LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
+                "RefBase: Explicit destruction with non-zero weak "
+                "reference count");
+        // TODO: Always report if we get here. Currently MediaMetadataRetriever
+        // C++ objects are inconsistently managed and sometimes get here.
+        // There may be other cases, but we believe they should all be fixed.
+        delete mRefs;
     }
-    // for debugging purposes, clear this.
+    // For debugging purposes, clear mRefs.  Ineffective against outstanding wp's.
     const_cast<weakref_impl*&>(mRefs) = NULL;
 }
 
diff --git a/libutils/tests/RefBase_test.cpp b/libutils/tests/RefBase_test.cpp
index 224c2ca..2e0cf6e 100644
--- a/libutils/tests/RefBase_test.cpp
+++ b/libutils/tests/RefBase_test.cpp
@@ -87,7 +87,7 @@
     EXPECT_EQ(1, foo->getWeakRefs()->getWeakCount());
     ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!";
     wp1 = nullptr;
-    ASSERT_TRUE(isDeleted) << "foo2 was leaked!";
+    ASSERT_FALSE(isDeleted) << "Deletion on wp destruction should no longer occur";
 }
 
 
@@ -121,8 +121,33 @@
 
 cpu_set_t otherCpus;
 
+// Divide the cpus we're allowed to run on into myCpus and otherCpus.
+// Set origCpus to the processors we were originally allowed to run on.
+// Return false if origCpus doesn't include at least processors 0 and 1.
+static bool setExclusiveCpus(cpu_set_t* origCpus /* out */,
+        cpu_set_t* myCpus /* out */, cpu_set_t* otherCpus) {
+    if (sched_getaffinity(0, sizeof(cpu_set_t), origCpus) != 0) {
+        return false;
+    }
+    if (!CPU_ISSET(0,  origCpus) || !CPU_ISSET(1, origCpus)) {
+        return false;
+    }
+    CPU_ZERO(myCpus);
+    CPU_ZERO(otherCpus);
+    CPU_OR(myCpus, myCpus, origCpus);
+    CPU_OR(otherCpus, otherCpus, origCpus);
+    for (unsigned i = 0; i < CPU_SETSIZE; ++i) {
+        // I get the even cores, the other thread gets the odd ones.
+        if (i & 1) {
+            CPU_CLR(i, myCpus);
+        } else {
+            CPU_CLR(i, otherCpus);
+        }
+    }
+    return true;
+}
+
 static void visit2AndRemove() {
-    EXPECT_TRUE(CPU_ISSET(1,  &otherCpus));
     if (sched_setaffinity(0, sizeof(cpu_set_t), &otherCpus) != 0) {
         FAIL() << "setaffinity returned:" << errno;
     }
@@ -139,27 +164,10 @@
     cpu_set_t myCpus;
     // Restrict us and the helper thread to disjoint cpu sets.
     // This prevents us from getting scheduled against each other,
-    // which would be atrociously slow.  We fail if that's impossible.
-    if (sched_getaffinity(0, sizeof(cpu_set_t), &origCpus) != 0) {
-        FAIL();
-    }
-    EXPECT_TRUE(CPU_ISSET(0,  &origCpus));
-    if (CPU_ISSET(1, &origCpus)) {
-        CPU_ZERO(&myCpus);
-        CPU_ZERO(&otherCpus);
-        CPU_OR(&myCpus, &myCpus, &origCpus);
-        CPU_OR(&otherCpus, &otherCpus, &origCpus);
-        for (unsigned i = 0; i < CPU_SETSIZE; ++i) {
-            // I get the even cores, the other thread gets the odd ones.
-            if (i & 1) {
-                CPU_CLR(i, &myCpus);
-            } else {
-                CPU_CLR(i, &otherCpus);
-            }
-        }
+    // which would be atrociously slow.
+    if (setExclusiveCpus(&origCpus, &myCpus, &otherCpus)) {
         std::thread t(visit2AndRemove);
         std::atomic<int> deleteCount(0);
-        EXPECT_TRUE(CPU_ISSET(0,  &myCpus));
         if (sched_setaffinity(0, sizeof(cpu_set_t), &myCpus) != 0) {
             FAIL() << "setaffinity returned:" << errno;
         }
@@ -182,3 +190,69 @@
         ASSERT_EQ(NITERS, deleteCount) << "Deletions missed!";
     }  // Otherwise this is slow and probably pointless on a uniprocessor.
 }
+
+static wp<Bar> wpBuffer;
+static std::atomic<bool> wpBufferFull(false);
+
+// Wait until wpBufferFull has value val.
+static inline void wpWaitFor(bool val) {
+    while (wpBufferFull != val) {}
+}
+
+static void visit3AndRemove() {
+    if (sched_setaffinity(0, sizeof(cpu_set_t), &otherCpus) != 0) {
+        FAIL() << "setaffinity returned:" << errno;
+    }
+    for (int i = 0; i < NITERS; ++i) {
+        wpWaitFor(true);
+        {
+            sp<Bar> sp1 = wpBuffer.promote();
+            // We implicitly check that sp1 != NULL
+            sp1->mVisited2 = true;
+        }
+        wpBuffer = nullptr;
+        wpBufferFull = false;
+    }
+}
+
+TEST(RefBase, RacingPromotions) {
+    cpu_set_t origCpus;
+    cpu_set_t myCpus;
+    // Restrict us and the helper thread to disjoint cpu sets.
+    // This prevents us from getting scheduled against each other,
+    // which would be atrociously slow.
+    if (setExclusiveCpus(&origCpus, &myCpus, &otherCpus)) {
+        std::thread t(visit3AndRemove);
+        std::atomic<int> deleteCount(0);
+        if (sched_setaffinity(0, sizeof(cpu_set_t), &myCpus) != 0) {
+            FAIL() << "setaffinity returned:" << errno;
+        }
+        for (int i = 0; i < NITERS; ++i) {
+            Bar* bar = new Bar(&deleteCount);
+            wp<Bar> wp1(bar);
+            bar->mVisited1 = true;
+            if (i % (NITERS / 10) == 0) {
+                // Do this rarely, since it generates a log message.
+                wp1 = nullptr;  // No longer destroys the object.
+                wp1 = bar;
+            }
+            wpBuffer = wp1;
+            ASSERT_EQ(bar->getWeakRefs()->getWeakCount(), 2);
+            wpBufferFull = true;
+            // Promotion races with that in visit3AndRemove.
+            // This may or may not succeed, but it shouldn't interfere with
+            // the concurrent one.
+            sp<Bar> sp1 = wp1.promote();
+            wpWaitFor(false);  // Waits for other thread to drop strong pointer.
+            sp1 = nullptr;
+            // No strong pointers here.
+            sp1 = wp1.promote();
+            ASSERT_EQ(sp1.get(), nullptr) << "Dead wp promotion succeeded!";
+        }
+        t.join();
+        if (sched_setaffinity(0, sizeof(cpu_set_t), &origCpus) != 0) {
+            FAIL();
+        }
+        ASSERT_EQ(NITERS, deleteCount) << "Deletions missed!";
+    }  // Otherwise this is slow and probably pointless on a uniprocessor.
+}
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 1f27500..350be31 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -825,8 +825,9 @@
       // disk does not have enough space.
       result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
       if (result == -1 && errno == ENOSPC) {
-        ALOGW("Zip: unable to allocate space for file to %" PRId64 ": %s",
-              static_cast<int64_t>(declared_length + current_offset), strerror(errno));
+        ALOGW("Zip: unable to allocate  %" PRId64 " bytes at offset %" PRId64 " : %s",
+              static_cast<int64_t>(declared_length), static_cast<int64_t>(current_offset),
+              strerror(errno));
         return std::unique_ptr<FileWriter>(nullptr);
       }
     }
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index e404e44..df1b9af 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -397,9 +397,6 @@
 }
 
 static void ctrl_connect_handler(uint32_t events __unused) {
-    struct sockaddr_storage ss;
-    struct sockaddr *addrp = (struct sockaddr *)&ss;
-    socklen_t alen;
     struct epoll_event epev;
 
     if (ctrl_dfd >= 0) {
@@ -407,8 +404,7 @@
         ctrl_dfd_reopened = 1;
     }
 
-    alen = sizeof(ss);
-    ctrl_dfd = accept(ctrl_lfd, addrp, &alen);
+    ctrl_dfd = accept(ctrl_lfd, NULL, NULL);
 
     if (ctrl_dfd < 0) {
         ALOGE("lmkd control socket accept failed; errno=%d", errno);
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 5bac717..7e2bac7 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -26,6 +26,7 @@
 #include <string>
 
 #include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <cutils/sched_policy.h>
 #include <cutils/sockets.h>
@@ -109,29 +110,27 @@
             (g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0;
 
     for (int i = g_maxRotatedLogs ; i > 0 ; i--) {
-        char *file0, *file1;
+        std::string file1 = android::base::StringPrintf(
+            "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
 
-        asprintf(&file1, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
-
+        std::string file0;
         if (i - 1 == 0) {
-            asprintf(&file0, "%s", g_outputFileName);
+            file0 = android::base::StringPrintf("%s", g_outputFileName);
         } else {
-            asprintf(&file0, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i - 1);
+            file0 = android::base::StringPrintf(
+                "%s.%.*d", g_outputFileName, maxRotationCountDigits, i - 1);
         }
 
-        if (!file0 || !file1) {
+        if ((file0.length() == 0) || (file1.length() == 0)) {
             perror("while rotating log files");
             break;
         }
 
-        err = rename(file0, file1);
+        err = rename(file0.c_str(), file1.c_str());
 
         if (err < 0 && errno != ENOENT) {
             perror("while rotating log files");
         }
-
-        free(file1);
-        free(file0);
     }
 
     g_outFD = openLogFile(g_outputFileName);
@@ -231,13 +230,15 @@
     }
 }
 
-static void setupOutput()
-{
-
+static void setupOutputAndSchedulingPolicy(bool blocking) {
     if (g_outputFileName == NULL) {
         g_outFD = STDOUT_FILENO;
+        return;
+    }
 
-    } else {
+    if (blocking) {
+        // Lower priority and set to batch scheduling if we are saving
+        // the logs into files and taking continuous content.
         if (set_sched_policy(0, SP_BACKGROUND) < 0) {
             fprintf(stderr, "failed to set background scheduling policy\n");
         }
@@ -251,26 +252,26 @@
         if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
             fprintf(stderr, "failed set to priority\n");
         }
-
-        g_outFD = openLogFile (g_outputFileName);
-
-        if (g_outFD < 0) {
-            logcat_panic(false, "couldn't open output file");
-        }
-
-        struct stat statbuf;
-        if (fstat(g_outFD, &statbuf) == -1) {
-            close(g_outFD);
-            logcat_panic(false, "couldn't get output file stat\n");
-        }
-
-        if ((size_t) statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {
-            close(g_outFD);
-            logcat_panic(false, "invalid output file stat\n");
-        }
-
-        g_outByteCount = statbuf.st_size;
     }
+
+    g_outFD = openLogFile (g_outputFileName);
+
+    if (g_outFD < 0) {
+        logcat_panic(false, "couldn't open output file");
+    }
+
+    struct stat statbuf;
+    if (fstat(g_outFD, &statbuf) == -1) {
+        close(g_outFD);
+        logcat_panic(false, "couldn't get output file stat\n");
+    }
+
+    if ((size_t) statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {
+        close(g_outFD);
+        logcat_panic(false, "invalid output file stat\n");
+    }
+
+    g_outByteCount = statbuf.st_size;
 }
 
 static void show_help(const char *cmd)
@@ -284,6 +285,8 @@
                     "                  Rotate log every kbytes. Requires -f option\n"
                     "  -n <count>, --rotate-count=<count>\n"
                     "                  Sets max number of rotated logs to <count>, default 4\n"
+                    "  --id=<id>       If the signature id for logging to file changes, then clear\n"
+                    "                  the fileset and continue\n"
                     "  -v <format>, --format=<format>\n"
                     "                  Sets log print format verb and adverbs, where <format> is:\n"
                     "                    brief long process raw tag thread threadtime time\n"
@@ -443,7 +446,7 @@
     return t.strptime(cp, "%s.%q");
 }
 
-// Find last logged line in gestalt of all matching existing output files
+// Find last logged line in <outputFileName>, or <outputFileName>.1
 static log_time lastLogTime(char *outputFileName) {
     log_time retval(log_time::EPOCH);
     if (!outputFileName) {
@@ -468,24 +471,18 @@
         return retval;
     }
 
-    clockid_t clock_type = android_log_clockid();
-    log_time now(clock_type);
-    bool monotonic = clock_type == CLOCK_MONOTONIC;
+    log_time now(android_log_clockid());
 
     size_t len = strlen(file);
     log_time modulo(0, NS_PER_SEC);
     struct dirent *dp;
 
     while ((dp = readdir(dir.get())) != NULL) {
-        if ((dp->d_type != DT_REG)
-                // If we are using realtime, check all files that match the
-                // basename for latest time. If we are using monotonic time
-                // then only check the main file because time cycles on
-                // every reboot.
-                || strncmp(dp->d_name, file, len + monotonic)
-                || (dp->d_name[len]
-                    && ((dp->d_name[len] != '.')
-                        || !isdigit(dp->d_name[len+1])))) {
+        if ((dp->d_type != DT_REG) ||
+                (strncmp(dp->d_name, file, len) != 0) ||
+                (dp->d_name[len] &&
+                     ((dp->d_name[len] != '.') ||
+                         (strtoll(dp->d_name + 1, NULL, 10) != 1)))) {
             continue;
         }
 
@@ -547,6 +544,7 @@
     unsigned long setLogSize = 0;
     int getPruneList = 0;
     char *setPruneList = NULL;
+    char *setId = NULL;
     int printStatistics = 0;
     int mode = ANDROID_LOG_RDONLY;
     const char *forceFilters = NULL;
@@ -574,6 +572,7 @@
         int option_index = 0;
         // list of long-argument only strings for later comparison
         static const char pid_str[] = "pid";
+        static const char id_str[] = "id";
         static const char wrap_str[] = "wrap";
         static const char print_str[] = "print";
         static const struct option long_options[] = {
@@ -588,6 +587,7 @@
           { "grep",          required_argument, NULL,   'e' },
           // hidden and undocumented reserved alias for --max-count
           { "head",          required_argument, NULL,   'm' },
+          { id_str,          required_argument, NULL,   0 },
           { "last",          no_argument,       NULL,   'L' },
           { "max-count",     required_argument, NULL,   'm' },
           { pid_str,         required_argument, NULL,   0 },
@@ -613,7 +613,7 @@
 
         switch (ret) {
             case 0:
-                // One of the long options
+                // only long options
                 if (long_options[option_index].name == pid_str) {
                     // ToDo: determine runtime PID_MAX?
                     if (!getSizeTArg(optarg, &pid, 1)) {
@@ -644,6 +644,10 @@
                     g_printItAnyways = true;
                     break;
                 }
+                if (long_options[option_index].name == id_str) {
+                    setId = optarg && optarg[0] ? optarg : NULL;
+                    break;
+                }
             break;
 
             case 's':
@@ -657,7 +661,7 @@
             break;
 
             case 'L':
-                mode |= ANDROID_LOG_PSTORE;
+                mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK;
             break;
 
             case 'd':
@@ -968,7 +972,20 @@
         logcat_panic(true, "-r requires -f as well\n");
     }
 
-    setupOutput();
+    if (setId != NULL) {
+        if (g_outputFileName == NULL) {
+            logcat_panic(true, "--id='%s' requires -f as well\n", setId);
+        }
+
+        std::string file_name = android::base::StringPrintf("%s.id", g_outputFileName);
+        std::string file;
+        bool file_ok = android::base::ReadFileToString(file_name, &file);
+        android::base::WriteStringToFile(setId, file_name,
+                                         S_IRUSR | S_IWUSR, getuid(), getgid());
+        if (!file_ok || (file.compare(setId) == 0)) {
+            setId = NULL;
+        }
+    }
 
     if (hasSetLogFormat == 0) {
         const char* logFormat = getenv("ANDROID_PRINTF_LOG");
@@ -1034,34 +1051,33 @@
             continue;
         }
 
-        if (clearLog) {
+        if (clearLog || setId) {
             if (g_outputFileName) {
                 int maxRotationCountDigits =
                     (g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0;
 
                 for (int i = g_maxRotatedLogs ; i >= 0 ; --i) {
-                    char *file;
+                    std::string file;
 
                     if (i == 0) {
-                        asprintf(&file, "%s", g_outputFileName);
+                        file = android::base::StringPrintf("%s", g_outputFileName);
                     } else {
-                        asprintf(&file, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
+                        file = android::base::StringPrintf("%s.%.*d",
+                            g_outputFileName, maxRotationCountDigits, i);
                     }
 
-                    if (!file) {
+                    if (file.length() == 0) {
                         perror("while clearing log files");
                         clearFail = clearFail ?: dev->device;
                         break;
                     }
 
-                    err = unlink(file);
+                    err = unlink(file.c_str());
 
                     if (err < 0 && errno != ENOENT && clearFail == NULL) {
                         perror("while clearing log files");
                         clearFail = dev->device;
                     }
-
-                    free(file);
                 }
             } else if (android_logger_clear(dev->logger)) {
                 clearFail = clearFail ?: dev->device;
@@ -1177,7 +1193,6 @@
         return EXIT_SUCCESS;
     }
 
-
     if (getLogSize) {
         return EXIT_SUCCESS;
     }
@@ -1188,6 +1203,8 @@
         return EXIT_SUCCESS;
     }
 
+    setupOutputAndSchedulingPolicy((mode & ANDROID_LOG_NONBLOCK) == 0);
+
     //LOG_EVENT_INT(10, 12345);
     //LOG_EVENT_LONG(11, 0x1122334455667788LL);
     //LOG_EVENT_STRING(0, "whassup, doc?");
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index 4d5c80c..b082a64 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -36,7 +36,7 @@
     mkdir /data/misc/logd 0700 logd log
     # logd for write to /data/misc/logd, log group for read from pstore (-L)
     # b/28788401 b/30041146 b/30612424
-    # exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
+    # exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
     start logcatd
 
 # stop logcatd service and clear data
@@ -57,7 +57,7 @@
     stop logcatd
 
 # logcatd service
-service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
+service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
     class late_start
     disabled
     # logd for write to /data/misc/logd, log group for read from log daemon
diff --git a/logcat/logpersist b/logcat/logpersist
index f0e7d42..c09b6b2 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -17,8 +17,9 @@
    ;;
 esac
 
+log_uid=logd
 log_tag_property=persist.log.tag
-data=/data/misc/logd
+data=/data/misc/logd/logcat
 service=logcatd
 size_default=256
 buffer_default=all
@@ -74,11 +75,12 @@
   if [ -n "${size}${buffer}" -o "true" = "${clear}" ]; then
     echo WARNING: Can not use --clear, --size or --buffer with ${progname%.*}.cat >&2
   fi
-  su logd ls "${data}" |
+  su ${log_uid} ls "${data%/*}" |
   tr -d '\r' |
   sort -ru |
-  sed "s#^#${data}/#" |
-  su logd xargs cat
+  sed "s#^#${data%/*}/#" |
+  grep "${data}[.]*[0-9]*\$" |
+  su ${log_uid} xargs cat
   ;;
 *.start)
   current_buffer="`getprop ${property#persist.}.buffer`"
@@ -139,7 +141,7 @@
   sleep 1
   getprop ${property#persist.}
   # also generate an error return code if not found running
-  pgrep -u ${data##*/} ${service%d}
+  pgrep -u ${log_uid} ${service%d}
   ;;
 *.stop)
   if [ -n "${size}${buffer}" ]; then
@@ -171,6 +173,6 @@
 
 if [ X"${log_tag}" != X"`getprop ${log_tag_property}`" ] ||
    [ X"${logd_logpersistd}" != X"`getprop ${property}`" ]; then
-  echo "WARNING: killing Settings" >&2
+  echo "WARNING: killing Settings application to pull in new values" >&2
   am force-stop com.android.settings
 fi
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 0043d1b..3daee13 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -848,6 +849,75 @@
     EXPECT_FALSE(system(command));
 }
 
+static int logrotate_count_id(const char *logcat_cmd, const char *tmp_out_dir) {
+
+    static const char log_filename[] = "log.txt";
+    char command[strlen(tmp_out_dir) + strlen(logcat_cmd) + strlen(log_filename) + 32];
+
+    snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
+
+    int ret;
+    EXPECT_FALSE((ret = system(command)));
+    if (ret) {
+        return -1;
+    }
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
+    EXPECT_NE(nullptr, dir);
+    if (!dir) {
+        return -1;
+    }
+    struct dirent *entry;
+    int count = 0;
+    while ((entry = readdir(dir.get()))) {
+        if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
+            continue;
+        }
+        ++count;
+    }
+    return count;
+}
+
+TEST(logcat, logrotate_id) {
+    static const char logcat_cmd[] = "logcat -b all -d -f %s/%s -n 32 -r 1 --id=test";
+    static const char logcat_short_cmd[] = "logcat -b all -t 10 -f %s/%s -n 32 -r 1 --id=test";
+    static const char tmp_out_dir_form[] = "/data/local/tmp/logcat.logrotate.XXXXXX";
+    static const char log_filename[] = "log.txt";
+    char tmp_out_dir[strlen(tmp_out_dir_form) + 1];
+    ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
+
+    EXPECT_EQ(34, logrotate_count_id(logcat_cmd, tmp_out_dir));
+    EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+
+    char id_file[strlen(tmp_out_dir_form) + strlen(log_filename) + 5];
+    snprintf(id_file, sizeof(id_file), "%s/%s.id", tmp_out_dir, log_filename);
+    if (getuid() != 0) {
+        chmod(id_file, 0);
+        EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+    }
+    unlink(id_file);
+    EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+
+    FILE *fp = fopen(id_file, "w");
+    if (fp) {
+        fprintf(fp, "not_a_test");
+        fclose(fp);
+    }
+    if (getuid() != 0) {
+        chmod(id_file, 0); // API to preserve content even with signature change
+        ASSERT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+        chmod(id_file, 0600);
+    }
+
+    int new_signature;
+    EXPECT_LE(2, (new_signature = logrotate_count_id(logcat_short_cmd, tmp_out_dir)));
+    EXPECT_GT(34, new_signature);
+
+    static const char cleanup_cmd[] = "rm -rf %s";
+    char command[strlen(cleanup_cmd) + strlen(tmp_out_dir_form)];
+    snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
+    EXPECT_FALSE(system(command));
+}
+
 TEST(logcat, logrotate_nodir) {
     // expect logcat to error out on writing content and exit(1) for nodir
     EXPECT_EQ(W_EXITCODE(1, 0),
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index fa95733..1ecf99c 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -508,7 +508,8 @@
     LogBufferElementCollection::iterator it;
 
     if (caller_uid != AID_ROOT) {
-        // Only here if clearAll condition (pruneRows == ULONG_MAX)
+        // Only here if clear all request from non system source, so chatty
+        // filter logistics is not required.
         it = mLastSet[id] ? mLast[id] : mLogElements.begin();
         while (it != mLogElements.end()) {
             LogBufferElement *element = *it;
@@ -534,7 +535,9 @@
             }
 
             it = erase(it);
-            pruneRows--;
+            if (--pruneRows == 0) {
+                break;
+            }
         }
         LogTimeEntry::unlock();
         return busy;
@@ -678,7 +681,7 @@
                         && ((!gc && (element->getPid() == worstPid))
                            || (mLastWorstPidOfSystem[id].find(element->getPid())
                                 == mLastWorstPidOfSystem[id].end()))) {
-                    mLastWorstPidOfSystem[id][key] = it;
+                    mLastWorstPidOfSystem[id][element->getPid()] = it;
                 }
                 if ((!gc && !worstPid && (key == worst))
                         || (mLastWorst[id].find(key) == mLastWorst[id].end())) {
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index a0b7499..c7506ef 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -26,6 +26,7 @@
 #include <syslog.h>
 
 #include <log/logger.h>
+#include <private/android_filesystem_config.h>
 
 #include "LogBuffer.h"
 #include "LogKlog.h"
@@ -614,7 +615,12 @@
     // Parse pid, tid and uid
     const pid_t pid = sniffPid(&p, len - (p - buf));
     const pid_t tid = pid;
-    const uid_t uid = pid ? logbuf->pidToUid(pid) : 0;
+    uid_t uid = AID_ROOT;
+    if (pid) {
+        logbuf->lock();
+        uid = logbuf->pidToUid(pid);
+        logbuf->unlock();
+    }
 
     // Parse (rules at top) to pull out a tag from the incoming kernel message.
     // Some may view the following as an ugly heuristic, the desire is to
@@ -630,126 +636,124 @@
     const char *tag = "";
     const char *etag = tag;
     size_t taglen = len - (p - buf);
-    if (!isspace(*p) && *p) {
-        const char *bt, *et, *cp;
+    const char *bt = p;
 
-        bt = p;
-        if ((taglen >= 6) && !fast<strncmp>(p, "[INFO]", 6)) {
-            // <PRI>[<TIME>] "[INFO]"<tag> ":" message
-            bt = p + 6;
-            taglen -= 6;
-        }
-        for(et = bt; taglen && *et && (*et != ':') && !isspace(*et); ++et, --taglen) {
-           // skip ':' within [ ... ]
-           if (*et == '[') {
-               while (taglen && *et && *et != ']') {
-                   ++et;
-                   --taglen;
-               }
-            }
-        }
-        for(cp = et; taglen && isspace(*cp); ++cp, --taglen);
-        size_t size;
+    static const char infoBrace[] = "[INFO]";
+    static const size_t infoBraceLen = strlen(infoBrace);
+    if ((taglen >= infoBraceLen) && !fast<strncmp>(p, infoBrace, infoBraceLen)) {
+        // <PRI>[<TIME>] "[INFO]"<tag> ":" message
+        bt = p + infoBraceLen;
+        taglen -= infoBraceLen;
+    }
 
+    const char *et;
+    for (et = bt; taglen && *et && (*et != ':') && !isspace(*et); ++et, --taglen) {
+       // skip ':' within [ ... ]
+       if (*et == '[') {
+           while (taglen && *et && *et != ']') {
+               ++et;
+               --taglen;
+           }
+           if (!taglen) {
+               break;
+           }
+       }
+    }
+    const char *cp;
+    for (cp = et; taglen && isspace(*cp); ++cp, --taglen);
+
+    // Validate tag
+    size_t size = et - bt;
+    if (taglen && size) {
         if (*cp == ':') {
+            // ToDo: handle case insensitive colon separated logging stutter:
+            //       <tag> : <tag>: ...
+
             // One Word
             tag = bt;
             etag = et;
             p = cp + 1;
-        } else if (taglen) {
-            size = et - bt;
-            if ((taglen > size) &&   // enough space for match plus trailing :
-                    (*bt == *cp) &&  // ubber fast<strncmp> pair
-                    fast<strncmp>(bt + 1, cp + 1, size - 1)) {
-                // <PRI>[<TIME>] <tag>_host '<tag>.<num>' : message
-                if (!fast<strncmp>(bt + size - 5, "_host", 5)
-                        && !fast<strncmp>(bt + 1, cp + 1, size - 6)) {
+        } else if ((taglen > size) && (tolower(*bt) == tolower(*cp))) {
+            // clean up any tag stutter
+            if (!fast<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match
+                // <PRI>[<TIME>] <tag> <tag> : message
+                // <PRI>[<TIME>] <tag> <tag>: message
+                // <PRI>[<TIME>] <tag> '<tag>.<num>' : message
+                // <PRI>[<TIME>] <tag> '<tag><num>' : message
+                // <PRI>[<TIME>] <tag> '<tag><stuff>' : message
+                const char *b = cp;
+                cp += size;
+                taglen -= size;
+                while (--taglen && !isspace(*++cp) && (*cp != ':'));
+                const char *e;
+                for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+                if (taglen && (*cp == ':')) {
+                    tag = b;
+                    etag = e;
+                    p = cp + 1;
+                }
+            } else {
+                // what about <PRI>[<TIME>] <tag>_host '<tag><stuff>' : message
+                static const char host[] = "_host";
+                static const size_t hostlen = strlen(host);
+                if ((size > hostlen) &&
+                        !fast<strncmp>(bt + size - hostlen, host, hostlen) &&
+                        !fast<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) {
                     const char *b = cp;
-                    cp += size - 5;
-                    taglen -= size - 5;
+                    cp += size - hostlen;
+                    taglen -= size - hostlen;
                     if (*cp == '.') {
                         while (--taglen && !isspace(*++cp) && (*cp != ':'));
                         const char *e;
-                        for(e = cp; taglen && isspace(*cp); ++cp, --taglen);
-                        if (*cp == ':') {
+                        for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+                        if (taglen && (*cp == ':')) {
                             tag = b;
                             etag = e;
                             p = cp + 1;
                         }
                     }
                 } else {
-                    while (--taglen && !isspace(*++cp) && (*cp != ':'));
-                    const char *e;
-                    for(e = cp; taglen && isspace(*cp); ++cp, --taglen);
-                    // Two words
-                    if (*cp == ':') {
-                        tag = bt;
-                        etag = e;
-                        p = cp + 1;
-                    }
-                }
-            } else if (isspace(cp[size])) {
-                cp += size;
-                taglen -= size;
-                while (--taglen && isspace(*++cp));
-                // <PRI>[<TIME>] <tag> <tag> : message
-                if (*cp == ':') {
-                    tag = bt;
-                    etag = et;
-                    p = cp + 1;
-                }
-            } else if (cp[size] == ':') {
-                // <PRI>[<TIME>] <tag> <tag> : message
-                tag = bt;
-                etag = et;
-                p = cp + size + 1;
-            } else if ((cp[size] == '.') || isdigit(cp[size])) {
-                // <PRI>[<TIME>] <tag> '<tag>.<num>' : message
-                // <PRI>[<TIME>] <tag> '<tag><num>' : message
-                const char *b = cp;
-                cp += size;
-                taglen -= size;
-                while (--taglen && !isspace(*++cp) && (*cp != ':'));
-                const char *e = cp;
-                while (taglen && isspace(*cp)) {
-                    ++cp;
-                    --taglen;
-                }
-                if (*cp == ':') {
-                    tag = b;
-                    etag = e;
-                    p = cp + 1;
-                }
-            } else {
-                while (--taglen && !isspace(*++cp) && (*cp != ':'));
-                const char *e = cp;
-                while (taglen && isspace(*cp)) {
-                    ++cp;
-                    --taglen;
-                }
-                // Two words
-                if (*cp == ':') {
-                    tag = bt;
-                    etag = e;
-                    p = cp + 1;
+                    goto twoWord;
                 }
             }
-        } /* else no tag */
-        size = etag - tag;
-        if ((size <= 1)
-            // register names like x9
-                || ((size == 2) && (isdigit(tag[0]) || isdigit(tag[1])))
-            // register names like x18 but not driver names like en0
-                || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
-            // blacklist
-                || ((size == 3) && !fast<strncmp>(tag, "CPU", 3))
-                || ((size == 7) && !fast<strncasecmp>(tag, "WARNING", 7))
-                || ((size == 5) && !fast<strncasecmp>(tag, "ERROR", 5))
-                || ((size == 4) && !fast<strncasecmp>(tag, "INFO", 4))) {
-            p = start;
-            etag = tag = "";
+        } else {
+            // <PRI>[<TIME>] <tag> <stuff>' : message
+twoWord:    while (--taglen && !isspace(*++cp) && (*cp != ':'));
+            const char *e;
+            for (e = cp; taglen && isspace(*cp); ++cp, --taglen);
+            // Two words
+            if (taglen && (*cp == ':')) {
+                tag = bt;
+                etag = e;
+                p = cp + 1;
+            }
         }
+    } // else no tag
+
+    static const char cpu[] = "CPU";
+    static const size_t cpuLen = strlen(cpu);
+    static const char warning[] = "WARNING";
+    static const size_t warningLen = strlen(warning);
+    static const char error[] = "ERROR";
+    static const size_t errorLen = strlen(error);
+    static const char info[] = "INFO";
+    static const size_t infoLen = strlen(info);
+
+    size = etag - tag;
+    if ((size <= 1)
+        // register names like x9
+            || ((size == 2) && (isdigit(tag[0]) || isdigit(tag[1])))
+        // register names like x18 but not driver names like en0
+            || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
+        // blacklist
+            || ((size == cpuLen) && !fast<strncmp>(tag, cpu, cpuLen))
+            || ((size == warningLen) && !fast<strncasecmp>(tag, warning, warningLen))
+            || ((size == errorLen) && !fast<strncasecmp>(tag, error, errorLen))
+            || ((size == infoLen) && !fast<strncasecmp>(tag, info, infoLen))) {
+        p = start;
+        etag = tag = "";
     }
+
     // Suppress additional stutter in tag:
     //   eg: [143:healthd]healthd -> [143:healthd]
     taglen = etag - tag;
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 2014374..301ede9 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -213,9 +213,15 @@
         version = 1;
         break;
 
-    case sizeof(msg->entry_v2):
+    case sizeof(msg->entry_v2): /* PLUS case sizeof(msg->entry_v3): */
         if (version == 0) {
-            version = 2;
+            version = (msg->entry_v3.lid < LOG_ID_MAX) ? 3 : 2;
+        }
+        break;
+
+    case sizeof(msg->entry_v4):
+        if (version == 0) {
+            version = 4;
         }
         break;
     }
@@ -269,6 +275,11 @@
     unsigned int len = msg->entry.len;
     fprintf(stderr, "msg[%u]={", len);
     unsigned char *cp = reinterpret_cast<unsigned char *>(msg->msg());
+    if (!cp) {
+        static const unsigned char garbage[] = "<INVALID>";
+        cp = const_cast<unsigned char *>(garbage);
+        len = strlen(reinterpret_cast<const char *>(garbage));
+    }
     while(len) {
         unsigned char *p = cp;
         while (*p && (((' ' <= *p) && (*p < 0x7F)) || (*p == '\n'))) {
diff --git a/metricsd/.clang-format b/metricsd/.clang-format
deleted file mode 120000
index f9066d4..0000000
--- a/metricsd/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../../../build/tools/brillo-clang-format
\ No newline at end of file
diff --git a/metricsd/Android.mk b/metricsd/Android.mk
deleted file mode 100644
index 65ca1f6..0000000
--- a/metricsd/Android.mk
+++ /dev/null
@@ -1,226 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-metrics_cpp_extension := .cc
-libmetrics_sources := \
-  c_metrics_library.cc \
-  metrics_library.cc \
-  timer.cc
-
-metrics_client_sources := \
-  metrics_client.cc
-
-metrics_collector_common := \
-  collectors/averaged_statistics_collector.cc \
-  collectors/cpu_usage_collector.cc \
-  collectors/disk_usage_collector.cc \
-  metrics_collector.cc \
-  metrics_collector_service_impl.cc \
-  persistent_integer.cc
-
-metricsd_common := \
-  persistent_integer.cc \
-  uploader/bn_metricsd_impl.cc \
-  uploader/crash_counters.cc \
-  uploader/metrics_hashes.cc \
-  uploader/metrics_log_base.cc \
-  uploader/metrics_log.cc \
-  uploader/metricsd_service_runner.cc \
-  uploader/sender_http.cc \
-  uploader/system_profile_cache.cc \
-  uploader/upload_service.cc
-
-metrics_collector_tests_sources := \
-  collectors/averaged_statistics_collector_test.cc \
-  collectors/cpu_usage_collector_test.cc \
-  metrics_collector_test.cc \
-  metrics_library_test.cc \
-  persistent_integer_test.cc \
-  timer_test.cc
-
-metricsd_tests_sources := \
-  uploader/metrics_hashes_unittest.cc \
-  uploader/metrics_log_base_unittest.cc \
-  uploader/mock/sender_mock.cc \
-  uploader/upload_service_test.cc
-
-metrics_CFLAGS := -Wall \
-  -Wno-char-subscripts \
-  -Wno-missing-field-initializers \
-  -Wno-unused-parameter \
-  -Werror \
-  -fvisibility=default
-metrics_CPPFLAGS := -Wno-non-virtual-dtor \
-  -Wno-sign-promo \
-  -Wno-strict-aliasing \
-  -fvisibility=default
-metrics_includes := external/gtest/include \
-  $(LOCAL_PATH)/include
-libmetrics_shared_libraries := libchrome libbinder libbrillo libutils
-metrics_collector_shared_libraries := $(libmetrics_shared_libraries) \
-  libbrillo-binder \
-  libbrillo-http \
-  libmetrics \
-  librootdev \
-  libweaved
-
-metrics_collector_static_libraries := libmetricscollectorservice
-
-metricsd_shared_libraries := \
-  libbinder \
-  libbrillo \
-  libbrillo-binder \
-  libbrillo-http \
-  libchrome \
-  libprotobuf-cpp-lite \
-  libupdate_engine_client \
-  libutils
-
-# Static proxy library for the metricsd binder interface.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd_binder_proxy
-LOCAL_SHARED_LIBRARIES := libbinder libutils
-LOCAL_SRC_FILES := aidl/android/brillo/metrics/IMetricsd.aidl
-include $(BUILD_STATIC_LIBRARY)
-
-# Static library for the metrics_collector binder interface.
-# ==========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libmetricscollectorservice
-LOCAL_CLANG := true
-LOCAL_SHARED_LIBRARIES := libbinder libbrillo-binder libchrome libutils
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SRC_FILES := \
-  aidl/android/brillo/metrics/IMetricsCollectorService.aidl \
-  metrics_collector_service_client.cc
-include $(BUILD_STATIC_LIBRARY)
-
-# Shared library for metrics.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := libmetrics
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := $(libmetrics_shared_libraries)
-LOCAL_SRC_FILES := $(libmetrics_sources)
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
-include $(BUILD_SHARED_LIBRARY)
-
-# CLI client for metrics.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics_client
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_SHARED_LIBRARIES := $(libmetrics_shared_libraries) \
-  libmetrics
-LOCAL_SRC_FILES := $(metrics_client_sources)
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy
-include $(BUILD_EXECUTABLE)
-
-# Protobuf library for metricsd.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd_protos
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-generated_sources_dir := $(call local-generated-sources-dir)
-LOCAL_EXPORT_C_INCLUDE_DIRS += \
-    $(generated_sources_dir)/proto/system/core/metricsd
-LOCAL_SRC_FILES :=  $(call all-proto-files-under,uploader/proto)
-include $(BUILD_STATIC_LIBRARY)
-
-# metrics_collector daemon.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics_collector
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_INIT_RC := metrics_collector.rc
-LOCAL_REQUIRED_MODULES := metrics.json
-LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
-LOCAL_SRC_FILES := $(metrics_collector_common) \
-  metrics_collector_main.cc
-LOCAL_STATIC_LIBRARIES := metricsd_binder_proxy \
-  $(metrics_collector_static_libraries)
-include $(BUILD_EXECUTABLE)
-
-# metricsd daemon.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd
-LOCAL_C_INCLUDES := $(metrics_includes)
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
-LOCAL_INIT_RC := metricsd.rc
-LOCAL_REQUIRED_MODULES := \
-  metrics_collector
-LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries)
-LOCAL_STATIC_LIBRARIES := metricsd_protos metricsd_binder_proxy
-LOCAL_SRC_FILES := $(metricsd_common) \
-  metricsd_main.cc
-include $(BUILD_EXECUTABLE)
-
-# Unit tests for metricsd.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metricsd_tests
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS) -Wno-sign-compare
-LOCAL_SHARED_LIBRARIES := $(metricsd_shared_libraries)
-LOCAL_SRC_FILES := $(metricsd_tests_sources) $(metricsd_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_protos metricsd_binder_proxy
-include $(BUILD_NATIVE_TEST)
-
-# Unit tests for metrics_collector.
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics_collector_tests
-LOCAL_CFLAGS := $(metrics_CFLAGS)
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
-LOCAL_CPPFLAGS := $(metrics_CPPFLAGS) -Wno-sign-compare
-LOCAL_SHARED_LIBRARIES := $(metrics_collector_shared_libraries)
-LOCAL_SRC_FILES := $(metrics_collector_tests_sources) \
-  $(metrics_collector_common)
-LOCAL_STATIC_LIBRARIES := libBionicGtestMain libgmock metricsd_binder_proxy \
-  $(metrics_collector_static_libraries)
-include $(BUILD_NATIVE_TEST)
-
-# Weave schema files
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := metrics.json
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/weaved/traits
-LOCAL_SRC_FILES := etc/weaved/traits/$(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
diff --git a/metricsd/OWNERS b/metricsd/OWNERS
deleted file mode 100644
index 7f5e50d..0000000
--- a/metricsd/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-semenzato@chromium.org
-derat@chromium.org
-bsimonnet@chromium.org
diff --git a/metricsd/README.md b/metricsd/README.md
deleted file mode 100644
index 8d4828c..0000000
--- a/metricsd/README.md
+++ /dev/null
@@ -1,124 +0,0 @@
-Metricsd
-========
-
-The metricsd daemon is used to gather metrics from the platform and application,
-aggregate them and upload them periodically to a server.
-The metrics will then be available in their aggregated form to the developer
-for analysis.
-
-Three components are provided to interact with `metricsd`: `libmetrics`,
-`metrics_collector` and `metrics_client`.
-
-The Metrics Library: libmetrics
--------------------------------
-
-`libmetrics` is a small library that implements the basic C++ API for
-metrics collection. All metrics collection is funneled through this library. The
-easiest and recommended way for a client-side module to collect user metrics is
-to link `libmetrics` and use its APIs to send metrics to `metricsd` for transport to
-UMA. In order to use the library in a module, you need to do the following:
-
-- Add a dependency on the shared library in your Android.mk file:
-  `LOCAL_SHARED_LIBRARIES += libmetrics`
-
-- To access the metrics library API in the module, include the
-  <metrics/metrics_library.h> header file.
-
-- The API is documented in `metrics_library.h`. Before using the API methods, a
-  MetricsLibrary object needs to be constructed and initialized through its
-  Init method.
-
-- Samples are uploaded only if the `/data/misc/metrics/enabled` file exists.
-
-
-Server Side
------------
-
-You will be able to see all uploaded metrics on the metrics dashboard,
-accessible via the developer console.
-
-*** note
-It usually takes a day for metrics to be available on the dashboard.
-***
-
-
-The Metrics Client: metrics_client
-----------------------------------
-
-`metrics_client` is a simple shell command-line utility for sending histogram
-samples and querying `metricsd`. It's installed under `/system/bin` on the target
-platform and uses `libmetrics`.
-
-For usage information and command-line options, run `metrics_client` on the
-target platform or look for "Usage:" in `metrics_client.cc`.
-
-
-The Metrics Daemon: metricsd
-----------------------------
-
-`metricsd` is the daemon that listens for metrics logging calls (via Binder),
-aggregates the metrics and uploads them periodically. This daemon should start as
-early as possible so that depending daemons can log at any time.
-
-`metricsd` is made of two threads that work as follows:
-
-* The binder thread listens for one-way Binder calls, aggregates the metrics in
-  memory (via `base::StatisticsRecorder`) and increments the crash counters when a
-  crash is reported. This thread is kept as simple as possible to ensure the
-  maximum throughput possible.
-* The uploader thread takes care of backing up the metrics to disk periodically
-  (to avoid losing metrics on crashes), collecting metadata about the client
-  (version number, channel, etc..) and uploading the metrics periodically to the
-  server.
-
-
-The Metrics Collector: metrics_collector
-----------------------------------------
-
-metrics_collector is a daemon that runs in the background on the target platform,
-gathers health information about the system and maintains long running counters
-(ex: number of crashes per week).
-
-The recommended way to generate metrics data from a module is to link and use
-libmetrics directly. However, we may not want to add a dependency on libmetrics
-to some modules (ex: kernel). In this case, we can add a collector to
-metrics_collector that will, for example, take measurements and report them
-periodically to metricsd (this is the case for the disk utilization histogram).
-
-
-FAQ
----
-
-### What should my histogram's |min| and |max| values be set at?
-
-You should set the values to a range that covers the vast majority of samples
-that would appear in the field. Note that samples below the |min| will still
-be collected in the underflow bucket and samples above the |max| will end up
-in the overflow bucket. Also, the reported mean of the data will be correct
-regardless of the range.
-
-### How many buckets should I use in my histogram?
-
-You should allocate as many buckets as necessary to perform proper analysis
-on the collected data. Note, however, that the memory allocated in metricsd
-for each histogram is proportional to the number of buckets. Therefore, it is
-strongly recommended to keep this number low (e.g., 50 is normal, while 100
-is probably high).
-
-### When should I use an enumeration (linear) histogram vs. a regular (exponential) histogram?
-
-Enumeration histograms should really be used only for sampling enumerated
-events and, in some cases, percentages. Normally, you should use a regular
-histogram with exponential bucket layout that provides higher resolution at
-the low end of the range and lower resolution at the high end. Regular
-histograms are generally used for collecting performance data (e.g., timing,
-memory usage, power) as well as aggregated event counts.
-
-### How can I test that my histogram was reported correctly?
-
-* Make sure no error messages appear in logcat when you log a sample.
-* Run `metrics_client -d` to dump the currently aggregated metrics. Your
-  histogram should appear in the list.
-* Make sure that the aggregated metrics were uploaded to the server successfully
-  (check for an OK message from `metricsd` in logcat).
-* After a day, your histogram should be available on the dashboard.
diff --git a/metricsd/WATCHLISTS b/metricsd/WATCHLISTS
deleted file mode 100644
index a051f35..0000000
--- a/metricsd/WATCHLISTS
+++ /dev/null
@@ -1,16 +0,0 @@
-# See http://dev.chromium.org/developers/contributing-code/watchlists for
-# a description of this file's format.
-# Please keep these keys in alphabetical order.
-
-{
-  'WATCHLIST_DEFINITIONS': {
-    'all': {
-      'filepath': '.',
-    },
-  },
-  'WATCHLISTS': {
-    'all': ['petkov@chromium.org',
-                'semenzato@chromium.org',
-                'sosa@chromium.org']
-  },
-}
diff --git a/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl b/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
deleted file mode 100644
index 49f484f..0000000
--- a/metricsd/aidl/android/brillo/metrics/IMetricsCollectorService.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-package android.brillo.metrics;
-
-interface IMetricsCollectorService {
-  oneway void notifyUserCrash();
-}
diff --git a/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl b/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl
deleted file mode 100644
index aa3cb34..0000000
--- a/metricsd/aidl/android/brillo/metrics/IMetricsd.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-package android.brillo.metrics;
-
-interface IMetricsd {
-  oneway void recordHistogram(String name, int sample, int min, int max,
-                              int nbuckets);
-  oneway void recordLinearHistogram(String name, int sample, int max);
-  oneway void recordSparseHistogram(String name, int sample);
-  oneway void recordCrash(String type);
-  String getHistogramsDump();
-}
diff --git a/metricsd/c_metrics_library.cc b/metricsd/c_metrics_library.cc
deleted file mode 100644
index 47a543e..0000000
--- a/metricsd/c_metrics_library.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.
- */
-
-//
-// C wrapper to libmetrics
-//
-
-#include "metrics/c_metrics_library.h"
-
-#include <string>
-
-#include "metrics/metrics_library.h"
-
-extern "C" CMetricsLibrary CMetricsLibraryNew(void) {
-  MetricsLibrary* lib = new MetricsLibrary;
-  return reinterpret_cast<CMetricsLibrary>(lib);
-}
-
-extern "C" void CMetricsLibraryDelete(CMetricsLibrary handle) {
-  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
-  delete lib;
-}
-
-extern "C" void CMetricsLibraryInit(CMetricsLibrary handle) {
-  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
-  if (lib != NULL)
-    lib->Init();
-}
-
-extern "C" int CMetricsLibrarySendToUMA(CMetricsLibrary handle,
-                                        const char* name, int sample,
-                                        int min, int max, int nbuckets) {
-  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
-  if (lib == NULL)
-    return 0;
-  return lib->SendToUMA(std::string(name), sample, min, max, nbuckets);
-}
-
-extern "C" int CMetricsLibrarySendEnumToUMA(CMetricsLibrary handle,
-                                            const char* name, int sample,
-                                            int max) {
-  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
-  if (lib == NULL)
-    return 0;
-  return lib->SendEnumToUMA(std::string(name), sample, max);
-}
-
-extern "C" int CMetricsLibrarySendSparseToUMA(CMetricsLibrary handle,
-                                              const char* name, int sample) {
-  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
-  if (lib == NULL)
-    return 0;
-  return lib->SendSparseToUMA(std::string(name), sample);
-}
-
-extern "C" int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
-                                            const char* crash_kind) {
-  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
-  if (lib == NULL)
-    return 0;
-  return lib->SendCrashToUMA(crash_kind);
-}
-
-extern "C" int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle) {
-  MetricsLibrary* lib = reinterpret_cast<MetricsLibrary*>(handle);
-  if (lib == NULL)
-    return 0;
-  return lib->AreMetricsEnabled();
-}
diff --git a/metricsd/collectors/averaged_statistics_collector.cc b/metricsd/collectors/averaged_statistics_collector.cc
deleted file mode 100644
index a3aaa98..0000000
--- a/metricsd/collectors/averaged_statistics_collector.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * 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.
- */
-
-#include "averaged_statistics_collector.h"
-
-#include <base/bind.h>
-#include <base/files/file_util.h>
-#include <base/files/file_path.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-
-#include "metrics_collector.h"
-
-namespace {
-
-// disk stats metrics
-
-// The {Read,Write}Sectors numbers are in sectors/second.
-// A sector is usually 512 bytes.
-const char kReadSectorsHistogramName[] = "Platform.ReadSectors";
-const char kWriteSectorsHistogramName[] = "Platform.WriteSectors";
-const int kDiskMetricsStatItemCount = 11;
-
-// Assume a max rate of 250Mb/s for reads (worse for writes) and 512 byte
-// sectors.
-const int kSectorsIOMax = 500000;  // sectors/second
-const int kSectorsBuckets = 50;    // buckets
-
-// Page size is 4k, sector size is 0.5k.  We're not interested in page fault
-// rates that the disk cannot sustain.
-const int kPageFaultsMax = kSectorsIOMax / 8;  // Page faults/second
-const int kPageFaultsBuckets = 50;
-
-// Major page faults, i.e. the ones that require data to be read from disk.
-const char kPageFaultsHistogramName[] = "Platform.PageFaults";
-
-// Swap in and Swap out
-const char kSwapInHistogramName[] = "Platform.SwapIn";
-const char kSwapOutHistogramName[] = "Platform.SwapOut";
-
-const int kIntervalBetweenCollection = 60;  // seconds
-const int kCollectionDuration = 1;  // seconds
-
-}  // namespace
-
-AveragedStatisticsCollector::AveragedStatisticsCollector(
-    MetricsLibraryInterface* metrics_library,
-    const std::string& diskstats_path,
-    const std::string& vmstats_path) :
-  metrics_lib_(metrics_library),
-  diskstats_path_(diskstats_path),
-  vmstats_path_(vmstats_path) {
-}
-
-void AveragedStatisticsCollector::ScheduleWait() {
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&AveragedStatisticsCollector::WaitCallback,
-                 base::Unretained(this)),
-      base::TimeDelta::FromSeconds(
-          kIntervalBetweenCollection - kCollectionDuration));
-}
-
-void AveragedStatisticsCollector::ScheduleCollect() {
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&AveragedStatisticsCollector::CollectCallback,
-                 base::Unretained(this)),
-      base::TimeDelta::FromSeconds(kCollectionDuration));
-}
-
-void AveragedStatisticsCollector::WaitCallback() {
-  ReadInitialValues();
-  ScheduleCollect();
-}
-
-void AveragedStatisticsCollector::CollectCallback() {
-  Collect();
-  ScheduleWait();
-}
-
-void AveragedStatisticsCollector::ReadInitialValues() {
-  stats_start_time_ = MetricsCollector::GetActiveTime();
-  DiskStatsReadStats(&read_sectors_, &write_sectors_);
-  VmStatsReadStats(&vmstats_);
-}
-
-bool AveragedStatisticsCollector::DiskStatsReadStats(
-    uint64_t* read_sectors, uint64_t* write_sectors) {
-  CHECK(read_sectors);
-  CHECK(write_sectors);
-  std::string line;
-  if (diskstats_path_.empty()) {
-    return false;
-  }
-
-  if (!base::ReadFileToString(base::FilePath(diskstats_path_), &line)) {
-    PLOG(WARNING) << "Could not read disk stats from "
-                  << diskstats_path_.value();
-    return false;
-  }
-
-  std::vector<std::string> parts = base::SplitString(
-      line, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-  if (parts.size() != kDiskMetricsStatItemCount) {
-    LOG(ERROR) << "Could not parse disk stat correctly. Expected "
-               << kDiskMetricsStatItemCount << " elements but got "
-               << parts.size();
-    return false;
-  }
-  if (!base::StringToUint64(parts[2], read_sectors)) {
-    LOG(ERROR) << "Couldn't convert read sectors " << parts[2] << " to uint64";
-    return false;
-  }
-  if (!base::StringToUint64(parts[6], write_sectors)) {
-    LOG(ERROR) << "Couldn't convert write sectors " << parts[6] << " to uint64";
-    return false;
-  }
-
-  return true;
-}
-
-bool AveragedStatisticsCollector::VmStatsParseStats(
-    const char* stats, struct VmstatRecord* record) {
-  CHECK(stats);
-  CHECK(record);
-  base::StringPairs pairs;
-  base::SplitStringIntoKeyValuePairs(stats, ' ', '\n', &pairs);
-
-  for (base::StringPairs::iterator it = pairs.begin();
-       it != pairs.end(); ++it) {
-    if (it->first == "pgmajfault" &&
-        !base::StringToUint64(it->second, &record->page_faults)) {
-      return false;
-    }
-    if (it->first == "pswpin" &&
-        !base::StringToUint64(it->second, &record->swap_in)) {
-      return false;
-    }
-    if (it->first == "pswpout" &&
-        !base::StringToUint64(it->second, &record->swap_out)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-bool AveragedStatisticsCollector::VmStatsReadStats(struct VmstatRecord* stats) {
-  CHECK(stats);
-  std::string value_string;
-  if (!base::ReadFileToString(vmstats_path_, &value_string)) {
-    LOG(WARNING) << "cannot read " << vmstats_path_.value();
-    return false;
-  }
-  return VmStatsParseStats(value_string.c_str(), stats);
-}
-
-void AveragedStatisticsCollector::Collect() {
-  uint64_t read_sectors_now, write_sectors_now;
-  struct VmstatRecord vmstats_now;
-  double time_now = MetricsCollector::GetActiveTime();
-  double delta_time = time_now - stats_start_time_;
-  bool diskstats_success = DiskStatsReadStats(&read_sectors_now,
-                                              &write_sectors_now);
-
-  int delta_read = read_sectors_now - read_sectors_;
-  int delta_write = write_sectors_now - write_sectors_;
-  int read_sectors_per_second = delta_read / delta_time;
-  int write_sectors_per_second = delta_write / delta_time;
-  bool vmstats_success = VmStatsReadStats(&vmstats_now);
-  uint64_t delta_faults = vmstats_now.page_faults - vmstats_.page_faults;
-  uint64_t delta_swap_in = vmstats_now.swap_in - vmstats_.swap_in;
-  uint64_t delta_swap_out = vmstats_now.swap_out - vmstats_.swap_out;
-  uint64_t page_faults_per_second = delta_faults / delta_time;
-  uint64_t swap_in_per_second = delta_swap_in / delta_time;
-  uint64_t swap_out_per_second = delta_swap_out / delta_time;
-  if (diskstats_success) {
-    metrics_lib_->SendToUMA(kReadSectorsHistogramName,
-                            read_sectors_per_second,
-                            1,
-                            kSectorsIOMax,
-                            kSectorsBuckets);
-    metrics_lib_->SendToUMA(kWriteSectorsHistogramName,
-                            write_sectors_per_second,
-                            1,
-                            kSectorsIOMax,
-                            kSectorsBuckets);
-  }
-  if (vmstats_success) {
-    metrics_lib_->SendToUMA(kPageFaultsHistogramName,
-                            page_faults_per_second,
-                            1,
-                            kPageFaultsMax,
-                            kPageFaultsBuckets);
-    metrics_lib_->SendToUMA(kSwapInHistogramName,
-                            swap_in_per_second,
-                            1,
-                            kPageFaultsMax,
-                            kPageFaultsBuckets);
-    metrics_lib_->SendToUMA(kSwapOutHistogramName,
-                            swap_out_per_second,
-                            1,
-                            kPageFaultsMax,
-                            kPageFaultsBuckets);
-  }
-}
diff --git a/metricsd/collectors/averaged_statistics_collector.h b/metricsd/collectors/averaged_statistics_collector.h
deleted file mode 100644
index 753f70c..0000000
--- a/metricsd/collectors/averaged_statistics_collector.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICSD_COLLECTORS_AVERAGED_STATISTICS_COLLECTOR_H_
-#define METRICSD_COLLECTORS_AVERAGED_STATISTICS_COLLECTOR_H_
-
-#include "metrics/metrics_library.h"
-
-class AveragedStatisticsCollector {
- public:
-  AveragedStatisticsCollector(MetricsLibraryInterface* metrics_library,
-                              const std::string& diskstats_path,
-                              const std::string& vmstat_path);
-
-  // Schedule a wait period.
-  void ScheduleWait();
-
-  // Schedule a collection period.
-  void ScheduleCollect();
-
-  // Callback used by the main loop.
-  void CollectCallback();
-
-  // Callback used by the main loop.
-  void WaitCallback();
-
-  // Read and store the initial values at the beginning of a collection cycle.
-  void ReadInitialValues();
-
-  // Collect the disk usage statistics and report them.
-  void Collect();
-
- private:
-  friend class AveragedStatisticsTest;
-  FRIEND_TEST(AveragedStatisticsTest, ParseDiskStats);
-  FRIEND_TEST(AveragedStatisticsTest, ParseVmStats);
-
-  // Record for retrieving and reporting values from /proc/vmstat
-  struct VmstatRecord {
-    uint64_t page_faults;    // major faults
-    uint64_t swap_in;        // pages swapped in
-    uint64_t swap_out;       // pages swapped out
-  };
-
-  // Read the disk read/write statistics for the main disk.
-  bool DiskStatsReadStats(uint64_t* read_sectors, uint64_t* write_sectors);
-
-  // Parse the content of the vmstats file into |record|.
-  bool VmStatsParseStats(const char* stats, struct VmstatRecord* record);
-
-  // Read the vmstats into |stats|.
-  bool VmStatsReadStats(struct VmstatRecord* stats);
-
-  MetricsLibraryInterface* metrics_lib_;
-  base::FilePath diskstats_path_;
-  base::FilePath vmstats_path_;
-
-  // Values observed at the beginning of the collection period.
-  uint64_t read_sectors_;
-  uint64_t write_sectors_;
-  struct VmstatRecord vmstats_;
-
-  double stats_start_time_;
-};
-
-#endif  // METRICSD_COLLECTORS_AVERAGED_STATISTICS_COLLECTOR_H_
diff --git a/metricsd/collectors/averaged_statistics_collector_test.cc b/metricsd/collectors/averaged_statistics_collector_test.cc
deleted file mode 100644
index 68f9f2f..0000000
--- a/metricsd/collectors/averaged_statistics_collector_test.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.
- */
-
-#include "averaged_statistics_collector.h"
-
-#include <memory>
-
-#include <inttypes.h>
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/stringprintf.h>
-#include <gtest/gtest.h>
-
-
-static const char kFakeDiskStatsFormat[] =
-    "    1793     1788    %" PRIu64 "   105580    "
-    "    196      175     %" PRIu64 "    30290    "
-    "    0    44060   135850\n";
-static const uint64_t kFakeReadSectors[] = {80000, 100000};
-static const uint64_t kFakeWriteSectors[] = {3000, 4000};
-
-
-class AveragedStatisticsTest : public testing::Test {
- protected:
-  std::string kFakeDiskStats0;
-  std::string kFakeDiskStats1;
-
-  virtual void SetUp() {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    disk_stats_path_ = temp_dir_.path().Append("disk_stats");
-    collector_.reset(new AveragedStatisticsCollector(
-        &metrics_lib_, disk_stats_path_.value(), ""));
-
-    kFakeDiskStats0 = base::StringPrintf(kFakeDiskStatsFormat,
-                                         kFakeReadSectors[0],
-                                         kFakeWriteSectors[0]);
-    kFakeDiskStats1 = base::StringPrintf(kFakeDiskStatsFormat,
-                                         kFakeReadSectors[1],
-                                         kFakeWriteSectors[1]);
-
-    CreateFakeDiskStatsFile(kFakeDiskStats0);
-  }
-
-  // Creates or overwrites an input file containing fake disk stats.
-  void CreateFakeDiskStatsFile(const std::string& fake_stats) {
-    EXPECT_EQ(base::WriteFile(disk_stats_path_,
-                              fake_stats.data(), fake_stats.size()),
-              fake_stats.size());
-  }
-
-  // Collector used for tests.
-  std::unique_ptr<AveragedStatisticsCollector> collector_;
-
-  // Temporary directory used for tests.
-  base::ScopedTempDir temp_dir_;
-
-  // Path for the fake files.
-  base::FilePath disk_stats_path_;
-
-  MetricsLibrary metrics_lib_;
-};
-
-TEST_F(AveragedStatisticsTest, ParseDiskStats) {
-  uint64_t read_sectors_now, write_sectors_now;
-  CreateFakeDiskStatsFile(kFakeDiskStats0);
-  ASSERT_TRUE(collector_->DiskStatsReadStats(&read_sectors_now,
-                                             &write_sectors_now));
-  EXPECT_EQ(read_sectors_now, kFakeReadSectors[0]);
-  EXPECT_EQ(write_sectors_now, kFakeWriteSectors[0]);
-
-  CreateFakeDiskStatsFile(kFakeDiskStats1);
-  ASSERT_TRUE(collector_->DiskStatsReadStats(&read_sectors_now,
-                                             &write_sectors_now));
-  EXPECT_EQ(read_sectors_now, kFakeReadSectors[1]);
-  EXPECT_EQ(write_sectors_now, kFakeWriteSectors[1]);
-}
-
-TEST_F(AveragedStatisticsTest, ParseVmStats) {
-  static char kVmStats[] = "pswpin 1345\npswpout 8896\n"
-    "foo 100\nbar 200\npgmajfault 42\netcetc 300\n";
-  struct AveragedStatisticsCollector::VmstatRecord stats;
-  EXPECT_TRUE(collector_->VmStatsParseStats(kVmStats, &stats));
-  EXPECT_EQ(stats.page_faults, 42);
-  EXPECT_EQ(stats.swap_in, 1345);
-  EXPECT_EQ(stats.swap_out, 8896);
-}
diff --git a/metricsd/collectors/cpu_usage_collector.cc b/metricsd/collectors/cpu_usage_collector.cc
deleted file mode 100644
index 9b0bb34..0000000
--- a/metricsd/collectors/cpu_usage_collector.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-#include "collectors/cpu_usage_collector.h"
-
-#include <base/bind.h>
-#include <base/files/file_path.h>
-#include <base/files/file_util.h>
-#include <base/message_loop/message_loop.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/sys_info.h>
-
-#include "metrics/metrics_library.h"
-
-namespace {
-
-const char kCpuUsagePercent[] = "Platform.CpuUsage.Percent";
-const char kMetricsProcStatFileName[] = "/proc/stat";
-const int kMetricsProcStatFirstLineItemsCount = 11;
-
-// Collect every minute.
-const int kCollectionIntervalSecs = 60;
-
-}  // namespace
-
-using base::TimeDelta;
-
-CpuUsageCollector::CpuUsageCollector(MetricsLibraryInterface* metrics_library) {
-  CHECK(metrics_library);
-  metrics_lib_ = metrics_library;
-  collect_interval_ = TimeDelta::FromSeconds(kCollectionIntervalSecs);
-}
-
-void CpuUsageCollector::Init() {
-  num_cpu_ = base::SysInfo::NumberOfProcessors();
-
-  // Get ticks per second (HZ) on this system.
-  // Sysconf cannot fail, so no sanity checks are needed.
-  ticks_per_second_ = sysconf(_SC_CLK_TCK);
-  CHECK_GT(ticks_per_second_, uint64_t(0))
-      << "Number of ticks per seconds should be positive.";
-
-  latest_cpu_use_ = GetCumulativeCpuUse();
-}
-
-void CpuUsageCollector::CollectCallback() {
-  Collect();
-  Schedule();
-}
-
-void CpuUsageCollector::Schedule() {
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&CpuUsageCollector::CollectCallback, base::Unretained(this)),
-      collect_interval_);
-}
-
-void CpuUsageCollector::Collect() {
-  TimeDelta cpu_use = GetCumulativeCpuUse();
-  TimeDelta diff_per_cpu = (cpu_use - latest_cpu_use_) / num_cpu_;
-  latest_cpu_use_ = cpu_use;
-
-  // Report the cpu usage as a percentage of the total cpu usage possible.
-  int percent_use = diff_per_cpu.InMilliseconds() * 100 /
-      (kCollectionIntervalSecs * 1000);
-
-  metrics_lib_->SendEnumToUMA(kCpuUsagePercent, percent_use, 101);
-}
-
-TimeDelta CpuUsageCollector::GetCumulativeCpuUse() {
-  base::FilePath proc_stat_path(kMetricsProcStatFileName);
-  std::string proc_stat_string;
-  if (!base::ReadFileToString(proc_stat_path, &proc_stat_string)) {
-    LOG(WARNING) << "cannot open " << kMetricsProcStatFileName;
-    return TimeDelta();
-  }
-
-  uint64_t user_ticks, user_nice_ticks, system_ticks;
-  if (!ParseProcStat(proc_stat_string, &user_ticks, &user_nice_ticks,
-                     &system_ticks)) {
-    return TimeDelta();
-  }
-
-  uint64_t total = user_ticks + user_nice_ticks + system_ticks;
-  return TimeDelta::FromMicroseconds(
-      total * 1000 * 1000 / ticks_per_second_);
-}
-
-bool CpuUsageCollector::ParseProcStat(const std::string& stat_content,
-                                      uint64_t *user_ticks,
-                                      uint64_t *user_nice_ticks,
-                                      uint64_t *system_ticks) {
-  std::vector<std::string> proc_stat_lines = base::SplitString(
-      stat_content, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-  if (proc_stat_lines.empty()) {
-    LOG(WARNING) << "No lines found in " << kMetricsProcStatFileName;
-    return false;
-  }
-  std::vector<std::string> proc_stat_totals =
-      base::SplitString(proc_stat_lines[0], base::kWhitespaceASCII,
-                        base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-
-  if (proc_stat_totals.size() != kMetricsProcStatFirstLineItemsCount ||
-      proc_stat_totals[0] != "cpu" ||
-      !base::StringToUint64(proc_stat_totals[1], user_ticks) ||
-      !base::StringToUint64(proc_stat_totals[2], user_nice_ticks) ||
-      !base::StringToUint64(proc_stat_totals[3], system_ticks)) {
-    LOG(WARNING) << "cannot parse first line: " << proc_stat_lines[0];
-    return false;
-  }
-  return true;
-}
diff --git a/metricsd/collectors/cpu_usage_collector.h b/metricsd/collectors/cpu_usage_collector.h
deleted file mode 100644
index 9f92cf3..0000000
--- a/metricsd/collectors/cpu_usage_collector.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICSD_COLLECTORS_CPU_USAGE_COLLECTOR_H_
-#define METRICSD_COLLECTORS_CPU_USAGE_COLLECTOR_H_
-
-#include <base/time/time.h>
-
-#include "metrics/metrics_library.h"
-
-class CpuUsageCollector {
- public:
-  explicit CpuUsageCollector(MetricsLibraryInterface* metrics_library);
-
-  // Initialize this collector's state.
-  void Init();
-
-  // Schedule a collection interval.
-  void Schedule();
-
-  // Callback called at the end of the collection interval.
-  void CollectCallback();
-
-  // Measure the cpu use and report it.
-  void Collect();
-
-  // Gets the current cumulated Cpu usage.
-  base::TimeDelta GetCumulativeCpuUse();
-
- private:
-  FRIEND_TEST(CpuUsageTest, ParseProcStat);
-  bool ParseProcStat(const std::string& stat_content,
-                     uint64_t *user_ticks,
-                     uint64_t *user_nice_ticks,
-                     uint64_t *system_ticks);
-
-  int num_cpu_;
-  uint32_t ticks_per_second_;
-
-  base::TimeDelta collect_interval_;
-  base::TimeDelta latest_cpu_use_;
-
-  MetricsLibraryInterface* metrics_lib_;
-};
-
-#endif  // METRICSD_COLLECTORS_CPU_USAGE_COLLECTOR_H_
diff --git a/metricsd/collectors/cpu_usage_collector_test.cc b/metricsd/collectors/cpu_usage_collector_test.cc
deleted file mode 100644
index ee5c92b..0000000
--- a/metricsd/collectors/cpu_usage_collector_test.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-
-#include <gtest/gtest.h>
-
-#include "collectors/cpu_usage_collector.h"
-#include "metrics/metrics_library_mock.h"
-
-
-TEST(CpuUsageTest, ParseProcStat) {
-  MetricsLibraryMock metrics_lib_mock;
-  CpuUsageCollector collector(&metrics_lib_mock);
-  std::vector<std::string> invalid_contents = {
-    "",
-    // First line does not start with cpu.
-    "spu  17191 11 36579 151118 289 0 2 0 0 0\n"
-    "cpu0 1564 2 866 48650 68 0 2 0 0 0\n"
-    "cpu1 14299 0 35116 1844 81 0 0 0 0 0\n",
-    // One of the field is not a number.
-    "cpu  a17191 11 36579 151118 289 0 2 0 0 0",
-    // To many numbers in the first line.
-    "cpu  17191 11 36579 151118 289 0 2 0 0 0 102"
-  };
-
-  uint64_t user, nice, system;
-  for (int i = 0; i < invalid_contents.size(); i++) {
-    ASSERT_FALSE(collector.ParseProcStat(invalid_contents[i], &user, &nice,
-                                         &system));
-  }
-
-  ASSERT_TRUE(collector.ParseProcStat(
-      std::string("cpu  17191 11 36579 151118 289 0 2 0 0 0"),
-      &user, &nice, &system));
-  ASSERT_EQ(17191, user);
-  ASSERT_EQ(11, nice);
-  ASSERT_EQ(36579, system);
-}
diff --git a/metricsd/collectors/disk_usage_collector.cc b/metricsd/collectors/disk_usage_collector.cc
deleted file mode 100644
index 5ab51fb..0000000
--- a/metricsd/collectors/disk_usage_collector.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.
- */
-
-#include "collectors/disk_usage_collector.h"
-
-#include <base/bind.h>
-#include <base/bind_helpers.h>
-#include <base/message_loop/message_loop.h>
-#include <sys/statvfs.h>
-
-#include "metrics/metrics_library.h"
-
-namespace {
-
-const char kDiskUsageMB[] = "Platform.DataPartitionUsed.MB";
-const char kDiskUsagePercent[] = "Platform.DataPartitionUsed.Percent";
-const char kDataPartitionPath[] = "/data";
-
-// Collect every 15 minutes.
-const int kDiskUsageCollectorIntervalSeconds = 900;
-
-}  // namespace
-
-DiskUsageCollector::DiskUsageCollector(
-    MetricsLibraryInterface* metrics_library) {
-  collect_interval_ = base::TimeDelta::FromSeconds(
-      kDiskUsageCollectorIntervalSeconds);
-  CHECK(metrics_library);
-  metrics_lib_ = metrics_library;
-}
-
-void DiskUsageCollector::Collect() {
-  struct statvfs buf;
-  int result = statvfs(kDataPartitionPath, &buf);
-  if (result != 0) {
-    PLOG(ERROR) << "Failed to check the available space in "
-                << kDataPartitionPath;
-    return;
-  }
-
-  unsigned long total_space = buf.f_blocks * buf.f_bsize;
-  unsigned long used_space = (buf.f_blocks - buf.f_bfree) * buf.f_bsize;
-  int percent_used = (used_space * 100) / total_space;
-
-  metrics_lib_->SendToUMA(kDiskUsageMB,
-                          used_space / (1024 * 1024),
-                          0,
-                          1024, // up to 1 GB.
-                          100);
-  metrics_lib_->SendEnumToUMA(kDiskUsagePercent, percent_used, 101);
-}
-
-void DiskUsageCollector::CollectCallback() {
-  Collect();
-  Schedule();
-}
-
-void DiskUsageCollector::Schedule() {
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&DiskUsageCollector::CollectCallback, base::Unretained(this)),
-      collect_interval_);
-}
diff --git a/metricsd/collectors/disk_usage_collector.h b/metricsd/collectors/disk_usage_collector.h
deleted file mode 100644
index 288b34b..0000000
--- a/metricsd/collectors/disk_usage_collector.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICSD_COLLECTORS_DISK_USAGE_COLLECTOR_H_
-#define METRICSD_COLLECTORS_DISK_USAGE_COLLECTOR_H_
-
-#include <base/time/time.h>
-
-#include "metrics/metrics_library.h"
-
-class DiskUsageCollector {
- public:
-  explicit DiskUsageCollector(MetricsLibraryInterface* metrics_library);
-
-  // Schedule the next collection.
-  void Schedule();
-
-  // Callback used by the main loop.
-  void CollectCallback();
-
-  // Collect the disk usage statistics and report them.
-  void Collect();
-
- private:
-  base::TimeDelta collect_interval_;
-  MetricsLibraryInterface* metrics_lib_;
-};
-
-#endif  // METRICSD_COLLECTORS_DISK_USAGE_COLLECTOR_H_
diff --git a/metricsd/constants.h b/metricsd/constants.h
deleted file mode 100644
index b702737..0000000
--- a/metricsd/constants.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// 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.
-//
-
-#ifndef METRICS_CONSTANTS_H_
-#define METRICS_CONSTANTS_H_
-
-namespace metrics {
-static const char kSharedMetricsDirectory[] = "/data/misc/metrics/";
-static const char kMetricsdDirectory[] = "/data/misc/metricsd/";
-static const char kMetricsCollectorDirectory[] =
-    "/data/misc/metrics_collector/";
-static const char kMetricsGUIDFileName[] = "Sysinfo.GUID";
-static const char kMetricsServer[] = "https://clients4.google.com/uma/v2";
-static const char kConsentFileName[] = "enabled";
-static const char kStagedLogName[] = "staged_log";
-static const char kSavedLogName[] = "saved_log";
-static const char kFailedUploadCountName[] = "failed_upload_count";
-static const char kDefaultVersion[] = "0.0.0.0";
-
-// Build time properties name.
-static const char kProductId[] = "product_id";
-static const char kProductVersion[] = "product_version";
-
-// Weave configuration.
-static const char kWeaveConfigurationFile[] = "/system/etc/weaved/weaved.conf";
-static const char kModelManifestId[] = "model_id";
-}  // namespace metrics
-
-#endif  // METRICS_CONSTANTS_H_
diff --git a/metricsd/etc/weaved/traits/metrics.json b/metricsd/etc/weaved/traits/metrics.json
deleted file mode 100644
index 7583270..0000000
--- a/metricsd/etc/weaved/traits/metrics.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "_metrics": {
-    "commands": {
-      "enableAnalyticsReporting": {
-        "minimalRole": "manager",
-        "parameters": {}
-      },
-      "disableAnalyticsReporting": {
-        "minimalRole": "manager",
-        "parameters": {}
-      }
-    },
-    "state": {
-      "analyticsReportingState": {
-        "type": "string",
-        "enum": [ "enabled", "disabled" ]
-      }
-    }
-  }
-}
diff --git a/metricsd/include/metrics/c_metrics_library.h b/metricsd/include/metrics/c_metrics_library.h
deleted file mode 100644
index 1e597c2..0000000
--- a/metricsd/include/metrics/c_metrics_library.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_C_METRICS_LIBRARY_H_
-#define METRICS_C_METRICS_LIBRARY_H_
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-typedef struct CMetricsLibraryOpaque* CMetricsLibrary;
-
-// C wrapper for MetricsLibrary::MetricsLibrary.
-CMetricsLibrary CMetricsLibraryNew(void);
-
-// C wrapper for MetricsLibrary::~MetricsLibrary.
-void CMetricsLibraryDelete(CMetricsLibrary handle);
-
-// C wrapper for MetricsLibrary::Init.
-void CMetricsLibraryInit(CMetricsLibrary handle);
-
-// C wrapper for MetricsLibrary::SendToUMA.
-int CMetricsLibrarySendToUMA(CMetricsLibrary handle,
-                             const char* name, int sample,
-                             int min, int max, int nbuckets);
-
-// C wrapper for MetricsLibrary::SendEnumToUMA.
-int CMetricsLibrarySendEnumToUMA(CMetricsLibrary handle,
-                                 const char* name, int sample, int max);
-
-// C wrapper for MetricsLibrary::SendSparseToUMA.
-int CMetricsLibrarySendSparseToUMA(CMetricsLibrary handle,
-                                   const char* name, int sample);
-
-// C wrapper for MetricsLibrary::SendCrashToUMA.
-int CMetricsLibrarySendCrashToUMA(CMetricsLibrary handle,
-                                  const char* crash_kind);
-
-// C wrapper for MetricsLibrary::AreMetricsEnabled.
-int CMetricsLibraryAreMetricsEnabled(CMetricsLibrary handle);
-
-#if defined(__cplusplus)
-}
-#endif
-#endif  // METRICS_C_METRICS_LIBRARY_H_
diff --git a/metricsd/include/metrics/metrics_collector_service_client.h b/metricsd/include/metrics/metrics_collector_service_client.h
deleted file mode 100644
index c800eae..0000000
--- a/metricsd/include/metrics/metrics_collector_service_client.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- */
-
-// Client interface to IMetricsCollectorService.
-
-#ifndef METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
-#define METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
-
-#include "android/brillo/metrics/IMetricsCollectorService.h"
-
-class MetricsCollectorServiceClient {
- public:
-  MetricsCollectorServiceClient() = default;
-  ~MetricsCollectorServiceClient() = default;
-
-  // Initialize.  Returns true if OK, or false if IMetricsCollectorService
-  // is not registered.
-  bool Init();
-
-  // Called by crash_reporter to report a userspace crash event.  Returns
-  // true if successfully called the IMetricsCollectorService method of the
-  // same name, or false if the service was not registered at Init() time.
-  bool notifyUserCrash();
-
- private:
-  // IMetricsCollectorService binder proxy
-  android::sp<android::brillo::metrics::IMetricsCollectorService>
-      metrics_collector_service_;
-};
-
-#endif  // METRICS_METRICS_COLLECTOR_SERVICE_CLIENT_H_
diff --git a/metricsd/include/metrics/metrics_library.h b/metricsd/include/metrics/metrics_library.h
deleted file mode 100644
index a1bb926..0000000
--- a/metricsd/include/metrics/metrics_library.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_METRICS_LIBRARY_H_
-#define METRICS_METRICS_LIBRARY_H_
-
-#include <sys/types.h>
-#include <string>
-#include <unistd.h>
-
-#include <base/compiler_specific.h>
-#include <base/files/file_path.h>
-#include <base/macros.h>
-#include <binder/IServiceManager.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-namespace android {
-namespace brillo {
-namespace metrics {
-class IMetricsd;
-}  // namespace metrics
-}  // namespace brillo
-}  // namespace android
-
-class MetricsLibraryInterface {
- public:
-  virtual void Init() = 0;
-  virtual bool AreMetricsEnabled() = 0;
-  virtual bool SendToUMA(const std::string& name, int sample,
-                         int min, int max, int nbuckets) = 0;
-  virtual bool SendEnumToUMA(const std::string& name, int sample, int max) = 0;
-  virtual bool SendBoolToUMA(const std::string& name, bool sample) = 0;
-  virtual bool SendSparseToUMA(const std::string& name, int sample) = 0;
-  virtual ~MetricsLibraryInterface() {}
-};
-
-// Library used to send metrics to Chrome/UMA.
-class MetricsLibrary : public MetricsLibraryInterface {
- public:
-  MetricsLibrary();
-  virtual ~MetricsLibrary();
-
-  // Initializes the library.
-  void Init() override;
-
-  // Initializes the library and disables the cache of whether or not the
-  // metrics collection is enabled.
-  // By disabling this, we may have to check for the metrics status more often
-  // but the result will never be stale.
-  void InitWithNoCaching();
-
-  // Returns whether or not the machine is running in guest mode.
-  bool IsGuestMode();
-
-  // Returns whether or not metrics collection is enabled.
-  bool AreMetricsEnabled() override;
-
-  // Sends histogram data to Chrome for transport to UMA and returns
-  // true on success. This method results in the equivalent of an
-  // asynchronous non-blocking RPC to UMA_HISTOGRAM_CUSTOM_COUNTS
-  // inside Chrome (see base/histogram.h).
-  //
-  // |sample| is the sample value to be recorded (|min| <= |sample| < |max|).
-  // |min| is the minimum value of the histogram samples (|min| > 0).
-  // |max| is the maximum value of the histogram samples.
-  // |nbuckets| is the number of histogram buckets.
-  // [0,min) is the implicit underflow bucket.
-  // [|max|,infinity) is the implicit overflow bucket.
-  //
-  // Note that the memory allocated in Chrome for each histogram is
-  // proportional to the number of buckets. Therefore, it is strongly
-  // recommended to keep this number low (e.g., 50 is normal, while
-  // 100 is high).
-  bool SendToUMA(const std::string& name, int sample,
-                 int min, int max, int nbuckets) override;
-
-  // Sends linear histogram data to Chrome for transport to UMA and
-  // returns true on success. This method results in the equivalent of
-  // an asynchronous non-blocking RPC to UMA_HISTOGRAM_ENUMERATION
-  // inside Chrome (see base/histogram.h).
-  //
-  // |sample| is the sample value to be recorded (1 <= |sample| < |max|).
-  // |max| is the maximum value of the histogram samples.
-  // 0 is the implicit underflow bucket.
-  // [|max|,infinity) is the implicit overflow bucket.
-  //
-  // An enumeration histogram requires |max| + 1 number of
-  // buckets. Note that the memory allocated in Chrome for each
-  // histogram is proportional to the number of buckets. Therefore, it
-  // is strongly recommended to keep this number low (e.g., 50 is
-  // normal, while 100 is high).
-  bool SendEnumToUMA(const std::string& name, int sample, int max) override;
-
-  // Specialization of SendEnumToUMA for boolean values.
-  bool SendBoolToUMA(const std::string& name, bool sample) override;
-
-  // Sends sparse histogram sample to Chrome for transport to UMA.  Returns
-  // true on success.
-  //
-  // |sample| is the 32-bit integer value to be recorded.
-  bool SendSparseToUMA(const std::string& name, int sample) override;
-
-  // Sends a signal to UMA that a crash of the given |crash_kind|
-  // has occurred.  Used by UMA to generate stability statistics.
-  bool SendCrashToUMA(const char *crash_kind);
-
-  // Sends a "generic Chrome OS event" to UMA.  This is an event name
-  // that is translated into an enumerated histogram entry.  Event names
-  // are added to metrics_library.cc.  Optionally, they can be added
-  // to histograms.xml---but part of the reason for this is to simplify
-  // the addition of events (at the cost of having to look them up by
-  // number in the histograms dashboard).
-  bool SendCrosEventToUMA(const std::string& event);
-
-  // Debugging only.
-  // Dumps the histograms aggregated since metricsd started into |dump|.
-  // Returns true iff the dump succeeds.
-  bool GetHistogramsDump(std::string* dump);
-
- private:
-  friend class CMetricsLibraryTest;
-  friend class MetricsLibraryTest;
-  friend class UploadServiceTest;
-  FRIEND_TEST(MetricsLibraryTest, AreMetricsEnabled);
-  FRIEND_TEST(MetricsLibraryTest, AreMetricsEnabledNoCaching);
-  FRIEND_TEST(MetricsLibraryTest, FormatChromeMessage);
-  FRIEND_TEST(MetricsLibraryTest, FormatChromeMessageTooLong);
-  FRIEND_TEST(MetricsLibraryTest, IsDeviceMounted);
-  FRIEND_TEST(MetricsLibraryTest, SendMessageToChrome);
-  FRIEND_TEST(MetricsLibraryTest, SendMessageToChromeUMAEventsBadFileLocation);
-
-  void InitForTest(const base::FilePath& metrics_directory);
-
-  // Sets |*result| to whether or not the |mounts_file| indicates that
-  // the |device_name| is currently mounted.  Uses |buffer| of
-  // |buffer_size| to read the file.  Returns false if any error.
-  bool IsDeviceMounted(const char* device_name,
-                       const char* mounts_file,
-                       char* buffer, int buffer_size,
-                       bool* result);
-
-  // Connects to IMetricsd if the proxy does not exist or is not alive.
-  // Don't block if we fail to get the proxy for any reason.
-  bool CheckService();
-
-  // Time at which we last checked if metrics were enabled.
-  time_t cached_enabled_time_;
-
-  // Cached state of whether or not metrics were enabled.
-  bool cached_enabled_;
-
-  // True iff we should cache the enabled/disabled status.
-  bool use_caching_;
-
-  android::sp<android::IServiceManager> manager_;
-  android::sp<android::brillo::metrics::IMetricsd> metricsd_proxy_;
-  base::FilePath consent_file_;
-
-  DISALLOW_COPY_AND_ASSIGN(MetricsLibrary);
-};
-
-#endif  // METRICS_METRICS_LIBRARY_H_
diff --git a/metricsd/include/metrics/metrics_library_mock.h b/metricsd/include/metrics/metrics_library_mock.h
deleted file mode 100644
index 3b0b24d..0000000
--- a/metricsd/include/metrics/metrics_library_mock.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_METRICS_LIBRARY_MOCK_H_
-#define METRICS_METRICS_LIBRARY_MOCK_H_
-
-#include <string>
-
-#include "metrics/metrics_library.h"
-
-#include <gmock/gmock.h>
-
-class MetricsLibraryMock : public MetricsLibraryInterface {
- public:
-  bool metrics_enabled_ = true;
-
-  MOCK_METHOD0(Init, void());
-  MOCK_METHOD5(SendToUMA, bool(const std::string& name, int sample,
-                               int min, int max, int nbuckets));
-  MOCK_METHOD3(SendEnumToUMA, bool(const std::string& name, int sample,
-                                   int max));
-  MOCK_METHOD2(SendBoolToUMA, bool(const std::string& name, bool sample));
-  MOCK_METHOD2(SendSparseToUMA, bool(const std::string& name, int sample));
-
-  bool AreMetricsEnabled() override {return metrics_enabled_;};
-};
-
-#endif  // METRICS_METRICS_LIBRARY_MOCK_H_
diff --git a/metricsd/include/metrics/timer.h b/metricsd/include/metrics/timer.h
deleted file mode 100644
index c1b8ede..0000000
--- a/metricsd/include/metrics/timer.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.
- */
-
-// Timer - class that provides timer tracking.
-
-#ifndef METRICS_TIMER_H_
-#define METRICS_TIMER_H_
-
-#include <memory>
-#include <string>
-
-#include <base/macros.h>
-#include <base/time/time.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-class MetricsLibraryInterface;
-
-namespace chromeos_metrics {
-
-class TimerInterface {
- public:
-  virtual ~TimerInterface() {}
-
-  virtual bool Start() = 0;
-  virtual bool Stop() = 0;
-  virtual bool Reset() = 0;
-  virtual bool HasStarted() const = 0;
-};
-
-// Wrapper for calls to the system clock.
-class ClockWrapper {
- public:
-  ClockWrapper() {}
-  virtual ~ClockWrapper() {}
-
-  // Returns the current time from the system.
-  virtual base::TimeTicks GetCurrentTime() const;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ClockWrapper);
-};
-
-// Implements a Timer.
-class Timer : public TimerInterface {
- public:
-  Timer();
-  virtual ~Timer() {}
-
-  // Starts the timer. If a timer is already running, also resets current
-  // timer. Always returns true.
-  virtual bool Start();
-
-  // Stops the timer and calculates the total time elapsed between now and when
-  // Start() was called. Note that this method needs a prior call to Start().
-  // Otherwise, it fails (returns false).
-  virtual bool Stop();
-
-  // Pauses a timer.  If the timer is stopped, this call starts the timer in
-  // the paused state. Fails (returns false) if the timer is already paused.
-  virtual bool Pause();
-
-  // Restarts a paused timer (or starts a stopped timer). This method fails
-  // (returns false) if the timer is already running; otherwise, returns true.
-  virtual bool Resume();
-
-  // Resets the timer, erasing the current duration being tracked. Always
-  // returns true.
-  virtual bool Reset();
-
-  // Returns whether the timer has started or not.
-  virtual bool HasStarted() const;
-
-  // Stores the current elapsed time in |elapsed_time|. If timer is stopped,
-  // stores the elapsed time from when Stop() was last called. Otherwise,
-  // calculates and stores the elapsed time since the last Start().
-  // Returns false if the timer was never Start()'ed or if called with a null
-  // pointer argument.
-  virtual bool GetElapsedTime(base::TimeDelta* elapsed_time) const;
-
- private:
-  enum TimerState { kTimerStopped, kTimerRunning, kTimerPaused };
-  friend class TimerTest;
-  friend class TimerReporterTest;
-  FRIEND_TEST(TimerReporterTest, StartStopReport);
-  FRIEND_TEST(TimerTest, InvalidElapsedTime);
-  FRIEND_TEST(TimerTest, InvalidStop);
-  FRIEND_TEST(TimerTest, PauseResumeStop);
-  FRIEND_TEST(TimerTest, PauseStartStopResume);
-  FRIEND_TEST(TimerTest, PauseStop);
-  FRIEND_TEST(TimerTest, Reset);
-  FRIEND_TEST(TimerTest, ReStart);
-  FRIEND_TEST(TimerTest, ResumeStartStopPause);
-  FRIEND_TEST(TimerTest, SeparatedTimers);
-  FRIEND_TEST(TimerTest, StartPauseResumePauseResumeStop);
-  FRIEND_TEST(TimerTest, StartPauseResumePauseStop);
-  FRIEND_TEST(TimerTest, StartPauseResumeStop);
-  FRIEND_TEST(TimerTest, StartPauseStop);
-  FRIEND_TEST(TimerTest, StartResumeStop);
-  FRIEND_TEST(TimerTest, StartStop);
-
-  // Elapsed time of the last use of the timer.
-  base::TimeDelta elapsed_time_;
-
-  // Starting time value.
-  base::TimeTicks start_time_;
-
-  // Whether the timer is running, stopped, or paused.
-  TimerState timer_state_;
-
-  // Wrapper for the calls to the system clock.
-  std::unique_ptr<ClockWrapper> clock_wrapper_;
-
-  DISALLOW_COPY_AND_ASSIGN(Timer);
-};
-
-// Extends the Timer class to report the elapsed time in milliseconds through
-// the UMA metrics library.
-class TimerReporter : public Timer {
- public:
-  // Initializes the timer by providing a |histogram_name| to report to with
-  // |min|, |max| and |num_buckets| attributes for the histogram.
-  TimerReporter(const std::string& histogram_name, int min, int max,
-                int num_buckets);
-  virtual ~TimerReporter() {}
-
-  // Sets the metrics library used by all instances of this class.
-  static void set_metrics_lib(MetricsLibraryInterface* metrics_lib) {
-    metrics_lib_ = metrics_lib;
-  }
-
-  // Reports the current duration to UMA, in milliseconds. Returns false if
-  // there is nothing to report, e.g. a metrics library is not set.
-  virtual bool ReportMilliseconds() const;
-
-  // Accessor methods.
-  const std::string& histogram_name() const { return histogram_name_; }
-  int min() const { return min_; }
-  int max() const { return max_; }
-  int num_buckets() const { return num_buckets_; }
-
- private:
-  friend class TimerReporterTest;
-  FRIEND_TEST(TimerReporterTest, StartStopReport);
-  FRIEND_TEST(TimerReporterTest, InvalidReport);
-
-  static MetricsLibraryInterface* metrics_lib_;
-  std::string histogram_name_;
-  int min_;
-  int max_;
-  int num_buckets_;
-
-  DISALLOW_COPY_AND_ASSIGN(TimerReporter);
-};
-
-}  // namespace chromeos_metrics
-
-#endif  // METRICS_TIMER_H_
diff --git a/metricsd/include/metrics/timer_mock.h b/metricsd/include/metrics/timer_mock.h
deleted file mode 100644
index 200ee9a..0000000
--- a/metricsd/include/metrics/timer_mock.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_TIMER_MOCK_H_
-#define METRICS_TIMER_MOCK_H_
-
-#include <string>
-
-#include <gmock/gmock.h>
-
-#include "metrics/timer.h"
-
-namespace chromeos_metrics {
-
-class TimerMock : public Timer {
- public:
-  MOCK_METHOD0(Start, bool());
-  MOCK_METHOD0(Stop, bool());
-  MOCK_METHOD0(Reset, bool());
-  MOCK_CONST_METHOD0(HasStarted, bool());
-  MOCK_CONST_METHOD1(GetElapsedTime, bool(base::TimeDelta* elapsed_time));
-};
-
-class TimerReporterMock : public TimerReporter {
- public:
-  TimerReporterMock() : TimerReporter("", 0, 0, 0) {}
-  MOCK_METHOD0(Start, bool());
-  MOCK_METHOD0(Stop, bool());
-  MOCK_METHOD0(Reset, bool());
-  MOCK_CONST_METHOD0(HasStarted, bool());
-  MOCK_CONST_METHOD1(GetElapsedTime, bool(base::TimeDelta* elapsed_time));
-  MOCK_CONST_METHOD0(ReportMilliseconds, bool());
-  MOCK_CONST_METHOD0(histogram_name, std::string&());
-  MOCK_CONST_METHOD0(min, int());
-  MOCK_CONST_METHOD0(max, int());
-  MOCK_CONST_METHOD0(num_buckets, int());
-};
-
-class ClockWrapperMock : public ClockWrapper {
- public:
-  MOCK_CONST_METHOD0(GetCurrentTime, base::TimeTicks());
-};
-
-}  // namespace chromeos_metrics
-
-#endif  // METRICS_TIMER_MOCK_H_
diff --git a/metricsd/libmetrics-369476.gyp b/metricsd/libmetrics-369476.gyp
deleted file mode 100644
index b545d35..0000000
--- a/metricsd/libmetrics-369476.gyp
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  'variables': {
-    'libbase_ver': 369476,
-  },
-  'includes': [
-    'libmetrics.gypi',
-  ],
-}
diff --git a/metricsd/libmetrics.gypi b/metricsd/libmetrics.gypi
deleted file mode 100644
index 3c8fc7c..0000000
--- a/metricsd/libmetrics.gypi
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  'target_defaults': {
-    'variables': {
-      'deps': [
-        'libbrillo-<(libbase_ver)',
-        'libchrome-<(libbase_ver)',
-      ]
-    },
-    'cflags_cc': [
-      '-fno-exceptions',
-    ],
-  },
-  'targets': [
-    {
-      'target_name': 'libmetrics-<(libbase_ver)',
-      'type': 'shared_library',
-      'cflags': [
-        '-fvisibility=default',
-      ],
-      'libraries+': [
-        '-lpolicy-<(libbase_ver)',
-      ],
-      'sources': [
-        'c_metrics_library.cc',
-        'metrics_library.cc',
-        'serialization/metric_sample.cc',
-        'serialization/serialization_utils.cc',
-        'timer.cc',
-      ],
-      'include_dirs': ['.'],
-    },
-  ],
-}
diff --git a/metricsd/libmetrics.pc.in b/metricsd/libmetrics.pc.in
deleted file mode 100644
index 233f318..0000000
--- a/metricsd/libmetrics.pc.in
+++ /dev/null
@@ -1,7 +0,0 @@
-bslot=@BSLOT@
-
-Name: libmetrics
-Description: Chrome OS metrics library
-Version: ${bslot}
-Requires.private: libchrome-${bslot}
-Libs: -lmetrics-${bslot}
diff --git a/metricsd/metrics.gyp b/metricsd/metrics.gyp
deleted file mode 100644
index c9c02d7..0000000
--- a/metricsd/metrics.gyp
+++ /dev/null
@@ -1,184 +0,0 @@
-{
-  'target_defaults': {
-    'variables': {
-      'deps': [
-        'dbus-1',
-        'libbrillo-<(libbase_ver)',
-        'libchrome-<(libbase_ver)',
-      ]
-    },
-    'cflags_cc': [
-      '-fno-exceptions',
-    ],
-  },
-  'targets': [
-    {
-      'target_name': 'libmetrics_daemon',
-      'type': 'static_library',
-      'dependencies': [
-        '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
-        'libupload_service',
-        'metrics_proto',
-      ],
-      'link_settings': {
-        'libraries': [
-          '-lrootdev',
-        ],
-      },
-      'sources': [
-        'persistent_integer.cc',
-        'metrics_daemon.cc',
-        'metrics_daemon_main.cc',
-      ],
-      'include_dirs': ['.'],
-    },
-    {
-      'target_name': 'metrics_client',
-      'type': 'executable',
-      'dependencies': [
-        '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
-      ],
-      'sources': [
-        'metrics_client.cc',
-      ]
-    },
-    {
-      'target_name': 'libupload_service',
-      'type': 'static_library',
-      'dependencies': [
-        'metrics_proto',
-        '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
-      ],
-      'link_settings': {
-        'libraries': [
-          '-lvboot_host',
-        ],
-      },
-      'variables': {
-        'exported_deps': [
-          'protobuf-lite',
-        ],
-        'deps': [
-          '<@(exported_deps)',
-        ],
-      },
-      'all_dependent_settings': {
-        'variables': {
-          'deps+': [
-            '<@(exported_deps)',
-          ],
-        },
-      },
-      'sources': [
-        'uploader/upload_service.cc',
-        'uploader/metrics_hashes.cc',
-        'uploader/metrics_log.cc',
-        'uploader/metrics_log_base.cc',
-        'uploader/system_profile_cache.cc',
-        'uploader/sender_http.cc',
-      ],
-      'include_dirs': ['.']
-    },
-    {
-      'target_name': 'metrics_proto',
-      'type': 'static_library',
-      'variables': {
-        'proto_in_dir': 'uploader/proto',
-        'proto_out_dir': 'include/metrics/uploader/proto',
-      },
-      'sources': [
-        '<(proto_in_dir)/chrome_user_metrics_extension.proto',
-        '<(proto_in_dir)/histogram_event.proto',
-        '<(proto_in_dir)/system_profile.proto',
-        '<(proto_in_dir)/user_action_event.proto',
-      ],
-      'includes': [
-        '../common-mk/protoc.gypi'
-      ],
-    },
-  ],
-  'conditions': [
-    ['USE_passive_metrics == 1', {
-      'targets': [
-        {
-          'target_name': 'metrics_daemon',
-          'type': 'executable',
-          'dependencies': ['libmetrics_daemon'],
-        },
-      ],
-    }],
-    ['USE_test == 1', {
-      'targets': [
-        {
-          'target_name': 'persistent_integer_test',
-          'type': 'executable',
-          'includes': ['../common-mk/common_test.gypi'],
-          'sources': [
-            'persistent_integer.cc',
-            'persistent_integer_test.cc',
-          ]
-        },
-        {
-          'target_name': 'metrics_library_test',
-          'type': 'executable',
-          'dependencies': [
-            '../metrics/libmetrics-<(libbase_ver).gyp:libmetrics-<(libbase_ver)',
-          ],
-          'includes': ['../common-mk/common_test.gypi'],
-          'sources': [
-            'metrics_library_test.cc',
-            'serialization/serialization_utils_unittest.cc',
-          ],
-          'link_settings': {
-            'libraries': [
-              '-lpolicy-<(libbase_ver)',
-            ]
-          }
-        },
-        {
-          'target_name': 'timer_test',
-          'type': 'executable',
-          'includes': ['../common-mk/common_test.gypi'],
-          'sources': [
-            'timer.cc',
-            'timer_test.cc',
-          ]
-        },
-        {
-          'target_name': 'upload_service_test',
-          'type': 'executable',
-          'sources': [
-            'persistent_integer.cc',
-            'uploader/metrics_hashes_unittest.cc',
-            'uploader/metrics_log_base_unittest.cc',
-            'uploader/mock/sender_mock.cc',
-            'uploader/upload_service_test.cc',
-          ],
-          'dependencies': [
-            'libupload_service',
-          ],
-          'includes':[
-            '../common-mk/common_test.gypi',
-          ],
-          'include_dirs': ['.']
-        },
-      ],
-    }],
-    ['USE_passive_metrics == 1 and USE_test == 1', {
-      'targets': [
-        {
-          'target_name': 'metrics_daemon_test',
-          'type': 'executable',
-          'dependencies': [
-            'libmetrics_daemon',
-          ],
-          'includes': ['../common-mk/common_test.gypi'],
-          'sources': [
-            'metrics_daemon_test.cc',
-          ],
-          'include_dirs': ['.'],
-        },
-      ],
-    }],
-  ]
-}
diff --git a/metricsd/metrics_client.cc b/metricsd/metrics_client.cc
deleted file mode 100644
index c66b975..0000000
--- a/metricsd/metrics_client.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * 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.
- */
-
-#include <cstdio>
-#include <cstdlib>
-
-#include "constants.h"
-#include "metrics/metrics_library.h"
-
-enum Mode {
-    kModeDumpHistograms,
-    kModeSendSample,
-    kModeSendEnumSample,
-    kModeSendSparseSample,
-    kModeSendCrosEvent,
-    kModeHasConsent,
-    kModeIsGuestMode,
-};
-
-void ShowUsage() {
-  fprintf(stderr,
-          "Usage:  metrics_client [-t] name sample min max nbuckets\n"
-          "        metrics_client -e   name sample max\n"
-          "        metrics_client -s   name sample\n"
-          "        metrics_client -v   event\n"
-          "        metrics_client [-cdg]\n"
-          "\n"
-          "  default: send metric with integer values \n"
-          "           |min| > 0, |min| <= sample < |max|\n"
-          "  -c: return exit status 0 if user consents to stats, 1 otherwise,\n"
-          "      in guest mode always return 1\n"
-          "  -d: dump the histograms recorded by metricsd to stdout\n"
-          "  -e: send linear/enumeration histogram data\n"
-          "  -g: return exit status 0 if machine in guest mode, 1 otherwise\n"
-          "  -s: send a sparse histogram sample\n"
-          "  -t: convert sample from double seconds to int milliseconds\n"
-          "  -v: send a Platform.CrOSEvent enum histogram sample\n");
-  exit(1);
-}
-
-static int ParseInt(const char *arg) {
-  char *endptr;
-  int value = strtol(arg, &endptr, 0);
-  if (*endptr != '\0') {
-    fprintf(stderr, "metrics client: bad integer \"%s\"\n", arg);
-    ShowUsage();
-  }
-  return value;
-}
-
-static double ParseDouble(const char *arg) {
-  char *endptr;
-  double value = strtod(arg, &endptr);
-  if (*endptr != '\0') {
-    fprintf(stderr, "metrics client: bad double \"%s\"\n", arg);
-    ShowUsage();
-  }
-  return value;
-}
-
-static int DumpHistograms() {
-  MetricsLibrary metrics_lib;
-  metrics_lib.Init();
-
-  std::string dump;
-  if (!metrics_lib.GetHistogramsDump(&dump)) {
-    printf("Failed to dump the histograms.");
-    return 1;
-  }
-
-  printf("%s\n", dump.c_str());
-  return 0;
-}
-
-static int SendStats(char* argv[],
-                     int name_index,
-                     enum Mode mode,
-                     bool secs_to_msecs) {
-  const char* name = argv[name_index];
-  int sample;
-  if (secs_to_msecs) {
-    sample = static_cast<int>(ParseDouble(argv[name_index + 1]) * 1000.0);
-  } else {
-    sample = ParseInt(argv[name_index + 1]);
-  }
-
-  MetricsLibrary metrics_lib;
-  metrics_lib.Init();
-  if (mode == kModeSendSparseSample) {
-    metrics_lib.SendSparseToUMA(name, sample);
-  } else if (mode == kModeSendEnumSample) {
-    int max = ParseInt(argv[name_index + 2]);
-    metrics_lib.SendEnumToUMA(name, sample, max);
-  } else {
-    int min = ParseInt(argv[name_index + 2]);
-    int max = ParseInt(argv[name_index + 3]);
-    int nbuckets = ParseInt(argv[name_index + 4]);
-    metrics_lib.SendToUMA(name, sample, min, max, nbuckets);
-  }
-  return 0;
-}
-
-static int SendCrosEvent(char* argv[], int action_index) {
-  const char* event = argv[action_index];
-  bool result;
-  MetricsLibrary metrics_lib;
-  metrics_lib.Init();
-  result = metrics_lib.SendCrosEventToUMA(event);
-  if (!result) {
-    fprintf(stderr, "metrics_client: could not send event %s\n", event);
-    return 1;
-  }
-  return 0;
-}
-
-static int HasConsent() {
-  MetricsLibrary metrics_lib;
-  metrics_lib.Init();
-  return metrics_lib.AreMetricsEnabled() ? 0 : 1;
-}
-
-static int IsGuestMode() {
-  MetricsLibrary metrics_lib;
-  metrics_lib.Init();
-  return metrics_lib.IsGuestMode() ? 0 : 1;
-}
-
-int main(int argc, char** argv) {
-  enum Mode mode = kModeSendSample;
-  bool secs_to_msecs = false;
-
-  // Parse arguments
-  int flag;
-  while ((flag = getopt(argc, argv, "abcdegstv")) != -1) {
-    switch (flag) {
-      case 'c':
-        mode = kModeHasConsent;
-        break;
-      case 'd':
-        mode = kModeDumpHistograms;
-        break;
-      case 'e':
-        mode = kModeSendEnumSample;
-        break;
-      case 'g':
-        mode = kModeIsGuestMode;
-        break;
-      case 's':
-        mode = kModeSendSparseSample;
-        break;
-      case 't':
-        secs_to_msecs = true;
-        break;
-      case 'v':
-        mode = kModeSendCrosEvent;
-        break;
-      default:
-        ShowUsage();
-        break;
-    }
-  }
-  int arg_index = optind;
-
-  int expected_args = 0;
-  if (mode == kModeSendSample)
-    expected_args = 5;
-  else if (mode == kModeSendEnumSample)
-    expected_args = 3;
-  else if (mode == kModeSendSparseSample)
-    expected_args = 2;
-  else if (mode == kModeSendCrosEvent)
-    expected_args = 1;
-
-  if ((arg_index + expected_args) != argc) {
-    ShowUsage();
-  }
-
-  switch (mode) {
-    case kModeDumpHistograms:
-      return DumpHistograms();
-    case kModeSendSample:
-    case kModeSendEnumSample:
-    case kModeSendSparseSample:
-      if ((mode != kModeSendSample) && secs_to_msecs) {
-        ShowUsage();
-      }
-      return SendStats(argv,
-                       arg_index,
-                       mode,
-                       secs_to_msecs);
-    case kModeSendCrosEvent:
-      return SendCrosEvent(argv, arg_index);
-    case kModeHasConsent:
-      return HasConsent();
-    case kModeIsGuestMode:
-      return IsGuestMode();
-    default:
-      ShowUsage();
-      return 0;
-  }
-}
diff --git a/metricsd/metrics_collector.cc b/metricsd/metrics_collector.cc
deleted file mode 100644
index 45ae0a4..0000000
--- a/metricsd/metrics_collector.cc
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * 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.
- */
-
-#include "metrics_collector.h"
-
-#include <sysexits.h>
-#include <time.h>
-
-#include <memory>
-
-#include <base/bind.h>
-#include <base/files/file_path.h>
-#include <base/files/file_util.h>
-#include <base/hash.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_split.h>
-#include <base/strings/string_util.h>
-#include <base/strings/stringprintf.h>
-#include <brillo/binder_watcher.h>
-#include <brillo/osrelease_reader.h>
-
-#include "constants.h"
-#include "metrics_collector_service_impl.h"
-
-using base::FilePath;
-using base::StringPrintf;
-using base::Time;
-using base::TimeDelta;
-using base::TimeTicks;
-using chromeos_metrics::PersistentInteger;
-using std::map;
-using std::string;
-using std::vector;
-
-namespace {
-
-const int kSecondsPerMinute = 60;
-const int kMinutesPerHour = 60;
-const int kHoursPerDay = 24;
-const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
-const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay;
-const int kDaysPerWeek = 7;
-const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek;
-
-// Interval between calls to UpdateStats().
-const uint32_t kUpdateStatsIntervalMs = 300000;
-
-const char kKernelCrashDetectedFile[] =
-    "/data/misc/crash_reporter/run/kernel-crash-detected";
-const char kUncleanShutdownDetectedFile[] =
-    "/var/run/unclean-shutdown-detected";
-
-const int kMetricMeminfoInterval = 30;    // seconds
-
-const char kMeminfoFileName[] = "/proc/meminfo";
-const char kVmStatFileName[] = "/proc/vmstat";
-
-const char kWeaveComponent[] = "metrics";
-const char kWeaveTrait[] = "_metrics";
-
-}  // namespace
-
-// Zram sysfs entries.
-
-const char MetricsCollector::kComprDataSizeName[] = "compr_data_size";
-const char MetricsCollector::kOrigDataSizeName[] = "orig_data_size";
-const char MetricsCollector::kZeroPagesName[] = "zero_pages";
-
-// Memory use stats collection intervals.  We collect some memory use interval
-// at these intervals after boot, and we stop collecting after the last one,
-// with the assumption that in most cases the memory use won't change much
-// after that.
-static const int kMemuseIntervals[] = {
-  1 * kSecondsPerMinute,    // 1 minute mark
-  4 * kSecondsPerMinute,    // 5 minute mark
-  25 * kSecondsPerMinute,   // 0.5 hour mark
-  120 * kSecondsPerMinute,  // 2.5 hour mark
-  600 * kSecondsPerMinute,  // 12.5 hour mark
-};
-
-MetricsCollector::MetricsCollector()
-    : memuse_final_time_(0),
-      memuse_interval_index_(0) {}
-
-MetricsCollector::~MetricsCollector() {
-}
-
-// static
-double MetricsCollector::GetActiveTime() {
-  struct timespec ts;
-  int r = clock_gettime(CLOCK_MONOTONIC, &ts);
-  if (r < 0) {
-    PLOG(WARNING) << "clock_gettime(CLOCK_MONOTONIC) failed";
-    return 0;
-  } else {
-    return ts.tv_sec + static_cast<double>(ts.tv_nsec) / (1000 * 1000 * 1000);
-  }
-}
-
-int MetricsCollector::Run() {
-  if (CheckSystemCrash(kKernelCrashDetectedFile)) {
-    ProcessKernelCrash();
-  }
-
-  if (CheckSystemCrash(kUncleanShutdownDetectedFile)) {
-    ProcessUncleanShutdown();
-  }
-
-  // On OS version change, clear version stats (which are reported daily).
-  int32_t version = GetOsVersionHash();
-  if (version_cycle_->Get() != version) {
-    version_cycle_->Set(version);
-    kernel_crashes_version_count_->Set(0);
-    version_cumulative_active_use_->Set(0);
-    version_cumulative_cpu_use_->Set(0);
-  }
-
-  // Start metricscollectorservice
-  android::sp<BnMetricsCollectorServiceImpl> metrics_collector_service =
-      new BnMetricsCollectorServiceImpl(this);
-  android::status_t status = android::defaultServiceManager()->addService(
-      metrics_collector_service->getInterfaceDescriptor(),
-      metrics_collector_service);
-  CHECK(status == android::OK)
-      << "failed to register service metricscollectorservice";
-
-  // Watch Binder events in the main loop
-  brillo::BinderWatcher binder_watcher;
-  CHECK(binder_watcher.Init()) << "Binder FD watcher init failed";
-  return brillo::Daemon::Run();
-}
-
-uint32_t MetricsCollector::GetOsVersionHash() {
-  brillo::OsReleaseReader reader;
-  reader.Load();
-  string version;
-  if (!reader.GetString(metrics::kProductVersion, &version)) {
-    LOG(ERROR) << "failed to read the product version.";
-    version = metrics::kDefaultVersion;
-  }
-
-  uint32_t version_hash = base::Hash(version);
-  if (testing_) {
-    version_hash = 42;  // return any plausible value for the hash
-  }
-  return version_hash;
-}
-
-void MetricsCollector::Init(bool testing, MetricsLibraryInterface* metrics_lib,
-                            const string& diskstats_path,
-                            const base::FilePath& private_metrics_directory,
-                            const base::FilePath& shared_metrics_directory) {
-  CHECK(metrics_lib);
-  testing_ = testing;
-  shared_metrics_directory_ = shared_metrics_directory;
-  metrics_lib_ = metrics_lib;
-
-  daily_active_use_.reset(new PersistentInteger("Platform.UseTime.PerDay",
-                                                private_metrics_directory));
-  version_cumulative_active_use_.reset(new PersistentInteger(
-      "Platform.CumulativeUseTime", private_metrics_directory));
-  version_cumulative_cpu_use_.reset(new PersistentInteger(
-      "Platform.CumulativeCpuTime", private_metrics_directory));
-
-  kernel_crash_interval_.reset(new PersistentInteger(
-      "Platform.KernelCrashInterval", private_metrics_directory));
-  unclean_shutdown_interval_.reset(new PersistentInteger(
-      "Platform.UncleanShutdownInterval", private_metrics_directory));
-  user_crash_interval_.reset(new PersistentInteger("Platform.UserCrashInterval",
-                                                   private_metrics_directory));
-
-  any_crashes_daily_count_.reset(new PersistentInteger(
-      "Platform.AnyCrashes.PerDay", private_metrics_directory));
-  any_crashes_weekly_count_.reset(new PersistentInteger(
-      "Platform.AnyCrashes.PerWeek", private_metrics_directory));
-  user_crashes_daily_count_.reset(new PersistentInteger(
-      "Platform.UserCrashes.PerDay", private_metrics_directory));
-  user_crashes_weekly_count_.reset(new PersistentInteger(
-      "Platform.UserCrashes.PerWeek", private_metrics_directory));
-  kernel_crashes_daily_count_.reset(new PersistentInteger(
-      "Platform.KernelCrashes.PerDay", private_metrics_directory));
-  kernel_crashes_weekly_count_.reset(new PersistentInteger(
-      "Platform.KernelCrashes.PerWeek", private_metrics_directory));
-  kernel_crashes_version_count_.reset(new PersistentInteger(
-      "Platform.KernelCrashesSinceUpdate", private_metrics_directory));
-  unclean_shutdowns_daily_count_.reset(new PersistentInteger(
-      "Platform.UncleanShutdown.PerDay", private_metrics_directory));
-  unclean_shutdowns_weekly_count_.reset(new PersistentInteger(
-      "Platform.UncleanShutdowns.PerWeek", private_metrics_directory));
-
-  daily_cycle_.reset(
-      new PersistentInteger("daily.cycle", private_metrics_directory));
-  weekly_cycle_.reset(
-      new PersistentInteger("weekly.cycle", private_metrics_directory));
-  version_cycle_.reset(
-      new PersistentInteger("version.cycle", private_metrics_directory));
-
-  disk_usage_collector_.reset(new DiskUsageCollector(metrics_lib_));
-  averaged_stats_collector_.reset(
-      new AveragedStatisticsCollector(metrics_lib_, diskstats_path,
-                                      kVmStatFileName));
-  cpu_usage_collector_.reset(new CpuUsageCollector(metrics_lib_));
-}
-
-int MetricsCollector::OnInit() {
-  int return_code = brillo::Daemon::OnInit();
-  if (return_code != EX_OK)
-    return return_code;
-
-  StatsReporterInit();
-
-  // Start collecting meminfo stats.
-  ScheduleMeminfoCallback(kMetricMeminfoInterval);
-  memuse_final_time_ = GetActiveTime() + kMemuseIntervals[0];
-  ScheduleMemuseCallback(kMemuseIntervals[0]);
-
-  if (testing_)
-    return EX_OK;
-
-  weave_service_subscription_ = weaved::Service::Connect(
-      brillo::MessageLoop::current(),
-      base::Bind(&MetricsCollector::OnWeaveServiceConnected,
-                 weak_ptr_factory_.GetWeakPtr()));
-
-  latest_cpu_use_microseconds_ = cpu_usage_collector_->GetCumulativeCpuUse();
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&MetricsCollector::HandleUpdateStatsTimeout,
-                 weak_ptr_factory_.GetWeakPtr()),
-      base::TimeDelta::FromMilliseconds(kUpdateStatsIntervalMs));
-
-  return EX_OK;
-}
-
-void MetricsCollector::OnWeaveServiceConnected(
-    const std::weak_ptr<weaved::Service>& service) {
-  service_ = service;
-  auto weave_service = service_.lock();
-  if (!weave_service)
-    return;
-
-  weave_service->AddComponent(kWeaveComponent, {kWeaveTrait}, nullptr);
-  weave_service->AddCommandHandler(
-      kWeaveComponent, kWeaveTrait, "enableAnalyticsReporting",
-      base::Bind(&MetricsCollector::OnEnableMetrics,
-                 weak_ptr_factory_.GetWeakPtr()));
-  weave_service->AddCommandHandler(
-      kWeaveComponent, kWeaveTrait, "disableAnalyticsReporting",
-      base::Bind(&MetricsCollector::OnDisableMetrics,
-                 weak_ptr_factory_.GetWeakPtr()));
-
-  UpdateWeaveState();
-}
-
-void MetricsCollector::OnEnableMetrics(
-    std::unique_ptr<weaved::Command> command) {
-  if (base::WriteFile(
-          shared_metrics_directory_.Append(metrics::kConsentFileName), "", 0) !=
-      0) {
-    PLOG(ERROR) << "Could not create the consent file.";
-    command->Abort("metrics_error", "Could not create the consent file",
-                   nullptr);
-    return;
-  }
-
-  UpdateWeaveState();
-  command->Complete({}, nullptr);
-}
-
-void MetricsCollector::OnDisableMetrics(
-    std::unique_ptr<weaved::Command> command) {
-  if (!base::DeleteFile(
-          shared_metrics_directory_.Append(metrics::kConsentFileName), false)) {
-    PLOG(ERROR) << "Could not delete the consent file.";
-    command->Abort("metrics_error", "Could not delete the consent file",
-                   nullptr);
-    return;
-  }
-
-  UpdateWeaveState();
-  command->Complete({}, nullptr);
-}
-
-void MetricsCollector::UpdateWeaveState() {
-  auto weave_service = service_.lock();
-  if (!weave_service)
-    return;
-
-  std::string enabled =
-      metrics_lib_->AreMetricsEnabled() ? "enabled" : "disabled";
-
-  if (!weave_service->SetStateProperty(kWeaveComponent, kWeaveTrait,
-                                       "analyticsReportingState",
-                                       *brillo::ToValue(enabled),
-                                       nullptr)) {
-    LOG(ERROR) << "failed to update weave's state";
-  }
-}
-
-void MetricsCollector::ProcessUserCrash() {
-  // Counts the active time up to now.
-  UpdateStats(TimeTicks::Now(), Time::Now());
-
-  // Reports the active use time since the last crash and resets it.
-  SendAndResetCrashIntervalSample(user_crash_interval_);
-
-  any_crashes_daily_count_->Add(1);
-  any_crashes_weekly_count_->Add(1);
-  user_crashes_daily_count_->Add(1);
-  user_crashes_weekly_count_->Add(1);
-}
-
-void MetricsCollector::ProcessKernelCrash() {
-  // Counts the active time up to now.
-  UpdateStats(TimeTicks::Now(), Time::Now());
-
-  // Reports the active use time since the last crash and resets it.
-  SendAndResetCrashIntervalSample(kernel_crash_interval_);
-
-  any_crashes_daily_count_->Add(1);
-  any_crashes_weekly_count_->Add(1);
-  kernel_crashes_daily_count_->Add(1);
-  kernel_crashes_weekly_count_->Add(1);
-
-  kernel_crashes_version_count_->Add(1);
-}
-
-void MetricsCollector::ProcessUncleanShutdown() {
-  // Counts the active time up to now.
-  UpdateStats(TimeTicks::Now(), Time::Now());
-
-  // Reports the active use time since the last crash and resets it.
-  SendAndResetCrashIntervalSample(unclean_shutdown_interval_);
-
-  unclean_shutdowns_daily_count_->Add(1);
-  unclean_shutdowns_weekly_count_->Add(1);
-  any_crashes_daily_count_->Add(1);
-  any_crashes_weekly_count_->Add(1);
-}
-
-bool MetricsCollector::CheckSystemCrash(const string& crash_file) {
-  FilePath crash_detected(crash_file);
-  if (!base::PathExists(crash_detected))
-    return false;
-
-  // Deletes the crash-detected file so that the daemon doesn't report
-  // another kernel crash in case it's restarted.
-  base::DeleteFile(crash_detected, false);  // not recursive
-  return true;
-}
-
-void MetricsCollector::StatsReporterInit() {
-  disk_usage_collector_->Schedule();
-
-  cpu_usage_collector_->Init();
-  cpu_usage_collector_->Schedule();
-
-  // Don't start a collection cycle during the first run to avoid delaying the
-  // boot.
-  averaged_stats_collector_->ScheduleWait();
-}
-
-void MetricsCollector::ScheduleMeminfoCallback(int wait) {
-  if (testing_) {
-    return;
-  }
-  base::TimeDelta waitDelta = base::TimeDelta::FromSeconds(wait);
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&MetricsCollector::MeminfoCallback,
-                 weak_ptr_factory_.GetWeakPtr(), waitDelta),
-      waitDelta);
-}
-
-void MetricsCollector::MeminfoCallback(base::TimeDelta wait) {
-  string meminfo_raw;
-  const FilePath meminfo_path(kMeminfoFileName);
-  if (!base::ReadFileToString(meminfo_path, &meminfo_raw)) {
-    LOG(WARNING) << "cannot read " << meminfo_path.value().c_str();
-    return;
-  }
-  // Make both calls even if the first one fails.
-  if (ProcessMeminfo(meminfo_raw)) {
-    base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-        base::Bind(&MetricsCollector::MeminfoCallback,
-                   weak_ptr_factory_.GetWeakPtr(), wait),
-        wait);
-  }
-}
-
-// static
-bool MetricsCollector::ReadFileToUint64(const base::FilePath& path,
-                                         uint64_t* value) {
-  std::string content;
-  if (!base::ReadFileToString(path, &content)) {
-    PLOG(WARNING) << "cannot read " << path.MaybeAsASCII();
-    return false;
-  }
-  // Remove final newline.
-  base::TrimWhitespaceASCII(content, base::TRIM_TRAILING, &content);
-  if (!base::StringToUint64(content, value)) {
-    LOG(WARNING) << "invalid integer: " << content;
-    return false;
-  }
-  return true;
-}
-
-bool MetricsCollector::ReportZram(const base::FilePath& zram_dir) {
-  // Data sizes are in bytes.  |zero_pages| is in number of pages.
-  uint64_t compr_data_size, orig_data_size, zero_pages;
-  const size_t page_size = 4096;
-
-  if (!ReadFileToUint64(zram_dir.Append(kComprDataSizeName),
-                        &compr_data_size) ||
-      !ReadFileToUint64(zram_dir.Append(kOrigDataSizeName), &orig_data_size) ||
-      !ReadFileToUint64(zram_dir.Append(kZeroPagesName), &zero_pages)) {
-    return false;
-  }
-
-  // |orig_data_size| does not include zero-filled pages.
-  orig_data_size += zero_pages * page_size;
-
-  const int compr_data_size_mb = compr_data_size >> 20;
-  const int savings_mb = (orig_data_size - compr_data_size) >> 20;
-  const int zero_ratio_percent = zero_pages * page_size * 100 / orig_data_size;
-
-  // Report compressed size in megabytes.  100 MB or less has little impact.
-  SendSample("Platform.ZramCompressedSize", compr_data_size_mb, 100, 4000, 50);
-  SendSample("Platform.ZramSavings", savings_mb, 100, 4000, 50);
-  // The compression ratio is multiplied by 100 for better resolution.  The
-  // ratios of interest are between 1 and 6 (100% and 600% as reported).  We
-  // don't want samples when very little memory is being compressed.
-  if (compr_data_size_mb >= 1) {
-    SendSample("Platform.ZramCompressionRatioPercent",
-               orig_data_size * 100 / compr_data_size, 100, 600, 50);
-  }
-  // The values of interest for zero_pages are between 1MB and 1GB.  The units
-  // are number of pages.
-  SendSample("Platform.ZramZeroPages", zero_pages, 256, 256 * 1024, 50);
-  SendSample("Platform.ZramZeroRatioPercent", zero_ratio_percent, 1, 50, 50);
-
-  return true;
-}
-
-bool MetricsCollector::ProcessMeminfo(const string& meminfo_raw) {
-  static const MeminfoRecord fields_array[] = {
-    { "MemTotal", "MemTotal" },  // SPECIAL CASE: total system memory
-    { "MemFree", "MemFree" },
-    { "Buffers", "Buffers" },
-    { "Cached", "Cached" },
-    // { "SwapCached", "SwapCached" },
-    { "Active", "Active" },
-    { "Inactive", "Inactive" },
-    { "ActiveAnon", "Active(anon)" },
-    { "InactiveAnon", "Inactive(anon)" },
-    { "ActiveFile" , "Active(file)" },
-    { "InactiveFile", "Inactive(file)" },
-    { "Unevictable", "Unevictable", kMeminfoOp_HistLog },
-    // { "Mlocked", "Mlocked" },
-    { "SwapTotal", "SwapTotal", kMeminfoOp_SwapTotal },
-    { "SwapFree", "SwapFree", kMeminfoOp_SwapFree },
-    // { "Dirty", "Dirty" },
-    // { "Writeback", "Writeback" },
-    { "AnonPages", "AnonPages" },
-    { "Mapped", "Mapped" },
-    { "Shmem", "Shmem", kMeminfoOp_HistLog },
-    { "Slab", "Slab", kMeminfoOp_HistLog },
-    // { "SReclaimable", "SReclaimable" },
-    // { "SUnreclaim", "SUnreclaim" },
-  };
-  vector<MeminfoRecord> fields(fields_array,
-                               fields_array + arraysize(fields_array));
-  if (!FillMeminfo(meminfo_raw, &fields)) {
-    return false;
-  }
-  int total_memory = fields[0].value;
-  if (total_memory == 0) {
-    // this "cannot happen"
-    LOG(WARNING) << "borked meminfo parser";
-    return false;
-  }
-  int swap_total = 0;
-  int swap_free = 0;
-  // Send all fields retrieved, except total memory.
-  for (unsigned int i = 1; i < fields.size(); i++) {
-    string metrics_name = base::StringPrintf("Platform.Meminfo%s",
-                                             fields[i].name);
-    int percent;
-    switch (fields[i].op) {
-      case kMeminfoOp_HistPercent:
-        // report value as percent of total memory
-        percent = fields[i].value * 100 / total_memory;
-        SendLinearSample(metrics_name, percent, 100, 101);
-        break;
-      case kMeminfoOp_HistLog:
-        // report value in kbytes, log scale, 4Gb max
-        SendSample(metrics_name, fields[i].value, 1, 4 * 1000 * 1000, 100);
-        break;
-      case kMeminfoOp_SwapTotal:
-        swap_total = fields[i].value;
-      case kMeminfoOp_SwapFree:
-        swap_free = fields[i].value;
-        break;
-    }
-  }
-  if (swap_total > 0) {
-    int swap_used = swap_total - swap_free;
-    int swap_used_percent = swap_used * 100 / swap_total;
-    SendSample("Platform.MeminfoSwapUsed", swap_used, 1, 8 * 1000 * 1000, 100);
-    SendLinearSample("Platform.MeminfoSwapUsed.Percent", swap_used_percent,
-                     100, 101);
-  }
-  return true;
-}
-
-bool MetricsCollector::FillMeminfo(const string& meminfo_raw,
-                                    vector<MeminfoRecord>* fields) {
-  vector<std::string> lines =
-      base::SplitString(meminfo_raw, "\n", base::KEEP_WHITESPACE,
-                        base::SPLIT_WANT_NONEMPTY);
-
-  // Scan meminfo output and collect field values.  Each field name has to
-  // match a meminfo entry (case insensitive) after removing non-alpha
-  // characters from the entry.
-  size_t ifield = 0;
-  for (size_t iline = 0;
-       iline < lines.size() && ifield < fields->size();
-       iline++) {
-    vector<string> tokens =
-        base::SplitString(lines[iline], ": ", base::KEEP_WHITESPACE,
-                          base::SPLIT_WANT_NONEMPTY);
-    if (strcmp((*fields)[ifield].match, tokens[0].c_str()) == 0) {
-      // Name matches. Parse value and save.
-      if (!base::StringToInt(tokens[1], &(*fields)[ifield].value)) {
-        LOG(WARNING) << "Cound not convert " << tokens[1] << " to int";
-        return false;
-      }
-      ifield++;
-    }
-  }
-  if (ifield < fields->size()) {
-    // End of input reached while scanning.
-    LOG(WARNING) << "cannot find field " << (*fields)[ifield].match
-                 << " and following";
-    return false;
-  }
-  return true;
-}
-
-void MetricsCollector::ScheduleMemuseCallback(double interval) {
-  if (testing_) {
-    return;
-  }
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&MetricsCollector::MemuseCallback,
-                 weak_ptr_factory_.GetWeakPtr()),
-      base::TimeDelta::FromSeconds(interval));
-}
-
-void MetricsCollector::MemuseCallback() {
-  // Since we only care about active time (i.e. uptime minus sleep time) but
-  // the callbacks are driven by real time (uptime), we check if we should
-  // reschedule this callback due to intervening sleep periods.
-  double now = GetActiveTime();
-  // Avoid intervals of less than one second.
-  double remaining_time = ceil(memuse_final_time_ - now);
-  if (remaining_time > 0) {
-    ScheduleMemuseCallback(remaining_time);
-  } else {
-    // Report stats and advance the measurement interval unless there are
-    // errors or we've completed the last interval.
-    if (MemuseCallbackWork() &&
-        memuse_interval_index_ < arraysize(kMemuseIntervals)) {
-      double interval = kMemuseIntervals[memuse_interval_index_++];
-      memuse_final_time_ = now + interval;
-      ScheduleMemuseCallback(interval);
-    }
-  }
-}
-
-bool MetricsCollector::MemuseCallbackWork() {
-  string meminfo_raw;
-  const FilePath meminfo_path(kMeminfoFileName);
-  if (!base::ReadFileToString(meminfo_path, &meminfo_raw)) {
-    LOG(WARNING) << "cannot read " << meminfo_path.value().c_str();
-    return false;
-  }
-  return ProcessMemuse(meminfo_raw);
-}
-
-bool MetricsCollector::ProcessMemuse(const string& meminfo_raw) {
-  static const MeminfoRecord fields_array[] = {
-    { "MemTotal", "MemTotal" },  // SPECIAL CASE: total system memory
-    { "ActiveAnon", "Active(anon)" },
-    { "InactiveAnon", "Inactive(anon)" },
-  };
-  vector<MeminfoRecord> fields(fields_array,
-                               fields_array + arraysize(fields_array));
-  if (!FillMeminfo(meminfo_raw, &fields)) {
-    return false;
-  }
-  int total = fields[0].value;
-  int active_anon = fields[1].value;
-  int inactive_anon = fields[2].value;
-  if (total == 0) {
-    // this "cannot happen"
-    LOG(WARNING) << "borked meminfo parser";
-    return false;
-  }
-  string metrics_name = base::StringPrintf("Platform.MemuseAnon%d",
-                                           memuse_interval_index_);
-  SendLinearSample(metrics_name, (active_anon + inactive_anon) * 100 / total,
-                   100, 101);
-  return true;
-}
-
-void MetricsCollector::SendSample(const string& name, int sample,
-                                   int min, int max, int nbuckets) {
-  metrics_lib_->SendToUMA(name, sample, min, max, nbuckets);
-}
-
-void MetricsCollector::SendKernelCrashesCumulativeCountStats() {
-  // Report the number of crashes for this OS version, but don't clear the
-  // counter.  It is cleared elsewhere on version change.
-  int64_t crashes_count = kernel_crashes_version_count_->Get();
-  SendSample(kernel_crashes_version_count_->Name(),
-             crashes_count,
-             1,                         // value of first bucket
-             500,                       // value of last bucket
-             100);                      // number of buckets
-
-
-  int64_t cpu_use_ms = version_cumulative_cpu_use_->Get();
-  SendSample(version_cumulative_cpu_use_->Name(),
-             cpu_use_ms / 1000,         // stat is in seconds
-             1,                         // device may be used very little...
-             8 * 1000 * 1000,           // ... or a lot (a little over 90 days)
-             100);
-
-  // On the first run after an autoupdate, cpu_use_ms and active_use_seconds
-  // can be zero.  Avoid division by zero.
-  if (cpu_use_ms > 0) {
-    // Send the crash frequency since update in number of crashes per CPU year.
-    SendSample("Logging.KernelCrashesPerCpuYear",
-               crashes_count * kSecondsPerDay * 365 * 1000 / cpu_use_ms,
-               1,
-               1000 * 1000,     // about one crash every 30s of CPU time
-               100);
-  }
-
-  int64_t active_use_seconds = version_cumulative_active_use_->Get();
-  if (active_use_seconds > 0) {
-    SendSample(version_cumulative_active_use_->Name(),
-               active_use_seconds,
-               1,                          // device may be used very little...
-               8 * 1000 * 1000,            // ... or a lot (about 90 days)
-               100);
-    // Same as above, but per year of active time.
-    SendSample("Logging.KernelCrashesPerActiveYear",
-               crashes_count * kSecondsPerDay * 365 / active_use_seconds,
-               1,
-               1000 * 1000,     // about one crash every 30s of active time
-               100);
-  }
-}
-
-void MetricsCollector::SendAndResetDailyUseSample(
-    const unique_ptr<PersistentInteger>& use) {
-  SendSample(use->Name(),
-             use->GetAndClear(),
-             1,                        // value of first bucket
-             kSecondsPerDay,           // value of last bucket
-             50);                      // number of buckets
-}
-
-void MetricsCollector::SendAndResetCrashIntervalSample(
-    const unique_ptr<PersistentInteger>& interval) {
-  SendSample(interval->Name(),
-             interval->GetAndClear(),
-             1,                        // value of first bucket
-             4 * kSecondsPerWeek,      // value of last bucket
-             50);                      // number of buckets
-}
-
-void MetricsCollector::SendAndResetCrashFrequencySample(
-    const unique_ptr<PersistentInteger>& frequency) {
-  SendSample(frequency->Name(),
-             frequency->GetAndClear(),
-             1,                        // value of first bucket
-             100,                      // value of last bucket
-             50);                      // number of buckets
-}
-
-void MetricsCollector::SendLinearSample(const string& name, int sample,
-                                         int max, int nbuckets) {
-  // TODO(semenzato): add a proper linear histogram to the Chrome external
-  // metrics API.
-  LOG_IF(FATAL, nbuckets != max + 1) << "unsupported histogram scale";
-  metrics_lib_->SendEnumToUMA(name, sample, max);
-}
-
-void MetricsCollector::UpdateStats(TimeTicks now_ticks,
-                                    Time now_wall_time) {
-  const int elapsed_seconds = (now_ticks - last_update_stats_time_).InSeconds();
-  daily_active_use_->Add(elapsed_seconds);
-  version_cumulative_active_use_->Add(elapsed_seconds);
-  user_crash_interval_->Add(elapsed_seconds);
-  kernel_crash_interval_->Add(elapsed_seconds);
-  TimeDelta cpu_use = cpu_usage_collector_->GetCumulativeCpuUse();
-  version_cumulative_cpu_use_->Add(
-      (cpu_use - latest_cpu_use_microseconds_).InMilliseconds());
-  latest_cpu_use_microseconds_ = cpu_use;
-  last_update_stats_time_ = now_ticks;
-
-  const TimeDelta since_epoch = now_wall_time - Time::UnixEpoch();
-  const int day = since_epoch.InDays();
-  const int week = day / 7;
-
-  if (daily_cycle_->Get() != day) {
-    daily_cycle_->Set(day);
-    SendAndResetDailyUseSample(daily_active_use_);
-    SendAndResetCrashFrequencySample(any_crashes_daily_count_);
-    SendAndResetCrashFrequencySample(user_crashes_daily_count_);
-    SendAndResetCrashFrequencySample(kernel_crashes_daily_count_);
-    SendAndResetCrashFrequencySample(unclean_shutdowns_daily_count_);
-    SendKernelCrashesCumulativeCountStats();
-  }
-
-  if (weekly_cycle_->Get() != week) {
-    weekly_cycle_->Set(week);
-    SendAndResetCrashFrequencySample(any_crashes_weekly_count_);
-    SendAndResetCrashFrequencySample(user_crashes_weekly_count_);
-    SendAndResetCrashFrequencySample(kernel_crashes_weekly_count_);
-    SendAndResetCrashFrequencySample(unclean_shutdowns_weekly_count_);
-  }
-}
-
-void MetricsCollector::HandleUpdateStatsTimeout() {
-  UpdateStats(TimeTicks::Now(), Time::Now());
-  base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
-      base::Bind(&MetricsCollector::HandleUpdateStatsTimeout,
-                 weak_ptr_factory_.GetWeakPtr()),
-      base::TimeDelta::FromMilliseconds(kUpdateStatsIntervalMs));
-}
diff --git a/metricsd/metrics_collector.h b/metricsd/metrics_collector.h
deleted file mode 100644
index 30659bd..0000000
--- a/metricsd/metrics_collector.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_METRICS_COLLECTOR_H_
-#define METRICS_METRICS_COLLECTOR_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/files/file_path.h>
-#include <base/memory/weak_ptr.h>
-#include <base/time/time.h>
-#include <brillo/binder_watcher.h>
-#include <brillo/daemons/daemon.h>
-#include <libweaved/command.h>
-#include <libweaved/service.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-#include "collectors/averaged_statistics_collector.h"
-#include "collectors/cpu_usage_collector.h"
-#include "collectors/disk_usage_collector.h"
-#include "metrics/metrics_library.h"
-#include "persistent_integer.h"
-
-using chromeos_metrics::PersistentInteger;
-using std::unique_ptr;
-
-class MetricsCollector : public brillo::Daemon {
- public:
-  MetricsCollector();
-  ~MetricsCollector();
-
-  // Initializes metrics class variables.
-  void Init(bool testing,
-            MetricsLibraryInterface* metrics_lib,
-            const std::string& diskstats_path,
-            const base::FilePath& private_metrics_directory,
-            const base::FilePath& shared_metrics_directory);
-
-  // Initializes the daemon.
-  int OnInit() override;
-
-  // Does all the work.
-  int Run() override;
-
-  // Returns the active time since boot (uptime minus sleep time) in seconds.
-  static double GetActiveTime();
-
-  // Updates the active use time and logs time between user-space
-  // process crashes.  Called via MetricsCollectorServiceTrampoline.
-  void ProcessUserCrash();
-
- protected:
-  // Used also by the unit tests.
-  static const char kComprDataSizeName[];
-  static const char kOrigDataSizeName[];
-  static const char kZeroPagesName[];
-
- private:
-  friend class MetricsCollectorTest;
-  FRIEND_TEST(MetricsCollectorTest, CheckSystemCrash);
-  FRIEND_TEST(MetricsCollectorTest, ComputeEpochNoCurrent);
-  FRIEND_TEST(MetricsCollectorTest, ComputeEpochNoLast);
-  FRIEND_TEST(MetricsCollectorTest, GetHistogramPath);
-  FRIEND_TEST(MetricsCollectorTest, IsNewEpoch);
-  FRIEND_TEST(MetricsCollectorTest, MessageFilter);
-  FRIEND_TEST(MetricsCollectorTest, ProcessKernelCrash);
-  FRIEND_TEST(MetricsCollectorTest, ProcessMeminfo);
-  FRIEND_TEST(MetricsCollectorTest, ProcessMeminfo2);
-  FRIEND_TEST(MetricsCollectorTest, ProcessUncleanShutdown);
-  FRIEND_TEST(MetricsCollectorTest, ProcessUserCrash);
-  FRIEND_TEST(MetricsCollectorTest, ReportCrashesDailyFrequency);
-  FRIEND_TEST(MetricsCollectorTest, ReportKernelCrashInterval);
-  FRIEND_TEST(MetricsCollectorTest, ReportUncleanShutdownInterval);
-  FRIEND_TEST(MetricsCollectorTest, ReportUserCrashInterval);
-  FRIEND_TEST(MetricsCollectorTest, SendSample);
-  FRIEND_TEST(MetricsCollectorTest, SendZramMetrics);
-
-  // Type of scale to use for meminfo histograms.  For most of them we use
-  // percent of total RAM, but for some we use absolute numbers, usually in
-  // megabytes, on a log scale from 0 to 4000, and 0 to 8000 for compressed
-  // swap (since it can be larger than total RAM).
-  enum MeminfoOp {
-    kMeminfoOp_HistPercent = 0,
-    kMeminfoOp_HistLog,
-    kMeminfoOp_SwapTotal,
-    kMeminfoOp_SwapFree,
-  };
-
-  // Record for retrieving and reporting values from /proc/meminfo.
-  struct MeminfoRecord {
-    const char* name;        // print name
-    const char* match;       // string to match in output of /proc/meminfo
-    MeminfoOp op;            // histogram scale selector, or other operator
-    int value;               // value from /proc/meminfo
-  };
-
-  // Enables metrics reporting.
-  void OnEnableMetrics(std::unique_ptr<weaved::Command> command);
-
-  // Disables metrics reporting.
-  void OnDisableMetrics(std::unique_ptr<weaved::Command> command);
-
-  // Updates the weave device state.
-  void UpdateWeaveState();
-
-  // Updates the active use time and logs time between kernel crashes.
-  void ProcessKernelCrash();
-
-  // Updates the active use time and logs time between unclean shutdowns.
-  void ProcessUncleanShutdown();
-
-  // Checks if a kernel crash has been detected and returns true if
-  // so.  The method assumes that a kernel crash has happened if
-  // |crash_file| exists.  It removes the file immediately if it
-  // exists, so it must not be called more than once.
-  bool CheckSystemCrash(const std::string& crash_file);
-
-  // Sends a regular (exponential) histogram sample to Chrome for
-  // transport to UMA. See MetricsLibrary::SendToUMA in
-  // metrics_library.h for a description of the arguments.
-  void SendSample(const std::string& name, int sample,
-                  int min, int max, int nbuckets);
-
-  // Sends a linear histogram sample to Chrome for transport to UMA. See
-  // MetricsLibrary::SendToUMA in metrics_library.h for a description of the
-  // arguments.
-  void SendLinearSample(const std::string& name, int sample,
-                        int max, int nbuckets);
-
-  // Sends various cumulative kernel crash-related stats, for instance the
-  // total number of kernel crashes since the last version update.
-  void SendKernelCrashesCumulativeCountStats();
-
-  // Sends a sample representing the number of seconds of active use
-  // for a 24-hour period and reset |use|.
-  void SendAndResetDailyUseSample(const unique_ptr<PersistentInteger>& use);
-
-  // Sends a sample representing a time interval between two crashes of the
-  // same type and reset |interval|.
-  void SendAndResetCrashIntervalSample(
-      const unique_ptr<PersistentInteger>& interval);
-
-  // Sends a sample representing a frequency of crashes of some type and reset
-  // |frequency|.
-  void SendAndResetCrashFrequencySample(
-      const unique_ptr<PersistentInteger>& frequency);
-
-  // Initializes vm and disk stats reporting.
-  void StatsReporterInit();
-
-  // Schedules meminfo collection callback.
-  void ScheduleMeminfoCallback(int wait);
-
-  // Reports memory statistics.  Reschedules callback on success.
-  void MeminfoCallback(base::TimeDelta wait);
-
-  // Parses content of /proc/meminfo and sends fields of interest to UMA.
-  // Returns false on errors.  |meminfo_raw| contains the content of
-  // /proc/meminfo.
-  bool ProcessMeminfo(const std::string& meminfo_raw);
-
-  // Parses meminfo data from |meminfo_raw|.  |fields| is a vector containing
-  // the fields of interest.  The order of the fields must be the same in which
-  // /proc/meminfo prints them.  The result of parsing fields[i] is placed in
-  // fields[i].value.
-  bool FillMeminfo(const std::string& meminfo_raw,
-                   std::vector<MeminfoRecord>* fields);
-
-  // Schedule a memory use callback in |interval| seconds.
-  void ScheduleMemuseCallback(double interval);
-
-  // Calls MemuseCallbackWork, and possibly schedules next callback, if enough
-  // active time has passed.  Otherwise reschedules itself to simulate active
-  // time callbacks (i.e. wall clock time minus sleep time).
-  void MemuseCallback();
-
-  // Reads /proc/meminfo and sends total anonymous memory usage to UMA.
-  bool MemuseCallbackWork();
-
-  // Parses meminfo data and sends it to UMA.
-  bool ProcessMemuse(const std::string& meminfo_raw);
-
-  // Reads the current OS version from /etc/lsb-release and hashes it
-  // to a unsigned 32-bit int.
-  uint32_t GetOsVersionHash();
-
-  // Updates stats, additionally sending them to UMA if enough time has elapsed
-  // since the last report.
-  void UpdateStats(base::TimeTicks now_ticks, base::Time now_wall_time);
-
-  // Invoked periodically by |update_stats_timeout_id_| to call UpdateStats().
-  void HandleUpdateStatsTimeout();
-
-  // Reports zram statistics.
-  bool ReportZram(const base::FilePath& zram_dir);
-
-  // Reads a string from a file and converts it to uint64_t.
-  static bool ReadFileToUint64(const base::FilePath& path, uint64_t* value);
-
-  // Callback invoked when a connection to weaved's service is established
-  // over Binder interface.
-  void OnWeaveServiceConnected(const std::weak_ptr<weaved::Service>& service);
-
-  // VARIABLES
-
-  // Test mode.
-  bool testing_;
-
-  // Publicly readable metrics directory.
-  base::FilePath shared_metrics_directory_;
-
-  // The metrics library handle.
-  MetricsLibraryInterface* metrics_lib_;
-
-  // The last time that UpdateStats() was called.
-  base::TimeTicks last_update_stats_time_;
-
-  // End time of current memuse stat collection interval.
-  double memuse_final_time_;
-
-  // Selects the wait time for the next memory use callback.
-  unsigned int memuse_interval_index_;
-
-  // Used internally by GetIncrementalCpuUse() to return the CPU utilization
-  // between calls.
-  base::TimeDelta latest_cpu_use_microseconds_;
-
-  // Persistent values and accumulators for crash statistics.
-  unique_ptr<PersistentInteger> daily_cycle_;
-  unique_ptr<PersistentInteger> weekly_cycle_;
-  unique_ptr<PersistentInteger> version_cycle_;
-
-  // Active use accumulated in a day.
-  unique_ptr<PersistentInteger> daily_active_use_;
-  // Active use accumulated since the latest version update.
-  unique_ptr<PersistentInteger> version_cumulative_active_use_;
-
-  // The CPU time accumulator.  This contains the CPU time, in milliseconds,
-  // used by the system since the most recent OS version update.
-  unique_ptr<PersistentInteger> version_cumulative_cpu_use_;
-
-  unique_ptr<PersistentInteger> user_crash_interval_;
-  unique_ptr<PersistentInteger> kernel_crash_interval_;
-  unique_ptr<PersistentInteger> unclean_shutdown_interval_;
-
-  unique_ptr<PersistentInteger> any_crashes_daily_count_;
-  unique_ptr<PersistentInteger> any_crashes_weekly_count_;
-  unique_ptr<PersistentInteger> user_crashes_daily_count_;
-  unique_ptr<PersistentInteger> user_crashes_weekly_count_;
-  unique_ptr<PersistentInteger> kernel_crashes_daily_count_;
-  unique_ptr<PersistentInteger> kernel_crashes_weekly_count_;
-  unique_ptr<PersistentInteger> kernel_crashes_version_count_;
-  unique_ptr<PersistentInteger> unclean_shutdowns_daily_count_;
-  unique_ptr<PersistentInteger> unclean_shutdowns_weekly_count_;
-
-  unique_ptr<CpuUsageCollector> cpu_usage_collector_;
-  unique_ptr<DiskUsageCollector> disk_usage_collector_;
-  unique_ptr<AveragedStatisticsCollector> averaged_stats_collector_;
-
-  unique_ptr<weaved::Service::Subscription> weave_service_subscription_;
-  std::weak_ptr<weaved::Service> service_;
-
-  base::WeakPtrFactory<MetricsCollector> weak_ptr_factory_{this};
-};
-
-#endif  // METRICS_METRICS_COLLECTOR_H_
diff --git a/metricsd/metrics_collector.rc b/metricsd/metrics_collector.rc
deleted file mode 100644
index 2d7667d..0000000
--- a/metricsd/metrics_collector.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service metricscollector /system/bin/metrics_collector --foreground --logtosyslog
-    class late_start
-    user metrics_coll
-    group metrics_coll
diff --git a/metricsd/metrics_collector_main.cc b/metricsd/metrics_collector_main.cc
deleted file mode 100644
index 14bb935..0000000
--- a/metricsd/metrics_collector_main.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-#include <base/at_exit.h>
-#include <base/command_line.h>
-#include <base/logging.h>
-#include <base/strings/string_util.h>
-#include <brillo/flag_helper.h>
-#include <brillo/syslog_logging.h>
-#include <rootdev.h>
-
-#include "constants.h"
-#include "metrics_collector.h"
-
-
-// Returns the path to the disk stats in the sysfs.  Returns the null string if
-// it cannot find the disk stats file.
-static
-const std::string MetricsMainDiskStatsPath() {
-  char dev_path_cstr[PATH_MAX];
-  std::string dev_prefix = "/dev/block/";
-  std::string dev_path;
-
-  int ret = rootdev(dev_path_cstr, sizeof(dev_path_cstr), true, true);
-  if (ret != 0) {
-    LOG(WARNING) << "error " << ret << " determining root device";
-    return "";
-  }
-  dev_path = dev_path_cstr;
-  // Check that rootdev begins with "/dev/block/".
-  if (!base::StartsWith(dev_path, dev_prefix,
-                        base::CompareCase::INSENSITIVE_ASCII)) {
-    LOG(WARNING) << "unexpected root device " << dev_path;
-    return "";
-  }
-  return "/sys/class/block/" + dev_path.substr(dev_prefix.length()) + "/stat";
-}
-
-int main(int argc, char** argv) {
-  DEFINE_bool(foreground, false, "Don't daemonize");
-
-  DEFINE_string(private_directory, metrics::kMetricsCollectorDirectory,
-                "Path to the private directory used by metrics_collector "
-                "(testing only)");
-  DEFINE_string(shared_directory, metrics::kSharedMetricsDirectory,
-                "Path to the shared metrics directory, used by "
-                "metrics_collector, metricsd and all metrics clients "
-                "(testing only)");
-
-  DEFINE_bool(logtostderr, false, "Log to standard error");
-  DEFINE_bool(logtosyslog, false, "Log to syslog");
-
-  brillo::FlagHelper::Init(argc, argv, "Chromium OS Metrics Daemon");
-
-  int logging_location = (FLAGS_foreground ? brillo::kLogToStderr
-                          : brillo::kLogToSyslog);
-  if (FLAGS_logtosyslog)
-    logging_location = brillo::kLogToSyslog;
-
-  if (FLAGS_logtostderr)
-    logging_location = brillo::kLogToStderr;
-
-  // Also log to stderr when not running as daemon.
-  brillo::InitLog(logging_location | brillo::kLogHeader);
-
-  if (FLAGS_logtostderr && FLAGS_logtosyslog) {
-    LOG(ERROR) << "only one of --logtosyslog and --logtostderr can be set";
-    return 1;
-  }
-
-  if (!FLAGS_foreground && daemon(0, 0) != 0) {
-    return errno;
-  }
-
-  MetricsLibrary metrics_lib;
-  metrics_lib.InitWithNoCaching();
-  MetricsCollector daemon;
-  daemon.Init(false,
-              &metrics_lib,
-              MetricsMainDiskStatsPath(),
-              base::FilePath(FLAGS_private_directory),
-              base::FilePath(FLAGS_shared_directory));
-
-  daemon.Run();
-}
diff --git a/metricsd/metrics_collector_service_client.cc b/metricsd/metrics_collector_service_client.cc
deleted file mode 100644
index 08aaa4a..0000000
--- a/metricsd/metrics_collector_service_client.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-
-// Client interface to IMetricsCollectorService.
-
-#include "metrics/metrics_collector_service_client.h"
-
-#include <base/logging.h>
-#include <binder/IServiceManager.h>
-#include <utils/String16.h>
-
-#include "android/brillo/metrics/IMetricsCollectorService.h"
-
-namespace {
-const char kMetricsCollectorServiceName[] =
-    "android.brillo.metrics.IMetricsCollectorService";
-}
-
-bool MetricsCollectorServiceClient::Init() {
-  const android::String16 name(kMetricsCollectorServiceName);
-  metrics_collector_service_ = android::interface_cast<
-      android::brillo::metrics::IMetricsCollectorService>(
-      android::defaultServiceManager()->checkService(name));
-
-  if (metrics_collector_service_ == nullptr)
-    LOG(ERROR) << "Unable to lookup service " << kMetricsCollectorServiceName;
-
-  return metrics_collector_service_ != nullptr;
-}
-
-bool MetricsCollectorServiceClient::notifyUserCrash() {
-  if (metrics_collector_service_ == nullptr)
-    return false;
-
-  metrics_collector_service_->notifyUserCrash();
-  return true;
-}
diff --git a/metricsd/metrics_collector_service_impl.cc b/metricsd/metrics_collector_service_impl.cc
deleted file mode 100644
index 4d9a05a..0000000
--- a/metricsd/metrics_collector_service_impl.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- */
-
-#include "metrics_collector_service_impl.h"
-
-#include <binder/IServiceManager.h>
-#include <binder/Status.h>
-#include <utils/Errors.h>
-
-#include "metrics_collector.h"
-
-using namespace android;
-
-BnMetricsCollectorServiceImpl::BnMetricsCollectorServiceImpl(
-    MetricsCollector* metrics_collector)
-    : metrics_collector_(metrics_collector) {
-}
-
-android::binder::Status BnMetricsCollectorServiceImpl::notifyUserCrash() {
-  metrics_collector_->ProcessUserCrash();
-  return android::binder::Status::ok();
-}
diff --git a/metricsd/metrics_collector_service_impl.h b/metricsd/metrics_collector_service_impl.h
deleted file mode 100644
index 8db418a..0000000
--- a/metricsd/metrics_collector_service_impl.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
-#define METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
-
-// metrics_collector binder service implementation.  Constructed by
-// MetricsCollector.
-
-#include "android/brillo/metrics/BnMetricsCollectorService.h"
-
-#include <binder/Status.h>
-
-class MetricsCollector;
-
-class BnMetricsCollectorServiceImpl
-    : public android::brillo::metrics::BnMetricsCollectorService {
- public:
-  // Passed a this pointer from the MetricsCollector object that constructs us.
-  explicit BnMetricsCollectorServiceImpl(
-      MetricsCollector* metrics_collector_service);
-
-  virtual ~BnMetricsCollectorServiceImpl() = default;
-
-  // Called by crash_reporter to report a userspace crash event.  We relay
-  // this to MetricsCollector.
-  android::binder::Status notifyUserCrash();
-
- private:
-  // MetricsCollector object that constructs us, we use this to call back
-  // to it.
-  MetricsCollector* metrics_collector_;
-};
-
-#endif  // METRICSD_METRICS_COLLECTOR_SERVICE_IMPL_H_
diff --git a/metricsd/metrics_collector_test.cc b/metricsd/metrics_collector_test.cc
deleted file mode 100644
index 8dda529..0000000
--- a/metricsd/metrics_collector_test.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.
- */
-
-#include <vector>
-
-#include <base/at_exit.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/strings/string_number_conversions.h>
-#include <brillo/flag_helper.h>
-#include <gtest/gtest.h>
-
-#include "constants.h"
-#include "metrics_collector.h"
-#include "metrics/metrics_library_mock.h"
-#include "persistent_integer_mock.h"
-
-using base::FilePath;
-using base::TimeDelta;
-using std::string;
-using std::vector;
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::AtLeast;
-using ::testing::Return;
-using ::testing::StrictMock;
-using chromeos_metrics::PersistentIntegerMock;
-
-
-class MetricsCollectorTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-    brillo::FlagHelper::Init(0, nullptr, "");
-    EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
-
-    base::FilePath private_dir = temp_dir_.path().Append("private");
-    base::FilePath shared_dir = temp_dir_.path().Append("shared");
-
-    EXPECT_TRUE(base::CreateDirectory(private_dir));
-    EXPECT_TRUE(base::CreateDirectory(shared_dir));
-
-    daemon_.Init(true, &metrics_lib_, "", private_dir, shared_dir);
-  }
-
-  // Adds a metrics library mock expectation that the specified metric
-  // will be generated.
-  void ExpectSample(const std::string& name, int sample) {
-    EXPECT_CALL(metrics_lib_, SendToUMA(name, sample, _, _, _))
-        .Times(1)
-        .WillOnce(Return(true))
-        .RetiresOnSaturation();
-  }
-
-  // Creates or overwrites the file in |path| so that it contains the printable
-  // representation of |value|.
-  void CreateUint64ValueFile(const base::FilePath& path, uint64_t value) {
-    std::string value_string = base::Uint64ToString(value);
-    ASSERT_EQ(value_string.length(),
-              base::WriteFile(path, value_string.c_str(),
-                              value_string.length()));
-  }
-
-  // The MetricsCollector under test.
-  MetricsCollector daemon_;
-
-  // Temporary directory used for tests.
-  base::ScopedTempDir temp_dir_;
-
-  // Mocks. They are strict mock so that all unexpected
-  // calls are marked as failures.
-  StrictMock<MetricsLibraryMock> metrics_lib_;
-};
-
-TEST_F(MetricsCollectorTest, SendSample) {
-  ExpectSample("Dummy.Metric", 3);
-  daemon_.SendSample("Dummy.Metric", /* sample */ 3,
-                     /* min */ 1, /* max */ 100, /* buckets */ 50);
-}
-
-TEST_F(MetricsCollectorTest, ProcessMeminfo) {
-  string meminfo =
-      "MemTotal:        2000000 kB\nMemFree:          500000 kB\n"
-      "Buffers:         1000000 kB\nCached:           213652 kB\n"
-      "SwapCached:            0 kB\nActive:           133400 kB\n"
-      "Inactive:         183396 kB\nActive(anon):      92984 kB\n"
-      "Inactive(anon):    58860 kB\nActive(file):      40416 kB\n"
-      "Inactive(file):   124536 kB\nUnevictable:           0 kB\n"
-      "Mlocked:               0 kB\nSwapTotal:             0 kB\n"
-      "SwapFree:              0 kB\nDirty:                40 kB\n"
-      "Writeback:             0 kB\nAnonPages:         92652 kB\n"
-      "Mapped:            59716 kB\nShmem:             59196 kB\n"
-      "Slab:              16656 kB\nSReclaimable:       6132 kB\n"
-      "SUnreclaim:        10524 kB\nKernelStack:        1648 kB\n"
-      "PageTables:         2780 kB\nNFS_Unstable:          0 kB\n"
-      "Bounce:                0 kB\nWritebackTmp:          0 kB\n"
-      "CommitLimit:      970656 kB\nCommitted_AS:    1260528 kB\n"
-      "VmallocTotal:     122880 kB\nVmallocUsed:       12144 kB\n"
-      "VmallocChunk:     103824 kB\nDirectMap4k:        9636 kB\n"
-      "DirectMap2M:     1955840 kB\n";
-
-  // All enum calls must report percents.
-  EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, _, 100)).Times(AtLeast(1));
-  // Check that MemFree is correctly computed at 25%.
-  EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMemFree", 25, 100))
-      .Times(AtLeast(1));
-  // Check that we call SendToUma at least once (log histogram).
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _))
-      .Times(AtLeast(1));
-  // Make sure we don't report fields not in the list.
-  EXPECT_CALL(metrics_lib_, SendToUMA("Platform.MeminfoMlocked", _, _, _, _))
-      .Times(0);
-  EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMlocked", _, _))
-      .Times(0);
-  EXPECT_TRUE(daemon_.ProcessMeminfo(meminfo));
-}
-
-TEST_F(MetricsCollectorTest, ProcessMeminfo2) {
-  string meminfo = "MemTotal:        2000000 kB\nMemFree:         1000000 kB\n";
-  // Not enough fields.
-  EXPECT_FALSE(daemon_.ProcessMeminfo(meminfo));
-}
-
-TEST_F(MetricsCollectorTest, SendZramMetrics) {
-  EXPECT_TRUE(daemon_.testing_);
-
-  // |compr_data_size| is the size in bytes of compressed data.
-  const uint64_t compr_data_size = 50 * 1000 * 1000;
-  // The constant '3' is a realistic but random choice.
-  // |orig_data_size| does not include zero pages.
-  const uint64_t orig_data_size = compr_data_size * 3;
-  const uint64_t page_size = 4096;
-  const uint64_t zero_pages = 10 * 1000 * 1000 / page_size;
-
-  CreateUint64ValueFile(
-      temp_dir_.path().Append(MetricsCollector::kComprDataSizeName),
-      compr_data_size);
-  CreateUint64ValueFile(
-      temp_dir_.path().Append(MetricsCollector::kOrigDataSizeName),
-      orig_data_size);
-  CreateUint64ValueFile(
-      temp_dir_.path().Append(MetricsCollector::kZeroPagesName), zero_pages);
-
-  const uint64_t real_orig_size = orig_data_size + zero_pages * page_size;
-  const uint64_t zero_ratio_percent =
-      zero_pages * page_size * 100 / real_orig_size;
-  // Ratio samples are in percents.
-  const uint64_t actual_ratio_sample = real_orig_size * 100 / compr_data_size;
-
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, compr_data_size >> 20, _, _, _));
-  EXPECT_CALL(metrics_lib_,
-              SendToUMA(_, (real_orig_size - compr_data_size) >> 20, _, _, _));
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, actual_ratio_sample, _, _, _));
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_pages, _, _, _));
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_ratio_percent, _, _, _));
-
-  EXPECT_TRUE(daemon_.ReportZram(temp_dir_.path()));
-}
diff --git a/metricsd/metrics_library.cc b/metricsd/metrics_library.cc
deleted file mode 100644
index d211ab4..0000000
--- a/metricsd/metrics_library.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.
- */
-
-#include "metrics/metrics_library.h"
-
-#include <base/logging.h>
-#include <base/strings/stringprintf.h>
-#include <binder/IServiceManager.h>
-#include <errno.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <utils/String16.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include "android/brillo/metrics/IMetricsd.h"
-#include "constants.h"
-
-static const char kCrosEventHistogramName[] = "Platform.CrOSEvent";
-static const int kCrosEventHistogramMax = 100;
-static const char kMetricsServiceName[] = "android.brillo.metrics.IMetricsd";
-
-/* Add new cros events here.
- *
- * The index of the event is sent in the message, so please do not
- * reorder the names.
- */
-static const char *kCrosEventNames[] = {
-  "ModemManagerCommandSendFailure",  // 0
-  "HwWatchdogReboot",  // 1
-  "Cras.NoCodecsFoundAtBoot",  // 2
-  "Chaps.DatabaseCorrupted",  // 3
-  "Chaps.DatabaseRepairFailure",  // 4
-  "Chaps.DatabaseCreateFailure",  // 5
-  "Attestation.OriginSpecificExhausted",  // 6
-  "SpringPowerSupply.Original.High",  // 7
-  "SpringPowerSupply.Other.High",  // 8
-  "SpringPowerSupply.Original.Low",  // 9
-  "SpringPowerSupply.ChargerIdle",  // 10
-  "TPM.NonZeroDictionaryAttackCounter",  // 11
-  "TPM.EarlyResetDuringCommand",  // 12
-};
-
-using android::binder::Status;
-using android::brillo::metrics::IMetricsd;
-using android::String16;
-
-MetricsLibrary::MetricsLibrary() {}
-MetricsLibrary::~MetricsLibrary() {}
-
-// We take buffer and buffer_size as parameters in order to simplify testing
-// of various alignments of the |device_name| with |buffer_size|.
-bool MetricsLibrary::IsDeviceMounted(const char* device_name,
-                                     const char* mounts_file,
-                                     char* buffer,
-                                     int buffer_size,
-                                     bool* result) {
-  if (buffer == nullptr || buffer_size < 1)
-    return false;
-  int mounts_fd = open(mounts_file, O_RDONLY);
-  if (mounts_fd < 0)
-    return false;
-  // match_offset describes:
-  //   -1 -- not beginning of line
-  //   0..strlen(device_name)-1 -- this offset in device_name is next to match
-  //   strlen(device_name) -- matched full name, just need a space.
-  int match_offset = 0;
-  bool match = false;
-  while (!match) {
-    int read_size = read(mounts_fd, buffer, buffer_size);
-    if (read_size <= 0) {
-      if (errno == -EINTR)
-        continue;
-      break;
-    }
-    for (int i = 0; i < read_size; ++i) {
-      if (buffer[i] == '\n') {
-        match_offset = 0;
-        continue;
-      }
-      if (match_offset < 0) {
-        continue;
-      }
-      if (device_name[match_offset] == '\0') {
-        if (buffer[i] == ' ') {
-          match = true;
-          break;
-        }
-        match_offset = -1;
-        continue;
-      }
-
-      if (buffer[i] == device_name[match_offset]) {
-        ++match_offset;
-      } else {
-        match_offset = -1;
-      }
-    }
-  }
-  close(mounts_fd);
-  *result = match;
-  return true;
-}
-
-bool MetricsLibrary::IsGuestMode() {
-  char buffer[256];
-  bool result = false;
-  if (!IsDeviceMounted("guestfs",
-                       "/proc/mounts",
-                       buffer,
-                       sizeof(buffer),
-                       &result)) {
-    return false;
-  }
-  return result && (access("/var/run/state/logged-in", F_OK) == 0);
-}
-
-bool MetricsLibrary::CheckService() {
-  if (metricsd_proxy_.get() &&
-      android::IInterface::asBinder(metricsd_proxy_)->isBinderAlive())
-    return true;
-
-  const String16 name(kMetricsServiceName);
-  metricsd_proxy_ = android::interface_cast<IMetricsd>(
-      android::defaultServiceManager()->checkService(name));
-  return metricsd_proxy_.get();
-}
-
-bool MetricsLibrary::AreMetricsEnabled() {
-  static struct stat stat_buffer;
-  time_t this_check_time = time(nullptr);
-  if (!use_caching_ || this_check_time != cached_enabled_time_) {
-    cached_enabled_time_ = this_check_time;
-    cached_enabled_ = stat(consent_file_.value().data(), &stat_buffer) >= 0;
-  }
-  return cached_enabled_;
-}
-
-void MetricsLibrary::Init() {
-  base::FilePath dir = base::FilePath(metrics::kSharedMetricsDirectory);
-  consent_file_ = dir.Append(metrics::kConsentFileName);
-  cached_enabled_ = false;
-  cached_enabled_time_ = 0;
-  use_caching_ = true;
-}
-
-void MetricsLibrary::InitWithNoCaching() {
-  Init();
-  use_caching_ = false;
-}
-
-void MetricsLibrary::InitForTest(const base::FilePath& metrics_directory) {
-  consent_file_ = metrics_directory.Append(metrics::kConsentFileName);
-  cached_enabled_ = false;
-  cached_enabled_time_ = 0;
-  use_caching_ = true;
-}
-
-bool MetricsLibrary::SendToUMA(
-    const std::string& name, int sample, int min, int max, int nbuckets) {
-  return CheckService() &&
-         metricsd_proxy_->recordHistogram(String16(name.c_str()), sample, min,
-                                          max, nbuckets)
-             .isOk();
-}
-
-bool MetricsLibrary::SendEnumToUMA(const std::string& name,
-                                   int sample,
-                                   int max) {
-  return CheckService() &&
-         metricsd_proxy_->recordLinearHistogram(String16(name.c_str()), sample,
-                                                max)
-             .isOk();
-}
-
-bool MetricsLibrary::SendBoolToUMA(const std::string& name, bool sample) {
-  return CheckService() &&
-         metricsd_proxy_->recordLinearHistogram(String16(name.c_str()),
-                                                sample ? 1 : 0, 2)
-             .isOk();
-}
-
-bool MetricsLibrary::SendSparseToUMA(const std::string& name, int sample) {
-  return CheckService() &&
-         metricsd_proxy_->recordSparseHistogram(String16(name.c_str()), sample)
-             .isOk();
-}
-
-bool MetricsLibrary::SendCrashToUMA(const char* crash_kind) {
-  return CheckService() &&
-         metricsd_proxy_->recordCrash(String16(crash_kind)).isOk();
-}
-
-bool MetricsLibrary::SendCrosEventToUMA(const std::string& event) {
-  for (size_t i = 0; i < arraysize(kCrosEventNames); i++) {
-    if (strcmp(event.c_str(), kCrosEventNames[i]) == 0) {
-      return SendEnumToUMA(kCrosEventHistogramName, i, kCrosEventHistogramMax);
-    }
-  }
-  return false;
-}
-
-bool MetricsLibrary::GetHistogramsDump(std::string* dump) {
-  android::String16 temp_dump;
-  if (!CheckService() ||
-      !metricsd_proxy_->getHistogramsDump(&temp_dump).isOk()) {
-    return false;
-  }
-
-  *dump = android::String8(temp_dump).string();
-  return true;
-}
diff --git a/metricsd/metrics_library_test.cc b/metricsd/metrics_library_test.cc
deleted file mode 100644
index 52fcce3..0000000
--- a/metricsd/metrics_library_test.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.
- */
-
-
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "metrics/c_metrics_library.h"
-#include "metrics/metrics_library.h"
-
-
-class MetricsLibraryTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    lib_.InitForTest(temp_dir_.path());
-    // Defeat metrics enabled caching between tests.
-    lib_.cached_enabled_time_ = 0;
-  }
-
-  void SetMetricsConsent(bool enabled) {
-    if (enabled) {
-      ASSERT_EQ(base::WriteFile(lib_.consent_file_, "", 0), 0);
-    } else {
-      ASSERT_TRUE(base::DeleteFile(lib_.consent_file_, false));
-    }
-  }
-
-  void VerifyEnabledCacheHit(bool to_value);
-  void VerifyEnabledCacheEviction(bool to_value);
-
-  MetricsLibrary lib_;
-  base::ScopedTempDir temp_dir_;
-};
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledFalse) {
-  SetMetricsConsent(false);
-  EXPECT_FALSE(lib_.AreMetricsEnabled());
-}
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledTrue) {
-  SetMetricsConsent(true);
-  EXPECT_TRUE(lib_.AreMetricsEnabled());
-}
-
-void MetricsLibraryTest::VerifyEnabledCacheHit(bool to_value) {
-  // We might step from one second to the next one time, but not 100
-  // times in a row.
-  for (int i = 0; i < 100; ++i) {
-    lib_.cached_enabled_time_ = 0;
-    SetMetricsConsent(to_value);
-    lib_.AreMetricsEnabled();
-    // If we check the metrics status twice in a row, we use the cached value
-    // the second time.
-    SetMetricsConsent(!to_value);
-    if (lib_.AreMetricsEnabled() == to_value)
-      return;
-  }
-  ADD_FAILURE() << "Did not see evidence of caching";
-}
-
-void MetricsLibraryTest::VerifyEnabledCacheEviction(bool to_value) {
-  lib_.cached_enabled_time_ = 0;
-  SetMetricsConsent(!to_value);
-  ASSERT_EQ(!to_value, lib_.AreMetricsEnabled());
-
-  SetMetricsConsent(to_value);
-  // Sleep one second (or cheat to be faster) and check that we are not using
-  // the cached value.
-  --lib_.cached_enabled_time_;
-  ASSERT_EQ(to_value, lib_.AreMetricsEnabled());
-}
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledCaching) {
-  VerifyEnabledCacheHit(false);
-  VerifyEnabledCacheHit(true);
-  VerifyEnabledCacheEviction(false);
-  VerifyEnabledCacheEviction(true);
-}
-
-TEST_F(MetricsLibraryTest, AreMetricsEnabledNoCaching) {
-  // disable caching.
-  lib_.use_caching_ = false;
-
-  // Checking the consent repeatedly should return the right result.
-  for (int i=0; i<100; ++i) {
-    SetMetricsConsent(true);
-    ASSERT_EQ(true, lib_.AreMetricsEnabled());
-    SetMetricsConsent(false);
-    ASSERT_EQ(false, lib_.AreMetricsEnabled());
-  }
-}
diff --git a/metricsd/metricsd.rc b/metricsd/metricsd.rc
deleted file mode 100644
index 3d3e695..0000000
--- a/metricsd/metricsd.rc
+++ /dev/null
@@ -1,9 +0,0 @@
-on post-fs-data
-    mkdir /data/misc/metrics 0750 metrics_coll system
-    mkdir /data/misc/metricsd 0700 metricsd metricsd
-    mkdir /data/misc/metrics_collector 0700 metrics_coll metrics_coll
-
-service metricsd /system/bin/metricsd --foreground --logtosyslog
-    class late_start
-    user metricsd
-    group system inet
diff --git a/metricsd/metricsd_main.cc b/metricsd/metricsd_main.cc
deleted file mode 100644
index 0178342..0000000
--- a/metricsd/metricsd_main.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.
- */
-
-#include <base/command_line.h>
-#include <base/files/file_path.h>
-#include <base/logging.h>
-#include <base/time/time.h>
-#include <brillo/flag_helper.h>
-#include <brillo/syslog_logging.h>
-
-#include "constants.h"
-#include "uploader/metricsd_service_runner.h"
-#include "uploader/upload_service.h"
-
-int main(int argc, char** argv) {
-  DEFINE_bool(foreground, false, "Don't daemonize");
-
-  // Upload the metrics once and exit. (used for testing)
-  DEFINE_bool(uploader_test, false, "run the uploader once and exit");
-
-  // Upload Service flags.
-  DEFINE_int32(upload_interval_secs, 1800,
-               "Interval at which metricsd uploads the metrics.");
-  DEFINE_int32(disk_persistence_interval_secs, 300,
-               "Interval at which metricsd saves the aggregated metrics to "
-               "disk to avoid losing them if metricsd stops in between "
-               "two uploads.");
-  DEFINE_string(server, metrics::kMetricsServer,
-                "Server to upload the metrics to.");
-  DEFINE_string(private_directory, metrics::kMetricsdDirectory,
-                "Path to the private directory used by metricsd "
-                "(testing only)");
-  DEFINE_string(shared_directory, metrics::kSharedMetricsDirectory,
-                "Path to the shared metrics directory, used by "
-                "metrics_collector, metricsd and all metrics clients "
-                "(testing only)");
-
-  DEFINE_bool(logtostderr, false, "Log to standard error");
-  DEFINE_bool(logtosyslog, false, "Log to syslog");
-
-  brillo::FlagHelper::Init(argc, argv, "Brillo metrics daemon.");
-
-  int logging_location =
-      (FLAGS_foreground ? brillo::kLogToStderr : brillo::kLogToSyslog);
-  if (FLAGS_logtosyslog)
-    logging_location = brillo::kLogToSyslog;
-
-  if (FLAGS_logtostderr)
-    logging_location = brillo::kLogToStderr;
-
-  // Also log to stderr when not running as daemon.
-  brillo::InitLog(logging_location | brillo::kLogHeader);
-
-  if (FLAGS_logtostderr && FLAGS_logtosyslog) {
-    LOG(ERROR) << "only one of --logtosyslog and --logtostderr can be set";
-    return 1;
-  }
-
-  if (!FLAGS_foreground && daemon(0, 0) != 0) {
-    return errno;
-  }
-
-  UploadService upload_service(
-      FLAGS_server, base::TimeDelta::FromSeconds(FLAGS_upload_interval_secs),
-      base::TimeDelta::FromSeconds(FLAGS_disk_persistence_interval_secs),
-      base::FilePath(FLAGS_private_directory),
-      base::FilePath(FLAGS_shared_directory));
-
-  return upload_service.Run();
-}
diff --git a/metricsd/persistent_integer.cc b/metricsd/persistent_integer.cc
deleted file mode 100644
index 7fe355e..0000000
--- a/metricsd/persistent_integer.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-#include "persistent_integer.h"
-
-#include <fcntl.h>
-
-#include <base/logging.h>
-#include <base/posix/eintr_wrapper.h>
-
-#include "constants.h"
-
-namespace chromeos_metrics {
-
-PersistentInteger::PersistentInteger(const std::string& name,
-                                     const base::FilePath& directory)
-    : value_(0),
-      version_(kVersion),
-      name_(name),
-      backing_file_path_(directory.Append(name_)),
-      synced_(false) {}
-
-PersistentInteger::~PersistentInteger() {}
-
-void PersistentInteger::Set(int64_t value) {
-  value_ = value;
-  Write();
-}
-
-int64_t PersistentInteger::Get() {
-  // If not synced, then read.  If the read fails, it's a good idea to write.
-  if (!synced_ && !Read())
-    Write();
-  return value_;
-}
-
-int64_t PersistentInteger::GetAndClear() {
-  int64_t v = Get();
-  Set(0);
-  return v;
-}
-
-void PersistentInteger::Add(int64_t x) {
-  Set(Get() + x);
-}
-
-void PersistentInteger::Write() {
-  int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(),
-                             O_WRONLY | O_CREAT | O_TRUNC,
-                             S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH));
-  PCHECK(fd >= 0) << "cannot open " << backing_file_path_.value()
-                  << " for writing";
-  PCHECK((HANDLE_EINTR(write(fd, &version_, sizeof(version_))) ==
-          sizeof(version_)) &&
-         (HANDLE_EINTR(write(fd, &value_, sizeof(value_))) ==
-          sizeof(value_)))
-      << "cannot write to " << backing_file_path_.value();
-  close(fd);
-  synced_ = true;
-}
-
-bool PersistentInteger::Read() {
-  int fd = HANDLE_EINTR(open(backing_file_path_.value().c_str(), O_RDONLY));
-  if (fd < 0) {
-    PLOG(WARNING) << "cannot open " << backing_file_path_.value()
-                  << " for reading";
-    return false;
-  }
-  int32_t version;
-  int64_t value;
-  bool read_succeeded = false;
-  if (HANDLE_EINTR(read(fd, &version, sizeof(version))) == sizeof(version) &&
-      version == version_ &&
-      HANDLE_EINTR(read(fd, &value, sizeof(value))) == sizeof(value)) {
-    value_ = value;
-    read_succeeded = true;
-    synced_ = true;
-  }
-  close(fd);
-  return read_succeeded;
-}
-
-}  // namespace chromeos_metrics
diff --git a/metricsd/persistent_integer.h b/metricsd/persistent_integer.h
deleted file mode 100644
index 96d9fc0..0000000
--- a/metricsd/persistent_integer.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_PERSISTENT_INTEGER_H_
-#define METRICS_PERSISTENT_INTEGER_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include <base/files/file_path.h>
-
-namespace chromeos_metrics {
-
-// PersistentIntegers is a named 64-bit integer value backed by a file.
-// The in-memory value acts as a write-through cache of the file value.
-// If the backing file doesn't exist or has bad content, the value is 0.
-
-class PersistentInteger {
- public:
-  PersistentInteger(const std::string& name, const base::FilePath& directory);
-
-  // Virtual only because of mock.
-  virtual ~PersistentInteger();
-
-  // Sets the value.  This writes through to the backing file.
-  void Set(int64_t v);
-
-  // Gets the value.  May sync from backing file first.
-  int64_t Get();
-
-  // Returns the name of the object.
-  std::string Name() { return name_; }
-
-  // Convenience function for Get() followed by Set(0).
-  int64_t GetAndClear();
-
-  // Convenience function for v = Get, Set(v + x).
-  // Virtual only because of mock.
-  virtual void Add(int64_t x);
-
- private:
-  static const int kVersion = 1001;
-
-  // Writes |value_| to the backing file, creating it if necessary.
-  void Write();
-
-  // Reads the value from the backing file, stores it in |value_|, and returns
-  // true if the backing file is valid.  Returns false otherwise, and creates
-  // a valid backing file as a side effect.
-  bool Read();
-
-  int64_t value_;
-  int32_t version_;
-  std::string name_;
-  base::FilePath backing_file_path_;
-  bool synced_;
-};
-
-}  // namespace chromeos_metrics
-
-#endif  // METRICS_PERSISTENT_INTEGER_H_
diff --git a/metricsd/persistent_integer_mock.h b/metricsd/persistent_integer_mock.h
deleted file mode 100644
index 0be54d4..0000000
--- a/metricsd/persistent_integer_mock.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_PERSISTENT_INTEGER_MOCK_H_
-#define METRICS_PERSISTENT_INTEGER_MOCK_H_
-
-#include <string>
-
-#include <gmock/gmock.h>
-
-#include "persistent_integer.h"
-
-namespace chromeos_metrics {
-
-class PersistentIntegerMock : public PersistentInteger {
- public:
-  explicit PersistentIntegerMock(const std::string& name,
-                                 const base::FilePath& directory)
-      : PersistentInteger(name, directory) {}
-  MOCK_METHOD1(Add, void(int64_t count));
-};
-
-}  // namespace chromeos_metrics
-
-#endif  // METRICS_PERSISTENT_INTEGER_MOCK_H_
diff --git a/metricsd/persistent_integer_test.cc b/metricsd/persistent_integer_test.cc
deleted file mode 100644
index bf76261..0000000
--- a/metricsd/persistent_integer_test.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-
-#include <memory>
-
-#include <base/compiler_specific.h>
-#include <base/files/file_enumerator.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <gtest/gtest.h>
-
-#include "persistent_integer.h"
-
-const char kBackingFileName[] = "1.pibakf";
-
-using chromeos_metrics::PersistentInteger;
-
-class PersistentIntegerTest : public testing::Test {
-  void SetUp() override {
-    // Set testing mode.
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  }
-
- protected:
-  base::ScopedTempDir temp_dir_;
-};
-
-TEST_F(PersistentIntegerTest, BasicChecks) {
-  std::unique_ptr<PersistentInteger> pi(
-      new PersistentInteger(kBackingFileName, temp_dir_.path()));
-
-  // Test initialization.
-  EXPECT_EQ(0, pi->Get());
-  EXPECT_EQ(kBackingFileName, pi->Name());  // boring
-
-  // Test set and add.
-  pi->Set(2);
-  pi->Add(3);
-  EXPECT_EQ(5, pi->Get());
-
-  // Test persistence.
-  pi.reset(new PersistentInteger(kBackingFileName, temp_dir_.path()));
-  EXPECT_EQ(5, pi->Get());
-
-  // Test GetAndClear.
-  EXPECT_EQ(5, pi->GetAndClear());
-  EXPECT_EQ(pi->Get(), 0);
-
-  // Another persistence test.
-  pi.reset(new PersistentInteger(kBackingFileName, temp_dir_.path()));
-  EXPECT_EQ(0, pi->Get());
-}
diff --git a/metricsd/timer.cc b/metricsd/timer.cc
deleted file mode 100644
index 06fc336..0000000
--- a/metricsd/timer.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.
- */
-
-#include "metrics/timer.h"
-
-#include <string>
-
-#include "metrics/metrics_library.h"
-
-namespace chromeos_metrics {
-
-base::TimeTicks ClockWrapper::GetCurrentTime() const {
-  return base::TimeTicks::Now();
-}
-
-Timer::Timer()
-    : timer_state_(kTimerStopped),
-      clock_wrapper_(new ClockWrapper()) {}
-
-bool Timer::Start() {
-  elapsed_time_ = base::TimeDelta();  // Sets elapsed_time_ to zero.
-  start_time_ = clock_wrapper_->GetCurrentTime();
-  timer_state_ = kTimerRunning;
-  return true;
-}
-
-bool Timer::Stop() {
-  if (timer_state_ == kTimerStopped)
-    return false;
-  if (timer_state_ == kTimerRunning)
-    elapsed_time_ += clock_wrapper_->GetCurrentTime() - start_time_;
-  timer_state_ = kTimerStopped;
-  return true;
-}
-
-bool Timer::Pause() {
-  switch (timer_state_) {
-    case kTimerStopped:
-      if (!Start())
-        return false;
-      timer_state_ = kTimerPaused;
-      return true;
-    case kTimerRunning:
-      timer_state_ = kTimerPaused;
-      elapsed_time_ += clock_wrapper_->GetCurrentTime() - start_time_;
-      return true;
-    default:
-      return false;
-  }
-}
-
-bool Timer::Resume() {
-  switch (timer_state_) {
-    case kTimerStopped:
-      return Start();
-    case kTimerPaused:
-      start_time_ = clock_wrapper_->GetCurrentTime();
-      timer_state_ = kTimerRunning;
-      return true;
-    default:
-      return false;
-  }
-}
-
-bool Timer::Reset() {
-  elapsed_time_ = base::TimeDelta();  // Sets elapsed_time_ to zero.
-  timer_state_ = kTimerStopped;
-  return true;
-}
-
-bool Timer::HasStarted() const {
-  return timer_state_ != kTimerStopped;
-}
-
-bool Timer::GetElapsedTime(base::TimeDelta* elapsed_time) const {
-  if (start_time_.is_null() || !elapsed_time)
-    return false;
-  *elapsed_time = elapsed_time_;
-  if (timer_state_ == kTimerRunning) {
-    *elapsed_time += clock_wrapper_->GetCurrentTime() - start_time_;
-  }
-  return true;
-}
-
-// static
-MetricsLibraryInterface* TimerReporter::metrics_lib_ = nullptr;
-
-TimerReporter::TimerReporter(const std::string& histogram_name, int min,
-                             int max, int num_buckets)
-    : histogram_name_(histogram_name),
-      min_(min),
-      max_(max),
-      num_buckets_(num_buckets) {}
-
-bool TimerReporter::ReportMilliseconds() const {
-  base::TimeDelta elapsed_time;
-  if (!metrics_lib_ || !GetElapsedTime(&elapsed_time)) return false;
-  return metrics_lib_->SendToUMA(histogram_name_,
-                                 elapsed_time.InMilliseconds(),
-                                 min_,
-                                 max_,
-                                 num_buckets_);
-}
-
-}  // namespace chromeos_metrics
diff --git a/metricsd/timer_test.cc b/metricsd/timer_test.cc
deleted file mode 100644
index cfbcd8a..0000000
--- a/metricsd/timer_test.cc
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * 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.
- */
-
-#include <stdint.h>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <memory>
-
-#include "metrics/metrics_library_mock.h"
-#include "metrics/timer.h"
-#include "metrics/timer_mock.h"
-
-using ::testing::_;
-using ::testing::Return;
-
-namespace chromeos_metrics {
-
-namespace {
-const int64_t kStime1MSec = 1400;
-const int64_t kEtime1MSec = 3000;
-const int64_t kDelta1MSec = 1600;
-
-const int64_t kStime2MSec = 4200;
-const int64_t kEtime2MSec = 5000;
-const int64_t kDelta2MSec = 800;
-
-const int64_t kStime3MSec = 6600;
-const int64_t kEtime3MSec = 6800;
-const int64_t kDelta3MSec = 200;
-}  // namespace
-
-class TimerTest : public testing::Test {
- public:
-  TimerTest() : clock_wrapper_mock_(new ClockWrapperMock()) {}
-
- protected:
-  virtual void SetUp() {
-    EXPECT_EQ(Timer::kTimerStopped, timer_.timer_state_);
-    stime += base::TimeDelta::FromMilliseconds(kStime1MSec);
-    etime += base::TimeDelta::FromMilliseconds(kEtime1MSec);
-    stime2 += base::TimeDelta::FromMilliseconds(kStime2MSec);
-    etime2 += base::TimeDelta::FromMilliseconds(kEtime2MSec);
-    stime3 += base::TimeDelta::FromMilliseconds(kStime3MSec);
-    etime3 += base::TimeDelta::FromMilliseconds(kEtime3MSec);
-  }
-
-  virtual void TearDown() {}
-
-  Timer timer_;
-  std::unique_ptr<ClockWrapperMock> clock_wrapper_mock_;
-  base::TimeTicks stime, etime, stime2, etime2, stime3, etime3;
-};
-
-TEST_F(TimerTest, StartStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_FALSE(timer_.HasStarted());
-}
-
-TEST_F(TimerTest, ReStart) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  timer_.Start();
-  base::TimeTicks buffer = timer_.start_time_;
-  timer_.Start();
-  ASSERT_FALSE(timer_.start_time_ == buffer);
-}
-
-TEST_F(TimerTest, Reset) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  timer_.Start();
-  ASSERT_TRUE(timer_.Reset());
-  ASSERT_FALSE(timer_.HasStarted());
-}
-
-TEST_F(TimerTest, SeparatedTimers) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime))
-      .WillOnce(Return(stime2))
-      .WillOnce(Return(etime2));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime2);
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, InvalidStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_FALSE(timer_.Stop());
-  // Now we try it again, but after a valid start/stop.
-  timer_.Start();
-  timer_.Stop();
-  base::TimeDelta elapsed_time = timer_.elapsed_time_;
-  ASSERT_FALSE(timer_.Stop());
-  ASSERT_TRUE(elapsed_time == timer_.elapsed_time_);
-}
-
-TEST_F(TimerTest, InvalidElapsedTime) {
-  base::TimeDelta elapsed_time;
-  ASSERT_FALSE(timer_.GetElapsedTime(&elapsed_time));
-}
-
-TEST_F(TimerTest, PauseStartStopResume) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(stime2))
-      .WillOnce(Return(etime2))
-      .WillOnce(Return(stime3))
-      .WillOnce(Return(etime3));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Pause());  // Starts timer paused.
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Start());  // Restarts timer.
-  ASSERT_TRUE(timer_.start_time_ == stime2);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Resume());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(kDelta3MSec, elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, ResumeStartStopPause) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(stime2))
-      .WillOnce(Return(etime2))
-      .WillOnce(Return(stime3));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Resume());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime2);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(0, elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartResumeStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_FALSE(timer_.Resume());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseResumeStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime))
-      .WillOnce(Return(stime2))
-      .WillOnce(Return(etime2));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Resume());
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec + kDelta2MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, PauseStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), 0);
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), 0);
-  ASSERT_FALSE(timer_.HasStarted());
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, PauseResumeStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(stime2))
-      .WillOnce(Return(etime2));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Resume());
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta2MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseResumePauseStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime))
-      .WillOnce(Return(stime2))
-      .WillOnce(Return(stime3))
-      .WillOnce(Return(etime3));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Resume());
-  ASSERT_TRUE(timer_.HasStarted());
-  // Make sure GetElapsedTime works while we're running.
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(kDelta1MSec + kStime3MSec - kStime2MSec,
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            kDelta1MSec + kEtime3MSec - kStime2MSec);
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            kDelta1MSec + kEtime3MSec - kStime2MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-TEST_F(TimerTest, StartPauseResumePauseResumeStop) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime))
-      .WillOnce(Return(stime2))
-      .WillOnce(Return(etime2))
-      .WillOnce(Return(stime3))
-      .WillOnce(Return(etime3));
-  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  ASSERT_TRUE(timer_.Start());
-  ASSERT_TRUE(timer_.start_time_ == stime);
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
-  base::TimeDelta elapsed_time;
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Resume());
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Pause());
-  ASSERT_TRUE(timer_.HasStarted());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec + kDelta2MSec);
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-
-  ASSERT_TRUE(timer_.Resume());
-  ASSERT_TRUE(timer_.HasStarted());
-
-  ASSERT_TRUE(timer_.Stop());
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            kDelta1MSec + kDelta2MSec + kDelta3MSec);
-  ASSERT_FALSE(timer_.HasStarted());
-  ASSERT_TRUE(timer_.GetElapsedTime(&elapsed_time));
-  ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(),
-            elapsed_time.InMilliseconds());
-}
-
-static const char kMetricName[] = "test-timer";
-static const int kMinSample = 0;
-static const int kMaxSample = 120 * 1E6;
-static const int kNumBuckets = 50;
-
-class TimerReporterTest : public testing::Test {
- public:
-  TimerReporterTest() : timer_reporter_(kMetricName, kMinSample, kMaxSample,
-                                        kNumBuckets),
-                        clock_wrapper_mock_(new ClockWrapperMock()) {}
-
- protected:
-  virtual void SetUp() {
-    timer_reporter_.set_metrics_lib(&lib_);
-    EXPECT_EQ(timer_reporter_.histogram_name_, kMetricName);
-    EXPECT_EQ(timer_reporter_.min_, kMinSample);
-    EXPECT_EQ(timer_reporter_.max_, kMaxSample);
-    EXPECT_EQ(timer_reporter_.num_buckets_, kNumBuckets);
-    stime += base::TimeDelta::FromMilliseconds(kStime1MSec);
-    etime += base::TimeDelta::FromMilliseconds(kEtime1MSec);
-  }
-
-  virtual void TearDown() {
-    timer_reporter_.set_metrics_lib(nullptr);
-  }
-
-  TimerReporter timer_reporter_;
-  MetricsLibraryMock lib_;
-  std::unique_ptr<ClockWrapperMock> clock_wrapper_mock_;
-  base::TimeTicks stime, etime;
-};
-
-TEST_F(TimerReporterTest, StartStopReport) {
-  EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
-      .WillOnce(Return(stime))
-      .WillOnce(Return(etime));
-  timer_reporter_.clock_wrapper_ = std::move(clock_wrapper_mock_);
-  EXPECT_CALL(lib_, SendToUMA(kMetricName, kDelta1MSec, kMinSample, kMaxSample,
-                              kNumBuckets)).WillOnce(Return(true));
-  ASSERT_TRUE(timer_reporter_.Start());
-  ASSERT_TRUE(timer_reporter_.Stop());
-  ASSERT_TRUE(timer_reporter_.ReportMilliseconds());
-}
-
-TEST_F(TimerReporterTest, InvalidReport) {
-  ASSERT_FALSE(timer_reporter_.ReportMilliseconds());
-}
-
-}  // namespace chromeos_metrics
-
-int main(int argc, char **argv) {
-  testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
diff --git a/metricsd/uploader/bn_metricsd_impl.cc b/metricsd/uploader/bn_metricsd_impl.cc
deleted file mode 100644
index 219ed60..0000000
--- a/metricsd/uploader/bn_metricsd_impl.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/bn_metricsd_impl.h"
-
-#include <base/metrics/histogram.h>
-#include <base/metrics/sparse_histogram.h>
-#include <base/metrics/statistics_recorder.h>
-#include <utils/Errors.h>
-#include <utils/String16.h>
-#include <utils/String8.h>
-
-using android::binder::Status;
-using android::String16;
-
-static const char16_t kCrashTypeKernel[] = u"kernel";
-static const char16_t kCrashTypeUncleanShutdown[] = u"uncleanshutdown";
-static const char16_t kCrashTypeUser[] = u"user";
-
-BnMetricsdImpl::BnMetricsdImpl(const std::shared_ptr<CrashCounters>& counters)
-    : counters_(counters) {
-  CHECK(counters_) << "Invalid counters argument to constructor";
-}
-
-Status BnMetricsdImpl::recordHistogram(
-    const String16& name, int sample, int min, int max, int nbuckets) {
-  base::HistogramBase* histogram = base::Histogram::FactoryGet(
-      android::String8(name).string(), min, max, nbuckets,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  // |histogram| may be null if a client reports two contradicting histograms
-  // with the same name but different limits.
-  // FactoryGet will print a useful message if that is the case.
-  if (histogram) {
-    histogram->Add(sample);
-  }
-  return Status::ok();
-}
-
-Status BnMetricsdImpl::recordLinearHistogram(const String16& name,
-                                             int sample,
-                                             int max) {
-  base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
-      android::String8(name).string(), 1, max, max + 1,
-      base::Histogram::kUmaTargetedHistogramFlag);
-  // |histogram| may be null if a client reports two contradicting histograms
-  // with the same name but different limits.
-  // FactoryGet will print a useful message if that is the case.
-  if (histogram) {
-    histogram->Add(sample);
-  }
-  return Status::ok();
-}
-
-Status BnMetricsdImpl::recordSparseHistogram(const String16& name, int sample) {
-  base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
-      android::String8(name).string(),
-      base::Histogram::kUmaTargetedHistogramFlag);
-  // |histogram| may be null if a client reports two contradicting histograms
-  // with the same name but different limits.
-  // FactoryGet will print a useful message if that is the case.
-  if (histogram) {
-    histogram->Add(sample);
-  }
-  return Status::ok();
-}
-
-Status BnMetricsdImpl::recordCrash(const String16& type) {
-  if (type == kCrashTypeUser) {
-    counters_->IncrementUserCrashCount();
-  } else if (type == kCrashTypeKernel) {
-    counters_->IncrementKernelCrashCount();
-  } else if (type == kCrashTypeUncleanShutdown) {
-    counters_->IncrementUncleanShutdownCount();
-  } else {
-    LOG(ERROR) << "Unknown crash type received: " << type;
-  }
-  return Status::ok();
-}
-
-Status BnMetricsdImpl::getHistogramsDump(String16* dump) {
-  std::string str_dump;
-  base::StatisticsRecorder::WriteGraph(std::string(), &str_dump);
-  *dump = String16(str_dump.c_str());
-  return Status::ok();
-}
diff --git a/metricsd/uploader/bn_metricsd_impl.h b/metricsd/uploader/bn_metricsd_impl.h
deleted file mode 100644
index bf47e80..0000000
--- a/metricsd/uploader/bn_metricsd_impl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
-#define METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
-
-#include "android/brillo/metrics/BnMetricsd.h"
-#include "uploader/crash_counters.h"
-
-class BnMetricsdImpl : public android::brillo::metrics::BnMetricsd {
- public:
-  explicit BnMetricsdImpl(const std::shared_ptr<CrashCounters>& counters);
-  virtual ~BnMetricsdImpl() = default;
-
-  // Records a histogram.
-  android::binder::Status recordHistogram(const android::String16& name,
-                                          int sample,
-                                          int min,
-                                          int max,
-                                          int nbuckets) override;
-
-  // Records a linear histogram.
-  android::binder::Status recordLinearHistogram(const android::String16& name,
-                                                int sample,
-                                                int max) override;
-
-  // Records a sparse histogram.
-  android::binder::Status recordSparseHistogram(const android::String16& name,
-                                                int sample) override;
-
-  // Records a crash.
-  android::binder::Status recordCrash(const android::String16& type) override;
-
-  // Returns a dump of the histograms aggregated in memory.
-  android::binder::Status getHistogramsDump(android::String16* dump) override;
-
- private:
-  std::shared_ptr<CrashCounters> counters_;
-};
-
-#endif  // METRICSD_UPLOADER_BN_METRICSD_IMPL_H_
diff --git a/metricsd/uploader/crash_counters.cc b/metricsd/uploader/crash_counters.cc
deleted file mode 100644
index 1478b9a..0000000
--- a/metricsd/uploader/crash_counters.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/crash_counters.h"
-
-CrashCounters::CrashCounters()
-    : kernel_crashes_(0), unclean_shutdowns_(0), user_crashes_(0) {}
-
-void CrashCounters::IncrementKernelCrashCount() {
-  kernel_crashes_++;
-}
-
-unsigned int CrashCounters::GetAndResetKernelCrashCount() {
-  return kernel_crashes_.exchange(0);
-}
-
-void CrashCounters::IncrementUncleanShutdownCount() {
-  unclean_shutdowns_++;
-}
-
-unsigned int CrashCounters::GetAndResetUncleanShutdownCount() {
-  return unclean_shutdowns_.exchange(0);
-}
-
-void CrashCounters::IncrementUserCrashCount() {
-  user_crashes_++;
-}
-
-unsigned int CrashCounters::GetAndResetUserCrashCount() {
-  return user_crashes_.exchange(0);
-}
diff --git a/metricsd/uploader/crash_counters.h b/metricsd/uploader/crash_counters.h
deleted file mode 100644
index 3fdbf3f..0000000
--- a/metricsd/uploader/crash_counters.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICSD_UPLOADER_CRASH_COUNTERS_H_
-#define METRICSD_UPLOADER_CRASH_COUNTERS_H_
-
-#include <atomic>
-
-// This class is used to keep track of the crash counters.
-// An instance of it will be used by both the binder thread (to increment the
-// counters) and the uploader thread (to gather and reset the counters).
-// As such, the internal counters are atomic uints to allow concurrent access.
-class CrashCounters {
- public:
-  CrashCounters();
-
-  void IncrementKernelCrashCount();
-  unsigned int GetAndResetKernelCrashCount();
-
-  void IncrementUserCrashCount();
-  unsigned int GetAndResetUserCrashCount();
-
-  void IncrementUncleanShutdownCount();
-  unsigned int GetAndResetUncleanShutdownCount();
-
- private:
-  std::atomic_uint kernel_crashes_;
-  std::atomic_uint unclean_shutdowns_;
-  std::atomic_uint user_crashes_;
-};
-
-#endif  // METRICSD_UPLOADER_CRASH_COUNTERS_H_
diff --git a/metricsd/uploader/metrics_hashes.cc b/metricsd/uploader/metrics_hashes.cc
deleted file mode 100644
index 208c560..0000000
--- a/metricsd/uploader/metrics_hashes.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/metrics_hashes.h"
-
-#include "base/logging.h"
-#include "base/md5.h"
-#include "base/sys_byteorder.h"
-
-namespace metrics {
-
-namespace {
-
-// Converts the 8-byte prefix of an MD5 hash into a uint64 value.
-inline uint64_t HashToUInt64(const std::string& hash) {
-  uint64_t value;
-  DCHECK_GE(hash.size(), sizeof(value));
-  memcpy(&value, hash.data(), sizeof(value));
-  return base::HostToNet64(value);
-}
-
-}  // namespace
-
-uint64_t HashMetricName(const std::string& name) {
-  // Create an MD5 hash of the given |name|, represented as a byte buffer
-  // encoded as an std::string.
-  base::MD5Context context;
-  base::MD5Init(&context);
-  base::MD5Update(&context, name);
-
-  base::MD5Digest digest;
-  base::MD5Final(&digest, &context);
-
-  std::string hash_str(reinterpret_cast<char*>(digest.a), arraysize(digest.a));
-  return HashToUInt64(hash_str);
-}
-
-}  // namespace metrics
diff --git a/metricsd/uploader/metrics_hashes.h b/metricsd/uploader/metrics_hashes.h
deleted file mode 100644
index 1082b42..0000000
--- a/metricsd/uploader/metrics_hashes.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_METRICS_HASHES_H_
-#define METRICS_UPLOADER_METRICS_HASHES_H_
-
-#include <string>
-
-namespace metrics {
-
-// Computes a uint64 hash of a given string based on its MD5 hash. Suitable for
-// metric names.
-uint64_t HashMetricName(const std::string& name);
-
-}  // namespace metrics
-
-#endif  // METRICS_UPLOADER_METRICS_HASHES_H_
diff --git a/metricsd/uploader/metrics_hashes_unittest.cc b/metricsd/uploader/metrics_hashes_unittest.cc
deleted file mode 100644
index b8c2575..0000000
--- a/metricsd/uploader/metrics_hashes_unittest.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/metrics_hashes.h"
-
-#include <base/format_macros.h>
-#include <base/macros.h>
-#include <base/strings/stringprintf.h>
-#include <gtest/gtest.h>
-
-namespace metrics {
-
-// Make sure our ID hashes are the same as what we see on the server side.
-TEST(MetricsUtilTest, HashMetricName) {
-  static const struct {
-    std::string input;
-    std::string output;
-  } cases[] = {
-    {"Back", "0x0557fa923dcee4d0"},
-    {"Forward", "0x67d2f6740a8eaebf"},
-    {"NewTab", "0x290eb683f96572f1"},
-  };
-
-  for (size_t i = 0; i < arraysize(cases); ++i) {
-    uint64_t hash = HashMetricName(cases[i].input);
-    std::string hash_hex = base::StringPrintf("0x%016" PRIx64, hash);
-    EXPECT_EQ(cases[i].output, hash_hex);
-  }
-}
-
-}  // namespace metrics
diff --git a/metricsd/uploader/metrics_log.cc b/metricsd/uploader/metrics_log.cc
deleted file mode 100644
index fcaa8c1..0000000
--- a/metricsd/uploader/metrics_log.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/metrics_log.h"
-
-#include <string>
-
-#include <base/files/file_util.h>
-
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/system_profile_setter.h"
-
-// We use default values for the MetricsLogBase constructor as the setter will
-// override them.
-MetricsLog::MetricsLog()
-    : MetricsLogBase("", 0, metrics::MetricsLogBase::ONGOING_LOG, "") {
-}
-
-bool MetricsLog::LoadFromFile(const base::FilePath& saved_log) {
-  std::string encoded_log;
-  if (!base::ReadFileToString(saved_log, &encoded_log)) {
-    LOG(ERROR) << "Failed to read the metrics log backup from "
-               << saved_log.value();
-    return false;
-  }
-
-  if (!uma_proto()->ParseFromString(encoded_log)) {
-    LOG(ERROR) << "Failed to parse log from " << saved_log.value()
-               << ", deleting the log";
-    base::DeleteFile(saved_log, false);
-    uma_proto()->Clear();
-    return false;
-  }
-
-  VLOG(1) << uma_proto()->histogram_event_size() << " histograms loaded from "
-          << saved_log.value();
-
-  return true;
-}
-
-bool MetricsLog::SaveToFile(const base::FilePath& path) {
-  std::string encoded_log;
-  GetEncodedLog(&encoded_log);
-
-  if (static_cast<int>(encoded_log.size()) !=
-      base::WriteFile(path, encoded_log.data(), encoded_log.size())) {
-    LOG(ERROR) << "Failed to persist the current log to " << path.value();
-    return false;
-  }
-  return true;
-}
-
-void MetricsLog::IncrementUserCrashCount(unsigned int count) {
-  metrics::SystemProfileProto::Stability* stability(
-      uma_proto()->mutable_system_profile()->mutable_stability());
-  int current = stability->other_user_crash_count();
-  stability->set_other_user_crash_count(current + count);
-}
-
-void MetricsLog::IncrementKernelCrashCount(unsigned int count) {
-  metrics::SystemProfileProto::Stability* stability(
-      uma_proto()->mutable_system_profile()->mutable_stability());
-  int current = stability->kernel_crash_count();
-  stability->set_kernel_crash_count(current + count);
-}
-
-void MetricsLog::IncrementUncleanShutdownCount(unsigned int count) {
-  metrics::SystemProfileProto::Stability* stability(
-      uma_proto()->mutable_system_profile()->mutable_stability());
-  int current = stability->unclean_system_shutdown_count();
-  stability->set_unclean_system_shutdown_count(current + count);
-}
-
-bool MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
-  CHECK(profile_setter);
-  return profile_setter->Populate(uma_proto());
-}
diff --git a/metricsd/uploader/metrics_log.h b/metricsd/uploader/metrics_log.h
deleted file mode 100644
index 9e60b97..0000000
--- a/metricsd/uploader/metrics_log.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICSD_UPLOADER_METRICS_LOG_H_
-#define METRICSD_UPLOADER_METRICS_LOG_H_
-
-#include <string>
-
-#include <base/files/file_path.h>
-#include <base/macros.h>
-
-#include "uploader/metrics_log_base.h"
-
-// This file defines a set of user experience metrics data recorded by
-// the MetricsService. This is the unit of data that is sent to the server.
-class SystemProfileSetter;
-
-// This class provides base functionality for logging metrics data.
-class MetricsLog : public metrics::MetricsLogBase {
- public:
-  // The constructor doesn't set any metadata. The metadata is only set by a
-  // SystemProfileSetter.
-  MetricsLog();
-
-  // Increment the crash counters in the protobuf.
-  // These methods don't have to be thread safe as metrics logs are only
-  // accessed by the uploader thread.
-  void IncrementUserCrashCount(unsigned int count);
-  void IncrementKernelCrashCount(unsigned int count);
-  void IncrementUncleanShutdownCount(unsigned int count);
-
-  // Populate the system profile with system information using setter.
-  bool PopulateSystemProfile(SystemProfileSetter* setter);
-
-  // Load the log from |path|.
-  bool LoadFromFile(const base::FilePath& path);
-
-  // Save this log to |path|.
-  bool SaveToFile(const base::FilePath& path);
-
- private:
-  friend class UploadServiceTest;
-  FRIEND_TEST(UploadServiceTest, CurrentLogSavedAndResumed);
-  FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
-  FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts);
-  FRIEND_TEST(UploadServiceTest, LogKernelCrash);
-  FRIEND_TEST(UploadServiceTest, LogUncleanShutdown);
-  FRIEND_TEST(UploadServiceTest, LogUserCrash);
-  FRIEND_TEST(UploadServiceTest, UnknownCrashIgnored);
-
-  DISALLOW_COPY_AND_ASSIGN(MetricsLog);
-};
-
-#endif  // METRICSD_UPLOADER_METRICS_LOG_H_
diff --git a/metricsd/uploader/metrics_log_base.cc b/metricsd/uploader/metrics_log_base.cc
deleted file mode 100644
index f23bd63..0000000
--- a/metricsd/uploader/metrics_log_base.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/metrics_log_base.h"
-
-#include <memory>
-
-#include "base/build_time.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_samples.h"
-#include "uploader/metrics_hashes.h"
-#include "uploader/proto/histogram_event.pb.h"
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/proto/user_action_event.pb.h"
-
-using base::Histogram;
-using base::HistogramBase;
-using base::HistogramSamples;
-using base::SampleCountIterator;
-using base::Time;
-using base::TimeDelta;
-using metrics::HistogramEventProto;
-using metrics::SystemProfileProto;
-using metrics::UserActionEventProto;
-
-namespace metrics {
-namespace {
-
-// Any id less than 16 bytes is considered to be a testing id.
-bool IsTestingID(const std::string& id) {
-  return id.size() < 16;
-}
-
-}  // namespace
-
-MetricsLogBase::MetricsLogBase(const std::string& client_id,
-                               int session_id,
-                               LogType log_type,
-                               const std::string& version_string)
-    : num_events_(0),
-      locked_(false),
-      log_type_(log_type) {
-  DCHECK_NE(NO_LOG, log_type);
-  if (IsTestingID(client_id))
-    uma_proto_.set_client_id(0);
-  else
-    uma_proto_.set_client_id(Hash(client_id));
-
-  uma_proto_.set_session_id(session_id);
-  uma_proto_.mutable_system_profile()->set_build_timestamp(GetBuildTime());
-  uma_proto_.mutable_system_profile()->set_app_version(version_string);
-}
-
-MetricsLogBase::~MetricsLogBase() {}
-
-// static
-uint64_t MetricsLogBase::Hash(const std::string& value) {
-  uint64_t hash = metrics::HashMetricName(value);
-
-  // The following log is VERY helpful when folks add some named histogram into
-  // the code, but forgot to update the descriptive list of histograms.  When
-  // that happens, all we get to see (server side) is a hash of the histogram
-  // name.  We can then use this logging to find out what histogram name was
-  // being hashed to a given MD5 value by just running the version of Chromium
-  // in question with --enable-logging.
-  VLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]";
-
-  return hash;
-}
-
-// static
-int64_t MetricsLogBase::GetBuildTime() {
-  static int64_t integral_build_time = 0;
-  if (!integral_build_time) {
-    Time time = base::GetBuildTime();
-    integral_build_time = static_cast<int64_t>(time.ToTimeT());
-  }
-  return integral_build_time;
-}
-
-// static
-int64_t MetricsLogBase::GetCurrentTime() {
-  return (base::TimeTicks::Now() - base::TimeTicks()).InSeconds();
-}
-
-void MetricsLogBase::CloseLog() {
-  DCHECK(!locked_);
-  locked_ = true;
-}
-
-void MetricsLogBase::GetEncodedLog(std::string* encoded_log) {
-  DCHECK(locked_);
-  uma_proto_.SerializeToString(encoded_log);
-}
-
-void MetricsLogBase::RecordUserAction(const std::string& key) {
-  DCHECK(!locked_);
-
-  UserActionEventProto* user_action = uma_proto_.add_user_action_event();
-  user_action->set_name_hash(Hash(key));
-  user_action->set_time(GetCurrentTime());
-
-  ++num_events_;
-}
-
-void MetricsLogBase::RecordHistogramDelta(const std::string& histogram_name,
-                                          const HistogramSamples& snapshot) {
-  DCHECK(!locked_);
-  DCHECK_NE(0, snapshot.TotalCount());
-
-  // We will ignore the MAX_INT/infinite value in the last element of range[].
-
-  HistogramEventProto* histogram_proto = uma_proto_.add_histogram_event();
-  histogram_proto->set_name_hash(Hash(histogram_name));
-  histogram_proto->set_sum(snapshot.sum());
-
-  for (std::unique_ptr<SampleCountIterator> it = snapshot.Iterator(); !it->Done();
-       it->Next()) {
-    HistogramBase::Sample min;
-    HistogramBase::Sample max;
-    HistogramBase::Count count;
-    it->Get(&min, &max, &count);
-    HistogramEventProto::Bucket* bucket = histogram_proto->add_bucket();
-    bucket->set_min(min);
-    bucket->set_max(max);
-    bucket->set_count(count);
-  }
-
-  // Omit fields to save space (see rules in histogram_event.proto comments).
-  for (int i = 0; i < histogram_proto->bucket_size(); ++i) {
-    HistogramEventProto::Bucket* bucket = histogram_proto->mutable_bucket(i);
-    if (i + 1 < histogram_proto->bucket_size() &&
-        bucket->max() == histogram_proto->bucket(i + 1).min()) {
-      bucket->clear_max();
-    } else if (bucket->max() == bucket->min() + 1) {
-      bucket->clear_min();
-    }
-  }
-}
-
-}  // namespace metrics
diff --git a/metricsd/uploader/metrics_log_base.h b/metricsd/uploader/metrics_log_base.h
deleted file mode 100644
index f4e1995..0000000
--- a/metricsd/uploader/metrics_log_base.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-
-// This file defines a set of user experience metrics data recorded by
-// the MetricsService.  This is the unit of data that is sent to the server.
-
-#ifndef METRICS_UPLOADER_METRICS_LOG_BASE_H_
-#define METRICS_UPLOADER_METRICS_LOG_BASE_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/metrics/histogram.h"
-#include "base/time/time.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-
-namespace base {
-class HistogramSamples;
-}  // namespace base
-
-namespace metrics {
-
-// This class provides base functionality for logging metrics data.
-class MetricsLogBase {
- public:
-  // TODO(asvitkine): Remove the NO_LOG value.
-  enum LogType {
-    INITIAL_STABILITY_LOG,  // The initial log containing stability stats.
-    ONGOING_LOG,            // Subsequent logs in a session.
-    NO_LOG,                 // Placeholder value for when there is no log.
-  };
-
-  // Creates a new metrics log of the specified type.
-  // client_id is the identifier for this profile on this installation
-  // session_id is an integer that's incremented on each application launch
-  MetricsLogBase(const std::string& client_id,
-                 int session_id,
-                 LogType log_type,
-                 const std::string& version_string);
-  virtual ~MetricsLogBase();
-
-  // Computes the MD5 hash of the given string, and returns the first 8 bytes of
-  // the hash.
-  static uint64_t Hash(const std::string& value);
-
-  // Get the GMT buildtime for the current binary, expressed in seconds since
-  // January 1, 1970 GMT.
-  // The value is used to identify when a new build is run, so that previous
-  // reliability stats, from other builds, can be abandoned.
-  static int64_t GetBuildTime();
-
-  // Convenience function to return the current time at a resolution in seconds.
-  // This wraps base::TimeTicks, and hence provides an abstract time that is
-  // always incrementing for use in measuring time durations.
-  static int64_t GetCurrentTime();
-
-  // Records a user-initiated action.
-  void RecordUserAction(const std::string& key);
-
-  // Record any changes in a given histogram for transmission.
-  void RecordHistogramDelta(const std::string& histogram_name,
-                            const base::HistogramSamples& snapshot);
-
-  // Stop writing to this record and generate the encoded representation.
-  // None of the Record* methods can be called after this is called.
-  void CloseLog();
-
-  // Fills |encoded_log| with the serialized protobuf representation of the
-  // record.  Must only be called after CloseLog() has been called.
-  void GetEncodedLog(std::string* encoded_log);
-
-  int num_events() { return num_events_; }
-
-  void set_hardware_class(const std::string& hardware_class) {
-    uma_proto_.mutable_system_profile()->mutable_hardware()->set_hardware_class(
-        hardware_class);
-  }
-
-  LogType log_type() const { return log_type_; }
-
- protected:
-  bool locked() const { return locked_; }
-
-  metrics::ChromeUserMetricsExtension* uma_proto() { return &uma_proto_; }
-  const metrics::ChromeUserMetricsExtension* uma_proto() const {
-    return &uma_proto_;
-  }
-
-  // TODO(isherman): Remove this once the XML pipeline is outta here.
-  int num_events_;  // the number of events recorded in this log
-
- private:
-  // locked_ is true when record has been packed up for sending, and should
-  // no longer be written to.  It is only used for sanity checking and is
-  // not a real lock.
-  bool locked_;
-
-  // The type of the log, i.e. initial or ongoing.
-  const LogType log_type_;
-
-  // Stores the protocol buffer representation for this log.
-  metrics::ChromeUserMetricsExtension uma_proto_;
-
-  DISALLOW_COPY_AND_ASSIGN(MetricsLogBase);
-};
-
-}  // namespace metrics
-
-#endif  // METRICS_UPLOADER_METRICS_LOG_BASE_H_
diff --git a/metricsd/uploader/metrics_log_base_unittest.cc b/metricsd/uploader/metrics_log_base_unittest.cc
deleted file mode 100644
index 980afd5..0000000
--- a/metricsd/uploader/metrics_log_base_unittest.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/metrics_log_base.h"
-
-#include <string>
-
-#include <base/metrics/bucket_ranges.h>
-#include <base/metrics/sample_vector.h>
-#include <gtest/gtest.h>
-
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-
-namespace metrics {
-
-namespace {
-
-class TestMetricsLogBase : public MetricsLogBase {
- public:
-  TestMetricsLogBase()
-      : MetricsLogBase("client_id", 1, MetricsLogBase::ONGOING_LOG, "1.2.3.4") {
-  }
-  virtual ~TestMetricsLogBase() {}
-
-  using MetricsLogBase::uma_proto;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestMetricsLogBase);
-};
-
-}  // namespace
-
-TEST(MetricsLogBaseTest, LogType) {
-  MetricsLogBase log1("id", 0, MetricsLogBase::ONGOING_LOG, "1.2.3");
-  EXPECT_EQ(MetricsLogBase::ONGOING_LOG, log1.log_type());
-
-  MetricsLogBase log2("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "1.2.3");
-  EXPECT_EQ(MetricsLogBase::INITIAL_STABILITY_LOG, log2.log_type());
-}
-
-TEST(MetricsLogBaseTest, EmptyRecord) {
-  MetricsLogBase log("totally bogus client ID", 137,
-                     MetricsLogBase::ONGOING_LOG, "bogus version");
-  log.set_hardware_class("sample-class");
-  log.CloseLog();
-
-  std::string encoded;
-  log.GetEncodedLog(&encoded);
-
-  // A couple of fields are hard to mock, so these will be copied over directly
-  // for the expected output.
-  metrics::ChromeUserMetricsExtension parsed;
-  ASSERT_TRUE(parsed.ParseFromString(encoded));
-
-  metrics::ChromeUserMetricsExtension expected;
-  expected.set_client_id(5217101509553811875);  // Hashed bogus client ID
-  expected.set_session_id(137);
-  expected.mutable_system_profile()->set_build_timestamp(
-      parsed.system_profile().build_timestamp());
-  expected.mutable_system_profile()->set_app_version("bogus version");
-  expected.mutable_system_profile()->mutable_hardware()->set_hardware_class(
-      "sample-class");
-
-  EXPECT_EQ(expected.SerializeAsString(), encoded);
-}
-
-TEST(MetricsLogBaseTest, HistogramBucketFields) {
-  // Create buckets: 1-5, 5-7, 7-8, 8-9, 9-10, 10-11, 11-12.
-  base::BucketRanges ranges(8);
-  ranges.set_range(0, 1);
-  ranges.set_range(1, 5);
-  ranges.set_range(2, 7);
-  ranges.set_range(3, 8);
-  ranges.set_range(4, 9);
-  ranges.set_range(5, 10);
-  ranges.set_range(6, 11);
-  ranges.set_range(7, 12);
-
-  base::SampleVector samples(&ranges);
-  samples.Accumulate(3, 1);   // Bucket 1-5.
-  samples.Accumulate(6, 1);   // Bucket 5-7.
-  samples.Accumulate(8, 1);   // Bucket 8-9. (7-8 skipped)
-  samples.Accumulate(10, 1);  // Bucket 10-11. (9-10 skipped)
-  samples.Accumulate(11, 1);  // Bucket 11-12.
-
-  TestMetricsLogBase log;
-  log.RecordHistogramDelta("Test", samples);
-
-  const metrics::ChromeUserMetricsExtension* uma_proto = log.uma_proto();
-  const metrics::HistogramEventProto& histogram_proto =
-      uma_proto->histogram_event(uma_proto->histogram_event_size() - 1);
-
-  // Buckets with samples: 1-5, 5-7, 8-9, 10-11, 11-12.
-  // Should become: 1-/, 5-7, /-9, 10-/, /-12.
-  ASSERT_EQ(5, histogram_proto.bucket_size());
-
-  // 1-5 becomes 1-/ (max is same as next min).
-  EXPECT_TRUE(histogram_proto.bucket(0).has_min());
-  EXPECT_FALSE(histogram_proto.bucket(0).has_max());
-  EXPECT_EQ(1, histogram_proto.bucket(0).min());
-
-  // 5-7 stays 5-7 (no optimization possible).
-  EXPECT_TRUE(histogram_proto.bucket(1).has_min());
-  EXPECT_TRUE(histogram_proto.bucket(1).has_max());
-  EXPECT_EQ(5, histogram_proto.bucket(1).min());
-  EXPECT_EQ(7, histogram_proto.bucket(1).max());
-
-  // 8-9 becomes /-9 (min is same as max - 1).
-  EXPECT_FALSE(histogram_proto.bucket(2).has_min());
-  EXPECT_TRUE(histogram_proto.bucket(2).has_max());
-  EXPECT_EQ(9, histogram_proto.bucket(2).max());
-
-  // 10-11 becomes 10-/ (both optimizations apply, omit max is prioritized).
-  EXPECT_TRUE(histogram_proto.bucket(3).has_min());
-  EXPECT_FALSE(histogram_proto.bucket(3).has_max());
-  EXPECT_EQ(10, histogram_proto.bucket(3).min());
-
-  // 11-12 becomes /-12 (last record must keep max, min is same as max - 1).
-  EXPECT_FALSE(histogram_proto.bucket(4).has_min());
-  EXPECT_TRUE(histogram_proto.bucket(4).has_max());
-  EXPECT_EQ(12, histogram_proto.bucket(4).max());
-}
-
-}  // namespace metrics
diff --git a/metricsd/uploader/metricsd_service_runner.cc b/metricsd/uploader/metricsd_service_runner.cc
deleted file mode 100644
index 4361cac..0000000
--- a/metricsd/uploader/metricsd_service_runner.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/metricsd_service_runner.h"
-
-#include <thread>
-
-#include <binder/IServiceManager.h>
-#include <brillo/binder_watcher.h>
-#include <brillo/message_loops/base_message_loop.h>
-#include <utils/Errors.h>
-
-#include "uploader/bn_metricsd_impl.h"
-
-MetricsdServiceRunner::MetricsdServiceRunner(
-    std::shared_ptr<CrashCounters> counters)
-    : counters_(counters) {}
-
-void MetricsdServiceRunner::Start() {
-  thread_.reset(new std::thread(&MetricsdServiceRunner::Run, this));
-}
-
-void MetricsdServiceRunner::Run() {
-  android::sp<BnMetricsdImpl> metrics_service(new BnMetricsdImpl(counters_));
-
-  android::status_t status = android::defaultServiceManager()->addService(
-      metrics_service->getInterfaceDescriptor(), metrics_service);
-  CHECK(status == android::OK) << "Metricsd service registration failed";
-
-  message_loop_for_io_.reset(new base::MessageLoopForIO);
-  message_loop_.reset(new brillo::BaseMessageLoop(message_loop_for_io_.get()));
-
-  brillo::BinderWatcher watcher(message_loop_.get());
-  CHECK(watcher.Init()) << "failed to initialize the binder file descriptor "
-                        << "watcher";
-
-  message_loop_->Run();
-
-  // Delete the message loop here as it needs to be deconstructed in the thread
-  // it is attached to.
-  message_loop_.reset();
-  message_loop_for_io_.reset();
-}
-
-void MetricsdServiceRunner::Stop() {
-  message_loop_for_io_->PostTask(FROM_HERE,
-                                 message_loop_for_io_->QuitWhenIdleClosure());
-
-  thread_->join();
-}
diff --git a/metricsd/uploader/metricsd_service_runner.h b/metricsd/uploader/metricsd_service_runner.h
deleted file mode 100644
index b36d4a5..0000000
--- a/metricsd/uploader/metricsd_service_runner.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_METRISCD_SERVICE_RUNNER_H_
-#define METRICS_UPLOADER_METRISCD_SERVICE_RUNNER_H_
-
-#include <memory>
-#include <thread>
-
-#include <base/message_loop/message_loop.h>
-#include <brillo/message_loops/message_loop.h>
-
-#include "uploader/crash_counters.h"
-
-class MetricsdServiceRunner {
- public:
-  explicit MetricsdServiceRunner(std::shared_ptr<CrashCounters> counters);
-
-  // Start the Metricsd Binder service in a new thread.
-  void Start();
-
-  // Stop the Metricsd service and wait for its thread to exit.
-  void Stop();
-
- private:
-  // Creates and run the main loop for metricsd's Binder service.
-  void Run();
-
-  std::unique_ptr<base::MessageLoopForIO> message_loop_for_io_;
-  std::unique_ptr<brillo::MessageLoop> message_loop_;
-
-  std::unique_ptr<std::thread> thread_;
-  std::shared_ptr<CrashCounters> counters_;
-};
-
-#endif  // METRICS_UPLOADER_METRISCD_SERVICE_RUNNER_H_
diff --git a/metricsd/uploader/mock/mock_system_profile_setter.h b/metricsd/uploader/mock/mock_system_profile_setter.h
deleted file mode 100644
index 9b20291..0000000
--- a/metricsd/uploader/mock/mock_system_profile_setter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
-#define METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
-
-#include "uploader/system_profile_setter.h"
-
-namespace metrics {
-class ChromeUserMetricsExtension;
-}
-
-// Mock profile setter used for testing.
-class MockSystemProfileSetter : public SystemProfileSetter {
- public:
-  bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) override {
-    return true;
-  }
-};
-
-#endif  // METRICS_UPLOADER_MOCK_MOCK_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/mock/sender_mock.cc b/metricsd/uploader/mock/sender_mock.cc
deleted file mode 100644
index bb4dc7d..0000000
--- a/metricsd/uploader/mock/sender_mock.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/mock/sender_mock.h"
-
-SenderMock::SenderMock() {
-  Reset();
-}
-
-bool SenderMock::Send(const std::string& content, const std::string& hash) {
-  send_call_count_ += 1;
-  last_message_ = content;
-  is_good_proto_ = last_message_proto_.ParseFromString(content);
-  return should_succeed_;
-}
-
-void SenderMock::Reset() {
-  send_call_count_ = 0;
-  last_message_ = "";
-  should_succeed_ = true;
-  last_message_proto_.Clear();
-  is_good_proto_ = false;
-}
diff --git a/metricsd/uploader/mock/sender_mock.h b/metricsd/uploader/mock/sender_mock.h
deleted file mode 100644
index e79233f..0000000
--- a/metricsd/uploader/mock/sender_mock.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
-#define METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-#include "uploader/sender.h"
-
-class SenderMock : public Sender {
- public:
-  SenderMock();
-
-  bool Send(const std::string& content, const std::string& hash) override;
-  void Reset();
-
-  bool is_good_proto() { return is_good_proto_; }
-  int send_call_count() { return send_call_count_; }
-  const std::string last_message() { return last_message_; }
-  metrics::ChromeUserMetricsExtension last_message_proto() {
-    return last_message_proto_;
-  }
-  void set_should_succeed(bool succeed) { should_succeed_ = succeed; }
-
- private:
-  // Is set to true if the proto was parsed successfully.
-  bool is_good_proto_;
-
-  // If set to true, the Send method will return true to simulate a successful
-  // send.
-  bool should_succeed_;
-
-  // Count of how many times Send was called since the last reset.
-  int send_call_count_;
-
-  // Last message received by Send.
-  std::string last_message_;
-
-  // If is_good_proto is true, last_message_proto is the deserialized
-  // representation of last_message.
-  metrics::ChromeUserMetricsExtension last_message_proto_;
-};
-
-#endif  // METRICS_UPLOADER_MOCK_SENDER_MOCK_H_
diff --git a/metricsd/uploader/proto/README b/metricsd/uploader/proto/README
deleted file mode 100644
index 4292a40..0000000
--- a/metricsd/uploader/proto/README
+++ /dev/null
@@ -1,37 +0,0 @@
-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.
-
-
-
-
-This directory contains the protocol buffers used by the standalone metrics
-uploader. Those protobuffers are copied from the chromium protobuffers from
-https://chromium.googlesource.com/chromium/src/+/master/components/metrics/proto/
-at 3bfe5f2b4c03d2cac718d137ed14cd2c6354bfed.
-
-Any change to this protobuf must first be made to the backend's protobuf and be
-compatible with the chromium protobuffers.
-
-
-Q: Why fork the chromium protobuffers ?
-A: The standalone metrics uploader needs chromium os fields that are not defined
-by the chromium protobufs. Instead of pushing chromium os specific changes to
-chromium, we can add them only to chromium os (and to the backend of course).
-
-
-Q: What's the difference between those protobuffers and chromium's protobuffers?
-A: When the protobuffers were copied, some chromium specific protobuffers were
-not imported:
-* omnibox related protobuffers.
-* performance profiling protobuffers (not used in chromium os).
diff --git a/metricsd/uploader/proto/chrome_user_metrics_extension.proto b/metricsd/uploader/proto/chrome_user_metrics_extension.proto
deleted file mode 100644
index a07830f..0000000
--- a/metricsd/uploader/proto/chrome_user_metrics_extension.proto
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-//
-// Protocol buffer for Chrome UMA (User Metrics Analysis).
-//
-// Note: this protobuf must be compatible with the one in chromium.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "ChromeUserMetricsExtensionProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-import "system/core/metricsd/uploader/proto/histogram_event.proto";
-import "system/core/metricsd/uploader/proto/system_profile.proto";
-import "system/core/metricsd/uploader/proto/user_action_event.proto";
-
-// Next tag: 13
-message ChromeUserMetricsExtension {
-  // The product (i.e. end user application) for a given UMA log.
-  enum Product {
-    // Google Chrome product family.
-    CHROME = 0;
-  }
-  // The product corresponding to this log. The field type is int32 instead of
-  // Product so that downstream users of the Chromium metrics component can
-  // introduce products without needing to make changes to the Chromium code
-  // (though they still need to add the new product to the server-side enum).
-  // Note: The default value is Chrome, so Chrome products will not transmit
-  // this field.
-  optional int32 product = 10 [default = 0];
-
-  // The id of the client install that generated these events.
-  //
-  // For Chrome clients, this id is unique to a top-level (one level above the
-  // "Default" directory) Chrome user data directory [1], and so is shared among
-  // all Chrome user profiles contained in this user data directory.
-  // An id of 0 is reserved for test data (monitoring and internal testing) and
-  // should normally be ignored in analysis of the data.
-  // [1] http://www.chromium.org/user-experience/user-data-directory
-  optional fixed64 client_id = 1;
-
-  // The session id for this user.
-  // Values such as tab ids are only meaningful within a particular session.
-  // The client keeps track of the session id and sends it with each event.
-  // The session id is simply an integer that is incremented each time the user
-  // relaunches Chrome.
-  optional int32 session_id = 2;
-
-  // Information about the user's browser and system configuration.
-  optional SystemProfileProto system_profile = 3;
-
-  // This message will log one or more of the following event types:
-  repeated UserActionEventProto user_action_event = 4;
-  repeated HistogramEventProto histogram_event = 6;
-
-}
diff --git a/metricsd/uploader/proto/histogram_event.proto b/metricsd/uploader/proto/histogram_event.proto
deleted file mode 100644
index 3825063..0000000
--- a/metricsd/uploader/proto/histogram_event.proto
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-//
-// Histogram-collected metrics.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "HistogramEventProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-// Next tag: 4
-message HistogramEventProto {
-  // The name of the histogram, hashed.
-  optional fixed64 name_hash = 1;
-
-  // The sum of all the sample values.
-  // Together with the total count of the sample values, this allows us to
-  // compute the average value.  The count of all sample values is just the sum
-  // of the counts of all the buckets.
-  optional int64 sum = 2;
-
-  // The per-bucket data.
-  message Bucket {
-    // Each bucket's range is bounded by min <= x < max.
-    // It is valid to omit one of these two fields in a bucket, but not both.
-    // If the min field is omitted, its value is assumed to be equal to max - 1.
-    // If the max field is omitted, its value is assumed to be equal to the next
-    // bucket's min value (possibly computed per above).  The last bucket in a
-    // histogram should always include the max field.
-    optional int64 min = 1;
-    optional int64 max = 2;
-
-    // The bucket's index in the list of buckets, sorted in ascending order.
-    // This field was intended to provide extra redundancy to detect corrupted
-    // records, but was never used.  As of M31, it is no longer sent by Chrome
-    // clients to reduce the UMA upload size.
-    optional int32 bucket_index = 3 [deprecated = true];
-
-    // The number of entries in this bucket.
-    optional int64 count = 4;
-  }
-  repeated Bucket bucket = 3;
-}
diff --git a/metricsd/uploader/proto/system_profile.proto b/metricsd/uploader/proto/system_profile.proto
deleted file mode 100644
index bac828b..0000000
--- a/metricsd/uploader/proto/system_profile.proto
+++ /dev/null
@@ -1,759 +0,0 @@
-/*
- * 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.
- */
-//
-// Stores information about the user's brower and system configuration.
-// The system configuration fields are recorded once per client session.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "SystemProfileProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-// Next tag: 21
-message SystemProfileProto {
-  // The time when the client was compiled/linked, in seconds since the epoch.
-  optional int64 build_timestamp = 1;
-
-  // A version number string for the application.
-  // Most commonly this is the browser version number found in a user agent
-  // string, and is typically a 4-tuple of numbers separated by periods.  In
-  // cases where the user agent version might be ambiguous (example: Linux 64-
-  // bit build, rather than 32-bit build, or a Windows version used in some
-  // special context, such as ChromeFrame running in IE), then this may include
-  // some additional postfix to provide clarification not available in the UA
-  // string.
-  //
-  // An example of a browser version 4-tuple is "5.0.322.0".  Currently used
-  // postfixes are:
-  //
-  //   "-64": a 64-bit build
-  //   "-F": Chrome is running under control of ChromeFrame
-  //   "-devel": this is not an official build of Chrome
-  //
-  // A full version number string could look similar to:
-  // "5.0.322.0-F-devel".
-  //
-  // This value, when available, is more trustworthy than the UA string
-  // associated with the request; and including the postfix, may be more
-  // specific.
-  optional string app_version = 2;
-
-  // The brand code or distribution tag assigned to a partner, if available.
-  // Brand codes are only available on Windows.  Not every Windows install
-  // though will have a brand code.
-  optional string brand_code = 12;
-
-  // The possible channels for an installation, from least to most stable.
-  enum Channel {
-    CHANNEL_UNKNOWN = 0;  // Unknown channel -- perhaps an unofficial build?
-    CHANNEL_CANARY = 1;
-    CHANNEL_DEV = 2;
-    CHANNEL_BETA = 3;
-    CHANNEL_STABLE = 4;
-  }
-  optional Channel channel = 10;
-
-  // True if Chrome build is ASan-instrumented.
-  optional bool is_asan_build = 20 [default = false];
-
-  // The date the user enabled UMA, in seconds since the epoch.
-  // If the user has toggled the UMA enabled state multiple times, this will
-  // be the most recent date on which UMA was enabled.
-  // For privacy, this is rounded to the nearest hour.
-  optional int64 uma_enabled_date = 3;
-
-  // The time when the client was installed, in seconds since the epoch.
-  // For privacy, this is rounded to the nearest hour.
-  optional int64 install_date = 16;
-
-  // The user's selected application locale, i.e. the user interface language.
-  // The locale includes a language code and, possibly, also a country code,
-  // e.g. "en-US".
-  optional string application_locale = 4;
-
-  message BrilloDeviceData {
-    optional string product_id = 1;
-  }
-  optional BrilloDeviceData brillo = 21;
-
-  // Information on the user's operating system.
-  message OS {
-    // The user's operating system. This should be one of:
-    // - Android
-    // - Windows NT
-    // - Linux (includes ChromeOS)
-    // - iPhone OS
-    // - Mac OS X
-    optional string name = 1;
-
-    // The version of the OS.  The meaning of this field is OS-dependent.
-    optional string version = 2;
-
-    // The fingerprint of the build.  This field is used only on Android.
-    optional string fingerprint = 3;
-
-    // Whether the version of iOS appears to be "jailbroken". This field is
-    // used only on iOS. Chrome for iOS detects whether device contains a
-    // DynamicLibraries/ directory. It's a necessary but insufficient indicator
-    // of whether the operating system has been jailbroken.
-    optional bool is_jailbroken = 4;
-  }
-  optional OS os = 5;
-
-  // Next tag for Hardware: 18
-  // Information on the user's hardware.
-  message Hardware {
-    // The CPU architecture (x86, PowerPC, x86_64, ...)
-    optional string cpu_architecture = 1;
-
-    // The amount of RAM present on the system, in megabytes.
-    optional int64 system_ram_mb = 2;
-
-    // The base memory address that chrome.dll was loaded at.
-    // (Logged only on Windows.)
-    optional int64 dll_base = 3;
-
-    // The Chrome OS device hardware class ID is a unique string associated with
-    // each Chrome OS device product revision generally assigned at hardware
-    // qualification time.  The hardware class effectively identifies the
-    // configured system components such as CPU, WiFi adapter, etc.
-    //
-    // An example of such a hardware class is "IEC MARIO PONY 6101".  An
-    // internal database associates this hardware class with the qualified
-    // device specifications including OEM information, schematics, hardware
-    // qualification reports, test device tags, etc.
-    optional string hardware_class = 4;
-
-    // The number of physical screens.
-    optional int32 screen_count = 5;
-
-    // The screen dimensions of the primary screen, in pixels.
-    optional int32 primary_screen_width = 6;
-    optional int32 primary_screen_height = 7;
-
-    // The device scale factor of the primary screen.
-    optional float primary_screen_scale_factor = 12;
-
-    // Max DPI for any attached screen. (Windows only)
-    optional float max_dpi_x = 9;
-    optional float max_dpi_y = 10;
-
-    // Information on the CPU obtained by CPUID.
-    message CPU {
-      // A 12 character string naming the vendor, e.g. "GeniuneIntel".
-      optional string vendor_name = 1;
-
-      // The signature reported by CPUID (from EAX).
-      optional uint32 signature = 2;
-
-      // Number of logical processors/cores on the current machine.
-      optional uint32 num_cores = 3;
-    }
-    optional CPU cpu = 13;
-
-    // Information on the GPU
-    message Graphics {
-      // The GPU manufacturer's vendor id.
-      optional uint32 vendor_id = 1;
-
-      // The GPU manufacturer's device id for the chip set.
-      optional uint32 device_id = 2;
-
-      // The driver version on the GPU.
-      optional string driver_version = 3;
-
-      // The driver date on the GPU.
-      optional string driver_date = 4;
-
-      // The GL_VENDOR string. An example of a gl_vendor string is
-      // "Imagination Technologies". "" if we are not using OpenGL.
-      optional string gl_vendor = 6;
-
-      // The GL_RENDERER string. An example of a gl_renderer string is
-      // "PowerVR SGX 540". "" if we are not using OpenGL.
-      optional string gl_renderer = 7;
-    }
-    optional Graphics gpu = 8;
-
-    // Information about Bluetooth devices paired with the system.
-    message Bluetooth {
-      // Whether Bluetooth is present on this system.
-      optional bool is_present = 1;
-
-      // Whether Bluetooth is enabled on this system.
-      optional bool is_enabled = 2;
-
-      // Describes a paired device.
-      message PairedDevice {
-        // Assigned class of the device. This is a bitfield according to the
-        // Bluetooth specification available at the following URL:
-        // https://www.bluetooth.org/en-us/specification/assigned-numbers-overview/baseband
-        optional uint32 bluetooth_class = 1;
-
-        // Decoded device type.
-        enum Type {
-          DEVICE_UNKNOWN = 0;
-          DEVICE_COMPUTER = 1;
-          DEVICE_PHONE = 2;
-          DEVICE_MODEM = 3;
-          DEVICE_AUDIO = 4;
-          DEVICE_CAR_AUDIO = 5;
-          DEVICE_VIDEO = 6;
-          DEVICE_PERIPHERAL = 7;
-          DEVICE_JOYSTICK = 8;
-          DEVICE_GAMEPAD = 9;
-          DEVICE_KEYBOARD = 10;
-          DEVICE_MOUSE = 11;
-          DEVICE_TABLET = 12;
-          DEVICE_KEYBOARD_MOUSE_COMBO = 13;
-        }
-        optional Type type = 2;
-
-        // Vendor prefix of the Bluetooth address, these are OUI registered by
-        // the IEEE and are encoded with the first byte in bits 16-23, the
-        // second byte in bits 8-15 and the third byte in bits 0-7.
-        //
-        // ie. Google's OUI (00:1A:11) is encoded as 0x00001A11
-        optional uint32 vendor_prefix = 4;
-
-        // The Vendor ID of a device, returned in vendor_id below, can be
-        // either allocated by the Bluetooth SIG or USB IF, providing two
-        // completely overlapping namespaces for identifiers.
-        //
-        // This field should be read along with vendor_id to correctly
-        // identify the vendor. For example Google is identified by either
-        // vendor_id_source = VENDOR_ID_BLUETOOTH, vendor_id = 0x00E0 or
-        // vendor_id_source = VENDOR_ID_USB, vendor_id = 0x18D1.
-        //
-        // If the device does not support the Device ID specification the
-        // unknown value will be set.
-        enum VendorIDSource {
-          VENDOR_ID_UNKNOWN = 0;
-          VENDOR_ID_BLUETOOTH = 1;
-          VENDOR_ID_USB = 2;
-        }
-        optional VendorIDSource vendor_id_source = 8;
-
-        // Vendor ID of the device, where available.
-        optional uint32 vendor_id = 5;
-
-        // Product ID of the device, where available.
-        optional uint32 product_id = 6;
-
-        // Device ID of the device, generally the release or version number in
-        // BCD format, where available.
-        optional uint32 device_id = 7;
-      }
-      repeated PairedDevice paired_device = 3;
-    }
-    optional Bluetooth bluetooth = 11;
-
-    // Whether the internal display produces touch events. Omitted if unknown.
-    // Logged on ChromeOS only.
-    optional bool internal_display_supports_touch = 14;
-
-    // Vendor ids and product ids of external touchscreens.
-    message TouchScreen {
-      // Touch screen vendor id.
-      optional uint32 vendor_id = 1;
-      // Touch screen product id.
-      optional uint32 product_id = 2;
-    }
-    // Lists vendor and product ids of external touchscreens.
-    // Logged on ChromeOS only.
-    repeated TouchScreen external_touchscreen = 15;
-
-    // Drive messages are currently logged on Windows 7+, iOS, and Android.
-    message Drive {
-      // Whether this drive incurs a time penalty when randomly accessed. This
-      // should be true for spinning disks but false for SSDs or other
-      // flash-based drives.
-      optional bool has_seek_penalty = 1;
-    }
-    // The drive that the application executable was loaded from.
-    optional Drive app_drive = 16;
-    // The drive that the current user data directory was loaded from.
-    optional Drive user_data_drive = 17;
-  }
-  optional Hardware hardware = 6;
-
-  // Information about the network connection.
-  message Network {
-    // Set to true if connection_type changed during the lifetime of the log.
-    optional bool connection_type_is_ambiguous = 1;
-
-    // See net::NetworkChangeNotifier::ConnectionType.
-    enum ConnectionType {
-      CONNECTION_UNKNOWN = 0;
-      CONNECTION_ETHERNET = 1;
-      CONNECTION_WIFI = 2;
-      CONNECTION_2G = 3;
-      CONNECTION_3G = 4;
-      CONNECTION_4G = 5;
-      CONNECTION_BLUETOOTH = 6;
-    }
-    // The connection type according to NetworkChangeNotifier.
-    optional ConnectionType connection_type = 2;
-
-    // Set to true if wifi_phy_layer_protocol changed during the lifetime of the log.
-    optional bool wifi_phy_layer_protocol_is_ambiguous = 3;
-
-    // See net::WifiPHYLayerProtocol.
-    enum WifiPHYLayerProtocol {
-      WIFI_PHY_LAYER_PROTOCOL_NONE = 0;
-      WIFI_PHY_LAYER_PROTOCOL_ANCIENT = 1;
-      WIFI_PHY_LAYER_PROTOCOL_A = 2;
-      WIFI_PHY_LAYER_PROTOCOL_B = 3;
-      WIFI_PHY_LAYER_PROTOCOL_G = 4;
-      WIFI_PHY_LAYER_PROTOCOL_N = 5;
-      WIFI_PHY_LAYER_PROTOCOL_UNKNOWN = 6;
-    }
-    // The physical layer mode of the associated wifi access point, if any.
-    optional WifiPHYLayerProtocol wifi_phy_layer_protocol = 4;
-
-    // Describe wifi access point information.
-    message WifiAccessPoint {
-      // Vendor prefix of the access point's BSSID, these are OUIs
-      // (Organizationally Unique Identifiers) registered by
-      // the IEEE and are encoded with the first byte in bits 16-23, the
-      // second byte in bits 8-15 and the third byte in bits 0-7.
-      optional uint32 vendor_prefix = 1;
-
-      // Access point seurity mode definitions.
-      enum SecurityMode {
-        SECURITY_UNKNOWN = 0;
-        SECURITY_WPA = 1;
-        SECURITY_WEP = 2;
-        SECURITY_RSN = 3;
-        SECURITY_802_1X = 4;
-        SECURITY_PSK = 5;
-        SECURITY_NONE = 6;
-      }
-      // The security mode of the access point.
-      optional SecurityMode security_mode = 2;
-
-      // Vendor specific information.
-      message VendorInformation {
-        // The model number, for example "0".
-        optional string model_number = 1;
-
-        // The model name (sometimes the same as the model_number),
-        // for example "WZR-HP-AG300H".
-        optional string model_name = 2;
-
-        // The device name (sometimes the same as the model_number),
-        // for example "Dummynet"
-        optional string device_name = 3;
-
-        // The list of vendor-specific OUIs (Organziationally Unqiue
-        // Identifiers). These are provided by the vendor through WPS
-        // (Wireless Provisioning Service) information elements, which
-        // identifies the content of the element.
-        repeated uint32 element_identifier = 4;
-      }
-      // The wireless access point vendor information.
-      optional VendorInformation vendor_info = 3;
-    }
-    // Information of the wireless AP that device is connected to.
-    optional WifiAccessPoint access_point_info = 5;
-  }
-  optional Network network = 13;
-
-  // Information on the Google Update install that is managing this client.
-  message GoogleUpdate {
-    // Whether the Google Update install is system-level or user-level.
-    optional bool is_system_install = 1;
-
-    // The date at which Google Update last started performing an automatic
-    // update check, in seconds since the Unix epoch.
-    optional int64 last_automatic_start_timestamp = 2;
-
-    // The date at which Google Update last successfully sent an update check
-    // and recieved an intact response from the server, in seconds since the
-    // Unix epoch. (The updates don't need to be successfully installed.)
-    optional int64 last_update_check_timestamp = 3;
-
-    // Describes a product being managed by Google Update. (This can also
-    // describe Google Update itself.)
-    message ProductInfo {
-      // The current version of the product that is installed.
-      optional string version = 1;
-
-      // The date at which Google Update successfully updated this product,
-      // stored in seconds since the Unix epoch.  This is updated when an update
-      // is successfully applied, or if the server reports that no update
-      // is available.
-      optional int64 last_update_success_timestamp = 2;
-
-      // The result reported by the product updater on its last run.
-      enum InstallResult {
-        INSTALL_RESULT_SUCCESS = 0;
-        INSTALL_RESULT_FAILED_CUSTOM_ERROR = 1;
-        INSTALL_RESULT_FAILED_MSI_ERROR = 2;
-        INSTALL_RESULT_FAILED_SYSTEM_ERROR = 3;
-        INSTALL_RESULT_EXIT_CODE = 4;
-      }
-      optional InstallResult last_result = 3;
-
-      // The error code reported by the product updater on its last run.  This
-      // will typically be a error code specific to the product installer.
-      optional int32 last_error = 4;
-
-      // The extra error code reported by the product updater on its last run.
-      // This will typically be a Win32 error code.
-      optional int32 last_extra_error = 5;
-    }
-    optional ProductInfo google_update_status = 4;
-    optional ProductInfo client_status = 5;
-  }
-  optional GoogleUpdate google_update = 11;
-
-  // Information on all installed plugins.
-  message Plugin {
-    // The plugin's self-reported name and filename (without path).
-    optional string name = 1;
-    optional string filename = 2;
-
-    // The plugin's version.
-    optional string version = 3;
-
-    // True if the plugin is disabled.
-    // If a client has multiple local Chrome user accounts, this is logged based
-    // on the first user account launched during the current session.
-    optional bool is_disabled = 4;
-
-    // True if the plugin is PPAPI.
-    optional bool is_pepper = 5;
-  }
-  repeated Plugin plugin = 7;
-
-  // Figures that can be used to generate application stability metrics.
-  // All values are counts of events since the last time that these
-  // values were reported.
-  // Next tag: 24
-  message Stability {
-    // Total amount of time that the program was running, in seconds,
-    // since the last time a log was recorded, as measured using a client-side
-    // clock implemented via TimeTicks, which guarantees that it is monotonic
-    // and does not jump if the user changes his/her clock.  The TimeTicks
-    // implementation also makes the clock not count time the computer is
-    // suspended.
-    optional int64 incremental_uptime_sec = 1;
-
-    // Total amount of time that the program was running, in seconds,
-    // since startup, as measured using a client-side clock implemented
-    // via TimeTicks, which guarantees that it is monotonic and does not
-    // jump if the user changes his/her clock.  The TimeTicks implementation
-    // also makes the clock not count time the computer is suspended.
-    // This field was added for M-35.
-    optional int64 uptime_sec = 23;
-
-    // Page loads along with renderer crashes and hangs, since page load count
-    // roughly corresponds to usage.
-    optional int32 page_load_count = 2;
-    optional int32 renderer_crash_count = 3;
-    optional int32 renderer_hang_count = 4;
-
-    // Number of renderer crashes that were for extensions. These crashes are
-    // not counted in renderer_crash_count.
-    optional int32 extension_renderer_crash_count = 5;
-
-    // Number of non-renderer child process crashes.
-    optional int32 child_process_crash_count = 6;
-
-    // Number of times the browser has crashed while logged in as the "other
-    // user" (guest) account.
-    // Logged on ChromeOS only.
-    optional int32 other_user_crash_count = 7;
-
-    // Number of times the kernel has crashed.
-    // Logged on ChromeOS only.
-    optional int32 kernel_crash_count = 8;
-
-    // Number of times the system has shut down uncleanly.
-    // Logged on ChromeOS only.
-    optional int32 unclean_system_shutdown_count = 9;
-
-    //
-    // All the remaining fields in the Stability are recorded at most once per
-    // client session.
-    //
-
-    // The number of times the program was launched.
-    // This will typically be equal to 1.  However, it is possible that Chrome
-    // was unable to upload stability metrics for previous launches (e.g. due to
-    // crashing early during startup), and hence this value might be greater
-    // than 1.
-    optional int32 launch_count = 15;
-    // The number of times that it didn't exit cleanly (which we assume to be
-    // mostly crashes).
-    optional int32 crash_count = 16;
-
-    // The number of times the program began, but did not complete, the shutdown
-    // process.  (For example, this may occur when Windows is shutting down, and
-    // it only gives the process a few seconds to clean up.)
-    optional int32 incomplete_shutdown_count = 17;
-
-    // The number of times the program was able register with breakpad crash
-    // services.
-    optional int32 breakpad_registration_success_count = 18;
-
-    // The number of times the program failed to register with breakpad crash
-    // services.  If crash registration fails then when the program crashes no
-    // crash report will be generated.
-    optional int32 breakpad_registration_failure_count = 19;
-
-    // The number of times the program has run under a debugger.  This should
-    // be an exceptional condition.  Running under a debugger prevents crash
-    // dumps from being generated.
-    optional int32 debugger_present_count = 20;
-
-    // The number of times the program has run without a debugger attached.
-    // This should be most common scenario and should be very close to
-    // |launch_count|.
-    optional int32 debugger_not_present_count = 21;
-
-    // Stability information for all installed plugins.
-    message PluginStability {
-      // The relevant plugin's information (name, etc.)
-      optional Plugin plugin = 1;
-
-      // The number of times this plugin's process was launched.
-      optional int32 launch_count = 2;
-
-      // The number of times this plugin was instantiated on a web page.
-      // This will be >= |launch_count|.
-      // (A page load with multiple sections drawn by this plugin will
-      // increase this count multiple times.)
-      optional int32 instance_count = 3;
-
-      // The number of times this plugin process crashed.
-      // This value will be <= |launch_count|.
-      optional int32 crash_count = 4;
-
-      // The number of times this plugin could not be loaded.
-      optional int32 loading_error_count = 5;
-    }
-    repeated PluginStability plugin_stability = 22;
-  }
-  optional Stability stability = 8;
-
-  // Description of a field trial or experiment that the user is currently
-  // enrolled in.
-  // All metrics reported in this upload can potentially be influenced by the
-  // field trial.
-  message FieldTrial {
-    // The name of the field trial, as a 32-bit identifier.
-    // Currently, the identifier is a hash of the field trial's name.
-    optional fixed32 name_id = 1;
-
-    // The user's group within the field trial, as a 32-bit identifier.
-    // Currently, the identifier is a hash of the group's name.
-    optional fixed32 group_id = 2;
-  }
-  repeated FieldTrial field_trial = 9;
-
-  // Information about the A/V output device(s) (typically just a TV).
-  // However, a configuration may have one or more intermediate A/V devices
-  // between the source device and the TV (e.g. an A/V receiver, video
-  // processor, etc.).
-  message ExternalAudioVideoDevice {
-    // The manufacturer name (possibly encoded as a 3-letter code, e.g. "YMH"
-    // for Yamaha).
-    optional string manufacturer_name = 1;
-
-    // The model name (e.g. "RX-V1900"). Some devices may report generic names
-    // like "receiver" or use the full manufacturer name (e.g "PHILIPS").
-    optional string model_name = 2;
-
-    // The product code (e.g. "0218").
-    optional string product_code = 3;
-
-    // The device types. A single device can have multiple types (e.g. a set-top
-    // box could be both a tuner and a player).  The same type may even be
-    // repeated (e.g a device that reports two tuners).
-    enum AVDeviceType {
-      AV_DEVICE_TYPE_UNKNOWN = 0;
-      AV_DEVICE_TYPE_TV = 1;
-      AV_DEVICE_TYPE_RECORDER = 2;
-      AV_DEVICE_TYPE_TUNER = 3;
-      AV_DEVICE_TYPE_PLAYER = 4;
-      AV_DEVICE_TYPE_AUDIO_SYSTEM = 5;
-    }
-    repeated AVDeviceType av_device_type = 4;
-
-    // The year of manufacture.
-    optional int32 manufacture_year = 5;
-
-    // The week of manufacture.
-    // Note: per the Wikipedia EDID article, numbering for this field may not
-    // be consistent between manufacturers.
-    optional int32 manufacture_week = 6;
-
-    // Max horizontal resolution in pixels.
-    optional int32 horizontal_resolution = 7;
-
-    // Max vertical resolution in pixels.
-    optional int32 vertical_resolution = 8;
-
-    // Audio capabilities of the device.
-    // Ref: http://en.wikipedia.org/wiki/Extended_display_identification_data
-    message AudioDescription {
-      // Audio format
-      enum AudioFormat {
-        AUDIO_FORMAT_UNKNOWN = 0;
-        AUDIO_FORMAT_LPCM = 1;
-        AUDIO_FORMAT_AC_3 = 2;
-        AUDIO_FORMAT_MPEG1 = 3;
-        AUDIO_FORMAT_MP3 = 4;
-        AUDIO_FORMAT_MPEG2 = 5;
-        AUDIO_FORMAT_AAC = 6;
-        AUDIO_FORMAT_DTS = 7;
-        AUDIO_FORMAT_ATRAC = 8;
-        AUDIO_FORMAT_ONE_BIT = 9;
-        AUDIO_FORMAT_DD_PLUS = 10;
-        AUDIO_FORMAT_DTS_HD = 11;
-        AUDIO_FORMAT_MLP_DOLBY_TRUEHD = 12;
-        AUDIO_FORMAT_DST_AUDIO = 13;
-        AUDIO_FORMAT_MICROSOFT_WMA_PRO = 14;
-      }
-      optional AudioFormat audio_format = 1;
-
-      // Number of channels (e.g. 1, 2, 8, etc.).
-      optional int32 num_channels = 2;
-
-      // Supported sample frequencies in Hz (e.g. 32000, 44100, etc.).
-      // Multiple frequencies may be specified.
-      repeated int32 sample_frequency_hz = 3;
-
-      // Maximum bit rate in bits/s.
-      optional int32 max_bit_rate_per_second = 4;
-
-      // Bit depth (e.g. 16, 20, 24, etc.).
-      optional int32 bit_depth = 5;
-    }
-    repeated AudioDescription audio_description = 9;
-
-    // The position in AV setup.
-    // A value of 0 means this device is the TV.
-    // A value of 1 means this device is directly connected to one of
-    // the TV's inputs.
-    // Values > 1 indicate there are 1 or more devices between this device
-    // and the TV.
-    optional int32 position_in_setup = 10;
-
-    // Whether this device is in the path to the TV.
-    optional bool is_in_path_to_tv = 11;
-
-    // The CEC version the device supports.
-    // CEC stands for Consumer Electronics Control, a part of the HDMI
-    // specification.  Not all HDMI devices support CEC.
-    // Only devices that support CEC will report a value here.
-    optional int32 cec_version = 12;
-
-    // This message reports CEC commands seen by a device.
-    // After each log is sent, this information is cleared and gathered again.
-    // By collecting CEC status information by opcode we can determine
-    // which CEC features can be supported.
-    message CECCommand {
-      // The CEC command opcode.  CEC supports up to 256 opcodes.
-      // We add only one CECCommand message per unique opcode.  Only opcodes
-      // seen by the device will be reported. The remainder of the message
-      // accumulates status for this opcode (and device).
-      optional int32 opcode = 1;
-
-      // The total number of commands received from the external device.
-      optional int32 num_received_direct = 2;
-
-      // The number of commands received from the external device as part of a
-      // broadcast message.
-      optional int32 num_received_broadcast = 3;
-
-      // The total number of commands sent to the external device.
-      optional int32 num_sent_direct = 4;
-
-      // The number of commands sent to the external device as part of a
-      // broadcast message.
-      optional int32 num_sent_broadcast = 5;
-
-      // The number of aborted commands for unknown reasons.
-      optional int32 num_aborted_unknown_reason = 6;
-
-      // The number of aborted commands because of an unrecognized opcode.
-      optional int32 num_aborted_unrecognized = 7;
-    }
-    repeated CECCommand cec_command = 13;
-  }
-  repeated ExternalAudioVideoDevice external_audio_video_device = 14;
-
-  // Information about the current wireless access point. Collected directly
-  // from the wireless access point via standard apis if the device is
-  // connected to the Internet wirelessly. Introduced for Chrome on TV devices
-  // but also can be collected by ChromeOS, Android or other clients.
-  message ExternalAccessPoint {
-    // The manufacturer name, for example "ASUSTeK Computer Inc.".
-    optional string manufacturer = 1;
-
-    // The model name, for example "Wi-Fi Protected Setup Router".
-    optional string model_name = 2;
-
-    // The model number, for example "RT-N16".
-    optional string model_number = 3;
-
-    // The device name (sometime same as model_number), for example "RT-N16".
-    optional string device_name = 4;
-  }
-  optional ExternalAccessPoint external_access_point = 15;
-
-  // Number of users currently signed into a multiprofile session.
-  // A zero value indicates that the user count changed while the log is open.
-  // Logged only on ChromeOS.
-  optional uint32 multi_profile_user_count = 17;
-
-  // Information about extensions that are installed, masked to provide better
-  // privacy.  Only extensions from a single profile are reported; this will
-  // generally be the profile used when the browser is started.  The profile
-  // reported on will remain consistent at least until the browser is
-  // relaunched (or the profile is deleted by the user).
-  //
-  // Each client first picks a value for client_key derived from its UMA
-  // client_id:
-  //   client_key = client_id % 4096
-  // Then, each installed extension is mapped into a hash bucket according to
-  //   bucket = CityHash64(StringPrintf("%d:%s",
-  //                                    client_key, extension_id)) % 1024
-  // The client reports the set of hash buckets occupied by all installed
-  // extensions.  If multiple extensions map to the same bucket, that bucket is
-  // still only reported once.
-  repeated int32 occupied_extension_bucket = 18;
-
-  // The state of loaded extensions for this system. The system can have either
-  // no applicable extensions, extensions only from the webstore and verified by
-  // the webstore, extensions only from the webstore but not verified, or
-  // extensions not from the store. If there is a single off-store extension,
-  // then HAS_OFFSTORE is reported. This should be kept in sync with the
-  // corresponding enum in chrome/browser/metrics/extensions_metrics_provider.cc
-  enum ExtensionsState {
-    NO_EXTENSIONS = 0;
-    NO_OFFSTORE_VERIFIED = 1;
-    NO_OFFSTORE_UNVERIFIED = 2;
-    HAS_OFFSTORE = 3;
-  }
-  optional ExtensionsState offstore_extensions_state = 19;
-}
diff --git a/metricsd/uploader/proto/user_action_event.proto b/metricsd/uploader/proto/user_action_event.proto
deleted file mode 100644
index 464f3c8..0000000
--- a/metricsd/uploader/proto/user_action_event.proto
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- */
-//
-// Stores information about an event that occurs in response to a user action,
-// e.g. an interaction with a browser UI element.
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-option java_outer_classname = "UserActionEventProtos";
-option java_package = "org.chromium.components.metrics";
-
-package metrics;
-
-// Next tag: 3
-message UserActionEventProto {
-  // The name of the action, hashed.
-  optional fixed64 name_hash = 1;
-
-  // The timestamp for the event, in seconds since the epoch.
-  optional int64 time = 2;
-}
diff --git a/metricsd/uploader/sender.h b/metricsd/uploader/sender.h
deleted file mode 100644
index 369c9c2..0000000
--- a/metricsd/uploader/sender.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_SENDER_H_
-#define METRICS_UPLOADER_SENDER_H_
-
-#include <string>
-
-// Abstract class for a Sender that uploads a metrics message.
-class Sender {
- public:
-  virtual ~Sender() {}
-  // Sends a message |content| with its sha1 hash |hash|
-  virtual bool Send(const std::string& content, const std::string& hash) = 0;
-};
-
-#endif  // METRICS_UPLOADER_SENDER_H_
diff --git a/metricsd/uploader/sender_http.cc b/metricsd/uploader/sender_http.cc
deleted file mode 100644
index 1f775df..0000000
--- a/metricsd/uploader/sender_http.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/sender_http.h"
-
-#include <string>
-
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <brillo/http/http_utils.h>
-#include <brillo/mime_utils.h>
-
-HttpSender::HttpSender(const std::string& server_url)
-    : server_url_(server_url) {}
-
-bool HttpSender::Send(const std::string& content,
-                      const std::string& content_hash) {
-  const std::string hash =
-      base::HexEncode(content_hash.data(), content_hash.size());
-
-  brillo::http::HeaderList headers = {{"X-Chrome-UMA-Log-SHA1", hash}};
-  brillo::ErrorPtr error;
-  auto response = brillo::http::PostTextAndBlock(
-      server_url_,
-      content,
-      brillo::mime::application::kWwwFormUrlEncoded,
-      headers,
-      brillo::http::Transport::CreateDefault(),
-      &error);
-  if (!response || response->ExtractDataAsString() != "OK") {
-    if (error) {
-      DLOG(ERROR) << "Failed to send data: " << error->GetMessage();
-    }
-    return false;
-  }
-  return true;
-}
diff --git a/metricsd/uploader/sender_http.h b/metricsd/uploader/sender_http.h
deleted file mode 100644
index 0d64c74..0000000
--- a/metricsd/uploader/sender_http.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_SENDER_HTTP_H_
-#define METRICS_UPLOADER_SENDER_HTTP_H_
-
-#include <string>
-
-#include <base/macros.h>
-
-#include "uploader/sender.h"
-
-// Sender implemented using http_utils from libbrillo
-class HttpSender : public Sender {
- public:
-  explicit HttpSender(const std::string& server_url);
-  ~HttpSender() override = default;
-  // Sends |content| whose SHA1 hash is |hash| to server_url with a synchronous
-  // POST request to server_url.
-  bool Send(const std::string& content, const std::string& hash) override;
-
- private:
-  const std::string server_url_;
-
-  DISALLOW_COPY_AND_ASSIGN(HttpSender);
-};
-
-#endif  // METRICS_UPLOADER_SENDER_HTTP_H_
diff --git a/metricsd/uploader/system_profile_cache.cc b/metricsd/uploader/system_profile_cache.cc
deleted file mode 100644
index e6f6617..0000000
--- a/metricsd/uploader/system_profile_cache.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/system_profile_cache.h"
-
-#include <base/files/file_util.h>
-#include <base/guid.h>
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_util.h>
-#include <brillo/osrelease_reader.h>
-#include <string>
-#include <update_engine/client.h>
-#include <vector>
-
-#include "constants.h"
-#include "persistent_integer.h"
-#include "uploader/metrics_log_base.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-
-namespace {
-
-const char kPersistentSessionIdFilename[] = "Sysinfo.SessionId";
-
-}  // namespace
-
-std::string ChannelToString(
-    const metrics::SystemProfileProto_Channel& channel) {
-  switch (channel) {
-    case metrics::SystemProfileProto::CHANNEL_STABLE:
-    return "STABLE";
-  case metrics::SystemProfileProto::CHANNEL_DEV:
-    return "DEV";
-  case metrics::SystemProfileProto::CHANNEL_BETA:
-    return "BETA";
-  case metrics::SystemProfileProto::CHANNEL_CANARY:
-    return "CANARY";
-  default:
-    return "UNKNOWN";
-  }
-}
-
-SystemProfileCache::SystemProfileCache()
-    : initialized_(false),
-      testing_(false),
-      metrics_directory_(metrics::kMetricsdDirectory),
-      session_id_(new chromeos_metrics::PersistentInteger(
-          kPersistentSessionIdFilename, metrics_directory_)) {}
-
-SystemProfileCache::SystemProfileCache(bool testing,
-                                       const base::FilePath& metrics_directory)
-    : initialized_(false),
-      testing_(testing),
-      metrics_directory_(metrics_directory),
-      session_id_(new chromeos_metrics::PersistentInteger(
-          kPersistentSessionIdFilename, metrics_directory)) {}
-
-bool SystemProfileCache::Initialize() {
-  CHECK(!initialized_)
-      << "this should be called only once in the metrics_daemon lifetime.";
-
-  brillo::OsReleaseReader reader;
-  std::string channel;
-  if (testing_) {
-    reader.LoadTestingOnly(metrics_directory_);
-    channel = "unknown";
-  } else {
-    reader.Load();
-    auto client = update_engine::UpdateEngineClient::CreateInstance();
-    if (!client) {
-      LOG(ERROR) << "failed to create the update engine client";
-      return false;
-    }
-    if (!client->GetChannel(&channel)) {
-      LOG(ERROR) << "failed to read the current channel from update engine.";
-      return false;
-    }
-  }
-
-  if (!reader.GetString(metrics::kProductId, &profile_.product_id)
-      || profile_.product_id.empty()) {
-    LOG(ERROR) << "product_id is not set.";
-    return false;
-  }
-
-  if (!reader.GetString(metrics::kProductVersion, &profile_.version)) {
-    LOG(ERROR) << "failed to read the product version";
-  }
-
-  if (channel.empty() || profile_.version.empty()) {
-    // If the channel or version is missing, the image is not official.
-    // In this case, set the channel to unknown and the version to 0.0.0.0 to
-    // avoid polluting the production data.
-    channel = "";
-    profile_.version = metrics::kDefaultVersion;
-  }
-  std::string guid_path = metrics_directory_.Append(
-      metrics::kMetricsGUIDFileName).value();
-  profile_.client_id = testing_ ?
-      "client_id_test" :
-      GetPersistentGUID(guid_path);
-  profile_.model_manifest_id = "unknown";
-  if (!testing_) {
-    brillo::KeyValueStore weave_config;
-    if (!weave_config.Load(base::FilePath(metrics::kWeaveConfigurationFile))) {
-      LOG(ERROR) << "Failed to load the weave configuration file.";
-    } else if (!weave_config.GetString(metrics::kModelManifestId,
-                                       &profile_.model_manifest_id)) {
-      LOG(ERROR) << "The model manifest id (model_id) is undefined in "
-                 << metrics::kWeaveConfigurationFile;
-    }
-  }
-
-  profile_.channel = ProtoChannelFromString(channel);
-
-  // Increment the session_id everytime we initialize this. If metrics_daemon
-  // does not crash, this should correspond to the number of reboots of the
-  // system.
-  session_id_->Add(1);
-  profile_.session_id = static_cast<int32_t>(session_id_->Get());
-
-  initialized_ = true;
-  return initialized_;
-}
-
-bool SystemProfileCache::InitializeOrCheck() {
-  return initialized_ || Initialize();
-}
-
-bool SystemProfileCache::Populate(
-    metrics::ChromeUserMetricsExtension* metrics_proto) {
-  CHECK(metrics_proto);
-  if (not InitializeOrCheck()) {
-    return false;
-  }
-
-  // The client id is hashed before being sent.
-  metrics_proto->set_client_id(
-      metrics::MetricsLogBase::Hash(profile_.client_id));
-  metrics_proto->set_session_id(profile_.session_id);
-
-  // Sets the product id.
-  metrics_proto->set_product(9);
-
-  metrics::SystemProfileProto* profile_proto =
-      metrics_proto->mutable_system_profile();
-  profile_proto->mutable_hardware()->set_hardware_class(
-      profile_.model_manifest_id);
-  profile_proto->set_app_version(profile_.version);
-  profile_proto->set_channel(profile_.channel);
-  metrics::SystemProfileProto_BrilloDeviceData* device_data =
-      profile_proto->mutable_brillo();
-  device_data->set_product_id(profile_.product_id);
-
-  return true;
-}
-
-std::string SystemProfileCache::GetPersistentGUID(
-    const std::string& filename) {
-  std::string guid;
-  base::FilePath filepath(filename);
-  if (!base::ReadFileToString(filepath, &guid)) {
-    guid = base::GenerateGUID();
-    // If we can't read or write the file, the guid will not be preserved during
-    // the next reboot. Crash.
-    CHECK(base::WriteFile(filepath, guid.c_str(), guid.size()));
-  }
-  return guid;
-}
-
-metrics::SystemProfileProto_Channel SystemProfileCache::ProtoChannelFromString(
-    const std::string& channel) {
-  if (channel == "stable-channel") {
-    return metrics::SystemProfileProto::CHANNEL_STABLE;
-  } else if (channel == "dev-channel") {
-    return metrics::SystemProfileProto::CHANNEL_DEV;
-  } else if (channel == "beta-channel") {
-    return metrics::SystemProfileProto::CHANNEL_BETA;
-  } else if (channel == "canary-channel") {
-    return metrics::SystemProfileProto::CHANNEL_CANARY;
-  }
-
-  DLOG(INFO) << "unknown channel: " << channel;
-  return metrics::SystemProfileProto::CHANNEL_UNKNOWN;
-}
diff --git a/metricsd/uploader/system_profile_cache.h b/metricsd/uploader/system_profile_cache.h
deleted file mode 100644
index f9c484c..0000000
--- a/metricsd/uploader/system_profile_cache.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
-#define METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/gtest_prod_util.h"
-#include "persistent_integer.h"
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/system_profile_setter.h"
-
-namespace metrics {
-class ChromeUserMetricsExtension;
-}
-
-struct SystemProfile {
-  std::string version;
-  std::string model_manifest_id;
-  std::string client_id;
-  int session_id;
-  metrics::SystemProfileProto::Channel channel;
-  std::string product_id;
-};
-
-// Retrieves general system informations needed by the protobuf for context and
-// remembers them to avoid expensive calls.
-//
-// The cache is populated lazily. The only method needed is Populate.
-class SystemProfileCache : public SystemProfileSetter {
- public:
-  SystemProfileCache();
-
-  SystemProfileCache(bool testing, const base::FilePath& metrics_directory);
-
-  // Populates the ProfileSystem protobuf with system information.
-  bool Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
-
-  // Converts a string representation of the channel to a
-  // SystemProfileProto_Channel
-  static metrics::SystemProfileProto_Channel ProtoChannelFromString(
-      const std::string& channel);
-
-  // Gets the persistent GUID and create it if it has not been created yet.
-  static std::string GetPersistentGUID(const std::string& filename);
-
- private:
-  friend class UploadServiceTest;
-  FRIEND_TEST(UploadServiceTest, ExtractChannelFromDescription);
-  FRIEND_TEST(UploadServiceTest, ReadKeyValueFromFile);
-  FRIEND_TEST(UploadServiceTest, SessionIdIncrementedAtInitialization);
-  FRIEND_TEST(UploadServiceTest, ValuesInConfigFileAreSent);
-  FRIEND_TEST(UploadServiceTest, ProductIdMandatory);
-
-  // Fetches all informations and populates |profile_|
-  bool Initialize();
-
-  // Initializes |profile_| only if it has not been yet initialized.
-  bool InitializeOrCheck();
-
-  bool initialized_;
-  bool testing_;
-  base::FilePath metrics_directory_;
-  std::unique_ptr<chromeos_metrics::PersistentInteger> session_id_;
-  SystemProfile profile_;
-};
-
-#endif  // METRICS_UPLOADER_SYSTEM_PROFILE_CACHE_H_
diff --git a/metricsd/uploader/system_profile_setter.h b/metricsd/uploader/system_profile_setter.h
deleted file mode 100644
index bd3ff42..0000000
--- a/metricsd/uploader/system_profile_setter.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
-#define METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
-
-namespace metrics {
-class ChromeUserMetricsExtension;
-}
-
-// Abstract class used to delegate populating SystemProfileProto with system
-// information to simplify testing.
-class SystemProfileSetter {
- public:
-  virtual ~SystemProfileSetter() {}
-  // Populates the protobuf with system informations.
-  virtual bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
-};
-
-#endif  // METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/upload_service.cc b/metricsd/uploader/upload_service.cc
deleted file mode 100644
index 333a7e6..0000000
--- a/metricsd/uploader/upload_service.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * 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.
- */
-
-#include "uploader/upload_service.h"
-
-#include <sysexits.h>
-
-#include <memory>
-#include <string>
-
-#include <base/bind.h>
-#include <base/files/file_util.h>
-#include <base/logging.h>
-#include <base/memory/scoped_vector.h>
-#include <base/message_loop/message_loop.h>
-#include <base/metrics/histogram.h>
-#include <base/metrics/histogram_base.h>
-#include <base/metrics/histogram_snapshot_manager.h>
-#include <base/metrics/sparse_histogram.h>
-#include <base/metrics/statistics_recorder.h>
-#include <base/sha1.h>
-
-#include "constants.h"
-#include "uploader/metrics_log.h"
-#include "uploader/sender_http.h"
-#include "uploader/system_profile_setter.h"
-
-const int UploadService::kMaxFailedUpload = 10;
-
-UploadService::UploadService(const std::string& server,
-                             const base::TimeDelta& upload_interval,
-                             const base::TimeDelta& disk_persistence_interval,
-                             const base::FilePath& private_metrics_directory,
-                             const base::FilePath& shared_metrics_directory)
-    : brillo::Daemon(),
-      histogram_snapshot_manager_(this),
-      sender_(new HttpSender(server)),
-      failed_upload_count_(metrics::kFailedUploadCountName,
-                           private_metrics_directory),
-      counters_(new CrashCounters),
-      upload_interval_(upload_interval),
-      disk_persistence_interval_(disk_persistence_interval),
-      metricsd_service_runner_(counters_) {
-  staged_log_path_ = private_metrics_directory.Append(metrics::kStagedLogName);
-  saved_log_path_ = private_metrics_directory.Append(metrics::kSavedLogName);
-  consent_file_ = shared_metrics_directory.Append(metrics::kConsentFileName);
-}
-
-void UploadService::LoadSavedLog() {
-  if (base::PathExists(saved_log_path_)) {
-    GetOrCreateCurrentLog()->LoadFromFile(saved_log_path_);
-  }
-}
-
-int UploadService::OnInit() {
-  brillo::Daemon::OnInit();
-
-  base::StatisticsRecorder::Initialize();
-  metricsd_service_runner_.Start();
-
-  system_profile_setter_.reset(new SystemProfileCache());
-
-  base::MessageLoop::current()->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&UploadService::UploadEventCallback, base::Unretained(this)),
-      upload_interval_);
-
-  base::MessageLoop::current()->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&UploadService::PersistEventCallback, base::Unretained(this)),
-      disk_persistence_interval_);
-
-  LoadSavedLog();
-
-  return EX_OK;
-}
-
-void UploadService::OnShutdown(int* exit_code) {
-  metricsd_service_runner_.Stop();
-  PersistToDisk();
-}
-
-void UploadService::InitForTest(SystemProfileSetter* setter) {
-  LoadSavedLog();
-  system_profile_setter_.reset(setter);
-}
-
-void UploadService::StartNewLog() {
-  current_log_.reset(new MetricsLog());
-}
-
-void UploadService::UploadEventCallback() {
-  UploadEvent();
-
-  base::MessageLoop::current()->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&UploadService::UploadEventCallback, base::Unretained(this)),
-      upload_interval_);
-}
-
-void UploadService::PersistEventCallback() {
-  PersistToDisk();
-
-  base::MessageLoop::current()->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&UploadService::PersistEventCallback, base::Unretained(this)),
-      disk_persistence_interval_);
-}
-
-void UploadService::PersistToDisk() {
-  GatherHistograms();
-  if (current_log_) {
-    current_log_->SaveToFile(saved_log_path_);
-  }
-}
-
-void UploadService::UploadEvent() {
-  // If the system shutdown or crashed while uploading a report, we may not have
-  // deleted an old log.
-  RemoveFailedLog();
-
-  if (HasStagedLog()) {
-    // Previous upload failed, retry sending the logs.
-    SendStagedLog();
-    return;
-  }
-
-  // Previous upload successful, stage another log.
-  GatherHistograms();
-  StageCurrentLog();
-
-  // If a log is available for upload, upload it.
-  if (HasStagedLog()) {
-    SendStagedLog();
-  }
-}
-
-void UploadService::SendStagedLog() {
-  // If metrics are not enabled, discard the log and exit.
-  if (!AreMetricsEnabled()) {
-    LOG(INFO) << "Metrics disabled. Don't upload metrics samples.";
-    base::DeleteFile(staged_log_path_, false);
-    return;
-  }
-
-  std::string staged_log;
-  CHECK(base::ReadFileToString(staged_log_path_, &staged_log));
-
-  // Increase the failed count in case the daemon crashes while sending the log.
-  failed_upload_count_.Add(1);
-
-  if (!sender_->Send(staged_log, base::SHA1HashString(staged_log))) {
-    LOG(WARNING) << "log failed to upload";
-  } else {
-    VLOG(1) << "uploaded " << staged_log.length() << " bytes";
-    base::DeleteFile(staged_log_path_, false);
-  }
-
-  RemoveFailedLog();
-}
-
-void UploadService::Reset() {
-  base::DeleteFile(staged_log_path_, false);
-  current_log_.reset();
-  failed_upload_count_.Set(0);
-}
-
-void UploadService::GatherHistograms() {
-  base::StatisticsRecorder::Histograms histograms;
-  base::StatisticsRecorder::GetHistograms(&histograms);
-
-  histogram_snapshot_manager_.PrepareDeltas(
-      histograms.begin(), histograms.end(),
-      base::Histogram::kNoFlags, base::Histogram::kUmaTargetedHistogramFlag);
-
-  // Gather and reset the crash counters, shared with the binder threads.
-  unsigned int kernel_crashes = counters_->GetAndResetKernelCrashCount();
-  unsigned int unclean_shutdowns = counters_->GetAndResetUncleanShutdownCount();
-  unsigned int user_crashes = counters_->GetAndResetUserCrashCount();
-
-  // Only create a log if the counters have changed.
-  if (kernel_crashes > 0 || unclean_shutdowns > 0 || user_crashes > 0) {
-    GetOrCreateCurrentLog()->IncrementKernelCrashCount(kernel_crashes);
-    GetOrCreateCurrentLog()->IncrementUncleanShutdownCount(unclean_shutdowns);
-    GetOrCreateCurrentLog()->IncrementUserCrashCount(user_crashes);
-  }
-}
-
-void UploadService::RecordDelta(const base::HistogramBase& histogram,
-                                const base::HistogramSamples& snapshot) {
-  GetOrCreateCurrentLog()->RecordHistogramDelta(histogram.histogram_name(),
-                                                snapshot);
-}
-
-void UploadService::StageCurrentLog() {
-  // If we haven't logged anything since the last upload, don't upload an empty
-  // report.
-  if (!current_log_)
-    return;
-
-  std::unique_ptr<MetricsLog> staged_log;
-  staged_log.swap(current_log_);
-  staged_log->CloseLog();
-  if (!staged_log->PopulateSystemProfile(system_profile_setter_.get())) {
-    LOG(WARNING) << "Error while adding metadata to the log. Discarding the "
-                 << "log.";
-    return;
-  }
-
-  if (!base::DeleteFile(saved_log_path_, false)) {
-    // There is a chance that we will upload the same metrics twice but, if we
-    // are lucky, the backup should be overridden before that. In doubt, try not
-    // to lose any metrics.
-    LOG(ERROR) << "failed to delete the last backup of the current log.";
-  }
-
-  failed_upload_count_.Set(0);
-  staged_log->SaveToFile(staged_log_path_);
-}
-
-MetricsLog* UploadService::GetOrCreateCurrentLog() {
-  if (!current_log_) {
-    StartNewLog();
-  }
-  return current_log_.get();
-}
-
-bool UploadService::HasStagedLog() {
-  return base::PathExists(staged_log_path_);
-}
-
-void UploadService::RemoveFailedLog() {
-  if (failed_upload_count_.Get() > kMaxFailedUpload) {
-    LOG(INFO) << "log failed more than " << kMaxFailedUpload << " times.";
-    CHECK(base::DeleteFile(staged_log_path_, false))
-        << "failed to delete staged log at " << staged_log_path_.value();
-    failed_upload_count_.Set(0);
-  }
-}
-
-bool UploadService::AreMetricsEnabled() {
-  return base::PathExists(consent_file_);
-}
diff --git a/metricsd/uploader/upload_service.h b/metricsd/uploader/upload_service.h
deleted file mode 100644
index a1d9d3b..0000000
--- a/metricsd/uploader/upload_service.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef METRICS_UPLOADER_UPLOAD_SERVICE_H_
-#define METRICS_UPLOADER_UPLOAD_SERVICE_H_
-
-#include <memory>
-#include <string>
-
-#include <base/metrics/histogram_base.h>
-#include <base/metrics/histogram_flattener.h>
-#include <base/metrics/histogram_snapshot_manager.h>
-#include <brillo/daemons/daemon.h>
-
-#include "persistent_integer.h"
-#include "uploader/crash_counters.h"
-#include "uploader/metrics_log.h"
-#include "uploader/metricsd_service_runner.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-#include "uploader/sender.h"
-#include "uploader/system_profile_cache.h"
-
-class SystemProfileSetter;
-
-// Service responsible for backing up the currently aggregated metrics to disk
-// and uploading them periodically to the server.
-//
-// A given metrics sample can be in one of three locations.
-// * in-memory metrics: in memory aggregated metrics, waiting to be staged for
-//   upload.
-// * saved log: protobuf message, written to disk periodically and on shutdown
-//   to make a backup of metrics data for uploading later.
-// * staged log: protobuf message waiting to be uploaded.
-//
-// The service works as follows:
-// On startup, we create the in-memory metrics from the saved log if it exists.
-//
-// Periodically (every |disk_persistence_interval_| seconds), we take a snapshot
-// of the in-memory metrics and save them to disk.
-//
-// Periodically (every |upload_interval| seconds), we:
-// * take a snapshot of the in-memory metrics and create the staged log
-// * save the staged log to disk to avoid losing it if metricsd or the system
-//   crashes between two uploads.
-// * delete the last saved log: all the metrics contained in it are also in the
-//   newly created staged log.
-//
-// On shutdown (SIGINT or SIGTERM), we save the in-memory metrics to disk.
-//
-// Note: the in-memory metrics can be stored in |current_log_| or
-// base::StatisticsRecorder.
-class UploadService : public base::HistogramFlattener, public brillo::Daemon {
- public:
-  UploadService(const std::string& server,
-                const base::TimeDelta& upload_interval,
-                const base::TimeDelta& disk_persistence_interval,
-                const base::FilePath& private_metrics_directory,
-                const base::FilePath& shared_metrics_directory);
-
-  // Initializes the upload service.
-  int OnInit() override;
-
-  // Cleans up the internal state before exiting.
-  void OnShutdown(int* exit_code) override;
-
-  // Starts a new log. The log needs to be regenerated after each successful
-  // launch as it is destroyed when staging the log.
-  void StartNewLog();
-
-  // Saves the current metrics to a file.
-  void PersistToDisk();
-
-  // Triggers an upload event.
-  void UploadEvent();
-
-  // Sends the staged log.
-  void SendStagedLog();
-
-  // Implements inconsistency detection to match HistogramFlattener's
-  // interface.
-  void InconsistencyDetected(
-      base::HistogramBase::Inconsistency problem) override {}
-  void UniqueInconsistencyDetected(
-      base::HistogramBase::Inconsistency problem) override {}
-  void InconsistencyDetectedInLoggedCount(int amount) override {}
-
- private:
-  friend class UploadServiceTest;
-
-  FRIEND_TEST(UploadServiceTest, CanSendMultipleTimes);
-  FRIEND_TEST(UploadServiceTest, CorruptedSavedLog);
-  FRIEND_TEST(UploadServiceTest, CurrentLogSavedAndResumed);
-  FRIEND_TEST(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload);
-  FRIEND_TEST(UploadServiceTest, EmptyLogsAreNotSent);
-  FRIEND_TEST(UploadServiceTest, FailedSendAreRetried);
-  FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
-  FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts);
-  FRIEND_TEST(UploadServiceTest, LogEmptyAfterUpload);
-  FRIEND_TEST(UploadServiceTest, LogEmptyByDefault);
-  FRIEND_TEST(UploadServiceTest, LogFromTheMetricsLibrary);
-  FRIEND_TEST(UploadServiceTest, LogKernelCrash);
-  FRIEND_TEST(UploadServiceTest, LogUncleanShutdown);
-  FRIEND_TEST(UploadServiceTest, LogUserCrash);
-  FRIEND_TEST(UploadServiceTest, PersistEmptyLog);
-  FRIEND_TEST(UploadServiceTest, UnknownCrashIgnored);
-  FRIEND_TEST(UploadServiceTest, ValuesInConfigFileAreSent);
-
-  // Initializes the upload service for testing.
-  void InitForTest(SystemProfileSetter* setter);
-
-  // If a staged log fails to upload more than kMaxFailedUpload times, it
-  // will be discarded.
-  static const int kMaxFailedUpload;
-
-  // Loads the log saved to disk if it exists.
-  void LoadSavedLog();
-
-  // Resets the internal state.
-  void Reset();
-
-  // Returns true iff metrics reporting is enabled.
-  bool AreMetricsEnabled();
-
-  // Event callback for handling Upload events.
-  void UploadEventCallback();
-
-  // Event callback for handling Persist events.
-  void PersistEventCallback();
-
-  // Aggregates all histogram available in memory and store them in the current
-  // log.
-  void GatherHistograms();
-
-  // Callback for HistogramSnapshotManager to store the histograms.
-  void RecordDelta(const base::HistogramBase& histogram,
-                   const base::HistogramSamples& snapshot) override;
-
-  // Compiles all the samples received into a single protobuf and adds all
-  // system information.
-  void StageCurrentLog();
-
-  // Returns true iff a log is staged.
-  bool HasStagedLog();
-
-  // Remove the staged log iff the upload failed more than |kMaxFailedUpload|.
-  void RemoveFailedLog();
-
-  // Returns the current log. If there is no current log, creates it first.
-  MetricsLog* GetOrCreateCurrentLog();
-
-  std::unique_ptr<SystemProfileSetter> system_profile_setter_;
-  base::HistogramSnapshotManager histogram_snapshot_manager_;
-  std::unique_ptr<Sender> sender_;
-  chromeos_metrics::PersistentInteger failed_upload_count_;
-  std::unique_ptr<MetricsLog> current_log_;
-  std::shared_ptr<CrashCounters> counters_;
-
-  base::TimeDelta upload_interval_;
-  base::TimeDelta disk_persistence_interval_;
-
-  MetricsdServiceRunner metricsd_service_runner_;
-
-  base::FilePath consent_file_;
-  base::FilePath staged_log_path_;
-  base::FilePath saved_log_path_;
-
-  bool testing_;
-};
-
-#endif  // METRICS_UPLOADER_UPLOAD_SERVICE_H_
diff --git a/metricsd/uploader/upload_service_test.cc b/metricsd/uploader/upload_service_test.cc
deleted file mode 100644
index 0f77fe4..0000000
--- a/metricsd/uploader/upload_service_test.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * 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.
- */
-
-#include <memory>
-
-#include <base/at_exit.h>
-#include <base/files/file_util.h>
-#include <base/files/scoped_temp_dir.h>
-#include <base/logging.h>
-#include <base/metrics/sparse_histogram.h>
-#include <base/metrics/statistics_recorder.h>
-#include <base/sys_info.h>
-#include <gtest/gtest.h>
-
-#include "constants.h"
-#include "persistent_integer.h"
-#include "uploader/metrics_log.h"
-#include "uploader/mock/mock_system_profile_setter.h"
-#include "uploader/mock/sender_mock.h"
-#include "uploader/proto/chrome_user_metrics_extension.pb.h"
-#include "uploader/proto/histogram_event.pb.h"
-#include "uploader/proto/system_profile.pb.h"
-#include "uploader/system_profile_cache.h"
-#include "uploader/upload_service.h"
-
-class UploadServiceTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-    CHECK(dir_.CreateUniqueTempDir());
-    // Make sure the statistics recorder is inactive (contains no metrics) then
-    // initialize it.
-    ASSERT_FALSE(base::StatisticsRecorder::IsActive());
-    base::StatisticsRecorder::Initialize();
-
-    private_dir_ = dir_.path().Append("private");
-    shared_dir_ = dir_.path().Append("shared");
-
-    EXPECT_TRUE(base::CreateDirectory(private_dir_));
-    EXPECT_TRUE(base::CreateDirectory(shared_dir_));
-
-    ASSERT_EQ(0, base::WriteFile(shared_dir_.Append(metrics::kConsentFileName),
-                                 "", 0));
-
-    upload_service_.reset(new UploadService(
-        "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
-    counters_ = upload_service_->counters_;
-
-    upload_service_->sender_.reset(new SenderMock);
-    upload_service_->InitForTest(new MockSystemProfileSetter);
-    upload_service_->GatherHistograms();
-    upload_service_->Reset();
-  }
-
-  void SendSparseHistogram(const std::string& name, int sample) {
-    base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
-        name, base::Histogram::kUmaTargetedHistogramFlag);
-    histogram->Add(sample);
-  }
-
-  void SendHistogram(
-      const std::string& name, int sample, int min, int max, int nbuckets) {
-    base::HistogramBase* histogram = base::Histogram::FactoryGet(
-        name, min, max, nbuckets, base::Histogram::kUmaTargetedHistogramFlag);
-    histogram->Add(sample);
-  }
-
-  void SetTestingProperty(const std::string& name, const std::string& value) {
-    base::FilePath filepath =
-        dir_.path().Append("etc/os-release.d").Append(name);
-    ASSERT_TRUE(base::CreateDirectory(filepath.DirName()));
-    ASSERT_EQ(value.size(),
-              base::WriteFile(filepath, value.data(), value.size()));
-  }
-
-  const metrics::SystemProfileProto_Stability GetCurrentStability() {
-    EXPECT_TRUE(upload_service_->current_log_.get());
-
-    return upload_service_->current_log_->uma_proto()
-        ->system_profile()
-        .stability();
-  }
-
-  base::ScopedTempDir dir_;
-  std::unique_ptr<UploadService> upload_service_;
-
-  std::unique_ptr<base::AtExitManager> exit_manager_;
-  std::shared_ptr<CrashCounters> counters_;
-  base::FilePath private_dir_;
-  base::FilePath shared_dir_;
-};
-
-TEST_F(UploadServiceTest, FailedSendAreRetried) {
-  SenderMock* sender = new SenderMock();
-  upload_service_->sender_.reset(sender);
-
-  sender->set_should_succeed(false);
-
-  SendSparseHistogram("hello", 1);
-  upload_service_->UploadEvent();
-  EXPECT_EQ(1, sender->send_call_count());
-  std::string sent_string = sender->last_message();
-
-  upload_service_->UploadEvent();
-  EXPECT_EQ(2, sender->send_call_count());
-  EXPECT_EQ(sent_string, sender->last_message());
-}
-
-TEST_F(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload) {
-  SenderMock* sender = new SenderMock();
-  upload_service_->sender_.reset(sender);
-
-  sender->set_should_succeed(false);
-
-  SendSparseHistogram("hello", 1);
-
-  for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
-    upload_service_->UploadEvent();
-  }
-
-  EXPECT_TRUE(upload_service_->HasStagedLog());
-  upload_service_->UploadEvent();
-  EXPECT_FALSE(upload_service_->HasStagedLog());
-
-  // Log a new sample. The failed upload counter should be reset.
-  SendSparseHistogram("hello", 1);
-  for (int i = 0; i < UploadService::kMaxFailedUpload; i++) {
-    upload_service_->UploadEvent();
-  }
-  // The log is not discarded after multiple failed uploads.
-  EXPECT_TRUE(upload_service_->HasStagedLog());
-}
-
-TEST_F(UploadServiceTest, EmptyLogsAreNotSent) {
-  SenderMock* sender = new SenderMock();
-  upload_service_->sender_.reset(sender);
-  upload_service_->UploadEvent();
-  EXPECT_FALSE(upload_service_->current_log_);
-  EXPECT_EQ(0, sender->send_call_count());
-}
-
-TEST_F(UploadServiceTest, LogEmptyByDefault) {
-  // current_log_ should be initialized later as it needs AtExitManager to exist
-  // in order to gather system information from SysInfo.
-  EXPECT_FALSE(upload_service_->current_log_);
-}
-
-TEST_F(UploadServiceTest, CanSendMultipleTimes) {
-  SenderMock* sender = new SenderMock();
-  upload_service_->sender_.reset(sender);
-
-  SendSparseHistogram("hello", 1);
-
-  upload_service_->UploadEvent();
-
-  std::string first_message = sender->last_message();
-  SendSparseHistogram("hello", 2);
-
-  upload_service_->UploadEvent();
-
-  EXPECT_NE(first_message, sender->last_message());
-}
-
-TEST_F(UploadServiceTest, LogEmptyAfterUpload) {
-  SendSparseHistogram("hello", 2);
-
-  upload_service_->UploadEvent();
-  EXPECT_FALSE(upload_service_->current_log_);
-}
-
-TEST_F(UploadServiceTest, LogContainsAggregatedValues) {
-  SendHistogram("foo", 11, 0, 42, 10);
-  SendHistogram("foo", 12, 0, 42, 10);
-
-  upload_service_->GatherHistograms();
-  metrics::ChromeUserMetricsExtension* proto =
-      upload_service_->current_log_->uma_proto();
-  EXPECT_EQ(1, proto->histogram_event().size());
-}
-
-TEST_F(UploadServiceTest, LogContainsCrashCounts) {
-  // By default, there is no current log.
-  upload_service_->GatherHistograms();
-  EXPECT_FALSE(upload_service_->current_log_);
-
-  // If the user crash counter is incremented, we add the count to the current
-  // log.
-  counters_->IncrementUserCrashCount();
-  upload_service_->GatherHistograms();
-  EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
-
-  // If the kernel crash counter is incremented, we add the count to the current
-  // log.
-  counters_->IncrementKernelCrashCount();
-  upload_service_->GatherHistograms();
-  EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
-
-  // If the kernel crash counter is incremented, we add the count to the current
-  // log.
-  counters_->IncrementUncleanShutdownCount();
-  counters_->IncrementUncleanShutdownCount();
-  upload_service_->GatherHistograms();
-  EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
-
-  // If no counter is incremented, the reported numbers don't change.
-  upload_service_->GatherHistograms();
-  EXPECT_EQ(1, GetCurrentStability().other_user_crash_count());
-  EXPECT_EQ(1, GetCurrentStability().kernel_crash_count());
-  EXPECT_EQ(2, GetCurrentStability().unclean_system_shutdown_count());
-}
-
-TEST_F(UploadServiceTest, ExtractChannelFromString) {
-  EXPECT_EQ(SystemProfileCache::ProtoChannelFromString("developer-build"),
-            metrics::SystemProfileProto::CHANNEL_UNKNOWN);
-
-  EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_DEV,
-            SystemProfileCache::ProtoChannelFromString("dev-channel"));
-
-  EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_STABLE,
-            SystemProfileCache::ProtoChannelFromString("stable-channel"));
-
-  EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_UNKNOWN,
-            SystemProfileCache::ProtoChannelFromString("this is a test"));
-}
-
-TEST_F(UploadServiceTest, ValuesInConfigFileAreSent) {
-  SenderMock* sender = new SenderMock();
-  upload_service_->sender_.reset(sender);
-
-  SetTestingProperty(metrics::kProductId, "hello");
-  SetTestingProperty(metrics::kProductVersion, "1.2.3.4");
-
-  SendSparseHistogram("hello", 1);
-
-  // Reset to create the new log with the profile setter.
-  upload_service_->system_profile_setter_.reset(
-      new SystemProfileCache(true, dir_.path()));
-  upload_service_->Reset();
-  upload_service_->UploadEvent();
-
-  EXPECT_EQ(1, sender->send_call_count());
-  EXPECT_TRUE(sender->is_good_proto());
-  EXPECT_EQ(1, sender->last_message_proto().histogram_event().size());
-
-  EXPECT_NE(0, sender->last_message_proto().client_id());
-  EXPECT_NE(0, sender->last_message_proto().system_profile().build_timestamp());
-  EXPECT_NE(0, sender->last_message_proto().session_id());
-}
-
-TEST_F(UploadServiceTest, PersistentGUID) {
-  std::string tmp_file = dir_.path().Append("tmpfile").value();
-
-  std::string first_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
-  std::string second_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
-
-  // The GUID are cached.
-  EXPECT_EQ(first_guid, second_guid);
-
-  base::DeleteFile(base::FilePath(tmp_file), false);
-
-  first_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
-  base::DeleteFile(base::FilePath(tmp_file), false);
-  second_guid = SystemProfileCache::GetPersistentGUID(tmp_file);
-
-  // Random GUIDs are generated (not all the same).
-  EXPECT_NE(first_guid, second_guid);
-}
-
-TEST_F(UploadServiceTest, SessionIdIncrementedAtInitialization) {
-  SetTestingProperty(metrics::kProductId, "hello");
-  SystemProfileCache cache(true, dir_.path());
-  cache.Initialize();
-  int session_id = cache.profile_.session_id;
-  cache.initialized_ = false;
-  cache.Initialize();
-  EXPECT_EQ(cache.profile_.session_id, session_id + 1);
-}
-
-// The product id must be set for metrics to be uploaded.
-// If it is not set, the system profile cache should fail to initialize.
-TEST_F(UploadServiceTest, ProductIdMandatory) {
-  SystemProfileCache cache(true, dir_.path());
-  ASSERT_FALSE(cache.Initialize());
-  SetTestingProperty(metrics::kProductId, "");
-  ASSERT_FALSE(cache.Initialize());
-  SetTestingProperty(metrics::kProductId, "hello");
-  ASSERT_TRUE(cache.Initialize());
-}
-
-TEST_F(UploadServiceTest, CurrentLogSavedAndResumed) {
-  SendHistogram("hello", 10, 0, 100, 10);
-  upload_service_->PersistToDisk();
-  EXPECT_EQ(
-      1, upload_service_->current_log_->uma_proto()->histogram_event().size());
-  // Destroy the old service before creating a new one.
-  upload_service_.reset();
-  upload_service_.reset(new UploadService(
-      "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
-  upload_service_->InitForTest(nullptr);
-
-  SendHistogram("hello", 10, 0, 100, 10);
-  upload_service_->GatherHistograms();
-  EXPECT_EQ(2, upload_service_->GetOrCreateCurrentLog()
-                   ->uma_proto()
-                   ->histogram_event()
-                   .size());
-}
-
-TEST_F(UploadServiceTest, PersistEmptyLog) {
-  upload_service_->PersistToDisk();
-  EXPECT_FALSE(base::PathExists(upload_service_->saved_log_path_));
-}
-
-TEST_F(UploadServiceTest, CorruptedSavedLog) {
-  // Write a bogus saved log.
-  EXPECT_EQ(5, base::WriteFile(upload_service_->saved_log_path_, "hello", 5));
-
-  // Destroy the old service before creating a new one.
-  upload_service_.reset();
-  upload_service_.reset(new UploadService(
-      "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
-
-  upload_service_->InitForTest(nullptr);
-  // If the log is unreadable, we drop it and continue execution.
-  ASSERT_NE(nullptr, upload_service_->GetOrCreateCurrentLog());
-  ASSERT_FALSE(base::PathExists(upload_service_->saved_log_path_));
-}
diff --git a/rootdir/asan.options b/rootdir/asan.options
index 70e0eca..d728f12 100644
--- a/rootdir/asan.options
+++ b/rootdir/asan.options
@@ -3,4 +3,5 @@
 alloc_dealloc_mismatch=0
 allocator_may_return_null=1
 detect_container_overflow=0
+abort_on_error=1
 include_if_exists=/system/asan.options.%b
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f65f470..bb9928b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -236,6 +236,9 @@
 
     export DOWNLOAD_CACHE /data/cache
 
+    # set RLIMIT_NICE to allow priorities from 19 to -20
+    setrlimit 13 40 40
+
 # Healthd can trigger a full boot from charger mode by signaling this
 # property when the power button is held.
 on property:sys.boot_from_charger_mode=1
@@ -258,6 +261,11 @@
 # Mount filesystems and start core system services.
 on late-init
     trigger early-fs
+
+    # Mount fstab in init.{$device}.rc by mount_all command. Optional parameter
+    # '--early' can be specified to skip entries with 'latemount'.
+    # /system and /vendor must be mounted by the end of the fs stage,
+    # while /data is optional.
     trigger fs
     trigger post-fs
 
@@ -266,9 +274,18 @@
     # issued fs triggers have completed.
     trigger load_system_props_action
 
+    # Mount fstab in init.{$device}.rc by mount_all with '--late' parameter
+    # to only mount entries with 'latemount'. This is needed if '--early' is
+    # specified in the previous mount_all command on the fs stage.
+    # With /system mounted and properties form /system + /factory available,
+    # some services can be started.
+    trigger late-fs
+
     # Now we can mount /data. File encryption requires keymaster to decrypt
-    # /data, which in turn can only be loaded when system properties are present
+    # /data, which in turn can only be loaded when system properties are present.
     trigger post-fs-data
+
+    # Load persist properties and override properties (if enabled) from /data.
     trigger load_persist_props_action
 
     # Remove a file to wake up anything waiting for firmware.
@@ -479,9 +496,6 @@
     hostname localhost
     domainname localdomain
 
-    # set RLIMIT_NICE to allow priorities from 19 to -20
-    setrlimit 13 40 40
-
     # Memory management.  Basic kernel parameters, and allow the high
     # level system server to be able to adjust the kernel OOM driver
     # parameters to match how it is managing things.
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index 1fd1e2a..915d159 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -103,7 +103,7 @@
 
 # Used to set USB configuration at boot and to switch the configuration
 # when changing the default configuration
-on property:persist.sys.usb.config=*
+on boot && property:persist.sys.usb.config=*
     setprop sys.usb.config ${persist.sys.usb.config}
 
 #
diff --git a/sdcard/fuse.cpp b/sdcard/fuse.cpp
index 6a972ea..f549606 100644
--- a/sdcard/fuse.cpp
+++ b/sdcard/fuse.cpp
@@ -23,9 +23,6 @@
 /* FUSE_CANONICAL_PATH is not currently upstreamed */
 #define FUSE_CANONICAL_PATH 2016
 
-#define PROP_SDCARDFS_DEVICE "ro.sys.sdcardfs"
-#define PROP_SDCARDFS_USER "persist.sys.sdcardfs"
-
 #define FUSE_UNKNOWN_INO 0xffffffff
 
 /* Pseudo-error constant used to indicate that no fuse status is needed
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index 3481ec3..70bbf26 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -28,11 +28,16 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 
 #include <cutils/fs.h>
 #include <cutils/multiuser.h>
+#include <cutils/properties.h>
+
 #include <packagelistparser/packagelistparser.h>
 
 #include <libminijail.h>
@@ -73,6 +78,9 @@
 
 #include "fuse.h"
 
+#define PROP_SDCARDFS_DEVICE "ro.sys.sdcardfs"
+#define PROP_SDCARDFS_USER "persist.sys.sdcardfs"
+
 /* Supplementary groups to execute with. */
 static const gid_t kGroups[1] = { AID_PACKAGE_INFO };
 
@@ -307,6 +315,98 @@
     LOG(FATAL) << "terminated prematurely";
 }
 
+static bool sdcardfs_setup(const std::string& source_path, const std::string& dest_path, uid_t fsuid,
+                        gid_t fsgid, bool multi_user, userid_t userid, gid_t gid, mode_t mask) {
+    std::string opts = android::base::StringPrintf("fsuid=%d,fsgid=%d,%smask=%d,userid=%d,gid=%d",
+            fsuid, fsgid, multi_user?"multiuser,":"", mask, userid, gid);
+
+    if (mount(source_path.c_str(), dest_path.c_str(), "sdcardfs",
+                        MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) {
+        PLOG(ERROR) << "failed to mount sdcardfs filesystem";
+        return false;
+    }
+
+    return true;
+}
+
+static void run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid,
+        gid_t gid, userid_t userid, bool multi_user, bool full_write) {
+    std::string dest_path_default = "/mnt/runtime/default/" + label;
+    std::string dest_path_read = "/mnt/runtime/read/" + label;
+    std::string dest_path_write = "/mnt/runtime/write/" + label;
+
+    umask(0);
+    if (multi_user) {
+        // Multi-user storage is fully isolated per user, so "other"
+        // permissions are completely masked off.
+        if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
+                                                      AID_SDCARD_RW, 0006)
+                || !sdcardfs_setup(source_path, dest_path_read, uid, gid, multi_user, userid,
+                                                      AID_EVERYBODY, 0027)
+                || !sdcardfs_setup(source_path, dest_path_write, uid, gid, multi_user, userid,
+                                                      AID_EVERYBODY, full_write ? 0007 : 0027)) {
+            LOG(FATAL) << "failed to sdcardfs_setup";
+        }
+    } else {
+        // Physical storage is readable by all users on device, but
+        // the Android directories are masked off to a single user
+        // deep inside attr_from_stat().
+        if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
+                                                      AID_SDCARD_RW, 0006)
+                || !sdcardfs_setup(source_path, dest_path_read, uid, gid, multi_user, userid,
+                                                      AID_EVERYBODY, full_write ? 0027 : 0022)
+                || !sdcardfs_setup(source_path, dest_path_write, uid, gid, multi_user, userid,
+                                                      AID_EVERYBODY, full_write ? 0007 : 0022)) {
+            LOG(FATAL) << "failed to sdcardfs_setup";
+        }
+    }
+
+    // Will abort if priv-dropping fails.
+    drop_privs(uid, gid);
+
+    if (multi_user) {
+        std::string obb_path = source_path + "/obb";
+        fs_prepare_dir(obb_path.c_str(), 0775, uid, gid);
+    }
+
+    exit(0);
+}
+
+static bool supports_sdcardfs(void) {
+    std::string filesystems;
+    if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) {
+        PLOG(ERROR) << "Could not read /proc/filesystems";
+        return false;
+    }
+    for (const auto& fs : android::base::Split(filesystems, "\n")) {
+        if (fs.find("sdcardfs") != std::string::npos) return true;
+    }
+    return false;
+}
+
+static bool should_use_sdcardfs(void) {
+    char property[PROPERTY_VALUE_MAX];
+
+    // Allow user to have a strong opinion about state
+    property_get(PROP_SDCARDFS_USER, property, "");
+    if (!strcmp(property, "force_on")) {
+        LOG(WARNING) << "User explicitly enabled sdcardfs";
+        return supports_sdcardfs();
+    } else if (!strcmp(property, "force_off")) {
+        LOG(WARNING) << "User explicitly disabled sdcardfs";
+        return false;
+    }
+
+    // Fall back to device opinion about state
+    if (property_get_bool(PROP_SDCARDFS_DEVICE, false)) {
+        LOG(WARNING) << "Device explicitly enabled sdcardfs";
+        return supports_sdcardfs();
+    } else {
+        LOG(WARNING) << "Device explicitly disabled sdcardfs";
+        return false;
+    }
+}
+
 static int usage() {
     LOG(ERROR) << "usage: sdcard [OPTIONS] <source_path> <label>"
                << "    -u: specify UID to run as"
@@ -389,6 +489,10 @@
         sleep(1);
     }
 
-    run(source_path, label, uid, gid, userid, multi_user, full_write);
+    if (should_use_sdcardfs()) {
+        run_sdcardfs(source_path, label, uid, gid, userid, multi_user, full_write);
+    } else {
+        run(source_path, label, uid, gid, userid, multi_user, full_write);
+    }
     return 1;
 }