Merge "Invoke perfprofd daemon (only for userdebug/eng builds)."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index de82cd4..e526914 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -33,6 +33,7 @@
 #include <string>
 
 #include <base/stringprintf.h>
+#include <base/strings.h>
 
 #include "adb_auth.h"
 #include "adb_io.h"
@@ -381,87 +382,64 @@
 }
 #endif // ADB_HOST
 
-/* qual_overwrite is used to overwrite a qualifier string.  dst is a
- * pointer to a char pointer.  It is assumed that if *dst is non-NULL, it
- * was malloc'ed and needs to freed.  *dst will be set to a dup of src.
- */
-static void qual_overwrite(char **dst, const char *src)
-{
-    if (!dst)
-        return;
-
+// qual_overwrite is used to overwrite a qualifier string.  dst is a
+// pointer to a char pointer.  It is assumed that if *dst is non-NULL, it
+// was malloc'ed and needs to freed.  *dst will be set to a dup of src.
+// TODO: switch to std::string for these atransport fields instead.
+static void qual_overwrite(char** dst, const std::string& src) {
     free(*dst);
-    *dst = NULL;
-
-    if (!src || !*src)
-        return;
-
-    *dst = strdup(src);
+    *dst = strdup(src.c_str());
 }
 
-void parse_banner(char *banner, atransport *t)
-{
-    static const char *prop_seps = ";";
-    static const char key_val_sep = '=';
-    char *cp;
-    char *type;
-
+void parse_banner(const char* banner, atransport* t) {
     D("parse_banner: %s\n", banner);
-    type = banner;
-    cp = strchr(type, ':');
-    if (cp) {
-        *cp++ = 0;
-        /* Nothing is done with second field. */
-        cp = strchr(cp, ':');
-        if (cp) {
-            char *save;
-            char *key;
-            key = adb_strtok_r(cp + 1, prop_seps, &save);
-            while (key) {
-                cp = strchr(key, key_val_sep);
-                if (cp) {
-                    *cp++ = '\0';
-                    if (!strcmp(key, "ro.product.name"))
-                        qual_overwrite(&t->product, cp);
-                    else if (!strcmp(key, "ro.product.model"))
-                        qual_overwrite(&t->model, cp);
-                    else if (!strcmp(key, "ro.product.device"))
-                        qual_overwrite(&t->device, cp);
-                }
-                key = adb_strtok_r(NULL, prop_seps, &save);
+
+    // The format is something like:
+    // "device::ro.product.name=x;ro.product.model=y;ro.product.device=z;".
+    std::vector<std::string> pieces = android::base::Split(banner, ":");
+
+    if (pieces.size() > 2) {
+        const std::string& props = pieces[2];
+        for (auto& prop : android::base::Split(props, ";")) {
+            // The list of properties was traditionally ;-terminated rather than ;-separated.
+            if (prop.empty()) continue;
+
+            std::vector<std::string> key_value = android::base::Split(prop, "=");
+            if (key_value.size() != 2) continue;
+
+            const std::string& key = key_value[0];
+            const std::string& value = key_value[1];
+            if (key == "ro.product.name") {
+                qual_overwrite(&t->product, value);
+            } else if (key == "ro.product.model") {
+                qual_overwrite(&t->model, value);
+            } else if (key == "ro.product.device") {
+                qual_overwrite(&t->device, value);
             }
         }
     }
 
-    if(!strcmp(type, "bootloader")){
+    const std::string& type = pieces[0];
+    if (type == "bootloader") {
         D("setting connection_state to CS_BOOTLOADER\n");
         t->connection_state = CS_BOOTLOADER;
         update_transports();
-        return;
-    }
-
-    if(!strcmp(type, "device")) {
+    } else if (type == "device") {
         D("setting connection_state to CS_DEVICE\n");
         t->connection_state = CS_DEVICE;
         update_transports();
-        return;
-    }
-
-    if(!strcmp(type, "recovery")) {
+    } else if (type == "recovery") {
         D("setting connection_state to CS_RECOVERY\n");
         t->connection_state = CS_RECOVERY;
         update_transports();
-        return;
-    }
-
-    if(!strcmp(type, "sideload")) {
+    } else if (type == "sideload") {
         D("setting connection_state to CS_SIDELOAD\n");
         t->connection_state = CS_SIDELOAD;
         update_transports();
-        return;
+    } else {
+        D("setting connection_state to CS_HOST\n");
+        t->connection_state = CS_HOST;
     }
-
-    t->connection_state = CS_HOST;
 }
 
 void handle_packet(apacket *p, atransport *t)
@@ -493,7 +471,7 @@
             handle_offline(t);
         }
 
-        parse_banner((char*) p->data, t);
+        parse_banner(reinterpret_cast<const char*>(p->data), t);
 
         if (HOST || !auth_enabled) {
             handle_online(t);
diff --git a/adb/adb.h b/adb/adb.h
index cb2cf60..b8c6156 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -243,8 +243,6 @@
 void remove_socket(asocket *s);
 void close_all_sockets(atransport *t);
 
-#define  LOCAL_CLIENT_PREFIX  "emulator-"
-
 asocket *create_local_socket(int fd);
 asocket *create_local_service_socket(const char *destination);
 
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 7c2bcfb..510dcc2 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -43,6 +43,7 @@
 #include "mincrypt/rsa.h"
 #undef RSA_verify
 
+#include <base/strings.h>
 #include <cutils/list.h>
 
 #include <openssl/evp.h>
@@ -172,7 +173,7 @@
         return 0;
     }
 
-    outfile = fopen(path, "w");
+    outfile = fopen(path, "we");
     if (!outfile) {
         D("Failed to open '%s'\n", path);
         return 0;
@@ -191,7 +192,7 @@
     encoded_length = 1 + ((sizeof(pkey) + 2) / 3 * 4);
 #endif
 
-    encoded = reinterpret_cast<uint8_t*>(malloc(encoded_length));
+    encoded = new uint8_t[encoded_length];
     if (encoded == nullptr) {
         D("Allocation failure");
         goto out;
@@ -212,9 +213,7 @@
     if (outfile != NULL) {
         fclose(outfile);
     }
-    if (encoded != NULL) {
-        free(encoded);
-    }
+    delete[] encoded;
     return ret;
 }
 
@@ -240,7 +239,7 @@
 
     old_mask = umask(077);
 
-    f = fopen(file, "w");
+    f = fopen(file, "we");
     if (!f) {
         D("Failed to open '%s'\n", file);
         umask(old_mask);
@@ -274,30 +273,24 @@
 {
     D("read_key '%s'\n", file);
 
-    FILE* f = fopen(file, "r");
-    if (!f) {
-        D("Failed to open '%s'\n", file);
+    FILE* fp = fopen(file, "re");
+    if (!fp) {
+        D("Failed to open '%s': %s\n", file, strerror(errno));
         return 0;
     }
 
-    adb_private_key* key = reinterpret_cast<adb_private_key*>(
-        malloc(sizeof(adb_private_key)));
-    if (!key) {
-        D("Failed to alloc key\n");
-        fclose(f);
-        return 0;
-    }
+    adb_private_key* key = new adb_private_key;
     key->rsa = RSA_new();
 
-    if (!PEM_read_RSAPrivateKey(f, &key->rsa, NULL, NULL)) {
+    if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
         D("Failed to read key\n");
-        fclose(f);
+        fclose(fp);
         RSA_free(key->rsa);
-        free(key);
+        delete key;
         return 0;
     }
 
-    fclose(f);
+    fclose(fp);
     list_add_tail(list, &key->node);
     return 1;
 }
@@ -362,29 +355,16 @@
     return read_key(path, list);
 }
 
-static void get_vendor_keys(struct listnode *list)
-{
-    const char *adb_keys_path;
-    char keys_path[MAX_PAYLOAD];
-    char *path;
-    char *save;
-    struct stat buf;
-
-    adb_keys_path = getenv("ADB_VENDOR_KEYS");
-    if (!adb_keys_path)
+static void get_vendor_keys(struct listnode* key_list) {
+    const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
+    if (adb_keys_path == nullptr) {
         return;
-    strncpy(keys_path, adb_keys_path, sizeof(keys_path));
+    }
 
-    path = adb_strtok_r(keys_path, ENV_PATH_SEPARATOR_STR, &save);
-    while (path) {
-        D("Reading: '%s'\n", path);
-
-        if (stat(path, &buf))
-            D("Can't read '%s'\n", path);
-        else if (!read_key(path, list))
-            D("Failed to read '%s'\n", path);
-
-        path = adb_strtok_r(NULL, ENV_PATH_SEPARATOR_STR, &save);
+    for (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'\n", path.c_str());
+        }
     }
 }
 
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 0f64998..62f79fa 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -29,6 +29,10 @@
 #include <sys/types.h>
 
 #include <string>
+#include <vector>
+
+#include <base/stringprintf.h>
+#include <base/strings.h>
 
 #include "adb_io.h"
 
@@ -38,6 +42,29 @@
 static int __adb_server_port = DEFAULT_ADB_PORT;
 static const char* __adb_server_name = NULL;
 
+static std::string perror_str(const char* msg) {
+    return android::base::StringPrintf("%s: %s", msg, strerror(errno));
+}
+
+static bool ReadProtocolString(int fd, std::string* s, std::string* error) {
+    char buf[5];
+
+    if (!ReadFdExactly(fd, buf, 4)) {
+        *error = perror_str("protocol fault (couldn't read status length)");
+        return false;
+    }
+    buf[4] = 0;
+
+    unsigned long len = strtoul(buf, 0, 16);
+    s->resize(len + 1, '\0'); // Ensure NUL-termination.
+    if (!ReadFdExactly(fd, &(*s)[0], len)) {
+        *error = perror_str("protocol fault (couldn't read status message)");
+        return false;
+    }
+
+    return true;
+}
+
 void adb_set_transport(transport_type type, const char* serial)
 {
     __adb_transport = type;
@@ -54,62 +81,37 @@
     __adb_server_name = hostname;
 }
 
-int  adb_get_emulator_console_port(void)
-{
-    const char*   serial = __adb_serial;
-    int           port;
+int adb_get_emulator_console_port() {
+    if (__adb_serial) {
+        // The user specified a serial number; is it an emulator?
+        int port;
+        return (sscanf(__adb_serial, "emulator-%d", &port) == 1) ? port : -1;
+    }
 
-    if (serial == NULL) {
-        /* if no specific device was specified, we need to look at */
-        /* the list of connected devices, and extract an emulator  */
-        /* name from it. two emulators is an error                 */
-        char*  tmp = adb_query("host:devices");
-        char*  p   = tmp;
-        if(!tmp) {
-            printf("no emulator connected\n");
-            return -1;
-        }
-        while (*p) {
-            char*  q = strchr(p, '\n');
-            if (q != NULL)
-                *q++ = 0;
-            else
-                q = p + strlen(p);
+    // No specific device was given, so get the list of connected
+    // devices and search for emulators. If there's one, we'll
+    // take it. If there are more than one, that's an error.
+    std::string devices;
+    std::string error;
+    if (!adb_query("host:devices", &devices, &error)) {
+        printf("no emulator connected: %s\n", error.c_str());
+        return -1;
+    }
 
-            if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
-                if (serial != NULL) {  /* more than one emulator listed */
-                    free(tmp);
-                    return -2;
-                }
-                serial = p;
+    int port;
+    size_t emulator_count = 0;
+    for (auto& device : android::base::Split(devices, "\n")) {
+        if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
+            if (++emulator_count > 1) {
+                return -2;
             }
-
-            p = q;
         }
-        free(tmp);
-
-        if (serial == NULL)
-            return -1;  /* no emulator found */
     }
-    else {
-        if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
-            return -1;  /* not an emulator */
-    }
-
-    serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
-    port    = strtol(serial, NULL, 10);
+    if (emulator_count == 0) return -1;
     return port;
 }
 
-static char __adb_error[256] = { 0 };
-
-const char *adb_error(void)
-{
-    return __adb_error;
-}
-
-static int switch_socket_transport(int fd)
-{
+static int switch_socket_transport(int fd, std::string* error) {
     std::string service;
     if (__adb_serial) {
         service += "host:transport:";
@@ -137,92 +139,75 @@
     char tmp[5];
     snprintf(tmp, sizeof(tmp), "%04zx", service.size());
     if (!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service.c_str(), service.size())) {
-        strcpy(__adb_error, "write failure during connection");
+        *error = perror_str("write failure during connection");
         adb_close(fd);
         return -1;
     }
     D("Switch transport in progress\n");
 
-    if (adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
-        D("Switch transport failed\n");
+        D("Switch transport failed: %s\n", error->c_str());
         return -1;
     }
     D("Switch transport success\n");
     return 0;
 }
 
-int adb_status(int fd)
-{
-    unsigned char buf[5];
-    unsigned len;
+bool adb_status(int fd, std::string* error) {
+    char buf[5];
 
-    if(!ReadFdExactly(fd, buf, 4)) {
-        strcpy(__adb_error, "protocol fault (no status)");
-        return -1;
+    if (!ReadFdExactly(fd, buf, 4)) {
+        *error = perror_str("protocol fault (couldn't read status)");
+        return false;
     }
 
-    if(!memcmp(buf, "OKAY", 4)) {
-        return 0;
+    if (!memcmp(buf, "OKAY", 4)) {
+        return true;
     }
 
-    if(memcmp(buf, "FAIL", 4)) {
-        sprintf(__adb_error,
-                "protocol fault (status %02x %02x %02x %02x?!)",
-                buf[0], buf[1], buf[2], buf[3]);
-        return -1;
+    if (memcmp(buf, "FAIL", 4)) {
+        *error = android::base::StringPrintf("protocol fault (status %02x %02x %02x %02x?!)",
+                                             buf[0], buf[1], buf[2], buf[3]);
+        return false;
     }
 
-    if(!ReadFdExactly(fd, buf, 4)) {
-        strcpy(__adb_error, "protocol fault (status len)");
-        return -1;
-    }
-    buf[4] = 0;
-    len = strtoul((char*)buf, 0, 16);
-    if(len > 255) len = 255;
-    if(!ReadFdExactly(fd, __adb_error, len)) {
-        strcpy(__adb_error, "protocol fault (status read)");
-        return -1;
-    }
-    __adb_error[len] = 0;
-    return -1;
+    ReadProtocolString(fd, error, error);
+    return false;
 }
 
-int _adb_connect(const char *service)
-{
-    char tmp[5];
-    int len;
-    int fd;
-
-    D("_adb_connect: %s\n", service);
-    len = strlen(service);
-    if((len < 1) || (len > 1024)) {
-        strcpy(__adb_error, "service name too long");
+int _adb_connect(const std::string& service, std::string* error) {
+    D("_adb_connect: %s\n", service.c_str());
+    if (service.empty() || service.size() > 1024) {
+        *error = android::base::StringPrintf("bad service name length (%d)",
+                                             static_cast<int>(service.size()));
         return -1;
     }
-    snprintf(tmp, sizeof tmp, "%04x", len);
 
-    if (__adb_server_name)
+    int fd;
+    if (__adb_server_name) {
         fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
-    else
+    } else {
         fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
-
-    if(fd < 0) {
-        strcpy(__adb_error, "cannot connect to daemon");
+    }
+    if (fd < 0) {
+        *error = perror_str("cannot connect to daemon");
         return -2;
     }
 
-    if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
+    if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
         return -1;
     }
 
-    if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
-        strcpy(__adb_error, "write failure during connection");
+    char tmp[5];
+    snprintf(tmp, sizeof(tmp), "%04zx", service.size());
+    if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, &service[0], service.size())) {
+        *error = perror_str("write failure during connection");
         adb_close(fd);
         return -1;
     }
 
-    if(adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
         return -1;
     }
@@ -231,20 +216,19 @@
     return fd;
 }
 
-int adb_connect(const char *service)
-{
+int adb_connect(const std::string& service, std::string* error) {
     // first query the adb server's version
-    int fd = _adb_connect("host:version");
+    int fd = _adb_connect("host:version", error);
 
-    D("adb_connect: service %s\n", service);
-    if(fd == -2 && __adb_server_name) {
+    D("adb_connect: service %s\n", service.c_str());
+    if (fd == -2 && __adb_server_name) {
         fprintf(stderr,"** Cannot start server on remote host\n");
         return fd;
-    } else if(fd == -2) {
+    } else if (fd == -2) {
         fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
                 __adb_server_port);
     start_server:
-        if(launch_server(__adb_server_port)) {
+        if (launch_server(__adb_server_port)) {
             fprintf(stderr,"* failed to start daemon *\n");
             return -1;
         } else {
@@ -255,31 +239,31 @@
         // fall through to _adb_connect
     } else {
         // if server was running, check its version to make sure it is not out of date
-        char buf[100];
-        size_t n;
         int version = ADB_SERVER_VERSION - 1;
 
         // if we have a file descriptor, then parse version result
-        if(fd >= 0) {
-            if(!ReadFdExactly(fd, buf, 4)) goto error;
+        if (fd >= 0) {
+            std::string version_string;
+            if (!ReadProtocolString(fd, &version_string, error)) {
+                goto error;
+            }
 
-            buf[4] = 0;
-            n = strtoul(buf, 0, 16);
-            if(n > sizeof(buf)) goto error;
-            if(!ReadFdExactly(fd, buf, n)) goto error;
             adb_close(fd);
 
-            if (sscanf(buf, "%04x", &version) != 1) goto error;
+            if (sscanf(&version_string[0], "%04x", &version) != 1) {
+                goto error;
+            }
         } else {
             // if fd is -1, then check for "unknown host service",
             // which would indicate a version of adb that does not support the version command
-            if (strcmp(__adb_error, "unknown host service") != 0)
+            if (*error == "unknown host service") {
                 return fd;
+            }
         }
 
-        if(version != ADB_SERVER_VERSION) {
+        if (version != ADB_SERVER_VERSION) {
             printf("adb server is out of date.  killing...\n");
-            fd = _adb_connect("host:kill");
+            fd = _adb_connect("host:kill", error);
             adb_close(fd);
 
             /* XXX can we better detect its death? */
@@ -289,12 +273,13 @@
     }
 
     // if the command is start-server, we are done.
-    if (!strcmp(service, "host:start-server"))
+    if (service == "host:start-server") {
         return 0;
+    }
 
-    fd = _adb_connect(service);
-    if(fd == -1) {
-        D("_adb_connect error: %s", __adb_error);
+    fd = _adb_connect(service, error);
+    if (fd == -1) {
+        D("_adb_connect error: %s", error->c_str());
     } else if(fd == -2) {
         fprintf(stderr,"** daemon still not running\n");
     }
@@ -307,15 +292,14 @@
 }
 
 
-int adb_command(const char *service)
-{
-    int fd = adb_connect(service);
-    if(fd < 0) {
-        fprintf(stderr, "error: %s\n", adb_error());
+int adb_command(const std::string& service, std::string* error) {
+    int fd = adb_connect(service, error);
+    if (fd < 0) {
+        fprintf(stderr, "error: %s\n", error->c_str());
         return -1;
     }
 
-    if(adb_status(fd)) {
+    if (!adb_status(fd, error)) {
         adb_close(fd);
         return -1;
     }
@@ -323,39 +307,18 @@
     return 0;
 }
 
-char *adb_query(const char *service)
-{
-    char buf[5];
-    unsigned long n;
-    char* tmp;
-
-    D("adb_query: %s\n", service);
-    int fd = adb_connect(service);
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", __adb_error);
+bool adb_query(const std::string& service, std::string* result, std::string* error) {
+    D("adb_query: %s\n", service.c_str());
+    int fd = adb_connect(service, error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error->c_str());
         return 0;
     }
 
-    if(!ReadFdExactly(fd, buf, 4)) goto oops;
-
-    buf[4] = 0;
-    n = strtoul(buf, 0, 16);
-    if(n >= 0xffff) {
-        strcpy(__adb_error, "reply is too long (>= 64kB)");
-        goto oops;
-    }
-
-    tmp = reinterpret_cast<char*>(malloc(n + 1));
-    if(tmp == 0) goto oops;
-
-    if(!ReadFdExactly(fd, tmp, n) == 0) {
-        tmp[n] = 0;
+    result->clear();
+    if (!ReadProtocolString(fd, result, error)) {
         adb_close(fd);
-        return tmp;
+        return false;
     }
-    free(tmp);
-
-oops:
-    adb_close(fd);
-    return 0;
+    return true;
 }
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 934362a..96416f5 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -3,23 +3,23 @@
 
 #include "adb.h"
 
+#include <string>
+
 /* connect to adb, connect to the named service, and return
 ** a valid fd for interacting with that service upon success
 ** or a negative number on failure
 */
-int adb_connect(const char *service);
-int _adb_connect(const char *service);
+int adb_connect(const std::string& service, std::string* error);
+int _adb_connect(const std::string& service, std::string* error);
 
 /* connect to adb, connect to the named service, return 0 if
 ** the connection succeeded AND the service returned OKAY
 */
-int adb_command(const char *service);
+int adb_command(const std::string& service, std::string* error);
 
-/* connect to adb, connect to the named service, return
-** a malloc'd string of its response upon success or NULL
-** on failure.
-*/
-char *adb_query(const char *service);
+// Connects to the named adb service and fills 'result' with the response.
+// Returns true on success; returns false and fills 'error' on failure.
+bool adb_query(const std::string& service, std::string* result, std::string* error);
 
 /* Set the preferred transport to connect to.
 */
@@ -45,13 +45,9 @@
  */
 int  adb_send_emulator_command(int  argc, const char**  argv);
 
-/* return verbose error string from last operation */
-const char *adb_error(void);
-
-/* read a standard adb status response (OKAY|FAIL) and
-** return 0 in the event of OKAY, -1 in the event of FAIL
-** or protocol error
-*/
-int adb_status(int fd);
+// Reads a standard adb status response (OKAY|FAIL) and
+// returns true in the event of OKAY, false in the event of FAIL
+// or protocol error.
+bool adb_status(int fd, std::string* error);
 
 #endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index e59a96a..4941689 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -201,7 +201,6 @@
         "  adb get-state                - prints: offline | bootloader | device\n"
         "  adb get-serialno             - prints: <serial-number>\n"
         "  adb get-devpath              - prints: <device-path>\n"
-        "  adb status-window            - continuously print device status for a specified device\n"
         "  adb remount                  - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
         "  adb reboot [bootloader|recovery]\n"
         "                               - reboots the device, optionally into the bootloader or recovery program.\n"
@@ -410,11 +409,12 @@
 
 static int interactive_shell() {
     adb_thread_t thr;
-    int fdi, fd;
+    int fdi;
 
-    fd = adb_connect("shell:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+    std::string error;
+    int fd = adb_connect("shell:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
     fdi = 0; //dup(0);
@@ -436,64 +436,62 @@
 }
 
 
-static void format_host_command(char* buffer, size_t  buflen, const char* command, transport_type ttype, const char* serial)
-{
+static std::string format_host_command(const char* command, transport_type type, const char* serial) {
     if (serial) {
-        snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
-    } else {
-        const char* prefix = "host";
-        if (ttype == kTransportUsb)
-            prefix = "host-usb";
-        else if (ttype == kTransportLocal)
-            prefix = "host-local";
-
-        snprintf(buffer, buflen, "%s:%s", prefix, command);
+        return android::base::StringPrintf("host-serial:%s:%s", serial, command);
     }
+
+    const char* prefix = "host";
+    if (type == kTransportUsb) {
+        prefix = "host-usb";
+    } else if (type == kTransportLocal) {
+        prefix = "host-local";
+    }
+    return android::base::StringPrintf("%s:%s", prefix, command);
 }
 
-static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
-                               unsigned progress)
+static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
+                               bool show_progress)
 {
-    char buf[4096];
-    unsigned total;
-    int fd;
-
-    sprintf(buf,"%s:%d", service, sz);
-    fd = adb_connect(buf);
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+    std::string error;
+    int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return -1;
     }
 
     int opt = CHUNK_SIZE;
     opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
 
-    total = sz;
+    unsigned total = sz;
     const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
 
-    if(progress) {
+    if (show_progress) {
         char *x = strrchr(service, ':');
         if(x) service = x + 1;
     }
 
-    while(sz > 0) {
+    while (sz > 0) {
         unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
-        if(!WriteFdExactly(fd, ptr, xfer)) {
-            adb_status(fd);
-            fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+        if (!WriteFdExactly(fd, ptr, xfer)) {
+            std::string error;
+            adb_status(fd, &error);
+            fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
             return -1;
         }
         sz -= xfer;
         ptr += xfer;
-        if(progress) {
+        if (show_progress) {
             printf("sending: '%s' %4d%%    \r", fn, (int)(100LL - ((100LL * sz) / (total))));
             fflush(stdout);
         }
     }
-    if(progress) {
+    if (show_progress) {
         printf("\n");
     }
 
+    // TODO: should this be adb_status?
+    char buf[5];
     if(!ReadFdExactly(fd, buf, 4)){
         fprintf(stderr,"* error reading response *\n");
         adb_close(fd);
@@ -547,37 +545,39 @@
         return -1;
     }
 
-    char buf[100];
-    sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
-    int fd = adb_connect(buf);
+    std::string service =
+            android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
+    std::string error;
+    int fd = adb_connect(service, &error);
     if (fd < 0) {
         // Try falling back to the older sideload method.  Maybe this
         // is an older device that doesn't support sideload-host.
         printf("\n");
-        status = adb_download_buffer("sideload", fn, data, sz, 1);
+        status = adb_download_buffer("sideload", fn, data, sz, true);
         goto done;
     }
 
     opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
 
     while (true) {
+        char buf[9];
         if (!ReadFdExactly(fd, buf, 8)) {
-            fprintf(stderr, "* failed to read command: %s\n", adb_error());
+            fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
             status = -1;
             goto done;
         }
+        buf[8] = '\0';
 
-        if (strncmp("DONEDONE", buf, 8) == 0) {
+        if (strcmp("DONEDONE", buf) == 0) {
             status = 0;
             break;
         }
 
-        buf[8] = '\0';
         int block = strtol(buf, NULL, 10);
 
         size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
         if (offset >= sz) {
-            fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
+            fprintf(stderr, "* attempt to read block %d past end\n", block);
             status = -1;
             goto done;
         }
@@ -589,8 +589,8 @@
         }
 
         if(!WriteFdExactly(fd, start, to_write)) {
-            adb_status(fd);
-            fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
+            adb_status(fd, &error);
+            fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
             status = -1;
             goto done;
         }
@@ -618,50 +618,6 @@
     return status;
 }
 
-static void status_window(transport_type ttype, const char* serial)
-{
-    char command[4096];
-    char *state = 0;
-    char *laststate = 0;
-
-        /* silence stderr */
-#ifdef _WIN32
-    /* XXX: TODO */
-#else
-    int  fd;
-    fd = unix_open("/dev/null", O_WRONLY);
-    dup2(fd, 2);
-    adb_close(fd);
-#endif
-
-    format_host_command(command, sizeof command, "get-state", ttype, serial);
-
-    for(;;) {
-        adb_sleep_ms(250);
-
-        if(state) {
-            free(state);
-            state = 0;
-        }
-
-        state = adb_query(command);
-
-        if(state) {
-            if(laststate && !strcmp(state,laststate)){
-                continue;
-            } else {
-                if(laststate) free(laststate);
-                laststate = strdup(state);
-            }
-        }
-
-        printf("%c[2J%c[2H", 27, 27);
-        printf("Android Debug Bridge\n");
-        printf("State: %s\n", state ? state : "offline");
-        fflush(stdout);
-    }
-}
-
 /**
  * Run ppp in "notty" mode against a resource listed as the first parameter
  * eg:
@@ -674,9 +630,6 @@
     fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
     return -1;
 #else
-    pid_t pid;
-    int fd;
-
     if (argc < 2) {
         fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
                 argv[0]);
@@ -685,15 +638,15 @@
     }
 
     const char* adb_service_name = argv[1];
-    fd = adb_connect(adb_service_name);
-
-    if(fd < 0) {
+    std::string error;
+    int fd = adb_connect(adb_service_name, &error);
+    if (fd < 0) {
         fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
-                adb_service_name, adb_error());
+                adb_service_name, error.c_str());
         return 1;
     }
 
-    pid = fork();
+    pid_t pid = fork();
 
     if (pid < 0) {
         perror("from fork()");
@@ -738,9 +691,11 @@
                               const std::string& command) {
     int fd;
     while (true) {
-        fd = adb_connect(command.c_str());
-        if (fd >= 0)
+        std::string error;
+        fd = adb_connect(command, &error);
+        if (fd >= 0) {
             break;
+        }
         fprintf(stderr,"- waiting for device -\n");
         adb_sleep_ms(1000);
         do_cmd(transport, serial, "wait-for-device", 0);
@@ -830,9 +785,10 @@
     }
 
     D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
-    int fd = adb_connect(cmd.c_str());
+    std::string error;
+    int fd = adb_connect(cmd, &error);
     if (fd < 0) {
-        fprintf(stderr, "adb: unable to connect for backup\n");
+        fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
         adb_close(outFd);
         return -1;
     }
@@ -846,21 +802,19 @@
 }
 
 static int restore(int argc, const char** argv) {
-    const char* filename;
-    int fd, tarFd;
-
     if (argc != 2) return usage();
 
-    filename = argv[1];
-    tarFd = adb_open(filename, O_RDONLY);
+    const char* filename = argv[1];
+    int tarFd = adb_open(filename, O_RDONLY);
     if (tarFd < 0) {
-        fprintf(stderr, "adb: unable to open file %s\n", filename);
+        fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
         return -1;
     }
 
-    fd = adb_connect("restore:");
+    std::string error;
+    int fd = adb_connect("restore:", &error);
     if (fd < 0) {
-        fprintf(stderr, "adb: unable to connect for restore\n");
+        fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
         adb_close(tarFd);
         return -1;
     }
@@ -961,17 +915,29 @@
     }
 }
 
-static int adb_connect_command(const char* command) {
-    int fd = adb_connect(command);
+static int adb_connect_command(const std::string& command) {
+    std::string error;
+    int fd = adb_connect(command, &error);
     if (fd != -1) {
         read_and_dump(fd);
         adb_close(fd);
         return 0;
     }
-    fprintf(stderr, "Error: %s\n", adb_error());
+    fprintf(stderr, "Error: %s\n", error.c_str());
     return 1;
 }
 
+static int adb_query_command(const std::string& command) {
+    std::string result;
+    std::string error;
+    if (!adb_query(command, &result, &error)) {
+        fprintf(stderr, "error: %s\n", error.c_str());
+        return 1;
+    }
+    printf("%s\n", result.c_str());
+    return 0;
+}
+
 int adb_commandline(int argc, const char **argv)
 {
     char buf[4096];
@@ -1125,11 +1091,11 @@
             }
         }
 
-        format_host_command(buf, sizeof buf, service, ttype, serial);
-
-        if (adb_command(buf)) {
-            D("failure: %s *\n",adb_error());
-            fprintf(stderr,"error: %s\n", adb_error());
+        std::string cmd = format_host_command(service, ttype, serial);
+        std::string error;
+        if (adb_command(cmd, &error)) {
+            D("failure: %s *\n", error.c_str());
+            fprintf(stderr,"error: %s\n", error.c_str());
             return 1;
         }
 
@@ -1147,59 +1113,38 @@
 
     /* adb_connect() commands */
     if (!strcmp(argv[0], "devices")) {
-        char *tmp;
         const char *listopt;
-        if (argc < 2)
+        if (argc < 2) {
             listopt = "";
-        else if (argc == 2 && !strcmp(argv[1], "-l"))
+        } else if (argc == 2 && !strcmp(argv[1], "-l")) {
             listopt = argv[1];
-        else {
+        } else {
             fprintf(stderr, "Usage: adb devices [-l]\n");
             return 1;
         }
-        snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
-        tmp = adb_query(buf);
-        if (tmp) {
-            printf("List of devices attached \n");
-            printf("%s\n", tmp);
-            return 0;
-        } else {
-            return 1;
-        }
+
+        std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
+        printf("List of devices attached\n");
+        return adb_query_command(query);
     }
     else if (!strcmp(argv[0], "connect")) {
-        char *tmp;
         if (argc != 2) {
             fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
             return 1;
         }
-        snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
-        tmp = adb_query(buf);
-        if (tmp) {
-            printf("%s\n", tmp);
-            return 0;
-        } else {
-            return 1;
-        }
+
+        std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
+        return adb_query_command(query);
     }
     else if (!strcmp(argv[0], "disconnect")) {
-        char *tmp;
         if (argc > 2) {
             fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
             return 1;
         }
-        if (argc == 2) {
-            snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
-        } else {
-            snprintf(buf, sizeof buf, "host:disconnect:");
-        }
-        tmp = adb_query(buf);
-        if (tmp) {
-            printf("%s\n", tmp);
-            return 0;
-        } else {
-            return 1;
-        }
+
+        std::string query = android::base::StringPrintf("host:disconnect:%s",
+                                                        (argc == 2) ? argv[1] : "");
+        return adb_query_command(query);
     }
     else if (!strcmp(argv[0], "emu")) {
         return adb_send_emulator_command(argc, argv);
@@ -1232,7 +1177,8 @@
 
         while (true) {
             D("interactive shell loop. cmd=%s\n", cmd.c_str());
-            int fd = adb_connect(cmd.c_str());
+            std::string error;
+            int fd = adb_connect(cmd, &error);
             int r;
             if (fd >= 0) {
                 D("about to read_and_dump(fd=%d)\n", fd);
@@ -1241,7 +1187,7 @@
                 adb_close(fd);
                 r = 0;
             } else {
-                fprintf(stderr,"error: %s\n", adb_error());
+                fprintf(stderr,"error: %s\n", error.c_str());
                 r = -1;
             }
 
@@ -1270,9 +1216,10 @@
             cmd += " " + escape_arg(*argv++);
         }
 
-        int fd = adb_connect(cmd.c_str());
+        std::string error;
+        int fd = adb_connect(cmd, &error);
         if (fd < 0) {
-            fprintf(stderr, "error: %s\n", adb_error());
+            fprintf(stderr, "error: %s\n", error.c_str());
             return -1;
         }
 
@@ -1286,8 +1233,8 @@
         return 0;
     }
     else if (!strcmp(argv[0], "kill-server")) {
-        int fd;
-        fd = _adb_connect("host:kill");
+        std::string error;
+        int fd = _adb_connect("host:kill", &error);
         if (fd == -1) {
             fprintf(stderr,"* server not running *\n");
             return 1;
@@ -1375,17 +1322,12 @@
 
         // Implement forward --list
         if (list) {
-            if (argc != 1)
+            if (argc != 1) {
                 return usage();
-            snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
-            char* forwards = adb_query(buf);
-            if (forwards == NULL) {
-                fprintf(stderr, "error: %s\n", adb_error());
-                return 1;
             }
-            printf("%s", forwards);
-            free(forwards);
-            return 0;
+
+            std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
+            return adb_query_command(query);
         }
 
         // Implement forward --remove-all
@@ -1412,8 +1354,9 @@
           snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
         }
 
-        if (adb_command(buf)) {
-            fprintf(stderr,"error: %s\n", adb_error());
+        std::string error;
+        if (adb_command(buf, &error)) {
+            fprintf(stderr,"error: %s\n", error.c_str());
             return 1;
         }
         return 0;
@@ -1511,22 +1454,9 @@
         !strcmp(argv[0],"get-serialno") ||
         !strcmp(argv[0],"get-devpath"))
     {
-        char *tmp;
-
-        format_host_command(buf, sizeof buf, argv[0], ttype, serial);
-        tmp = adb_query(buf);
-        if (tmp) {
-            printf("%s\n", tmp);
-            return 0;
-        } else {
-            return 1;
-        }
+        return adb_query_command(format_host_command(argv[0], ttype, serial));
     }
     /* other commands */
-    else if (!strcmp(argv[0],"status-window")) {
-        status_window(ttype, serial);
-        return 0;
-    }
     else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
         return logcat(ttype, serial, argc, argv);
     }
@@ -1534,7 +1464,8 @@
         return ppp(argc, argv);
     }
     else if (!strcmp(argv[0], "start-server")) {
-        return adb_connect("host:start-server");
+        std::string error;
+        return adb_connect("host:start-server", &error);
     }
     else if (!strcmp(argv[0], "backup")) {
         return backup(argc, argv);
@@ -1742,9 +1673,10 @@
     }
 
     // Create install session
-    int fd = adb_connect(cmd.c_str());
+    std::string error;
+    int fd = adb_connect(cmd, &error);
     if (fd < 0) {
-        fprintf(stderr, "Connect error for create: %s\n", adb_error());
+        fprintf(stderr, "Connect error for create: %s\n", error.c_str());
         return -1;
     }
     char buf[BUFSIZ];
@@ -1788,14 +1720,15 @@
 
         int localFd = adb_open(file, O_RDONLY);
         if (localFd < 0) {
-            fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
+            fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
             success = 0;
             goto finalize_session;
         }
 
-        int remoteFd = adb_connect(cmd.c_str());
+        std::string error;
+        int remoteFd = adb_connect(cmd, &error);
         if (remoteFd < 0) {
-            fprintf(stderr, "Connect error for write: %s\n", adb_error());
+            fprintf(stderr, "Connect error for write: %s\n", error.c_str());
             adb_close(localFd);
             success = 0;
             goto finalize_session;
@@ -1817,15 +1750,12 @@
 
 finalize_session:
     // Commit session if we streamed everything okay; otherwise abandon
-    if (success) {
-        snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
-    } else {
-        snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
-    }
-
-    fd = adb_connect(buf);
+    std::string service =
+            android::base::StringPrintf("exec:pm install-%s %d",
+                                        success ? "commit" : "abandon", session_id);
+    fd = adb_connect(service, &error);
     if (fd < 0) {
-        fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
+        fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
         return -1;
     }
     read_status_line(fd, buf, sizeof(buf));
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 49d8783..aded301 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -539,11 +539,11 @@
     printf("%08x %08x %08x %s\n", mode, size, time, name);
 }
 
-int do_sync_ls(const char *path)
-{
-    int fd = adb_connect("sync:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+int do_sync_ls(const char* path) {
+    std::string error;
+    int fd = adb_connect("sync:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
 
@@ -743,11 +743,11 @@
 {
     struct stat st;
     unsigned mode;
-    int fd;
 
-    fd = adb_connect("sync:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+    std::string error;
+    int fd = adb_connect("sync:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
 
@@ -967,11 +967,10 @@
     unsigned mode, time;
     struct stat st;
 
-    int fd;
-
-    fd = adb_connect("sync:");
-    if(fd < 0) {
-        fprintf(stderr,"error: %s\n", adb_error());
+    std::string error;
+    int fd = adb_connect("sync:", &error);
+    if (fd < 0) {
+        fprintf(stderr,"error: %s\n", error.c_str());
         return 1;
     }
 
@@ -1031,9 +1030,10 @@
 {
     fprintf(stderr, "syncing %s...\n", rpath.c_str());
 
-    int fd = adb_connect("sync:");
+    std::string error;
+    int fd = adb_connect("sync:", &error);
     if (fd < 0) {
-        fprintf(stderr, "error: %s\n", adb_error());
+        fprintf(stderr, "error: %s\n", error.c_str());
         return 1;
     }
 
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index d9a1518..59e5b0b 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -271,8 +271,6 @@
     return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
 }
 
-extern char*  adb_strtok_r(char *str, const char *delim, char **saveptr);
-
 #else /* !_WIN32 a.k.a. Unix */
 
 #include "fdevent.h"
@@ -517,19 +515,11 @@
     return path[0] == '/';
 }
 
-static __inline__ char*  adb_strtok_r(char *str, const char *delim, char **saveptr)
-{
-    return strtok_r(str, delim, saveptr);
-}
-
 static __inline__ unsigned long adb_thread_id()
 {
     return (unsigned long)pthread_self();
 }
 
-#undef   strtok_r
-#define  strtok_r  ___xxx_strtok_r
-
 #endif /* !_WIN32 */
 
 #endif /* _ADB_SYSDEPS_H */
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index de47638..633f6f5 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -2151,85 +2151,6 @@
     InitializeCriticalSection( &_win32_lock );
 }
 
-/* Windows doesn't have strtok_r.  Use the one from bionic. */
-
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
- */
-
-char *
-adb_strtok_r(char *s, const char *delim, char **last)
-{
-	char *spanp;
-	int c, sc;
-	char *tok;
-
-
-	if (s == NULL && (s = *last) == NULL)
-		return (NULL);
-
-	/*
-	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
-	 */
-cont:
-	c = *s++;
-	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
-		if (c == sc)
-			goto cont;
-	}
-
-	if (c == 0) {		/* no non-delimiter characters */
-		*last = NULL;
-		return (NULL);
-	}
-	tok = s - 1;
-
-	/*
-	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
-	 * Note that delim must have one NUL; we stop if we see that, too.
-	 */
-	for (;;) {
-		c = *s++;
-		spanp = (char *)delim;
-		do {
-			if ((sc = *spanp++) == c) {
-				if (c == 0)
-					s = NULL;
-				else
-					s[-1] = 0;
-				*last = s;
-				return (tok);
-			}
-		} while (sc != 0);
-	}
-	/* NOTREACHED */
-}
-
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
diff --git a/adb/transport.cpp b/adb/transport.cpp
index d395a80..45740a8 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -847,7 +847,7 @@
                 result = t;
             } else if (ttype == kTransportAny) {
                 if (result) {
-                    if (error_out) *error_out = "more than one device and emulator";
+                    if (error_out) *error_out = "more than one device/emulator";
                     ambiguous = 1;
                     result = NULL;
                     break;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 30e6bf5..4d93bb5 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -105,7 +105,7 @@
         D("client: connected on remote on fd %d\n", fd);
         close_on_exec(fd);
         disable_tcp_nagle(fd);
-        snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
+        snprintf(buf, sizeof buf, "emulator-%d", console_port);
         register_socket_transport(fd, buf, adb_port, 1);
         return 0;
     }
diff --git a/base/Android.mk b/base/Android.mk
index ad85c6b..7bd317b 100644
--- a/base/Android.mk
+++ b/base/Android.mk
@@ -18,11 +18,13 @@
 
 libbase_src_files := \
     file.cpp \
+    logging.cpp \
     stringprintf.cpp \
     strings.cpp \
 
 libbase_test_src_files := \
     file_test.cpp \
+    logging_test.cpp \
     stringprintf_test.cpp \
     strings_test.cpp \
     test_main.cpp \
@@ -38,7 +40,7 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbase
 LOCAL_CLANG := true
-LOCAL_SRC_FILES := $(libbase_src_files) logging.cpp
+LOCAL_SRC_FILES := $(libbase_src_files)
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_CPPFLAGS := $(libbase_cppflags)
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@@ -61,9 +63,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbase
 LOCAL_SRC_FILES := $(libbase_src_files)
-ifneq ($(HOST_OS),windows)
-    LOCAL_SRC_FILES += logging.cpp
-endif
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_CPPFLAGS := $(libbase_cppflags)
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
@@ -85,7 +84,7 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbase_test
 LOCAL_CLANG := true
-LOCAL_SRC_FILES := $(libbase_test_src_files) logging_test.cpp
+LOCAL_SRC_FILES := $(libbase_test_src_files)
 LOCAL_C_INCLUDES := $(LOCAL_PATH)
 LOCAL_CPPFLAGS := $(libbase_cppflags)
 LOCAL_SHARED_LIBRARIES := libbase
@@ -97,9 +96,6 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbase_test
 LOCAL_SRC_FILES := $(libbase_test_src_files)
-ifneq ($(HOST_OS),windows)
-    LOCAL_SRC_FILES += logging_test.cpp
-endif
 LOCAL_C_INCLUDES := $(LOCAL_PATH)
 LOCAL_CPPFLAGS := $(libbase_cppflags)
 LOCAL_SHARED_LIBRARIES := libbase
diff --git a/base/file_test.cpp b/base/file_test.cpp
index e5cf696..b138094 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -36,7 +36,8 @@
 
 TEST(file, ReadFileToString_success) {
   std::string s("hello");
-  ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s))
+    << strerror(errno);
   EXPECT_GT(s.length(), 6U);
   EXPECT_EQ('\n', s[s.length() - 1]);
   s[5] = 0;
@@ -46,37 +47,44 @@
 TEST(file, WriteStringToFile) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
-  ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename)) << errno;
+  ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename))
+    << strerror(errno);
   std::string s;
-  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+    << strerror(errno);
   EXPECT_EQ("abc", s);
 }
 
+// WriteStringToFile2 is explicitly for setting Unix permissions, which make no
+// sense on Windows.
+#if !defined(_WIN32)
 TEST(file, WriteStringToFile2) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
   ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename, 0660,
                                                getuid(), getgid()))
-      << errno;
+      << strerror(errno);
   struct stat sb;
   ASSERT_EQ(0, stat(tf.filename, &sb));
-  ASSERT_EQ(0660U, (sb.st_mode & ~S_IFMT));
+  ASSERT_EQ(0660U, static_cast<unsigned int>(sb.st_mode & ~S_IFMT));
   ASSERT_EQ(getuid(), sb.st_uid);
   ASSERT_EQ(getgid(), sb.st_gid);
   std::string s;
-  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+    << strerror(errno);
   EXPECT_EQ("abc", s);
 }
+#endif
 
 TEST(file, WriteStringToFd) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
   ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
 
-  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << errno;
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
 
   std::string s;
-  ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << strerror(errno);
   EXPECT_EQ("abc", s);
 }
 
@@ -101,6 +109,7 @@
   ASSERT_TRUE(tf.fd != -1);
   ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3));
   std::string s;
-  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+    << strerror(errno);
   EXPECT_EQ("abc", s);
 }
diff --git a/base/include/base/strings.h b/base/include/base/strings.h
index 3559342..5dbc5fb 100644
--- a/base/include/base/strings.h
+++ b/base/include/base/strings.h
@@ -27,8 +27,6 @@
 //
 // The string is split at each occurrence of a character in delimiters.
 //
-// Empty splits will be omitted. I.e. Split("a,,b", ",") -> {"a", "b"}
-//
 // The empty string is not a valid delimiter list.
 std::vector<std::string> Split(const std::string& s,
                                const std::string& delimiters);
diff --git a/base/logging.cpp b/base/logging.cpp
index 0142b70..83957b3 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -27,12 +27,19 @@
 
 #include <iostream>
 #include <limits>
-#include <mutex>
 #include <sstream>
 #include <string>
 #include <utility>
 #include <vector>
 
+#ifndef _WIN32
+#include <mutex>
+#else
+#define NOGDI // Suppress the evil ERROR macro.
+#include <windows.h>
+#endif
+
+#include "base/macros.h"
 #include "base/strings.h"
 #include "cutils/threads.h"
 
@@ -45,10 +52,79 @@
 #include <unistd.h>
 #endif
 
+namespace {
+#ifndef _WIN32
+using std::mutex;
+using std::lock_guard;
+
+#if defined(__GLIBC__)
+const char* getprogname() {
+  return program_invocation_short_name;
+}
+#endif
+
+#else
+const char* getprogname() {
+  static bool first = true;
+  static char progname[MAX_PATH] = {};
+
+  if (first) {
+    // TODO(danalbert): This is a full path on Windows. Just get the basename.
+    DWORD nchars = GetModuleFileName(nullptr, progname, sizeof(progname));
+    DCHECK_GT(nchars, 0U);
+    first = false;
+  }
+
+  return progname;
+}
+
+class mutex {
+ public:
+  mutex() {
+    semaphore_ = CreateSemaphore(nullptr, 1, 1, nullptr);
+    CHECK(semaphore_ != nullptr) << "Failed to create Mutex";
+  }
+  ~mutex() {
+    CloseHandle(semaphore_);
+  }
+
+  void lock() {
+    DWORD result = WaitForSingleObject(semaphore_, INFINITE);
+    CHECK_EQ(result, WAIT_OBJECT_0) << GetLastError();
+  }
+
+  void unlock() {
+    bool result = ReleaseSemaphore(semaphore_, 1, nullptr);
+    CHECK(result);
+  }
+
+ private:
+  HANDLE semaphore_;
+};
+
+template <typename LockT>
+class lock_guard {
+ public:
+  explicit lock_guard(LockT& lock) : lock_(lock) {
+    lock_.lock();
+  }
+
+  ~lock_guard() {
+    lock_.unlock();
+  }
+
+ private:
+  LockT& lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(lock_guard);
+};
+#endif
+} // namespace
+
 namespace android {
 namespace base {
 
-static std::mutex logging_lock;
+static mutex logging_lock;
 
 #ifdef __ANDROID__
 static LogFunction gLogger = LogdLogger();
@@ -60,12 +136,6 @@
 static LogSeverity gMinimumLogSeverity = INFO;
 static std::unique_ptr<std::string> gProgramInvocationName;
 
-#if defined(__GLIBC__)
-static const char* getprogname() {
-  return program_invocation_short_name;
-}
-#endif
-
 static const char* ProgramInvocationName() {
   if (gProgramInvocationName == nullptr) {
     gProgramInvocationName.reset(new std::string(getprogname()));
@@ -182,7 +252,7 @@
 }
 
 void SetLogger(LogFunction&& logger) {
-  std::lock_guard<std::mutex> lock(logging_lock);
+  lock_guard<mutex> lock(logging_lock);
   gLogger = std::move(logger);
 }
 
@@ -287,7 +357,7 @@
 void LogMessage::LogLine(const char* file, unsigned int line, LogId id,
                          LogSeverity severity, const char* message) {
   const char* tag = ProgramInvocationName();
-  std::lock_guard<std::mutex> lock(logging_lock);
+  lock_guard<mutex> lock(logging_lock);
   gLogger(id, severity, tag, file, line, message);
 }
 
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index d947c1d..c91857a 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -85,6 +85,9 @@
 TEST(logging, LOG) {
   ASSERT_DEATH(LOG(FATAL) << "foobar", "foobar");
 
+  // 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";
@@ -92,10 +95,13 @@
 
     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::WARNING, "foobar"));
     ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
   }
 
   {
@@ -105,10 +111,13 @@
 
     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));
+#endif
   }
 
   {
@@ -129,10 +138,13 @@
 
     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));
+#endif
   }
 }
 
@@ -145,10 +157,13 @@
 
     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: No such file or directory"));
     ASSERT_TRUE(std::regex_search(output, message_regex));
+#endif
   }
 }
 
@@ -161,11 +176,14 @@
 
     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));
+#endif
   }
 }
diff --git a/base/stringprintf_test.cpp b/base/stringprintf_test.cpp
index 5cc2086..54b2b6c 100644
--- a/base/stringprintf_test.cpp
+++ b/base/stringprintf_test.cpp
@@ -20,11 +20,14 @@
 
 #include <string>
 
+// The z size sepcifier isn't supported on Windows, so this test isn't useful.
+#if !defined(_WIN32)
 TEST(StringPrintfTest, HexSizeT) {
   size_t size = 0x00107e59;
   EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size));
   EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size));
 }
+#endif
 
 TEST(StringPrintfTest, StringAppendF) {
   std::string s("a");
diff --git a/base/strings.cpp b/base/strings.cpp
index 6f698d9..d3375d9 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -32,24 +32,17 @@
                                const std::string& delimiters) {
   CHECK_NE(delimiters.size(), 0U);
 
-  std::vector<std::string> split;
-  if (s.size() == 0) {
-    // Split("", d) returns {} rather than {""}.
-    return split;
-  }
+  std::vector<std::string> result;
 
   size_t base = 0;
   size_t found;
   do {
     found = s.find_first_of(delimiters, base);
-    if (found != base) {
-      split.push_back(s.substr(base, found - base));
-    }
-
+    result.push_back(s.substr(base, found - base));
     base = found + 1;
   } while (found != s.npos);
 
-  return split;
+  return result;
 }
 
 std::string Trim(const std::string& s) {
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index 1bf07a1..46a1ab5 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -23,7 +23,8 @@
 
 TEST(strings, split_empty) {
   std::vector<std::string> parts = android::base::Split("", ",");
-  ASSERT_EQ(0U, parts.size());
+  ASSERT_EQ(1U, parts.size());
+  ASSERT_EQ("", parts[0]);
 }
 
 TEST(strings, split_single) {
@@ -42,9 +43,10 @@
 
 TEST(strings, split_with_empty_part) {
   std::vector<std::string> parts = android::base::Split("foo,,bar", ",");
-  ASSERT_EQ(2U, parts.size());
+  ASSERT_EQ(3U, parts.size());
   ASSERT_EQ("foo", parts[0]);
-  ASSERT_EQ("bar", parts[1]);
+  ASSERT_EQ("", parts[1]);
+  ASSERT_EQ("bar", parts[2]);
 }
 
 TEST(strings, split_null_char) {
@@ -65,9 +67,10 @@
 
 TEST(strings, split_any_with_empty_part) {
   std::vector<std::string> parts = android::base::Split("foo:,bar", ",:");
-  ASSERT_EQ(2U, parts.size());
+  ASSERT_EQ(3U, parts.size());
   ASSERT_EQ("foo", parts[0]);
-  ASSERT_EQ("bar", parts[1]);
+  ASSERT_EQ("", parts[1]);
+  ASSERT_EQ("bar", parts[2]);
 }
 
 TEST(strings, trim_empty) {
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 1f6d3cf..0517bc7 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -16,15 +16,26 @@
 
 #include "test_utils.h"
 
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
 TemporaryFile::TemporaryFile() {
+#if defined(__ANDROID__)
   init("/data/local/tmp");
-  if (fd == -1) {
-    init("/tmp");
-  }
+#elif defined(_WIN32)
+  char wd[MAX_PATH] = {};
+  _getcwd(wd, sizeof(wd));
+  init(wd);
+#else
+  init("/tmp");
+#endif
 }
 
 TemporaryFile::~TemporaryFile() {
@@ -34,5 +45,15 @@
 
 void TemporaryFile::init(const char* tmp_dir) {
   snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
+#if !defined(_WIN32)
   fd = mkstemp(filename);
+#else
+  // Windows doesn't have mkstemp, and tmpfile creates the file in the root
+  // directory, requiring root (?!) permissions. We have to settle for mktemp.
+  if (mktemp(filename) == nullptr) {
+    abort();
+  }
+
+  fd = open(filename, O_RDWR | O_NOINHERIT | O_CREAT, _S_IREAD | _S_IWRITE);
+#endif
 }
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 7b2975b..dee471a 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -58,7 +58,8 @@
     libsparse_host \
     libutils \
     liblog \
-    libz
+    libz \
+    libbase
 
 ifneq ($(HOST_OS),windows)
 LOCAL_STATIC_LIBRARIES += libselinux
diff --git a/include/cutils/threads.h b/include/cutils/threads.h
index 3133cdb..5727494 100644
--- a/include/cutils/threads.h
+++ b/include/cutils/threads.h
@@ -17,6 +17,14 @@
 #ifndef _LIBS_CUTILS_THREADS_H
 #define _LIBS_CUTILS_THREADS_H
 
+#include  <sys/types.h>
+
+#if !defined(_WIN32)
+#include <pthread.h>
+#else
+#include <windows.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -29,10 +37,9 @@
 /***********************************************************************/
 /***********************************************************************/
 
-#if !defined(_WIN32)
+extern pid_t gettid();
 
-#include  <pthread.h>
-#include  <sys/types.h>
+#if !defined(_WIN32)
 
 typedef struct {
     pthread_mutex_t   lock;
@@ -40,14 +47,10 @@
     pthread_key_t     tls;
 } thread_store_t;
 
-extern pid_t gettid();
-
 #define  THREAD_STORE_INITIALIZER  { PTHREAD_MUTEX_INITIALIZER, 0, 0 }
 
 #else // !defined(_WIN32)
 
-#include <windows.h>
-
 typedef struct {
     int               lock_init;
     int               has_tls;
diff --git a/include/log/log.h b/include/log/log.h
index ce253e2..f9299b0 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -492,6 +492,7 @@
     EVENT_TYPE_LONG     = 1,
     EVENT_TYPE_STRING   = 2,
     EVENT_TYPE_LIST     = 3,
+    EVENT_TYPE_FLOAT    = 4,
 } AndroidEventLogType;
 #define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType)
 #define typeof_AndroidEventLogType unsigned char
@@ -510,6 +511,13 @@
             sizeof(longBuf));                                               \
     }
 #endif
+#ifndef LOG_EVENT_FLOAT
+#define LOG_EVENT_FLOAT(_tag, _value) {                                     \
+        float floatBuf = _value;                                            \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_FLOAT, &floatBuf,        \
+            sizeof(floatBuf));                                              \
+    }
+#endif
 #ifndef LOG_EVENT_STRING
 #define LOG_EVENT_STRING(_tag, _value)                                      \
         (void) __android_log_bswrite(_tag, _value);
diff --git a/include/system/window.h b/include/system/window.h
index a875427..508ce00 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -267,7 +267,16 @@
      * The default data space for the buffers as set by the consumer.
      * The values are defined in graphics.h.
      */
-    NATIVE_WINDOW_DEFAULT_DATASPACE = 12
+    NATIVE_WINDOW_DEFAULT_DATASPACE = 12,
+
+    /*
+     * Returns the age of the contents of the most recently dequeued buffer as
+     * the number of frames that have elapsed since it was last queued. For
+     * example, if the window is double-buffered, the age of any given buffer in
+     * steady state will be 2. If the dequeued buffer has never been queued, its
+     * age will be 0.
+     */
+    NATIVE_WINDOW_BUFFER_AGE = 13,
 };
 
 /* Valid operations for the (*perform)() hook.
diff --git a/init/Android.mk b/init/Android.mk
index 4bd4f3d..0dc257d 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -5,9 +5,9 @@
 # --
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_DISABLE_SELINUX=1
+init_options += -DALLOW_LOCAL_PROP_OVERRIDE=1 -DALLOW_PERMISSIVE_SELINUX=1
 else
-init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_DISABLE_SELINUX=0
+init_options += -DALLOW_LOCAL_PROP_OVERRIDE=0 -DALLOW_PERMISSIVE_SELINUX=0
 endif
 
 init_options += -DLOG_UEVENTS=0
diff --git a/init/init.cpp b/init/init.cpp
index dd74538..68c8b7f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -860,7 +860,7 @@
     sehandle_prop = selinux_android_prop_context_handle();
 }
 
-enum selinux_enforcing_status { SELINUX_DISABLED, SELINUX_PERMISSIVE, SELINUX_ENFORCING };
+enum selinux_enforcing_status { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
 
 static selinux_enforcing_status selinux_status_from_cmdline() {
     selinux_enforcing_status status = SELINUX_ENFORCING;
@@ -870,9 +870,7 @@
         if (value == nullptr) { return; }
         *value++ = '\0';
         if (strcmp(name, "androidboot.selinux") == 0) {
-            if (strcmp(value, "disabled") == 0) {
-                status = SELINUX_DISABLED;
-            } else if (strcmp(value, "permissive") == 0) {
+            if (strcmp(value, "permissive") == 0) {
                 status = SELINUX_PERMISSIVE;
             }
         }
@@ -882,24 +880,9 @@
     return status;
 }
 
-
-static bool selinux_is_disabled(void)
-{
-    if (ALLOW_DISABLE_SELINUX) {
-        if (access("/sys/fs/selinux", F_OK) != 0) {
-            // SELinux is not compiled into the kernel, or has been disabled
-            // via the kernel command line "selinux=0".
-            return true;
-        }
-        return selinux_status_from_cmdline() == SELINUX_DISABLED;
-    }
-
-    return false;
-}
-
 static bool selinux_is_enforcing(void)
 {
-    if (ALLOW_DISABLE_SELINUX) {
+    if (ALLOW_PERMISSIVE_SELINUX) {
         return selinux_status_from_cmdline() == SELINUX_ENFORCING;
     }
     return true;
@@ -907,10 +890,6 @@
 
 int selinux_reload_policy(void)
 {
-    if (selinux_is_disabled()) {
-        return -1;
-    }
-
     INFO("SELinux: Attempting to reload policy files\n");
 
     if (selinux_android_reload_policy() == -1) {
@@ -947,10 +926,6 @@
     cb.func_audit = audit_callback;
     selinux_set_callback(SELINUX_CB_AUDIT, cb);
 
-    if (selinux_is_disabled()) {
-        return;
-    }
-
     if (in_kernel_domain) {
         INFO("Loading SELinux policy...\n");
         if (selinux_android_load_policy() < 0) {
@@ -958,8 +933,15 @@
             security_failure();
         }
 
+        bool kernel_enforcing = (security_getenforce() == 1);
         bool is_enforcing = selinux_is_enforcing();
-        security_setenforce(is_enforcing);
+        if (kernel_enforcing != is_enforcing) {
+            if (security_setenforce(is_enforcing)) {
+                ERROR("security_setenforce(%s) failed: %s\n",
+                      is_enforcing ? "true" : "false", strerror(errno));
+                security_failure();
+            }
+        }
 
         if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) {
             security_failure();
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 54cace9..a2b4cfe 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -51,18 +51,10 @@
 	UnwindMap.cpp \
 	UnwindPtrace.cpp \
 
-libbacktrace_shared_libraries_target := \
-	libcutils \
-
 libbacktrace_shared_libraries := \
 	libbase \
-	libunwind \
-
-libbacktrace_shared_libraries_host := \
 	liblog \
-
-libbacktrace_static_libraries_host := \
-	libcutils \
+	libunwind \
 
 libbacktrace_ldlibs_host := \
 	-lpthread \
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 91ca8b7..b2d8297 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -27,6 +27,8 @@
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 
+#include <cutils/threads.h>
+
 #include "BacktraceLog.h"
 #include "thread_utils.h"
 #include "UnwindCurrent.h"
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index fd1f4da..14f04de 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -29,6 +29,8 @@
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 
+#include <cutils/threads.h>
+
 #include "BacktraceCurrent.h"
 #include "BacktraceLog.h"
 #include "ThreadEntry.h"
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index b0ada46..ca47f67 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -135,7 +135,7 @@
 #if defined(__APPLE__)
 // Corkscrew and libunwind don't compile on the mac, so create a generic
 // map object.
-BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) {
+BacktraceMap* BacktraceMap::Create(pid_t pid, bool /*uncached*/) {
   BacktraceMap* map = new BacktraceMap(pid);
   if (!map->Build()) {
     delete map;
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 4af6592..36c73c5 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -30,20 +30,21 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-// For the THREAD_SIGNAL definition.
-#include "BacktraceCurrent.h"
-
-#include <cutils/atomic.h>
-#include <gtest/gtest.h>
-
 #include <algorithm>
 #include <memory>
 #include <string>
 #include <vector>
 
+#include <backtrace/Backtrace.h>
+#include <backtrace/BacktraceMap.h>
+
+#include <cutils/atomic.h>
+#include <cutils/threads.h>
+
+#include <gtest/gtest.h>
+
+// For the THREAD_SIGNAL definition.
+#include "BacktraceCurrent.h"
 #include "thread_utils.h"
 
 // Number of microseconds per milliseconds.
diff --git a/libbacktrace/thread_utils.c b/libbacktrace/thread_utils.c
index 6f4cd3c..e75f56e 100644
--- a/libbacktrace/thread_utils.c
+++ b/libbacktrace/thread_utils.c
@@ -16,25 +16,12 @@
 
 #include "thread_utils.h"
 
-#if defined(__APPLE__)
+#if !defined(__BIONIC__)
 
-#include <sys/syscall.h>
-
-// Mac OS >= 10.6 has a system call equivalent to Linux's gettid().
-pid_t gettid() {
-  return syscall(SYS_thread_selfid);
-}
-
-#elif !defined(__BIONIC__)
-
-// glibc doesn't implement or export either gettid or tgkill.
+// glibc doesn't implement or export tgkill.
 #include <unistd.h>
 #include <sys/syscall.h>
 
-pid_t gettid() {
-  return syscall(__NR_gettid);
-}
-
 int tgkill(int tgid, int tid, int sig) {
   return syscall(__NR_tgkill, tgid, tid, sig);
 }
diff --git a/libbacktrace/thread_utils.h b/libbacktrace/thread_utils.h
index ae4c929..df83581 100644
--- a/libbacktrace/thread_utils.h
+++ b/libbacktrace/thread_utils.h
@@ -23,8 +23,6 @@
 
 int tgkill(int tgid, int tid, int sig);
 
-pid_t gettid();
-
 __END_DECLS
 
 #endif /* _LIBBACKTRACE_THREAD_UTILS_H */
diff --git a/libcutils/threads.c b/libcutils/threads.c
index 5f5577b..036f8c5 100644
--- a/libcutils/threads.c
+++ b/libcutils/threads.c
@@ -16,8 +16,6 @@
 
 #include "cutils/threads.h"
 
-#if !defined(_WIN32)
-
 // For gettid.
 #if defined(__APPLE__)
 #include "AvailabilityMacros.h"  // For MAC_OS_X_VERSION_MAX_ALLOWED
@@ -30,9 +28,24 @@
 #include <syscall.h>
 #include <unistd.h>
 #elif defined(_WIN32)
-#include <Windows.h>
+#include <windows.h>
 #endif
 
+// No definition needed for Android because we'll just pick up bionic's copy.
+#ifndef __ANDROID__
+pid_t gettid() {
+#if defined(__APPLE__)
+  return syscall(SYS_thread_selfid);
+#elif defined(__linux__)
+  return syscall(__NR_gettid);
+#elif defined(_WIN32)
+  return GetCurrentThreadId();
+#endif
+}
+#endif  // __ANDROID__
+
+#if !defined(_WIN32)
+
 void*  thread_store_get( thread_store_t*  store )
 {
     if (!store->has_tls)
@@ -58,24 +71,6 @@
     pthread_setspecific( store->tls, value );
 }
 
-// No definition needed for Android because we'll just pick up bionic's copy.
-#ifndef __ANDROID__
-pid_t gettid() {
-#if defined(__APPLE__)
-  uint64_t owner;
-  int rc = pthread_threadid_np(NULL, &owner);
-  if (rc != 0) {
-    abort();
-  }
-  return owner;
-#elif defined(__linux__)
-  return syscall(__NR_gettid);
-#elif defined(_WIN32)
-  return (pid_t)GetCurrentThreadId();
-#endif
-}
-#endif  // __ANDROID__
-
 #else /* !defined(_WIN32) */
 void*  thread_store_get( thread_store_t*  store )
 {
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 7ba4c8e..0f01542 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
 #include <sys/param.h>
 
 #include <log/logd.h>
@@ -432,7 +433,7 @@
 
     low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
     high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-    return ((long long) high << 32) | (long long) low;
+    return ((uint64_t) high << 32) | (uint64_t) low;
 }
 
 
@@ -490,7 +491,7 @@
     case EVENT_TYPE_LONG:
         /* 64-bit signed long */
         {
-            long long lval;
+            uint64_t lval;
 
             if (eventDataLen < 8)
                 return -1;
@@ -498,7 +499,30 @@
             eventData += 8;
             eventDataLen -= 8;
 
-            outCount = snprintf(outBuf, outBufLen, "%lld", lval);
+            outCount = snprintf(outBuf, outBufLen, "%" PRId64, lval);
+            if (outCount < outBufLen) {
+                outBuf += outCount;
+                outBufLen -= outCount;
+            } else {
+                /* halt output */
+                goto no_room;
+            }
+        }
+        break;
+    case EVENT_TYPE_FLOAT:
+        /* float */
+        {
+            uint32_t ival;
+            float fval;
+
+            if (eventDataLen < 4)
+                return -1;
+            ival = get4LE(eventData);
+            fval = *(float*)&ival;
+            eventData += 4;
+            eventDataLen -= 4;
+
+            outCount = snprintf(outBuf, outBufLen, "%f", fval);
             if (outCount < outBufLen) {
                 outBuf += outCount;
                 outBufLen -= outCount;
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index 6ece31d..c70d45f 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -135,7 +135,7 @@
           break;
         else:
           crc_bin = FH.read(4)
-          crc = struct.unpack("<I", crc)
+          crc = struct.unpack("<I", crc_bin)
           print("Unverified CRC32 0x%08X" % (crc))
       else:
           print("Unknown chunk type 0x%04X" % (chunk_type), end="")
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 34131f1..79c4c53 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -30,6 +30,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/file.h"
 #include "base/macros.h"  // TEMP_FAILURE_RETRY may or may not be in unistd
 #include "base/memory.h"
 #include "log/log.h"
@@ -1033,24 +1034,14 @@
       return false;
     }
 
-    // Keep track of the start position so we can calculate the
-    // total number of bytes written.
-    const uint8_t* const start = buf;
-    while (buf_size > 0) {
-      ssize_t bytes_written = TEMP_FAILURE_RETRY(write(fd_, buf, buf_size));
-      if (bytes_written == -1) {
-        ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
-        return false;
-      }
-
-      buf_size -= bytes_written;
-      buf += bytes_written;
+    const bool result = android::base::WriteFully(fd_, buf, buf_size);
+    if (result) {
+      total_bytes_written_ += buf_size;
+    } else {
+      ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
     }
 
-    total_bytes_written_ += static_cast<size_t>(
-        reinterpret_cast<uintptr_t>(buf) - reinterpret_cast<uintptr_t>(start));
-
-    return true;
+    return result;
   }
  private:
   FileWriter(const int fd, const size_t declared_length) :
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 1b5c6f4..909f8e2 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -21,6 +21,7 @@
 # 2: long
 # 3: string
 # 4: list
+# 5: float
 #
 # The data unit is a number taken from the following list:
 # 1: Number of objects
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 1dced11..b6b6124 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -295,7 +295,8 @@
         uint64_t current = e->getRealTime().nsec() - NS_PER_SEC;
         ssize_t index = -1;
         while((index = next(index)) >= 0) {
-            if (current > editEntryAt(index).getLast()->getRealTime().nsec()) {
+            LogBufferElement *l = editEntryAt(index).getLast();
+            if ((l->getDropped() >= 4) && (current > l->getRealTime().nsec())) {
                 removeAt(index);
                 index = -1;
             }
@@ -630,7 +631,7 @@
         pthread_mutex_unlock(&mLogElementsLock);
 
         // range locking in LastLogTimes looks after us
-        max = element->flushTo(reader);
+        max = element->flushTo(reader, this);
 
         if (max == element->FLUSH_ERROR) {
             return max;
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 9ee243d..00b19b6 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -74,6 +74,7 @@
     // helper
     char *pidToName(pid_t pid) { return stats.pidToName(pid); }
     uid_t pidToUid(pid_t pid) { return stats.pidToUid(pid); }
+    char *uidToName(uid_t uid) { return stats.uidToName(uid); }
 
 private:
     void maybePrune(log_id_t id);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index a173e63..6a05700 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
 #include <endian.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
@@ -48,19 +50,89 @@
     delete [] mMsg;
 }
 
-// assumption: mMsg == NULL
-size_t LogBufferElement::populateDroppedMessage(char *&buffer, bool privileged) {
-    static const char format_uid[] = "uid=%u dropped=%u";
-    static const size_t unprivileged_offset = 7;
-    static const char tag[] = "logd";
-
-    size_t len;
-    if (privileged) {
-        len = snprintf(NULL, 0, format_uid, mUid, mDropped);
-    } else {
-        len = snprintf(NULL, 0, format_uid + unprivileged_offset, mDropped);
+// caller must own and free character string
+static char *tidToName(pid_t tid) {
+    char *retval = NULL;
+    char buffer[256];
+    snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid);
+    int fd = open(buffer, O_RDONLY);
+    if (fd >= 0) {
+        ssize_t ret = read(fd, buffer, sizeof(buffer));
+        if (ret >= (ssize_t)sizeof(buffer)) {
+            ret = sizeof(buffer) - 1;
+        }
+        while ((ret > 0) && isspace(buffer[ret - 1])) {
+            --ret;
+        }
+        if (ret > 0) {
+            buffer[ret] = '\0';
+            retval = strdup(buffer);
+        }
+        close(fd);
     }
 
+    // if nothing for comm, check out cmdline
+    char *name = android::pidToName(tid);
+    if (!retval) {
+        retval = name;
+        name = NULL;
+    }
+
+    // check if comm is truncated, see if cmdline has full representation
+    if (name) {
+        // impossible for retval to be NULL if name not NULL
+        size_t retval_len = strlen(retval);
+        size_t name_len = strlen(name);
+        // KISS: ToDo: Only checks prefix truncated, not suffix, or both
+        if ((retval_len < name_len) && !strcmp(retval, name + name_len - retval_len)) {
+            free(retval);
+            retval = name;
+        } else {
+            free(name);
+        }
+    }
+    return retval;
+}
+
+// assumption: mMsg == NULL
+size_t LogBufferElement::populateDroppedMessage(char *&buffer,
+        LogBuffer *parent) {
+    static const char tag[] = "logd";
+    static const char format_uid[] = "uid=%u%s too chatty%s, expire %u line%s";
+
+    char *name = parent->uidToName(mUid);
+    char *commName = tidToName(mTid);
+    if (!commName && (mTid != mPid)) {
+        commName = tidToName(mPid);
+    }
+    if (!commName) {
+        commName = parent->pidToName(mPid);
+    }
+    if (name && commName && !strcmp(name, commName)) {
+        free(commName);
+        commName = NULL;
+    }
+    if (name) {
+        char *p = NULL;
+        asprintf(&p, "(%s)", name);
+        if (p) {
+            free(name);
+            name = p;
+        }
+    }
+    if (commName) {
+        char *p = NULL;
+        asprintf(&p, " comm=%s", commName);
+        if (p) {
+            free(commName);
+            commName = p;
+        }
+    }
+    // identical to below to calculate the buffer size required
+    size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "",
+                          commName ? commName : "",
+                          mDropped, (mDropped > 1) ? "s" : "");
+
     size_t hdrLen;
     if (mLogId == LOG_ID_EVENTS) {
         hdrLen = sizeof(android_log_event_string_t);
@@ -70,6 +142,8 @@
 
     buffer = static_cast<char *>(calloc(1, hdrLen + len + 1));
     if (!buffer) {
+        free(name);
+        free(commName);
         return 0;
     }
 
@@ -86,16 +160,16 @@
         strcpy(buffer + 1, tag);
     }
 
-    if (privileged) {
-        snprintf(buffer + hdrLen, len + 1, format_uid, mUid, mDropped);
-    } else {
-        snprintf(buffer + hdrLen, len + 1, format_uid + unprivileged_offset, mDropped);
-    }
+    snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
+             commName ? commName : "",
+             mDropped, (mDropped > 1) ? "s" : "");
+    free(name);
+    free(commName);
 
     return retval;
 }
 
-uint64_t LogBufferElement::flushTo(SocketClient *reader) {
+uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent) {
     struct logger_entry_v3 entry;
 
     memset(&entry, 0, sizeof(struct logger_entry_v3));
@@ -114,7 +188,7 @@
     char *buffer = NULL;
 
     if (!mMsg) {
-        entry.len = populateDroppedMessage(buffer, clientHasLogCredentials(reader));
+        entry.len = populateDroppedMessage(buffer, parent);
         if (!entry.len) {
             return mSequence;
         }
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 7b6456d..059c031 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -28,15 +28,19 @@
 namespace android {
 
 // Furnished in main.cpp. Caller must own and free returned value
-// This function is designed for a single caller and is NOT thread-safe
 char *uidToName(uid_t uid);
 
+// Furnished in LogStatistics.cpp. Caller must own and free returned value
+char *pidToName(pid_t pid);
+
 }
 
 static inline bool worstUidEnabledForLogid(log_id_t id) {
     return (id != LOG_ID_CRASH) && (id != LOG_ID_EVENTS);
 }
 
+class LogBuffer;
+
 class LogBufferElement {
     const log_id_t mLogId;
     const uid_t mUid;
@@ -52,7 +56,8 @@
     static atomic_int_fast64_t sequence;
 
     // assumption: mMsg == NULL
-    size_t populateDroppedMessage(char *&buffer, bool privileged);
+    size_t populateDroppedMessage(char *&buffer,
+                                  LogBuffer *parent);
 
 public:
     LogBufferElement(log_id_t log_id, log_time realtime,
@@ -78,7 +83,7 @@
     log_time getRealTime(void) const { return mRealTime; }
 
     static const uint64_t FLUSH_ERROR;
-    uint64_t flushTo(SocketClient *writer);
+    uint64_t flushTo(SocketClient *writer, LogBuffer *parent);
 };
 
 #endif
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index eadc4dd..b063630 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -39,7 +39,7 @@
 namespace android {
 
 // caller must own and free character string
-static char *pidToName(pid_t pid) {
+char *pidToName(pid_t pid) {
     char *retval = NULL;
     if (pid == 0) { // special case from auditd for kernel
         retval = strdup("logd.auditd");
diff --git a/logd/main.cpp b/logd/main.cpp
index eb29596..237c7c1 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -210,18 +210,26 @@
     return NULL;
 }
 
+static sem_t sem_name;
+
 char *android::uidToName(uid_t u) {
     if (!u || !reinit_running) {
         return NULL;
     }
 
-    // Not multi-thread safe, we know there is only one caller
+    sem_wait(&sem_name);
+
+    // Not multi-thread safe, we use sem_name to protect
     uid = u;
 
     name = NULL;
     sem_post(&reinit);
     sem_wait(&uidName);
-    return name;
+    char *ret = name;
+
+    sem_post(&sem_name);
+
+    return ret;
 }
 
 // Serves as a global method to trigger reinitialization
@@ -277,6 +285,7 @@
     // Reinit Thread
     sem_init(&reinit, 0, 0);
     sem_init(&uidName, 0, 0);
+    sem_init(&sem_name, 0, 1);
     pthread_attr_t attr;
     if (!pthread_attr_init(&attr)) {
         struct sched_param param;