am 6269a95a: resolved conflicts for merge of b67b92f2 to lmp-mr1-ub-dev

* commit '6269a95a8fe74193d25039cda45b42bfac243586':
  Do not dump maps/memory/code of sibling threads. DO NOT MERGE
diff --git a/adb/Android.mk b/adb/Android.mk
index 6951904..1613a88 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -11,6 +11,13 @@
   adb_host_clang := true
 endif
 
+adb_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=12 HEAD 2>/dev/null)-android
+
+ADB_COMMON_CFLAGS := \
+    -Wall -Werror \
+    -Wno-unused-parameter \
+    -DADB_REVISION='"$(adb_version)"' \
+
 # libadb
 # =========================================================
 
@@ -37,8 +44,7 @@
     transport_test.cpp \
 
 LIBADB_CFLAGS := \
-    -Wall -Werror \
-    -Wno-unused-parameter \
+    $(ADB_COMMON_CFLAGS) \
     -Wno-missing-field-initializers \
     -fvisibility=hidden \
 
@@ -124,6 +130,21 @@
 
 include $(BUILD_HOST_NATIVE_TEST)
 
+# adb device tracker (used by ddms) test tool
+# =========================================================
+
+ifeq ($(HOST_OS),linux)
+include $(CLEAR_VARS)
+LOCAL_CLANG := $(adb_host_clang)
+LOCAL_MODULE := adb_device_tracker_test
+LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
+LOCAL_SRC_FILES := test_track_devices.cpp
+LOCAL_SHARED_LIBRARIES := liblog libbase
+LOCAL_STATIC_LIBRARIES := libadb libcrypto_static libcutils
+LOCAL_LDLIBS += -lrt -ldl -lpthread
+include $(BUILD_HOST_EXECUTABLE)
+endif
+
 # adb host tool
 # =========================================================
 include $(CLEAR_VARS)
@@ -154,8 +175,7 @@
     file_sync_client.cpp \
 
 LOCAL_CFLAGS += \
-    -Wall -Werror \
-    -Wno-unused-parameter \
+    $(ADB_COMMON_CFLAGS) \
     -D_GNU_SOURCE \
     -DADB_HOST=1 \
 
@@ -167,6 +187,7 @@
     libbase \
     libcrypto_static \
     libcutils \
+    liblog \
     $(EXTRA_STATIC_LIBS) \
 
 # libc++ not available on windows yet
@@ -206,10 +227,9 @@
     set_verity_enable_state_service.cpp \
 
 LOCAL_CFLAGS := \
+    $(ADB_COMMON_CFLAGS) \
     -DADB_HOST=0 \
     -D_GNU_SOURCE \
-    -Wall -Werror \
-    -Wno-unused-parameter \
     -Wno-deprecated-declarations \
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
diff --git a/adb/adb.cpp b/adb/adb.cpp
index de82cd4..8a7b9c9 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"
@@ -47,9 +48,7 @@
 #include <sys/mount.h>
 #endif
 
-#if ADB_TRACE
 ADB_MUTEX_DEFINE( D_lock );
-#endif
 
 int HOST = 0;
 
@@ -90,10 +89,8 @@
     char timestamp[PATH_MAX];
     strftime(timestamp, sizeof(timestamp), "%Y-%m-%d-%H-%M-%S", &now);
 
-    char path[PATH_MAX];
-    snprintf(path, sizeof(path), "/data/adb/adb-%s-%d", timestamp, getpid());
-
-    int fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
+    std::string path = android::base::StringPrintf("/data/adb/adb-%s-%d", timestamp, getpid());
+    int fd = unix_open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
     if (fd == -1) {
         return;
     }
@@ -321,28 +318,6 @@
 #endif
 }
 
-#if !ADB_HOST
-static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
-    char header[5];
-    if (msglen > 0xffff)
-        msglen = 0xffff;
-    snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
-    WriteFdExactly(fd, header, 4);
-    WriteFdExactly(fd, msg, msglen);
-}
-#endif
-
-#if ADB_HOST
-static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
-    char header[9];
-    if (msglen > 0xffff)
-        msglen = 0xffff;
-    snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
-    WriteFdExactly(fd, header, 8);
-    WriteFdExactly(fd, msg, msglen);
-}
-#endif // ADB_HOST
-
 void send_connect(atransport *t)
 {
     D("Calling send_connect \n");
@@ -355,113 +330,64 @@
     send_packet(cp, t);
 }
 
-#if ADB_HOST
-static const char* connection_state_name(atransport *t)
-{
-    if (t == NULL) {
-        return "unknown";
-    }
-
-    switch(t->connection_state) {
-    case CS_BOOTLOADER:
-        return "bootloader";
-    case CS_DEVICE:
-        return "device";
-    case CS_RECOVERY:
-        return "recovery";
-    case CS_SIDELOAD:
-        return "sideload";
-    case CS_OFFLINE:
-        return "offline";
-    case CS_UNAUTHORIZED:
-        return "unauthorized";
-    default:
-        return "unknown";
-    }
-}
-#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 +419,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);
@@ -774,20 +700,11 @@
 {
     if (!strcmp(service, "list-forward")) {
         // Create the list of forward redirections.
-        int buffer_size = format_listeners(NULL, 0);
-        // Add one byte for the trailing zero.
-        char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1));
-        if (buffer == nullptr) {
-            sendfailmsg(reply_fd, "not enough memory");
-            return 1;
-        }
-        (void) format_listeners(buffer, buffer_size + 1);
+        std::string listeners = format_listeners();
 #if ADB_HOST
-        send_msg_with_okay(reply_fd, buffer, buffer_size);
-#else
-        send_msg_with_header(reply_fd, buffer, buffer_size);
+        SendOkay(reply_fd);
 #endif
-        free(buffer);
+        SendProtocolString(reply_fd, listeners);
         return 1;
     }
 
@@ -795,9 +712,9 @@
         remove_all_listeners();
 #if ADB_HOST
         /* On the host: 1st OKAY is connect, 2nd OKAY is status */
-        adb_write(reply_fd, "OKAY", 4);
+        SendOkay(reply_fd);
 #endif
-        adb_write(reply_fd, "OKAY", 4);
+        SendOkay(reply_fd);
         return 1;
     }
 
@@ -822,19 +739,19 @@
         if (createForward) {
             // Check forward: parameter format: '<local>;<remote>'
             if(remote == 0) {
-                sendfailmsg(reply_fd, "malformed forward spec");
+                SendFail(reply_fd, "malformed forward spec");
                 return 1;
             }
 
             *remote++ = 0;
             if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
-                sendfailmsg(reply_fd, "malformed forward spec");
+                SendFail(reply_fd, "malformed forward spec");
                 return 1;
             }
         } else {
             // Check killforward: parameter format: '<local>'
             if (local[0] == 0) {
-                sendfailmsg(reply_fd, "malformed forward spec");
+                SendFail(reply_fd, "malformed forward spec");
                 return 1;
             }
         }
@@ -842,7 +759,7 @@
         std::string error_msg;
         transport = acquire_one_transport(CS_ANY, ttype, serial, &error_msg);
         if (!transport) {
-            sendfailmsg(reply_fd, error_msg.c_str());
+            SendFail(reply_fd, error_msg);
             return 1;
         }
 
@@ -855,9 +772,9 @@
         if (r == INSTALL_STATUS_OK) {
 #if ADB_HOST
             /* On the host: 1st OKAY is connect, 2nd OKAY is status */
-            WriteFdExactly(reply_fd, "OKAY", 4);
+            SendOkay(reply_fd);
 #endif
-            WriteFdExactly(reply_fd, "OKAY", 4);
+            SendOkay(reply_fd);
             return 1;
         }
 
@@ -873,7 +790,7 @@
             break;
           case INSTALL_STATUS_LISTENER_NOT_FOUND: message = "listener not found"; break;
         }
-        sendfailmsg(reply_fd, message.c_str());
+        SendFail(reply_fd, message);
         return 1;
     }
     return 0;
@@ -884,7 +801,7 @@
     if(!strcmp(service, "kill")) {
         fprintf(stderr,"adb server killed by remote request\n");
         fflush(stdout);
-        adb_write(reply_fd, "OKAY", 4);
+        SendOkay(reply_fd);
         usb_cleanup();
         exit(0);
     }
@@ -914,25 +831,25 @@
 
         if (transport) {
             s->transport = transport;
-            adb_write(reply_fd, "OKAY", 4);
+            SendOkay(reply_fd);
         } else {
-            sendfailmsg(reply_fd, error_msg.c_str());
+            SendFail(reply_fd, error_msg);
         }
         return 1;
     }
 
     // return a list of all connected devices
     if (!strncmp(service, "devices", 7)) {
-        char buffer[4096];
-        int use_long = !strcmp(service+7, "-l");
-        if (use_long || service[7] == 0) {
-            memset(buffer, 0, sizeof(buffer));
-            D("Getting device list \n");
-            list_transports(buffer, sizeof(buffer), use_long);
-            D("Wrote device list \n");
-            send_msg_with_okay(reply_fd, buffer, strlen(buffer));
+        bool long_listing = (strcmp(service+7, "-l") == 0);
+        if (long_listing || service[7] == 0) {
+            D("Getting device list...\n");
+            std::string device_list = list_transports(long_listing);
+            D("Sending device list...\n");
+            SendOkay(reply_fd);
+            SendProtocolString(reply_fd, device_list);
             return 0;
         }
+        return 1;
     }
 
     // remove TCP transport
@@ -959,15 +876,15 @@
             }
         }
 
-        send_msg_with_okay(reply_fd, buffer, strlen(buffer));
+        SendOkay(reply_fd);
+        SendProtocolString(reply_fd, buffer);
         return 0;
     }
 
     // returns our value for ADB_SERVER_VERSION
     if (!strcmp(service, "version")) {
-        char version[12];
-        snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
-        send_msg_with_okay(reply_fd, version, strlen(version));
+        SendOkay(reply_fd);
+        SendProtocolString(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION));
         return 0;
     }
 
@@ -977,7 +894,8 @@
         if (transport && transport->serial) {
             out = transport->serial;
         }
-        send_msg_with_okay(reply_fd, out, strlen(out));
+        SendOkay(reply_fd);
+        SendProtocolString(reply_fd, out);
         return 0;
     }
     if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
@@ -986,7 +904,8 @@
         if (transport && transport->devpath) {
             out = transport->devpath;
         }
-        send_msg_with_okay(reply_fd, out, strlen(out));
+        SendOkay(reply_fd);
+        SendProtocolString(reply_fd, out);
         return 0;
     }
     // indicates a new emulator instance has started
@@ -999,8 +918,8 @@
 
     if(!strncmp(service,"get-state",strlen("get-state"))) {
         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
-        const char *state = connection_state_name(transport);
-        send_msg_with_okay(reply_fd, state, strlen(state));
+        SendOkay(reply_fd);
+        SendProtocolString(reply_fd, transport->connection_state_name());
         return 0;
     }
 #endif // ADB_HOST
diff --git a/adb/adb.h b/adb/adb.h
index cb2cf60..fd9d0e6 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -209,6 +209,8 @@
     unsigned char token[TOKEN_SIZE];
     fdevent auth_fde;
     unsigned failed_auth_attempts;
+
+    const char* connection_state_name() const;
 };
 
 
@@ -243,8 +245,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);
 
@@ -371,7 +371,6 @@
 #define USB_FFS_ADB_IN    USB_FFS_ADB_EP(ep2)
 #endif
 
-int sendfailmsg(int fd, const char *reason);
 int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
 
 void handle_online(atransport *t);
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 4751bff..7bb8e4a 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -28,6 +28,12 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <string>
+#include <vector>
+
+#include <base/stringprintf.h>
+#include <base/strings.h>
+
 #include "adb_io.h"
 
 static transport_type __adb_transport = kTransportAny;
@@ -36,6 +42,28 @@
 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, '\0');
+    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;
@@ -52,179 +80,128 @@
     __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)
-{
-    char service[64];
-    char tmp[5];
-    int len;
-
-    if (__adb_serial)
-        snprintf(service, sizeof service, "host:transport:%s", __adb_serial);
-    else {
+static int switch_socket_transport(int fd, std::string* error) {
+    std::string service;
+    if (__adb_serial) {
+        service += "host:transport:";
+        service += __adb_serial;
+    } else {
         const char* transport_type = "???";
-
-         switch (__adb_transport) {
-            case kTransportUsb:
-                transport_type = "transport-usb";
-                break;
-            case kTransportLocal:
-                transport_type = "transport-local";
-                break;
-            case kTransportAny:
-                transport_type = "transport-any";
-                break;
-            case kTransportHost:
-                // no switch necessary
-                return 0;
-                break;
+        switch (__adb_transport) {
+          case kTransportUsb:
+            transport_type = "transport-usb";
+            break;
+          case kTransportLocal:
+            transport_type = "transport-local";
+            break;
+          case kTransportAny:
+            transport_type = "transport-any";
+            break;
+          case kTransportHost:
+            // no switch necessary
+            return 0;
         }
-
-        snprintf(service, sizeof service, "host:%s", transport_type);
+        service += "host:";
+        service += transport_type;
     }
-    len = strlen(service);
-    snprintf(tmp, sizeof tmp, "%04x", len);
 
-    if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
-        strcpy(__adb_error, "write failure during connection");
+    if (!SendProtocolString(fd, service)) {
+        *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;
-
-    if(!ReadFdExactly(fd, buf, 4)) {
-        strcpy(__adb_error, "protocol fault (no status)");
-        return -1;
+bool adb_status(int fd, std::string* error) {
+    char buf[5];
+    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");
+    if(!SendProtocolString(fd, service)) {
+        *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;
     }
@@ -233,20 +210,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 {
@@ -257,31 +233,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? */
@@ -291,12 +267,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");
     }
@@ -309,15 +286,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;
     }
@@ -325,39 +301,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/adb_io.cpp b/adb/adb_io.cpp
index d89f304..5ae6ec3 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -16,20 +16,37 @@
 
 #define TRACE_TAG TRACE_RWX
 
-#include "sysdeps.h"
 #include "adb_io.h"
 
 #include <unistd.h>
 
+#include <base/stringprintf.h>
+
 #include "adb_trace.h"
-#include "transport.h"
+#include "adb_utils.h"
+#include "sysdeps.h"
+
+bool SendProtocolString(int fd, const std::string& s) {
+    int length = s.size();
+    if (length > 0xffff) {
+        length = 0xffff;
+    }
+
+    return WriteFdFmt(fd, "%04x", length) && WriteFdExactly(fd, s);
+}
+
+bool SendOkay(int fd) {
+    return WriteFdExactly(fd, "OKAY", 4);
+}
+
+bool SendFail(int fd, const std::string& reason) {
+    return WriteFdExactly(fd, "FAIL", 4) && SendProtocolString(fd, reason);
+}
 
 bool ReadFdExactly(int fd, void* buf, size_t len) {
     char* p = reinterpret_cast<char*>(buf);
 
-#if ADB_TRACE
     size_t len0 = len;
-#endif
 
     D("readx: fd=%d wanted=%zu\n", fd, len);
     while (len > 0) {
@@ -47,12 +64,10 @@
         }
     }
 
-#if ADB_TRACE
     D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
     if (ADB_TRACING) {
         dump_hex(reinterpret_cast<const unsigned char*>(buf), len0);
     }
-#endif
 
     return true;
 }
@@ -61,12 +76,10 @@
     const char* p = reinterpret_cast<const char*>(buf);
     int r;
 
-#if ADB_TRACE
     D("writex: fd=%d len=%d: ", fd, (int)len);
     if (ADB_TRACING) {
         dump_hex(reinterpret_cast<const unsigned char*>(buf), len);
     }
-#endif
 
     while (len > 0) {
         r = adb_write(fd, p, len);
@@ -90,6 +103,21 @@
     return true;
 }
 
-bool WriteStringFully(int fd, const char* str) {
+bool WriteFdExactly(int fd, const char* str) {
     return WriteFdExactly(fd, str, strlen(str));
 }
+
+bool WriteFdExactly(int fd, const std::string& str) {
+    return WriteFdExactly(fd, str.c_str(), str.size());
+}
+
+bool WriteFdFmt(int fd, const char* fmt, ...) {
+    std::string str;
+
+    va_list ap;
+    va_start(ap, fmt);
+    android::base::StringAppendV(&str, fmt, ap);
+    va_end(ap);
+
+    return WriteFdExactly(fd, str);
+}
diff --git a/adb/adb_io.h b/adb/adb_io.h
index 8d237ce..8d50a6d 100644
--- a/adb/adb_io.h
+++ b/adb/adb_io.h
@@ -17,9 +17,19 @@
 #ifndef ADB_IO_H
 #define ADB_IO_H
 
-#include <stdbool.h>
 #include <sys/types.h>
 
+#include <string>
+
+// Sends the protocol "OKAY" message.
+bool SendOkay(int fd);
+
+// Sends the protocol "FAIL" message, with the given failure reason.
+bool SendFail(int fd, const std::string& reason);
+
+// Writes a protocol-format string; a four hex digit length followed by the string data.
+bool SendProtocolString(int fd, const std::string& s);
+
 /*
  * Reads exactly len bytes from fd into buf.
  *
@@ -37,9 +47,13 @@
  * completed. If the other end of the fd (such as in a socket, pipe, or fifo),
  * is closed, errno will be set to 0.
  */
-bool WriteFdExactly(int fd, const void *buf, size_t len);
+bool WriteFdExactly(int fd, const void* buf, size_t len);
 
-/* Same as WriteFdExactly, but with an implicit len = strlen(buf). */
-bool WriteStringFully(int fd, const char* str);
+// Same as above, but for strings.
+bool WriteFdExactly(int fd, const char* s);
+bool WriteFdExactly(int fd, const std::string& s);
+
+// Same as above, but formats the string to send.
+bool WriteFdFmt(int fd, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
 
 #endif /* ADB_IO_H */
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index da340b2..8fd5cbf 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -139,16 +139,29 @@
     ASSERT_EQ(ENOSPC, errno);
 }
 
-TEST(io, WriteStringFully) {
+TEST(io, WriteFdExactly_string) {
   const char str[] = "Foobar";
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
 
   // Test writing a partial string to the file.
-  ASSERT_TRUE(WriteStringFully(tf.fd, str)) << strerror(errno);
+  ASSERT_TRUE(WriteFdExactly(tf.fd, str)) << strerror(errno);
   ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
 
   std::string s;
   ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
   EXPECT_STREQ(str, s.c_str());
 }
+
+TEST(io, WriteFdFmt) {
+    TemporaryFile tf;
+    ASSERT_NE(-1, tf.fd);
+
+    // Test writing a partial string to the file.
+    ASSERT_TRUE(WriteFdFmt(tf.fd, "Foo%s%d", "bar", 123)) << strerror(errno);
+    ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+
+    std::string s;
+    ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
+    EXPECT_STREQ("Foobar123", s.c_str());
+}
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index a1a5ddb..3fc4719 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <base/stringprintf.h>
+
 #include "sysdeps.h"
 #include "transport.h"
 
@@ -143,49 +145,17 @@
     return -1;
 }
 
-// Write a single line describing a listener to a user-provided buffer.
-// Appends a trailing zero, even in case of truncation, but the function
-// returns the full line length.
-// If |buffer| is NULL, does not write but returns required size.
-static int format_listener(alistener* l, char* buffer, size_t buffer_len) {
-    // Format is simply:
-    //
-    //  <device-serial> " " <local-name> " " <remote-name> "\n"
-    //
-    int local_len = strlen(l->local_name);
-    int connect_len = strlen(l->connect_to);
-    int serial_len = strlen(l->transport->serial);
-
-    if (buffer != NULL) {
-        snprintf(buffer, buffer_len, "%s %s %s\n",
-                l->transport->serial, l->local_name, l->connect_to);
-    }
-    // NOTE: snprintf() on Windows returns -1 in case of truncation, so
-    // return the computed line length instead.
-    return local_len + connect_len + serial_len + 3;
-}
-
-// Write the list of current listeners (network redirections) into a
-// user-provided buffer. Appends a trailing zero, even in case of
-// trunctaion, but return the full size in bytes.
-// If |buffer| is NULL, does not write but returns required size.
-int format_listeners(char* buf, size_t buflen)
-{
-    alistener* l;
-    int result = 0;
-    for (l = listener_list.next; l != &listener_list; l = l->next) {
+// Write the list of current listeners (network redirections) into a string.
+std::string format_listeners() {
+    std::string result;
+    for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
         // Ignore special listeners like those for *smartsocket*
-        if (l->connect_to[0] == '*')
-          continue;
-        int len = format_listener(l, buf, buflen);
-        // Ensure there is space for the trailing zero.
-        result += len;
-        if (buf != NULL) {
-          buf += len;
-          buflen -= len;
-          if (buflen <= 0)
-              break;
+        if (l->connect_to[0] == '*') {
+            continue;
         }
+        //  <device-serial> " " <local-name> " " <remote-name> "\n"
+        android::base::StringAppendF(&result, "%s %s %s\n",
+                                     l->transport->serial, l->local_name, l->connect_to);
     }
     return result;
 }
@@ -215,13 +185,13 @@
     }
 }
 
-install_status_t install_listener(const char *local_name,
+install_status_t install_listener(const std::string& local_name,
                                   const char *connect_to,
                                   atransport* transport,
                                   int no_rebind)
 {
     for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
-        if (strcmp(local_name, l->local_name) == 0) {
+        if (local_name == l->local_name) {
             char* cto;
 
             /* can't repurpose a smartsocket */
@@ -256,7 +226,7 @@
         goto nomem;
     }
 
-    listener->local_name = strdup(local_name);
+    listener->local_name = strdup(local_name.c_str());
     if (listener->local_name == nullptr) {
         goto nomem;
     }
@@ -266,9 +236,9 @@
         goto nomem;
     }
 
-    listener->fd = local_name_to_fd(local_name);
+    listener->fd = local_name_to_fd(listener->local_name);
     if (listener->fd < 0) {
-        printf("cannot bind '%s': %s\n", local_name, strerror(errno));
+        printf("cannot bind '%s': %s\n", listener->local_name, strerror(errno));
         free(listener->local_name);
         free(listener->connect_to);
         free(listener);
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index f55fdee..67168ae 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -19,6 +19,8 @@
 
 #include "adb.h"
 
+#include <string>
+
 // error/status codes for install_listener.
 enum install_status_t {
   INSTALL_STATUS_OK = 0,
@@ -34,12 +36,12 @@
 void listener_event_func(int _fd, unsigned ev, void *_l);
 void ss_listener_event_func(int _fd, unsigned ev, void *_l);
 
-install_status_t install_listener(const char *local_name,
-                                  const char *connect_to,
+install_status_t install_listener(const std::string& local_name,
+                                  const char* connect_to,
                                   atransport* transport,
                                   int no_rebind);
 
-int format_listeners(char* buf, size_t buflen);
+std::string format_listeners();
 
 install_status_t remove_listener(const char* local_name, atransport* transport);
 void remove_all_listeners(void);
diff --git a/adb/adb_main.cpp b/adb/adb_main.cpp
index 5acaf80..3f88d13 100644
--- a/adb/adb_main.cpp
+++ b/adb/adb_main.cpp
@@ -28,6 +28,8 @@
 #include "adb_listeners.h"
 #include "transport.h"
 
+#include <base/stringprintf.h>
+
 #if !ADB_HOST
 #include <getopt.h>
 #include <sys/prctl.h>
@@ -157,16 +159,6 @@
 }
 #endif /* ADB_HOST */
 
-/* Constructs a local name of form tcp:port.
- * target_str points to the target string, it's content will be overwritten.
- * target_size is the capacity of the target string.
- * server_port is the port number to use for the local name.
- */
-void build_local_name(char* target_str, size_t target_size, int server_port)
-{
-  snprintf(target_str, target_size, "tcp:%d", server_port);
-}
-
 void start_logging(void)
 {
 #if defined(_WIN32)
@@ -238,9 +230,8 @@
     local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
     adb_auth_init();
 
-    char local_name[30];
-    build_local_name(local_name, sizeof(local_name), server_port);
-    if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+    std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
+    if (install_listener(local_name, "*smartsocket*", NULL, 0)) {
         exit(1);
     }
 #else
@@ -295,15 +286,14 @@
 
         D("Local port disabled\n");
     } else {
-        char local_name[30];
         if ((root_seclabel != NULL) && (is_selinux_enabled() > 0)) {
             // b/12587913: fix setcon to allow const pointers
             if (setcon((char *)root_seclabel) < 0) {
                 exit(1);
             }
         }
-        build_local_name(local_name, sizeof(local_name), server_port);
-        if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
+        std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
+        if (install_listener(local_name, "*smartsocket*", NULL, 0)) {
             exit(1);
         }
     }
@@ -368,29 +358,25 @@
 }
 #endif
 
+// TODO(danalbert): Split this file up into adb_main.cpp and adbd_main.cpp.
 int main(int argc, char **argv) {
 #if ADB_HOST
+    // adb client/server
     adb_sysdeps_init();
-#else
-    close_stdin();
-#endif
     adb_trace_init();
-
-#if ADB_HOST
     D("Handling commandline()\n");
     return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
 #else
-    /* If adbd runs inside the emulator this will enable adb tracing via
-     * adb-debug qemud service in the emulator. */
-    adb_qemu_trace_init();
+    // adbd
     while (true) {
-        int c;
-        int option_index = 0;
         static struct option opts[] = {
-            {"root_seclabel", required_argument, 0, 's' },
-            {"device_banner", required_argument, 0, 'b' }
+            {"root_seclabel", required_argument, nullptr, 's'},
+            {"device_banner", required_argument, nullptr, 'b'},
+            {"version", no_argument, nullptr, 'v'},
         };
-        c = getopt_long(argc, argv, "", opts, &option_index);
+
+        int option_index = 0;
+        int c = getopt_long(argc, argv, "", opts, &option_index);
         if (c == -1)
             break;
         switch (c) {
@@ -400,11 +386,24 @@
         case 'b':
             adb_device_banner = optarg;
             break;
+        case 'v':
+            printf("Android Debug Bridge Daemon version %d.%d.%d %s\n",
+                   ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
+                   ADB_REVISION);
+            return 0;
         default:
             break;
         }
     }
 
+    close_stdin();
+
+    adb_trace_init();
+
+    /* If adbd runs inside the emulator this will enable adb tracing via
+     * adb-debug qemud service in the emulator. */
+    adb_qemu_trace_init();
+
     D("Handling main()\n");
     return adb_main(0, DEFAULT_ADB_PORT);
 #endif
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index 32b6ae4..63d4151 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -23,9 +23,6 @@
 #include <stdio.h>
 #endif
 
-/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
-#define  ADB_TRACE    1
-
 /* IMPORTANT: if you change the following list, don't
  * forget to update the corresponding 'tags' table in
  * the adb_trace_init() function implemented in adb.c
@@ -45,8 +42,6 @@
     TRACE_FDEVENT,
 } ;
 
-#if ADB_TRACE
-
 #if !ADB_HOST
 /*
  * When running inside the emulator, guest's adbd can connect to 'adb-debug'
@@ -97,19 +92,6 @@
                 errno = save_errno;                    \
            }                                           \
         } while (0)
-#  define  DD(...)                                     \
-        do {                                           \
-            int save_errno = errno;                    \
-            adb_mutex_lock(&D_lock);                   \
-            fprintf(stderr, "%16s: %5d:%5lu | ",       \
-                    __FUNCTION__,                      \
-                    getpid(), adb_thread_id());        \
-            errno = save_errno;                        \
-            fprintf(stderr, __VA_ARGS__ );             \
-            fflush(stderr);                            \
-            adb_mutex_unlock(&D_lock);                 \
-            errno = save_errno;                        \
-        } while (0)
 #else
 #  define  D(...)                                      \
         do {                                           \
@@ -129,19 +111,6 @@
                     __VA_ARGS__ );                     \
             }                                          \
         } while (0)
-#  define  DD(...)                                     \
-        do {                                           \
-          __android_log_print(                         \
-              ANDROID_LOG_INFO,                        \
-              __FUNCTION__,                            \
-              __VA_ARGS__ );                           \
-        } while (0)
 #endif /* ADB_HOST */
-#else
-#  define  D(...)          ((void)0)
-#  define  DR(...)         ((void)0)
-#  define  DD(...)         ((void)0)
-#  define  ADB_TRACING     0
-#endif /* ADB_TRACE */
 
 #endif /* __ADB_TRACE_H */
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index f10c143..0ce5ece 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define TRACE_TAG TRACE_ADB
+
 #include "adb_utils.h"
 
 #include <stdlib.h>
@@ -21,6 +23,11 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <algorithm>
+
+#include <base/stringprintf.h>
+
+#include "adb_trace.h"
 #include "sysdeps.h"
 
 bool getcwd(std::string* s) {
@@ -50,3 +57,25 @@
   result.push_back('\'');
   return result;
 }
+
+void dump_hex(const void* data, size_t byte_count) {
+    byte_count = std::min(byte_count, size_t(16));
+
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
+
+    std::string line;
+    for (size_t i = 0; i < byte_count; ++i) {
+        android::base::StringAppendF(&line, "%02x", p[i]);
+    }
+    line.push_back(' ');
+
+    for (size_t i = 0; i < byte_count; ++i) {
+        int c = p[i];
+        if (c < 32 || c > 127) {
+            c = '.';
+        }
+        line.push_back(c);
+    }
+
+    DR("%s\n", line.c_str());
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 4b64afa..84f7d0c 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -24,4 +24,6 @@
 
 std::string escape_arg(const std::string& s);
 
+void dump_hex(const void* ptr, size_t byte_count);
+
 #endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index e59a96a..1d71975 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -47,14 +47,9 @@
 #include "adb_utils.h"
 #include "file_sync_service.h"
 
-static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
-
-static int install_app(transport_type transport, const char* serial, int argc,
-                       const char** argv);
-static int install_multiple_app(transport_type transport, const char* serial, int argc,
-                                const char** argv);
-static int uninstall_app(transport_type transport, const char* serial, int argc,
-                         const char** argv);
+static int install_app(transport_type t, const char* serial, int argc, const char** argv);
+static int install_multiple_app(transport_type t, const char* serial, int argc, const char** argv);
+static int uninstall_app(transport_type t, const char* serial, int argc, const char** argv);
 
 static std::string gProductOutPath;
 extern int gListenAll;
@@ -71,8 +66,8 @@
 }
 
 static void version(FILE* out) {
-    fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
-            ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
+    fprintf(out, "Android Debug Bridge version %d.%d.%d %s\n", ADB_VERSION_MAJOR,
+            ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_REVISION);
 }
 
 static void help() {
@@ -201,7 +196,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 +404,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,73 +431,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");
     }
 
-    if(!ReadFdExactly(fd, buf, 4)){
-        fprintf(stderr,"* error reading response *\n");
-        adb_close(fd);
-        return -1;
-    }
-    if(memcmp(buf, "OKAY", 4)) {
-        buf[4] = 0;
-        fprintf(stderr,"* error response '%s' *\n", buf);
-        adb_close(fd);
+    if (!adb_status(fd, &error)) {
+        fprintf(stderr,"* error response '%s' *\n", error.c_str());
         return -1;
     }
 
@@ -547,37 +531,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 +575,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 +604,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 +616,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 +624,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()");
@@ -734,16 +673,42 @@
 #endif /* !defined(_WIN32) */
 }
 
-static int send_shell_command(transport_type transport, const char* serial,
+static bool wait_for_device(const char* service, transport_type t, const char* serial) {
+    // Was the caller vague about what they'd like us to wait for?
+    // If so, check they weren't more specific in their choice of transport type.
+    if (strcmp(service, "wait-for-device") == 0) {
+        if (t == kTransportUsb) {
+            service = "wait-for-usb";
+        } else if (t == kTransportLocal) {
+            service = "wait-for-local";
+        } else {
+            service = "wait-for-any";
+        }
+    }
+
+    std::string cmd = format_host_command(service, t, 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 false;
+    }
+
+    return true;
+}
+
+static int send_shell_command(transport_type transport_type, const char* serial,
                               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);
+        wait_for_device("wait-for-device", transport_type, serial);
     }
 
     read_and_dump(fd);
@@ -830,9 +795,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 +812,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,20 +925,30 @@
     }
 }
 
-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;
 }
 
-int adb_commandline(int argc, const char **argv)
-{
-    char buf[4096];
+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) {
     int no_daemon = 0;
     int is_daemon = 0;
     int is_server = 0;
@@ -1115,27 +1089,13 @@
     /* handle wait-for-* prefix */
     if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
         const char* service = argv[0];
-        if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
-            if (ttype == kTransportUsb) {
-                service = "wait-for-usb";
-            } else if (ttype == kTransportLocal) {
-                service = "wait-for-local";
-            } else {
-                service = "wait-for-any";
-            }
-        }
 
-        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());
+        if (!wait_for_device(service, ttype, serial)) {
             return 1;
         }
 
-        /* Allow a command to be run after wait-for-device,
-            * e.g. 'adb wait-for-device shell'.
-            */
+        // Allow a command to be run after wait-for-device,
+        // e.g. 'adb wait-for-device shell'.
         if (argc == 1) {
             return 0;
         }
@@ -1147,59 +1107,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);
@@ -1223,16 +1162,18 @@
         }
 
         std::string cmd = "shell:";
-        cmd += argv[1];
-        argc -= 2;
-        argv += 2;
+        --argc;
+        ++argv;
         while (argc-- > 0) {
-            cmd += " " + escape_arg(*argv++);
+            // We don't escape here, just like ssh(1). http://b/20564385.
+            cmd += *argv++;
+            if (*argv) cmd += " ";
         }
 
         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,14 +1182,14 @@
                 adb_close(fd);
                 r = 0;
             } else {
-                fprintf(stderr,"error: %s\n", adb_error());
+                fprintf(stderr,"error: %s\n", error.c_str());
                 r = -1;
             }
 
             if (persist) {
                 fprintf(stderr,"\n- waiting for device -\n");
                 adb_sleep_ms(1000);
-                do_cmd(ttype, serial, "wait-for-device", 0);
+                wait_for_device("wait-for-device", ttype, serial);
             } else {
                 if (h) {
                     printf("\x1b[0m");
@@ -1270,9 +1211,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 +1228,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;
@@ -1323,11 +1265,11 @@
     }
     else if (!strcmp(argv[0], "bugreport")) {
         if (argc != 1) return usage();
-        do_cmd(ttype, serial, "shell", "bugreport", 0);
-        return 0;
+        return send_shell_command(ttype, serial, "shell:bugreport");
     }
     /* adb_command() wrapper commands */
     else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
+        std::string cmd;
         char host_prefix[64];
         char reverse = (char) !strcmp(argv[0], "reverse");
         char remove = 0;
@@ -1375,45 +1317,37 @@
 
         // 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
         else if (remove_all) {
-            if (argc != 1)
-                return usage();
-            snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
+            if (argc != 1) return usage();
+            cmd = android::base::StringPrintf("%s:killforward-all", host_prefix);
         }
 
         // Implement forward --remove <local>
         else if (remove) {
-            if (argc != 2)
-                return usage();
-            snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
+            if (argc != 2) return usage();
+            cmd = android::base::StringPrintf("%s:killforward:%s", host_prefix, argv[1]);
         }
         // Or implement one of:
         //    forward <local> <remote>
         //    forward --no-rebind <local> <remote>
-        else
-        {
-          if (argc != 3)
-            return usage();
-          const char* command = no_rebind ? "forward:norebind" : "forward";
-          snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
+        else {
+            if (argc != 3) return usage();
+            const char* command = no_rebind ? "forward:norebind" : "forward";
+            cmd = android::base::StringPrintf("%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(cmd, &error)) {
+            fprintf(stderr, "error: %s\n", error.c_str());
             return 1;
         }
         return 0;
@@ -1511,22 +1445,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 +1455,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);
@@ -1563,42 +1485,6 @@
     return 1;
 }
 
-#define MAX_ARGV_LENGTH 16
-static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
-{
-    const char *argv[MAX_ARGV_LENGTH];
-    int argc;
-    va_list ap;
-
-    va_start(ap, cmd);
-    argc = 0;
-
-    if (serial) {
-        argv[argc++] = "-s";
-        argv[argc++] = serial;
-    } else if (ttype == kTransportUsb) {
-        argv[argc++] = "-d";
-    } else if (ttype == kTransportLocal) {
-        argv[argc++] = "-e";
-    }
-
-    argv[argc++] = cmd;
-    while(argc < MAX_ARGV_LENGTH &&
-        (argv[argc] = va_arg(ap, char*)) != 0) argc++;
-    assert(argc < MAX_ARGV_LENGTH);
-    va_end(ap);
-
-#if 0
-    int n;
-    fprintf(stderr,"argc = %d\n",argc);
-    for(n = 0; n < argc; n++) {
-        fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
-    }
-#endif
-
-    return adb_commandline(argc, argv);
-}
-
 static int pm_command(transport_type transport, const char* serial,
                       int argc, const char** argv)
 {
@@ -1742,9 +1628,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 +1675,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 +1705,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/remount_service.cpp b/adb/remount_service.cpp
index 1eaee73..87702b0 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -90,9 +90,7 @@
     return true;
   }
   if (remount(partition, ro)) {
-    char buf[200];
-    snprintf(buf, sizeof(buf), "remount of %s failed: %s\n", partition, strerror(errno));
-    WriteStringFully(fd, buf);
+    WriteFdFmt(fd, "remount of %s failed: %s\n", partition, strerror(errno));
     return false;
   }
   return true;
@@ -102,7 +100,7 @@
     char prop_buf[PROPERTY_VALUE_MAX];
 
     if (getuid() != 0) {
-        WriteStringFully(fd, "Not running as root. Try \"adb root\" first.\n");
+        WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n");
         adb_close(fd);
         return;
     }
@@ -121,19 +119,16 @@
     if (system_verified || vendor_verified) {
         // Allow remount but warn of likely bad effects
         bool both = system_verified && vendor_verified;
-        char buffer[200];
-        snprintf(buffer, sizeof(buffer),
-                 "dm_verity is enabled on the %s%s%s partition%s.\n",
-                 system_verified ? "system" : "",
-                 both ? " and " : "",
-                 vendor_verified ? "vendor" : "",
-                 both ? "s" : "");
-        WriteStringFully(fd, buffer);
-        snprintf(buffer, sizeof(buffer),
-                 "Use \"adb disable-verity\" to disable verity.\n"
-                 "If you do not, remount may succeed, however, you will still "
-                 "not be able to write to these volumes.\n");
-        WriteStringFully(fd, buffer);
+        WriteFdFmt(fd,
+                   "dm_verity is enabled on the %s%s%s partition%s.\n",
+                   system_verified ? "system" : "",
+                   both ? " and " : "",
+                   vendor_verified ? "vendor" : "",
+                   both ? "s" : "");
+        WriteFdExactly(fd,
+                       "Use \"adb disable-verity\" to disable verity.\n"
+                       "If you do not, remount may succeed, however, you will still "
+                       "not be able to write to these volumes.\n");
     }
 
     bool success = true;
@@ -141,7 +136,7 @@
     success &= remount_partition(fd, "/vendor", &vendor_ro);
     success &= remount_partition(fd, "/oem", &oem_ro);
 
-    WriteStringFully(fd, success ? "remount succeeded\n" : "remount failed\n");
+    WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n");
 
     adb_close(fd);
 }
diff --git a/adb/services.cpp b/adb/services.cpp
index e6c84a4..1847447 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -31,10 +31,11 @@
 #include <unistd.h>
 #endif
 
+#include <base/file.h>
 #include <base/stringprintf.h>
+#include <base/strings.h>
 
 #if !ADB_HOST
-#include "base/file.h"
 #include "cutils/android_reboot.h"
 #include "cutils/properties.h"
 #endif
@@ -62,74 +63,54 @@
 
 #if !ADB_HOST
 
-void restart_root_service(int fd, void *cookie)
-{
-    char buf[100];
-    char value[PROPERTY_VALUE_MAX];
-
+void restart_root_service(int fd, void *cookie) {
     if (getuid() == 0) {
-        snprintf(buf, sizeof(buf), "adbd is already running as root\n");
-        WriteFdExactly(fd, buf, strlen(buf));
+        WriteFdExactly(fd, "adbd is already running as root\n");
         adb_close(fd);
     } else {
+        char value[PROPERTY_VALUE_MAX];
         property_get("ro.debuggable", value, "");
         if (strcmp(value, "1") != 0) {
-            snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
-            WriteFdExactly(fd, buf, strlen(buf));
+            WriteFdExactly(fd, "adbd cannot run as root in production builds\n");
             adb_close(fd);
             return;
         }
 
         property_set("service.adb.root", "1");
-        snprintf(buf, sizeof(buf), "restarting adbd as root\n");
-        WriteFdExactly(fd, buf, strlen(buf));
+        WriteFdExactly(fd, "restarting adbd as root\n");
         adb_close(fd);
     }
 }
 
-void restart_unroot_service(int fd, void *cookie)
-{
-    char buf[100];
-
+void restart_unroot_service(int fd, void *cookie) {
     if (getuid() != 0) {
-        snprintf(buf, sizeof(buf), "adbd not running as root\n");
-        WriteFdExactly(fd, buf, strlen(buf));
+        WriteFdExactly(fd, "adbd not running as root\n");
         adb_close(fd);
     } else {
         property_set("service.adb.root", "0");
-        snprintf(buf, sizeof(buf), "restarting adbd as non root\n");
-        WriteFdExactly(fd, buf, strlen(buf));
+        WriteFdExactly(fd, "restarting adbd as non root\n");
         adb_close(fd);
     }
 }
 
-void restart_tcp_service(int fd, void *cookie)
-{
-    char buf[100];
-    char value[PROPERTY_VALUE_MAX];
+void restart_tcp_service(int fd, void *cookie) {
     int port = (int) (uintptr_t) cookie;
-
     if (port <= 0) {
-        snprintf(buf, sizeof(buf), "invalid port\n");
-        WriteFdExactly(fd, buf, strlen(buf));
+        WriteFdFmt(fd, "invalid port %d\n", port);
         adb_close(fd);
         return;
     }
 
+    char value[PROPERTY_VALUE_MAX];
     snprintf(value, sizeof(value), "%d", port);
     property_set("service.adb.tcp.port", value);
-    snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
-    WriteFdExactly(fd, buf, strlen(buf));
+    WriteFdFmt(fd, "restarting in TCP mode port: %d\n", port);
     adb_close(fd);
 }
 
-void restart_usb_service(int fd, void *cookie)
-{
-    char buf[100];
-
+void restart_usb_service(int fd, void *cookie) {
     property_set("service.adb.tcp.port", "0");
-    snprintf(buf, sizeof(buf), "restarting in USB mode\n");
-    WriteFdExactly(fd, buf, strlen(buf));
+    WriteFdExactly(fd, "restarting in USB mode\n");
     adb_close(fd);
 }
 
@@ -142,13 +123,11 @@
         reboot_arg = "sideload";
     }
 
-    char buf[100];
     // It reboots into sideload mode by setting "--sideload" or "--sideload_auto_reboot"
     // in the command file.
     if (strcmp(reboot_arg, "sideload") == 0) {
         if (getuid() != 0) {
-            snprintf(buf, sizeof(buf), "'adb root' is required for 'adb reboot sideload'.\n");
-            WriteStringFully(fd, buf);
+            WriteFdExactly(fd, "'adb root' is required for 'adb reboot sideload'.\n");
             return false;
         }
 
@@ -174,15 +153,13 @@
     char property_val[PROPERTY_VALUE_MAX];
     int ret = snprintf(property_val, sizeof(property_val), "reboot,%s", reboot_arg);
     if (ret >= static_cast<int>(sizeof(property_val))) {
-        snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
-        WriteStringFully(fd, buf);
+        WriteFdFmt(fd, "reboot string too long: %d\n", ret);
         return false;
     }
 
     ret = property_set(ANDROID_RB_PROPERTY, property_val);
     if (ret < 0) {
-        snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
-        WriteStringFully(fd, buf);
+        WriteFdFmt(fd, "reboot failed: %d\n", ret);
         return false;
     }
 
@@ -208,7 +185,7 @@
     const char* command = reinterpret_cast<const char*>(arg);
 
     if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
-        sendfailmsg(fd, "not a reverse forwarding command");
+        SendFail(fd, "not a reverse forwarding command");
     }
     free(arg);
     adb_close(fd);
@@ -551,9 +528,9 @@
     std::string error_msg = "unknown error";
     atransport* t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &error_msg);
     if (t != 0) {
-        WriteFdExactly(fd, "OKAY", 4);
+        SendOkay(fd);
     } else {
-        sendfailmsg(fd, error_msg.c_str());
+        SendFail(fd, error_msg);
     }
 
     if (sinfo->serial)
@@ -563,35 +540,31 @@
     D("wait_for_state is done\n");
 }
 
-static void connect_device(char* host, char* buffer, int buffer_size)
-{
-    int port, fd;
-    char* portstr = strchr(host, ':');
-    char hostbuf[100];
-    char serial[100];
-    int ret;
-
-    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
-    if (portstr) {
-        if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
-            snprintf(buffer, buffer_size, "bad host name %s", host);
-            return;
-        }
-        // zero terminate the host at the point we found the colon
-        hostbuf[portstr - host] = 0;
-        if (sscanf(portstr + 1, "%d", &port) != 1) {
-            snprintf(buffer, buffer_size, "bad port number %s", portstr);
-            return;
-        }
-    } else {
-        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+static void connect_device(const std::string& host, std::string* response) {
+    if (host.empty()) {
+        *response = "empty host name";
+        return;
     }
 
-    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
+    std::vector<std::string> pieces = android::base::Split(host, ":");
+    const std::string& hostname = pieces[0];
 
-    fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10);
+    int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    if (pieces.size() > 1) {
+        if (sscanf(pieces[1].c_str(), "%d", &port) != 1) {
+            *response = android::base::StringPrintf("bad port number %s", pieces[1].c_str());
+            return;
+        }
+    }
+
+    // This may look like we're putting 'host' back together,
+    // but we're actually inserting the default port if necessary.
+    std::string serial = android::base::StringPrintf("%s:%d", hostname.c_str(), port);
+
+    int fd = socket_network_client_timeout(hostname.c_str(), port, SOCK_STREAM, 10);
     if (fd < 0) {
-        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
+        *response = android::base::StringPrintf("unable to connect to %s:%d",
+                                                hostname.c_str(), port);
         return;
     }
 
@@ -599,85 +572,74 @@
     close_on_exec(fd);
     disable_tcp_nagle(fd);
 
-    ret = register_socket_transport(fd, serial, port, 0);
+    int ret = register_socket_transport(fd, serial.c_str(), port, 0);
     if (ret < 0) {
         adb_close(fd);
-        snprintf(buffer, buffer_size, "already connected to %s", serial);
+        *response = android::base::StringPrintf("already connected to %s", serial.c_str());
     } else {
-        snprintf(buffer, buffer_size, "connected to %s", serial);
+        *response = android::base::StringPrintf("connected to %s", serial.c_str());
     }
 }
 
-void connect_emulator(char* port_spec, char* buffer, int buffer_size)
-{
-    char* port_separator = strchr(port_spec, ',');
-    if (!port_separator) {
-        snprintf(buffer, buffer_size,
-                "unable to parse '%s' as <console port>,<adb port>",
-                port_spec);
+void connect_emulator(const std::string& port_spec, std::string* response) {
+    std::vector<std::string> pieces = android::base::Split(port_spec, ",");
+    if (pieces.size() != 2) {
+        *response = android::base::StringPrintf("unable to parse '%s' as <console port>,<adb port>",
+                                                port_spec.c_str());
         return;
     }
 
-    // Zero-terminate console port and make port_separator point to 2nd port.
-    *port_separator++ = 0;
-    int console_port = strtol(port_spec, NULL, 0);
-    int adb_port = strtol(port_separator, NULL, 0);
-    if (!(console_port > 0 && adb_port > 0)) {
-        *(port_separator - 1) = ',';
-        snprintf(buffer, buffer_size,
-                "Invalid port numbers: Expected positive numbers, got '%s'",
-                port_spec);
+    int console_port = strtol(pieces[0].c_str(), NULL, 0);
+    int adb_port = strtol(pieces[1].c_str(), NULL, 0);
+    if (console_port <= 0 || adb_port <= 0) {
+        *response = android::base::StringPrintf("Invalid port numbers: %s", port_spec.c_str());
         return;
     }
 
-    /* Check if the emulator is already known.
-     * Note: There's a small but harmless race condition here: An emulator not
-     * present just yet could be registered by another invocation right
-     * after doing this check here. However, local_connect protects
-     * against double-registration too. From here, a better error message
-     * can be produced. In the case of the race condition, the very specific
-     * error message won't be shown, but the data doesn't get corrupted. */
+    // Check if the emulator is already known.
+    // Note: There's a small but harmless race condition here: An emulator not
+    // present just yet could be registered by another invocation right
+    // after doing this check here. However, local_connect protects
+    // against double-registration too. From here, a better error message
+    // can be produced. In the case of the race condition, the very specific
+    // error message won't be shown, but the data doesn't get corrupted.
     atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
-    if (known_emulator != NULL) {
-        snprintf(buffer, buffer_size,
-                "Emulator on port %d already registered.", adb_port);
+    if (known_emulator != nullptr) {
+        *response = android::base::StringPrintf("Emulator already registered on port %d", adb_port);
         return;
     }
 
-    /* Check if more emulators can be registered. Similar unproblematic
-     * race condition as above. */
+    // Check if more emulators can be registered. Similar unproblematic
+    // race condition as above.
     int candidate_slot = get_available_local_transport_index();
     if (candidate_slot < 0) {
-        snprintf(buffer, buffer_size, "Cannot accept more emulators.");
+        *response = "Cannot accept more emulators";
         return;
     }
 
-    /* Preconditions met, try to connect to the emulator. */
+    // Preconditions met, try to connect to the emulator.
     if (!local_connect_arbitrary_ports(console_port, adb_port)) {
-        snprintf(buffer, buffer_size,
-                "Connected to emulator on ports %d,%d", console_port, adb_port);
+        *response = android::base::StringPrintf("Connected to emulator on ports %d,%d",
+                                                console_port, adb_port);
     } else {
-        snprintf(buffer, buffer_size,
-                "Could not connect to emulator on ports %d,%d",
-                console_port, adb_port);
+        *response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d",
+                                                console_port, adb_port);
     }
 }
 
 static void connect_service(int fd, void* cookie)
 {
-    char buf[4096];
-    char resp[4096];
     char *host = reinterpret_cast<char*>(cookie);
 
+    std::string response;
     if (!strncmp(host, "emu:", 4)) {
-        connect_emulator(host + 4, buf, sizeof(buf));
+        connect_emulator(host + 4, &response);
     } else {
-        connect_device(host, buf, sizeof(buf));
+        connect_device(host, &response);
     }
 
     // Send response for emulator and device
-    snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
-    WriteFdExactly(fd, resp, strlen(resp));
+    SendProtocolString(fd, response);
     adb_close(fd);
 }
 #endif
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index b75ed4c..cc42bc0 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -21,13 +21,13 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <stdarg.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <sys/stat.h>
 
 #include "cutils/properties.h"
 
 #include "adb.h"
+#include "adb_io.h"
 #include "ext4_sb.h"
 #include "fs_mgr.h"
 #include "remount_service.h"
@@ -41,18 +41,6 @@
 static const bool kAllowDisableVerity = false;
 #endif
 
-__attribute__((__format__(printf, 2, 3))) __nonnull((2))
-static void write_console(int fd, const char* format, ...)
-{
-    char buffer[256];
-    va_list args;
-    va_start (args, format);
-    vsnprintf (buffer, sizeof(buffer), format, args);
-    va_end (args);
-
-    adb_write(fd, buffer, strnlen(buffer, sizeof(buffer)));
-}
-
 static int get_target_device_size(int fd, const char *blk_device,
                                   uint64_t *device_size)
 {
@@ -64,18 +52,18 @@
 
     data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
     if (data_device < 0) {
-        write_console(fd, "Error opening block device (%s)\n", strerror(errno));
+        WriteFdFmt(fd, "Error opening block device (%s)\n", strerror(errno));
         return -1;
     }
 
     if (lseek64(data_device, 1024, SEEK_SET) < 0) {
-        write_console(fd, "Error seeking to superblock\n");
+        WriteFdFmt(fd, "Error seeking to superblock\n");
         adb_close(data_device);
         return -1;
     }
 
     if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
-        write_console(fd, "Error reading superblock\n");
+        WriteFdFmt(fd, "Error reading superblock\n");
         adb_close(data_device);
         return -1;
     }
@@ -99,73 +87,64 @@
     int retval = -1;
 
     if (make_block_device_writable(block_device)) {
-        write_console(fd, "Could not make block device %s writable (%s).\n",
-                      block_device, strerror(errno));
+        WriteFdFmt(fd, "Could not make block device %s writable (%s).\n",
+                   block_device, strerror(errno));
         goto errout;
     }
 
     device = adb_open(block_device, O_RDWR | O_CLOEXEC);
     if (device == -1) {
-        write_console(fd, "Could not open block device %s (%s).\n",
-                      block_device, strerror(errno));
-        write_console(fd, "Maybe run adb remount?\n");
+        WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno));
+        WriteFdFmt(fd, "Maybe run adb remount?\n");
         goto errout;
     }
 
     // find the start of the verity metadata
     if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
-        write_console(fd, "Could not get target device size.\n");
+        WriteFdFmt(fd, "Could not get target device size.\n");
         goto errout;
     }
 
     if (lseek64(device, device_length, SEEK_SET) < 0) {
-        write_console(fd,
-                      "Could not seek to start of verity metadata block.\n");
+        WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
         goto errout;
     }
 
     // check the magic number
-    if (adb_read(device, &magic_number, sizeof(magic_number))
-             != sizeof(magic_number)) {
-        write_console(fd, "Couldn't read magic number!\n");
+    if (adb_read(device, &magic_number, sizeof(magic_number)) != sizeof(magic_number)) {
+        WriteFdFmt(fd, "Couldn't read magic number!\n");
         goto errout;
     }
 
     if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) {
-        write_console(fd, "Verity already disabled on %s\n", mount_point);
+        WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point);
         goto errout;
     }
 
     if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) {
-        write_console(fd, "Verity already enabled on %s\n", mount_point);
+        WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point);
         goto errout;
     }
 
     if (magic_number != VERITY_METADATA_MAGIC_NUMBER
             && magic_number != VERITY_METADATA_MAGIC_DISABLE) {
-        write_console(fd,
-                      "Couldn't find verity metadata at offset %" PRIu64 "!\n",
-                      device_length);
+        WriteFdFmt(fd, "Couldn't find verity metadata at offset %" PRIu64 "!\n", device_length);
         goto errout;
     }
 
     if (lseek64(device, device_length, SEEK_SET) < 0) {
-        write_console(fd,
-                      "Could not seek to start of verity metadata block.\n");
+        WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
         goto errout;
     }
 
     if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) {
-        write_console(
-            fd, "Could not set verity %s flag on device %s with error %s\n",
-            enable ? "enabled" : "disabled",
-            block_device, strerror(errno));
+        WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n",
+                   enable ? "enabled" : "disabled",
+                   block_device, strerror(errno));
         goto errout;
     }
 
-    write_console(fd, "Verity %s on %s\n",
-                  enable ? "enabled" : "disabled",
-                  mount_point);
+    WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
     retval = 0;
 errout:
     if (device != -1)
@@ -184,14 +163,13 @@
 
         property_get("ro.secure", propbuf, "0");
         if (strcmp(propbuf, "1")) {
-            write_console(fd, "verity not enabled - ENG build\n");
+            WriteFdFmt(fd, "verity not enabled - ENG build\n");
             goto errout;
         }
 
         property_get("ro.debuggable", propbuf, "0");
         if (strcmp(propbuf, "1")) {
-            write_console(
-                fd, "verity cannot be disabled/enabled - USER build\n");
+            WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
             goto errout;
         }
 
@@ -201,8 +179,7 @@
 
         fstab = fs_mgr_read_fstab(fstab_filename);
         if (!fstab) {
-            write_console(fd, "Failed to open %s\nMaybe run adb root?\n",
-                          fstab_filename);
+            WriteFdFmt(fd, "Failed to open %s\nMaybe run adb root?\n", fstab_filename);
             goto errout;
         }
 
@@ -218,12 +195,11 @@
         }
 
         if (any_changed) {
-            write_console(
-                fd, "Now reboot your device for settings to take effect\n");
+            WriteFdFmt(fd, "Now reboot your device for settings to take effect\n");
         }
     } else {
-        write_console(fd, "%s-verity only works for userdebug builds\n",
-                      enable ? "enable" : "disable");
+        WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
+                   enable ? "enable" : "disable");
     }
 
 errout:
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index f468029..32ca17d 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -37,23 +37,6 @@
 
 static void local_socket_close_locked(asocket *s);
 
-int sendfailmsg(int fd, const char *reason)
-{
-    char buf[9];
-    int len;
-    len = strlen(reason);
-    if (len > 0xffff) {
-        len = 0xffff;
-    }
-
-    snprintf(buf, sizeof buf, "FAIL%04x", len);
-    if (!WriteFdExactly(fd, buf, 8)) {
-        return -1;
-    }
-
-    return WriteFdExactly(fd, reason, len) ? 0 : -1;
-}
-
 static unsigned local_socket_next_id = 1;
 
 static asocket local_socket_list = {
@@ -608,7 +591,7 @@
     s->ready = local_socket_ready;
     s->shutdown = NULL;
     s->close = local_socket_close;
-    adb_write(s->fd, "OKAY", 4);
+    SendOkay(s->fd);
     s->ready(s);
 }
 
@@ -620,11 +603,11 @@
     s->ready = local_socket_ready;
     s->shutdown = NULL;
     s->close = local_socket_close;
-    sendfailmsg(s->fd, "closed");
+    SendFail(s->fd, "closed");
     s->close(s);
 }
 
-unsigned unhex(unsigned char *s, int len)
+static unsigned unhex(unsigned char *s, int len)
 {
     unsigned n = 0, c;
 
@@ -654,6 +637,8 @@
     return n;
 }
 
+#if ADB_HOST
+
 #define PREFIX(str) { str, sizeof(str) - 1 }
 static const struct prefix_struct {
     const char *str;
@@ -670,7 +655,7 @@
    skipping over the 'serial' parameter in the ADB protocol,
    where parameter string may be a host:port string containing
    the protocol delimiter (colon). */
-char *skip_host_serial(char *service) {
+static char *skip_host_serial(char *service) {
     char *first_colon, *serial_end;
     int i;
 
@@ -698,6 +683,8 @@
     return serial_end;
 }
 
+#endif // ADB_HOST
+
 static int smart_socket_enqueue(asocket *s, apacket *p)
 {
     unsigned len;
@@ -799,7 +786,7 @@
         s2 = create_host_service_socket(service, serial);
         if(s2 == 0) {
             D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
-            sendfailmsg(s->peer->fd, "unknown host service");
+            SendFail(s->peer->fd, "unknown host service");
             goto fail;
         }
 
@@ -810,7 +797,7 @@
             ** connection, and close this smart socket now
             ** that its work is done.
             */
-        adb_write(s->peer->fd, "OKAY", 4);
+        SendOkay(s->peer->fd);
 
         s->peer->ready = local_socket_ready;
         s->peer->shutdown = NULL;
@@ -831,7 +818,7 @@
         s->transport = acquire_one_transport(CS_ANY, kTransportAny, NULL, &error_msg);
 
         if (s->transport == NULL) {
-            sendfailmsg(s->peer->fd, error_msg.c_str());
+            SendFail(s->peer->fd, error_msg);
             goto fail;
         }
     }
@@ -841,7 +828,7 @@
            /* if there's no remote we fail the connection
             ** right here and terminate it
             */
-        sendfailmsg(s->peer->fd, "device offline (x)");
+        SendFail(s->peer->fd, "device offline (x)");
         goto fail;
     }
 
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..a21272f 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -22,7 +22,6 @@
 #include <windows.h>
 
 #include <errno.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -2151,85 +2150,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/test_track_devices.cpp b/adb/test_track_devices.cpp
index 77b3ad9..3e823e9 100644
--- a/adb/test_track_devices.cpp
+++ b/adb/test_track_devices.cpp
@@ -1,3 +1,5 @@
+// TODO: replace this with a shell/python script.
+
 /* a simple test program, connects to ADB server, and opens a track-devices session */
 #include <netdb.h>
 #include <sys/socket.h>
@@ -6,6 +8,8 @@
 #include <errno.h>
 #include <memory.h>
 
+#include <base/file.h>
+
 static void
 panic( const char*  msg )
 {
@@ -13,82 +17,49 @@
     exit(1);
 }
 
-static int
-unix_write( int  fd, const char*  buf, int  len )
-{
-    int  result = 0;
-    while (len > 0) {
-        int  len2 = write(fd, buf, len);
-        if (len2 < 0) {
-            if (errno == EINTR || errno == EAGAIN)
-                continue;
-            return -1;
-        }
-        result += len2;
-        len -= len2;
-        buf += len2;
+int main(int argc, char* argv[]) {
+    const char* request = "host:track-devices";
+
+    if (argv[1] && strcmp(argv[1], "--jdwp") == 0) {
+        request = "track-jdwp";
     }
-    return  result;
-}
 
-static int
-unix_read( int  fd, char*  buf, int  len )
-{
-    int  result = 0;
-    while (len > 0) {
-        int  len2 = read(fd, buf, len);
-        if (len2 < 0) {
-            if (errno == EINTR || errno == EAGAIN)
-                continue;
-            return -1;
-        }
-        result += len2;
-        len -= len2;
-        buf += len2;
-    }
-    return  result;
-}
-
-
-int  main( void )
-{
-    int                  ret, s;
+    int                  ret;
     struct sockaddr_in   server;
     char                 buffer[1024];
-    const char*          request = "host:track-devices";
-    int                  len;
 
     memset( &server, 0, sizeof(server) );
     server.sin_family      = AF_INET;
     server.sin_port        = htons(5037);
     server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 
-    s = socket( PF_INET, SOCK_STREAM, 0 );
+    int s = socket( PF_INET, SOCK_STREAM, 0 );
     ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
     if (ret < 0) panic( "could not connect to server" );
 
     /* send the request */
-    len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
-    if (unix_write(s, buffer, len) < 0)
+    int len = snprintf(buffer, sizeof(buffer), "%04zx%s", strlen(request), request);
+    if (!android::base::WriteFully(s, buffer, len))
         panic( "could not send request" );
 
     /* read the OKAY answer */
-    if (unix_read(s, buffer, 4) != 4)
+    if (!android::base::ReadFully(s, buffer, 4))
         panic( "could not read request" );
 
     printf( "server answer: %.*s\n", 4, buffer );
 
     /* now loop */
-    for (;;) {
+    while (true) {
         char  head[5] = "0000";
 
-        if (unix_read(s, head, 4) < 0)
+        if (!android::base::ReadFully(s, head, 4))
             panic("could not read length");
 
-        if ( sscanf( head, "%04x", &len ) != 1 )
+        int len;
+        if (sscanf(head, "%04x", &len) != 1 )
             panic("could not decode length");
 
-        if (unix_read(s, buffer, len) != len)
+        if (!android::base::ReadFully(s, buffer, len))
             panic("could not read data");
 
         printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
diff --git a/adb/test_track_jdwp.cpp b/adb/test_track_jdwp.cpp
deleted file mode 100644
index 8ecc6b8..0000000
--- a/adb/test_track_jdwp.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/* a simple test program, connects to ADB server, and opens a track-devices session */
-#include <netdb.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <memory.h>
-
-static void
-panic( const char*  msg )
-{
-    fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
-    exit(1);
-}
-
-static int
-unix_write( int  fd, const char*  buf, int  len )
-{
-    int  result = 0;
-    while (len > 0) {
-        int  len2 = write(fd, buf, len);
-        if (len2 < 0) {
-            if (errno == EINTR || errno == EAGAIN)
-                continue;
-            return -1;
-        }
-        result += len2;
-        len -= len2;
-        buf += len2;
-    }
-    return  result;
-}
-
-static int
-unix_read( int  fd, char*  buf, int  len )
-{
-    int  result = 0;
-    while (len > 0) {
-        int  len2 = read(fd, buf, len);
-        if (len2 < 0) {
-            if (errno == EINTR || errno == EAGAIN)
-                continue;
-            return -1;
-        }
-        result += len2;
-        len -= len2;
-        buf += len2;
-    }
-    return  result;
-}
-
-
-int  main( void )
-{
-    int                  ret, s;
-    struct sockaddr_in   server;
-    char                 buffer[1024];
-    const char*          request = "track-jdwp";
-    int                  len;
-
-    memset( &server, 0, sizeof(server) );
-    server.sin_family      = AF_INET;
-    server.sin_port        = htons(5037);
-    server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-    s = socket( PF_INET, SOCK_STREAM, 0 );
-    ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
-    if (ret < 0) panic( "could not connect to server" );
-
-    /* send the request */
-    len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
-    if (unix_write(s, buffer, len) < 0)
-        panic( "could not send request" );
-
-    /* read the OKAY answer */
-    if (unix_read(s, buffer, 4) != 4)
-        panic( "could not read request" );
-
-    printf( "server answer: %.*s\n", 4, buffer );
-
-    /* now loop */
-    for (;;) {
-        char  head[5] = "0000";
-
-        if (unix_read(s, head, 4) < 0)
-            panic("could not read length");
-
-        if ( sscanf( head, "%04x", &len ) != 1 )
-            panic("could not decode length");
-
-        if (unix_read(s, buffer, len) != len)
-            panic("could not read data");
-
-        printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
-    }
-    close(s);
-}
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index 52d8056..237ef47 100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -272,13 +272,24 @@
         adb = AdbWrapper()
 
         # http://b/19734868
+        # Note that this actually matches ssh(1)'s behavior --- it's
+        # converted to "sh -c echo hello; echo world" which sh interprets
+        # as "sh -c echo" (with an argument to that shell of "hello"),
+        # and then "echo world" back in the first shell.
         result = adb.shell("sh -c 'echo hello; echo world'").splitlines()
+        self.assertEqual(["", "world"], result)
+        # If you really wanted "hello" and "world", here's what you'd do:
+        result = adb.shell("echo hello\;echo world").splitlines()
         self.assertEqual(["hello", "world"], result)
 
         # http://b/15479704
         self.assertEqual('t', adb.shell("'true && echo t'").strip())
         self.assertEqual('t', adb.shell("sh -c 'true && echo t'").strip())
 
+        # http://b/20564385
+        self.assertEqual('t', adb.shell("FOO=a BAR=b echo t").strip())
+        self.assertEqual('123Linux', adb.shell("echo -n 123\;uname").strip())
+
 
 class AdbFile(unittest.TestCase):
     SCRATCH_DIR = "/data/local/tmp"
diff --git a/adb/transport.cpp b/adb/transport.cpp
index d395a80..5c50c0a 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -26,7 +26,10 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <base/stringprintf.h>
+
 #include "adb.h"
+#include "adb_utils.h"
 
 static void transport_unref(atransport *t);
 
@@ -42,34 +45,6 @@
 
 ADB_MUTEX_DEFINE( transport_lock );
 
-#if ADB_TRACE
-#define MAX_DUMP_HEX_LEN 16
-void dump_hex(const unsigned char* ptr, size_t  len)
-{
-    int  nn, len2 = len;
-    // Build a string instead of logging each character.
-    // MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
-    char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
-
-    if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
-
-    for (nn = 0; nn < len2; nn++) {
-        sprintf(pb, "%02x", ptr[nn]);
-        pb += 2;
-    }
-    sprintf(pb++, " ");
-
-    for (nn = 0; nn < len2; nn++) {
-        int  c = ptr[nn];
-        if (c < 32 || c > 127)
-            c = '.';
-        *pb++ =  c;
-    }
-    *pb++ = '\0';
-    DR("%s\n", buffer);
-}
-#endif
-
 void kick_transport(atransport* t)
 {
     if (t && !t->kicked)
@@ -117,10 +92,7 @@
     }
 }
 
-#if ADB_TRACE
-static void
-dump_packet(const char* name, const char* func, apacket* p)
-{
+static void dump_packet(const char* name, const char* func, apacket* p) {
     unsigned  command = p->msg.command;
     int       len     = p->msg.data_length;
     char      cmd[9];
@@ -155,7 +127,6 @@
         name, func, cmd, arg0, arg1, len);
     dump_hex(p->data, len);
 }
-#endif /* ADB_TRACE */
 
 static int
 read_packet(int  fd, const char* name, apacket** ppacket)
@@ -180,11 +151,9 @@
         }
     }
 
-#if ADB_TRACE
     if (ADB_TRACING) {
         dump_packet(name, "from remote", *ppacket);
     }
-#endif
     return 0;
 }
 
@@ -199,11 +168,9 @@
         name = buff;
     }
 
-#if ADB_TRACE
     if (ADB_TRACING) {
         dump_packet(name, "to remote", *ppacket);
     }
-#endif
     len = sizeof(ppacket);
     while(len > 0) {
         r = adb_write(fd, p, len);
@@ -389,17 +356,6 @@
 
 
 #if ADB_HOST
-static int list_transports_msg(char*  buffer, size_t  bufferlen)
-{
-    char  head[5];
-    int   len;
-
-    len = list_transports(buffer+4, bufferlen-4, 0);
-    snprintf(head, sizeof(head), "%04x", len);
-    memcpy(buffer, head, 4);
-    len += 4;
-    return len;
-}
 
 /* this adds support required by the 'track-devices' service.
  * this is used to send the content of "list_transport" to any
@@ -457,39 +413,29 @@
     return -1;
 }
 
-static int
-device_tracker_send( device_tracker*  tracker,
-                     const char*      buffer,
-                     int              len )
-{
-    apacket*  p = get_apacket();
-    asocket*  peer = tracker->socket.peer;
+static int device_tracker_send(device_tracker* tracker, const std::string& string) {
+    apacket* p = get_apacket();
+    asocket* peer = tracker->socket.peer;
 
-    memcpy(p->data, buffer, len);
-    p->len = len;
-    return peer->enqueue( peer, p );
+    snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
+    memcpy(&p->data[4], string.data(), string.size());
+    p->len = 4 + string.size();
+    return peer->enqueue(peer, p);
 }
 
+static void device_tracker_ready(asocket* socket) {
+    device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
 
-static void
-device_tracker_ready( asocket*  socket )
-{
-    device_tracker*  tracker = (device_tracker*) socket;
-
-    /* we want to send the device list when the tracker connects
-    * for the first time, even if no update occured */
+    // We want to send the device list when the tracker connects
+    // for the first time, even if no update occurred.
     if (tracker->update_needed > 0) {
-        char  buffer[1024];
-        int   len;
-
         tracker->update_needed = 0;
 
-        len = list_transports_msg(buffer, sizeof(buffer));
-        device_tracker_send(tracker, buffer, len);
+        std::string transports = list_transports(false);
+        device_tracker_send(tracker, transports);
     }
 }
 
-
 asocket*
 create_device_tracker(void)
 {
@@ -510,27 +456,25 @@
 }
 
 
-/* call this function each time the transport list has changed */
-void update_transports(void) {
-    char             buffer[1024];
-    int              len;
-    device_tracker*  tracker;
+// Call this function each time the transport list has changed.
+void update_transports() {
+    std::string transports = list_transports(false);
 
-    len = list_transports_msg(buffer, sizeof(buffer));
-
-    tracker = device_tracker_list;
-    while (tracker != NULL) {
-        device_tracker*  next = tracker->next;
-        /* note: this may destroy the tracker if the connection is closed */
-        device_tracker_send(tracker, buffer, len);
+    device_tracker* tracker = device_tracker_list;
+    while (tracker != nullptr) {
+        device_tracker* next = tracker->next;
+        // This may destroy the tracker if the connection is closed.
+        device_tracker_send(tracker, transports);
         tracker = next;
     }
 }
+
 #else
-void  update_transports(void)
-{
-    // nothing to do on the device side
+
+void update_transports() {
+    // Nothing to do on the device side.
 }
+
 #endif // ADB_HOST
 
 struct tmsg
@@ -804,7 +748,7 @@
     int ambiguous = 0;
 
 retry:
-    if (error_out) *error_out = "device not found";
+    if (error_out) *error_out = android::base::StringPrintf("device '%s' not found", serial);
 
     adb_mutex_lock(&transport_lock);
     for (t = transport_list.next; t != &transport_list; t = t->next) {
@@ -847,7 +791,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;
@@ -895,100 +839,71 @@
     return result;
 }
 
-#if ADB_HOST
-static const char *statename(atransport *t)
-{
-    switch(t->connection_state){
+const char* atransport::connection_state_name() const {
+    switch (connection_state) {
     case CS_OFFLINE: return "offline";
     case CS_BOOTLOADER: return "bootloader";
     case CS_DEVICE: return "device";
     case CS_HOST: return "host";
     case CS_RECOVERY: return "recovery";
-    case CS_SIDELOAD: return "sideload";
     case CS_NOPERM: return "no permissions";
+    case CS_SIDELOAD: return "sideload";
     case CS_UNAUTHORIZED: return "unauthorized";
     default: return "unknown";
     }
 }
 
-static void add_qual(char **buf, size_t *buf_size,
-                     const char *prefix, const char *qual, bool sanitize_qual)
-{
-    if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
+#if ADB_HOST
+
+static void append_transport_info(std::string* result, const char* key, const char* value, bool sanitize) {
+    if (value == nullptr || *value == '\0') {
         return;
-
-    int prefix_len;
-    size_t len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
-
-    if (sanitize_qual) {
-        for (char* cp = *buf + prefix_len; cp < *buf + len; cp++) {
-            if (!isalnum(*cp))
-                *cp = '_';
-        }
     }
 
-    *buf_size -= len;
-    *buf += len;
+    *result += ' ';
+    *result += key;
+
+    for (const char* p = value; *p; ++p) {
+        result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
+    }
 }
 
-static size_t format_transport(atransport *t, char *buf, size_t bufsize,
-                               int long_listing)
-{
+static void append_transport(atransport* t, std::string* result, bool long_listing) {
     const char* serial = t->serial;
-    if (!serial || !serial[0])
+    if (!serial || !serial[0]) {
         serial = "????????????";
+    }
 
     if (!long_listing) {
-        return snprintf(buf, bufsize, "%s\t%s\n", serial, statename(t));
+        *result += serial;
+        *result += '\t';
+        *result += t->connection_state_name();
     } else {
-        size_t len, remaining = bufsize;
+        android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
 
-        len = snprintf(buf, remaining, "%-22s %s", serial, statename(t));
-        remaining -= len;
-        buf += len;
-
-        add_qual(&buf, &remaining, " ", t->devpath, false);
-        add_qual(&buf, &remaining, " product:", t->product, false);
-        add_qual(&buf, &remaining, " model:", t->model, true);
-        add_qual(&buf, &remaining, " device:", t->device, false);
-
-        len = snprintf(buf, remaining, "\n");
-        remaining -= len;
-
-        return bufsize - remaining;
+        append_transport_info(result, "", t->devpath, false);
+        append_transport_info(result, "product:", t->product, false);
+        append_transport_info(result, "model:", t->model, true);
+        append_transport_info(result, "device:", t->device, false);
     }
+    *result += '\n';
 }
 
-int list_transports(char *buf, size_t  bufsize, int long_listing)
-{
-    char*       p   = buf;
-    char*       end = buf + bufsize;
-    int         len;
-    atransport *t;
-
-        /* XXX OVERRUN PROBLEMS XXX */
+std::string list_transports(bool long_listing) {
+    std::string result;
     adb_mutex_lock(&transport_lock);
-    for(t = transport_list.next; t != &transport_list; t = t->next) {
-        len = format_transport(t, p, end - p, long_listing);
-        if (p + len >= end) {
-            /* discard last line if buffer is too short */
-            break;
-        }
-        p += len;
+    for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
+        append_transport(t, &result, long_listing);
     }
-    p[0] = 0;
     adb_mutex_unlock(&transport_lock);
-    return p - buf;
+    return result;
 }
 
-
 /* hack for osx */
 void close_usb_devices()
 {
-    atransport *t;
-
     adb_mutex_lock(&transport_lock);
-    for(t = transport_list.next; t != &transport_list; t = t->next) {
+    for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
         if ( !t->kicked ) {
             t->kicked = 1;
             t->kick(t);
diff --git a/adb/transport.h b/adb/transport.h
index a2077e8..5b6fdac 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -23,10 +23,6 @@
 
 #include "adb.h"
 
-#if ADB_TRACE
-void dump_hex(const unsigned char* ptr, size_t  len);
-#endif
-
 /*
  * Obtain a transport from the available transports.
  * If state is != CS_ANY, only transports in that state are considered.
@@ -45,7 +41,7 @@
 ** get_device_transport does an acquire on your behalf before returning
 */
 void init_transport_registration(void);
-int list_transports(char* buf, size_t bufsize, int long_listing);
+std::string list_transports(bool long_listing);
 atransport* find_transport(const char* serial);
 
 void register_usb_transport(usb_handle* h, const char* serial,
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 30e6bf5..b1deffd 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -25,6 +25,8 @@
 #include <string.h>
 #include <sys/types.h>
 
+#include <base/stringprintf.h>
+
 #if !ADB_HOST
 #include "cutils/properties.h"
 #endif
@@ -88,7 +90,6 @@
 
 int local_connect_arbitrary_ports(int console_port, int adb_port)
 {
-    char buf[64];
     int  fd = -1;
 
 #if ADB_HOST
@@ -105,8 +106,8 @@
         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);
-        register_socket_transport(fd, buf, adb_port, 1);
+        std::string serial = android::base::StringPrintf("emulator-%d", console_port);
+        register_socket_transport(fd, serial.c_str(), adb_port, 1);
         return 0;
     }
     return -1;
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 31fd167..999eb11 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -31,11 +31,11 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <unistd.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
 #include <linux/usb/ch9.h>
-#else
-#include <linux/usb_ch9.h>
-#endif
+
+#include <base/file.h>
+#include <base/stringprintf.h>
+#include <base/strings.h>
 
 #include "adb.h"
 #include "transport.h"
@@ -567,13 +567,10 @@
     return 0;
 }
 
-static void register_device(const char *dev_name, const char *devpath,
+static void register_device(const char* dev_name, const char* dev_path,
                             unsigned char ep_in, unsigned char ep_out,
                             int interface, int serial_index, unsigned zero_mask)
 {
-    int n = 0;
-    char serial[256];
-
         /* Since Linux will not reassign the device ID (and dev_name)
         ** as long as the device is open, we can add to the list here
         ** once we open it and remove from the list when we're finally
@@ -621,8 +618,7 @@
     D("[ usb opened %s%s, fd=%d]\n", usb->fname, (usb->writeable ? "" : " (read-only)"), usb->desc);
 
     if (usb->writeable) {
-        n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface);
-        if (n != 0) {
+        if (ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface) != 0) {
             D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]\n", usb->desc, strerror(errno));
             adb_close(usb->desc);
             free(usb);
@@ -630,56 +626,17 @@
         }
     }
 
-        /* read the device's serial number */
-    serial[0] = 0;
-    memset(serial, 0, sizeof(serial));
-    if (serial_index) {
-        struct usbdevfs_ctrltransfer  ctrl;
-        __u16 buffer[128];
-        __u16 languages[128];
-        int i, result;
-        int languageCount = 0;
-
-        memset(languages, 0, sizeof(languages));
-        memset(&ctrl, 0, sizeof(ctrl));
-
-            // read list of supported languages
-        ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
-        ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
-        ctrl.wValue = (USB_DT_STRING << 8) | 0;
-        ctrl.wIndex = 0;
-        ctrl.wLength = sizeof(languages);
-        ctrl.data = languages;
-        ctrl.timeout = 1000;
-
-        result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
-        if (result > 0)
-            languageCount = (result - 2) / 2;
-
-        for (i = 1; i <= languageCount; i++) {
-            memset(buffer, 0, sizeof(buffer));
-            memset(&ctrl, 0, sizeof(ctrl));
-
-            ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
-            ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
-            ctrl.wValue = (USB_DT_STRING << 8) | serial_index;
-            ctrl.wIndex = __le16_to_cpu(languages[i]);
-            ctrl.wLength = sizeof(buffer);
-            ctrl.data = buffer;
-            ctrl.timeout = 1000;
-
-            result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl);
-            if (result > 0) {
-                int i;
-                // skip first word, and copy the rest to the serial string, changing shorts to bytes.
-                result /= 2;
-                for (i = 1; i < result; i++)
-                    serial[i - 1] = __le16_to_cpu(buffer[i]);
-                serial[i - 1] = 0;
-                break;
-            }
-        }
+    // Read the device's serial number.
+    std::string serial_path =
+            android::base::StringPrintf("/sys/bus/usb/devices/%s/serial", dev_path + 4);
+    std::string serial;
+    if (!android::base::ReadFileToString(serial_path, &serial)) {
+        D("[ usb read %s failed: %s ]\n", serial_path.c_str(), strerror(errno));
+        adb_close(usb->desc);
+        free(usb);
+        return;
     }
+    serial = android::base::Trim(serial);
 
         /* add to the end of the active handles */
     adb_mutex_lock(&usb_lock);
@@ -689,10 +646,10 @@
     usb->next->prev = usb;
     adb_mutex_unlock(&usb_lock);
 
-    register_usb_transport(usb, serial, devpath, usb->writeable);
+    register_usb_transport(usb, serial.c_str(), dev_path, usb->writeable);
 }
 
-void* device_poll_thread(void* unused)
+static void* device_poll_thread(void* unused)
 {
     D("Created device thread\n");
     for(;;) {
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/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/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 094ab48..b7e6b17 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -371,7 +371,8 @@
     } else {
       line += '-';
     }
-    line += android::base::StringPrintf("  %8" PRIxPTR, it->end - it->start);
+    line += android::base::StringPrintf("  %8" PRIxPTR "  %8" PRIxPTR,
+                                        it->offset, it->end - it->start);
     if (it->name.length() > 0) {
       line += "  " + it->name;
       std::string build_id;
@@ -379,6 +380,9 @@
         line += " (BuildId: " + build_id + ")";
       }
     }
+    if (it->load_base != 0) {
+      line += android::base::StringPrintf(" (load base 0x%" PRIxPTR ")", it->load_base);
+    }
     _LOG(log, logtype::MAPS, "%s\n", line.c_str());
   }
   if (print_fault_address_marker) {
@@ -792,7 +796,7 @@
   *detach_failed = dump_crash(&log, pid, tid, signal, original_si_code, abort_msg_address,
                               dump_sibling_threads, total_sleep_time_usec);
 
-  ALOGI("\nTombstone written to: %s\n", path);
+  _LOG(&log, logtype::BACKTRACE, "\nTombstone written to: %s\n", path);
 
   // Either of these file descriptors can be -1, any error is ignored.
   close(amfd);
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index e10feff..e722f82 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -26,25 +26,12 @@
 #include <sys/wait.h>
 
 #include <backtrace/Backtrace.h>
+#include <base/file.h>
 #include <log/log.h>
 
 const int SLEEP_TIME_USEC = 50000;         // 0.05 seconds
 const int MAX_TOTAL_SLEEP_USEC = 10000000; // 10 seconds
 
-static int write_to_am(int fd, const char* buf, int len) {
-  int to_write = len;
-  while (to_write > 0) {
-    int written = TEMP_FAILURE_RETRY(write(fd, buf + len - to_write, to_write));
-    if (written < 0) {
-      // hard failure
-      ALOGE("AM write failure (%d / %s)\n", errno, strerror(errno));
-      return -1;
-    }
-    to_write -= written;
-  }
-  return len;
-}
-
 // Whitelist output desired in the logcat output.
 bool is_allowed_in_logcat(enum logtype ltype) {
   if ((ltype == ERROR)
@@ -80,11 +67,11 @@
   }
 
   if (write_to_logcat) {
-    __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_INFO, LOG_TAG, buf);
+    __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_FATAL, LOG_TAG, buf);
     if (write_to_activitymanager) {
-      int written = write_to_am(log->amfd, buf, len);
-      if (written <= 0) {
+      if (!android::base::WriteFully(log->amfd, buf, len)) {
         // timeout or other failure on write; stop informing the activity manager
+        ALOGE("AM write failed: %s", strerror(errno));
         log->amfd = -1;
       }
     }
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index e139bcd..e35cc70 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -285,9 +285,8 @@
             "                                           Can override the fs type and/or\n"
             "                                           size the bootloader reports.\n"
             "  getvar <variable>                        display a bootloader variable\n"
-            "  boot <kernel> [ <ramdisk> [ <second> ] ] download and boot kernel\n"
-            "  flash:raw boot <kernel> [ <ramdisk> [ <second> ] ] create bootimage and \n"
-            "                                           flash it\n"
+            "  boot <kernel> [ <ramdisk> ]              download and boot kernel\n"
+            "  flash:raw boot <kernel> [ <ramdisk> ]    create bootimage and flash it\n"
             "  devices                                  list all connected devices\n"
             "  continue                                 continue with autoboot\n"
             "  reboot [bootloader]                      reboot device, optionally into bootloader\n"
@@ -315,11 +314,10 @@
 }
 
 void *load_bootable_image(const char *kernel, const char *ramdisk,
-                          const char *secondstage, unsigned *sz,
-                          const char *cmdline)
+                          unsigned *sz, const char *cmdline)
 {
-    void *kdata = 0, *rdata = 0, *sdata = 0;
-    unsigned ksize = 0, rsize = 0, ssize = 0;
+    void *kdata = 0, *rdata = 0;
+    unsigned ksize = 0, rsize = 0;
     void *bdata;
     unsigned bsize;
 
@@ -355,18 +353,10 @@
         }
     }
 
-    if (secondstage) {
-        sdata = load_file(secondstage, &ssize);
-        if(sdata == 0) {
-            fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno));
-            return  0;
-        }
-    }
-
     fprintf(stderr,"creating boot image...\n");
     bdata = mkbootimg(kdata, ksize, kernel_offset,
                       rdata, rsize, ramdisk_offset,
-                      sdata, ssize, second_offset,
+                      0, 0, second_offset,
                       page_size, base_addr, tags_offset, &bsize);
     if(bdata == 0) {
         fprintf(stderr,"failed to create boot.img\n");
@@ -1134,7 +1124,6 @@
         } else if(!strcmp(*argv, "boot")) {
             char *kname = 0;
             char *rname = 0;
-            char *sname = 0;
             skip(1);
             if (argc > 0) {
                 kname = argv[0];
@@ -1144,11 +1133,7 @@
                 rname = argv[0];
                 skip(1);
             }
-            if (argc > 0) {
-                sname = argv[0];
-                skip(1);
-            }
-            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+            data = load_bootable_image(kname, rname, &sz, cmdline);
             if (data == 0) return 1;
             fb_queue_download("boot.img", data, sz);
             fb_queue_command("boot", "booting");
@@ -1172,18 +1157,14 @@
             char *pname = argv[1];
             char *kname = argv[2];
             char *rname = 0;
-            char *sname = 0;
             require(3);
-            skip(3);
-            if (argc > 0) {
-                rname = argv[0];
-                skip(1);
+            if(argc > 3) {
+                rname = argv[3];
+                skip(4);
+            } else {
+                skip(3);
             }
-            if (argc > 0) {
-                sname = argv[0];
-                skip(1);
-            }
-            data = load_bootable_image(kname, rname, sname, &sz, cmdline);
+            data = load_bootable_image(kname, rname, &sz, cmdline);
             if (data == 0) die("cannot load bootable image");
             fb_queue_flash(pname, data, sz);
         } else if(!strcmp(*argv, "flashall")) {
diff --git a/fs_mgr/fs_mgr_format.c b/fs_mgr/fs_mgr_format.c
index b5b92b5..95c6a74 100644
--- a/fs_mgr/fs_mgr_format.c
+++ b/fs_mgr/fs_mgr_format.c
@@ -52,7 +52,7 @@
     info.len = ((off64_t)nr_sec * 512);
 
     /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */
-    rc = make_ext4fs_internal(fd, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
+    rc = make_ext4fs_internal(fd, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
     if (rc) {
         ERROR("make_ext4fs returned %d.\n", rc);
     }
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 4e0ba4d..882585c 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -70,6 +70,7 @@
     { "zramsize=",   MF_ZRAMSIZE },
     { "verify",      MF_VERIFY },
     { "noemulatedsd", MF_NOEMULATEDSD },
+    { "notrim",       MF_NOTRIM },
     { "formattable", MF_FORMATTABLE },
     { "defaults",    0 },
     { 0,             0 },
@@ -450,6 +451,11 @@
     return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
 }
 
+int fs_mgr_is_notrim(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_NOTRIM;
+}
+
 int fs_mgr_is_formattable(struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & (MF_FORMATTABLE);
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 2d252e4..682fd11 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -76,8 +76,9 @@
 #define MF_FORCECRYPT   0x400
 #define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only
                                  external storage */
-#define MF_FORMATTABLE  0x1000
+#define MF_NOTRIM       0x1000
 #define MF_FILEENCRYPTION 0x2000
+#define MF_FORMATTABLE  0x4000
 
 #define DM_BUF_SIZE 4096
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 68af452..27fccf7 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -103,6 +103,7 @@
 int fs_mgr_is_encryptable(const struct fstab_rec *fstab);
 int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab);
 int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab);
+int fs_mgr_is_notrim(struct fstab_rec *fstab);
 int fs_mgr_is_formattable(struct fstab_rec *fstab);
 int fs_mgr_swapon_all(struct fstab *fstab);
 
diff --git a/gatekeeperd/Android.mk b/gatekeeperd/Android.mk
new file mode 100644
index 0000000..f743cc3
--- /dev/null
+++ b/gatekeeperd/Android.mk
@@ -0,0 +1,31 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
+LOCAL_SRC_FILES := IGateKeeperService.cpp gatekeeperd.cpp
+LOCAL_MODULE := gatekeeperd
+LOCAL_SHARED_LIBRARIES := \
+	libbinder \
+	liblog \
+	libhardware \
+	libutils \
+	libkeystore_binder
+LOCAL_C_INCLUDES := \
+	system/gatekeeper/include
+include $(BUILD_EXECUTABLE)
diff --git a/gatekeeperd/IGateKeeperService.cpp b/gatekeeperd/IGateKeeperService.cpp
new file mode 100644
index 0000000..f5bbbf1
--- /dev/null
+++ b/gatekeeperd/IGateKeeperService.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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.
+*/
+
+#define LOG_TAG "GateKeeperService"
+#include <utils/Log.h>
+
+#include "IGateKeeperService.h"
+
+namespace android {
+
+const android::String16 IGateKeeperService::descriptor("android.service.gatekeeper.IGateKeeperService");
+const android::String16& IGateKeeperService::getInterfaceDescriptor() const {
+    return IGateKeeperService::descriptor;
+}
+
+status_t BnGateKeeperService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch(code) {
+        case ENROLL: {
+            CHECK_INTERFACE(IGateKeeperService, data, reply);
+            uint32_t uid = data.readInt32();
+
+            ssize_t currentPasswordHandleSize = data.readInt32();
+            const uint8_t *currentPasswordHandle =
+                    static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
+            if (!currentPasswordHandle) currentPasswordHandleSize = 0;
+
+            ssize_t currentPasswordSize = data.readInt32();
+            const uint8_t *currentPassword =
+                    static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
+            if (!currentPassword) currentPasswordSize = 0;
+
+            ssize_t desiredPasswordSize = data.readInt32();
+            const uint8_t *desiredPassword =
+                    static_cast<const uint8_t *>(data.readInplace(desiredPasswordSize));
+            if (!desiredPassword) desiredPasswordSize = 0;
+
+            uint8_t *out = NULL;
+            uint32_t outSize = 0;
+            status_t ret = enroll(uid, currentPasswordHandle, currentPasswordHandleSize,
+                    currentPassword, currentPasswordSize, desiredPassword,
+                    desiredPasswordSize, &out, &outSize);
+
+            reply->writeNoException();
+            if (ret == NO_ERROR && outSize > 0 && out != NULL) {
+                reply->writeInt32(outSize);
+                void *buf = reply->writeInplace(outSize);
+                memcpy(buf, out, outSize);
+                free(out);
+            } else {
+                reply->writeInt32(-1);
+            }
+            return NO_ERROR;
+        }
+        case VERIFY: {
+            CHECK_INTERFACE(IGateKeeperService, data, reply);
+            uint32_t uid = data.readInt32();
+            ssize_t currentPasswordHandleSize = data.readInt32();
+            const uint8_t *currentPasswordHandle =
+                    static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
+            if (!currentPasswordHandle) currentPasswordHandleSize = 0;
+
+            ssize_t currentPasswordSize = data.readInt32();
+            const uint8_t *currentPassword =
+                static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
+            if (!currentPassword) currentPasswordSize = 0;
+
+            status_t ret = verify(uid, (uint8_t *) currentPasswordHandle,
+                    currentPasswordHandleSize, (uint8_t *) currentPassword, currentPasswordSize);
+            reply->writeNoException();
+            reply->writeInt32(ret == NO_ERROR ? 1 : 0);
+            return NO_ERROR;
+        }
+        case VERIFY_CHALLENGE: {
+            CHECK_INTERFACE(IGateKeeperService, data, reply);
+            uint32_t uid = data.readInt32();
+            uint64_t challenge = data.readInt64();
+            ssize_t currentPasswordHandleSize = data.readInt32();
+            const uint8_t *currentPasswordHandle =
+                    static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
+            if (!currentPasswordHandle) currentPasswordHandleSize = 0;
+
+            ssize_t currentPasswordSize = data.readInt32();
+            const uint8_t *currentPassword =
+                static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
+            if (!currentPassword) currentPasswordSize = 0;
+
+
+            uint8_t *out = NULL;
+            uint32_t outSize = 0;
+            status_t ret = verifyChallenge(uid, challenge, (uint8_t *) currentPasswordHandle,
+                    currentPasswordHandleSize, (uint8_t *) currentPassword, currentPasswordSize,
+                    &out, &outSize);
+            reply->writeNoException();
+            if (ret == NO_ERROR && outSize > 0 && out != NULL) {
+                reply->writeInt32(outSize);
+                void *buf = reply->writeInplace(outSize);
+                memcpy(buf, out, outSize);
+                free(out);
+            } else {
+                reply->writeInt32(-1);
+            }
+            return NO_ERROR;
+        }
+        case GET_SECURE_USER_ID: {
+            CHECK_INTERFACE(IGateKeeperService, data, reply);
+            uint32_t uid = data.readInt32();
+            uint64_t sid = getSecureUserId(uid);
+            reply->writeNoException();
+            reply->writeInt64(sid);
+            return NO_ERROR;
+        }
+        case CLEAR_SECURE_USER_ID: {
+            CHECK_INTERFACE(IGateKeeperService, data, reply);
+            uint32_t uid = data.readInt32();
+            clearSecureUserId(uid);
+            reply->writeNoException();
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+};
+
+
+}; // namespace android
diff --git a/gatekeeperd/IGateKeeperService.h b/gatekeeperd/IGateKeeperService.h
new file mode 100644
index 0000000..a777318
--- /dev/null
+++ b/gatekeeperd/IGateKeeperService.h
@@ -0,0 +1,92 @@
+/*
+ * 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 IGATEKEEPER_SERVICE_H_
+#define IGATEKEEPER_SERVICE_H_
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+/*
+ * This must be kept manually in sync with frameworks/base's IGateKeeperService.aidl
+ */
+class IGateKeeperService : public IInterface {
+public:
+    enum {
+        ENROLL = IBinder::FIRST_CALL_TRANSACTION + 0,
+        VERIFY = IBinder::FIRST_CALL_TRANSACTION + 1,
+        VERIFY_CHALLENGE = IBinder::FIRST_CALL_TRANSACTION + 2,
+        GET_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 3,
+        CLEAR_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 4,
+    };
+
+    // DECLARE_META_INTERFACE - C++ client interface not needed
+    static const android::String16 descriptor;
+    virtual const android::String16& getInterfaceDescriptor() const;
+    IGateKeeperService() {}
+    virtual ~IGateKeeperService() {}
+
+    /**
+     * Enrolls a password with the GateKeeper. Returns 0 on success, negative on failure.
+     */
+    virtual status_t enroll(uint32_t uid,
+            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+            const uint8_t *current_password, uint32_t current_password_length,
+            const uint8_t *desired_password, uint32_t desired_password_length,
+            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) = 0;
+
+    /**
+     * Verifies a password previously enrolled with the GateKeeper.
+     * Returns 0 on success, negative on failure.
+     */
+    virtual status_t verify(uint32_t uid, const uint8_t *enrolled_password_handle,
+            uint32_t enrolled_password_handle_length,
+            const uint8_t *provided_password, uint32_t provided_password_length) = 0;
+
+    /**
+     * Verifies a password previously enrolled with the GateKeeper.
+     * Returns 0 on success, negative on failure.
+     */
+    virtual status_t verifyChallenge(uint32_t uid, uint64_t challenge,
+            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
+            const uint8_t *provided_password, uint32_t provided_password_length,
+            uint8_t **auth_token, uint32_t *auth_token_length) = 0;
+
+    /**
+     * Returns the secure user ID for the provided android user
+     */
+    virtual uint64_t getSecureUserId(uint32_t uid) = 0;
+
+    /**
+     * Clears the secure user ID associated with the user.
+     */
+    virtual void clearSecureUserId(uint32_t uid) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnGateKeeperService: public BnInterface<IGateKeeperService> {
+public:
+    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+            uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif
+
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
new file mode 100644
index 0000000..75cd225
--- /dev/null
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -0,0 +1,247 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "gatekeeperd"
+
+#include "IGateKeeperService.h"
+
+#include <errno.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cutils/log.h>
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
+#include <utils/String16.h>
+
+#include <keystore/IKeystoreService.h>
+#include <keystore/keystore.h> // For error code
+#include <gatekeeper/password_handle.h> // for password_handle_t
+#include <hardware/gatekeeper.h>
+#include <hardware/hw_auth_token.h>
+
+namespace android {
+
+static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SECURE_STORAGE");
+static const String16 DUMP_PERMISSION("android.permission.DUMP");
+
+class GateKeeperProxy : public BnGateKeeperService {
+public:
+    GateKeeperProxy() {
+        int ret = hw_get_module_by_class(GATEKEEPER_HARDWARE_MODULE_ID, NULL, &module);
+        if (ret < 0)
+            LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to find GateKeeper HAL");
+        ret = gatekeeper_open(module, &device);
+        if (ret < 0)
+            LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL");
+    }
+
+    virtual ~GateKeeperProxy() {
+        gatekeeper_close(device);
+    }
+
+    void store_sid(uint32_t uid, uint64_t sid) {
+        char filename[21];
+        sprintf(filename, "%u", uid);
+        int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+        if (fd < 0) {
+            ALOGE("could not open file: %s: %s", filename, strerror(errno));
+            return;
+        }
+        write(fd, &sid, sizeof(sid));
+        close(fd);
+    }
+
+    void maybe_store_sid(uint32_t uid, uint64_t sid) {
+        char filename[21];
+        sprintf(filename, "%u", uid);
+        if (access(filename, F_OK) == -1) {
+            store_sid(uid, sid);
+        }
+    }
+
+    uint64_t read_sid(uint32_t uid) {
+        char filename[21];
+        uint64_t sid;
+        sprintf(filename, "%u", uid);
+        int fd = open(filename, O_RDONLY);
+        if (fd < 0) return 0;
+        read(fd, &sid, sizeof(sid));
+        return sid;
+    }
+
+    void clear_sid(uint32_t uid) {
+        char filename[21];
+        sprintf(filename, "%u", uid);
+        if (remove(filename) < 0) {
+            ALOGE("%s: could not remove file [%s], attempting 0 write", __func__, strerror(errno));
+            store_sid(uid, 0);
+        }
+    }
+
+    virtual status_t enroll(uint32_t uid,
+            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
+            const uint8_t *current_password, uint32_t current_password_length,
+            const uint8_t *desired_password, uint32_t desired_password_length,
+            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
+        IPCThreadState* ipc = IPCThreadState::self();
+        const int calling_pid = ipc->getCallingPid();
+        const int calling_uid = ipc->getCallingUid();
+        if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+            return PERMISSION_DENIED;
+        }
+
+        // need a desired password to enroll
+        if (desired_password_length == 0) return -EINVAL;
+        int ret = device->enroll(device, uid,
+                current_password_handle, current_password_handle_length,
+                current_password, current_password_length,
+                desired_password, desired_password_length,
+                enrolled_password_handle, enrolled_password_handle_length);
+        if (ret >= 0) {
+            gatekeeper::password_handle_t *handle =
+                    reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
+            store_sid(uid, handle->user_id);
+            return NO_ERROR;
+        }
+        return UNKNOWN_ERROR;
+    }
+
+    virtual status_t verify(uint32_t uid,
+            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
+            const uint8_t *provided_password, uint32_t provided_password_length) {
+        uint8_t *auth_token;
+        uint32_t auth_token_length;
+        return verifyChallenge(uid, 0, enrolled_password_handle, enrolled_password_handle_length,
+                provided_password, provided_password_length,
+                &auth_token, &auth_token_length);
+    }
+
+    virtual status_t verifyChallenge(uint32_t uid, uint64_t challenge,
+            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
+            const uint8_t *provided_password, uint32_t provided_password_length,
+            uint8_t **auth_token, uint32_t *auth_token_length) {
+        IPCThreadState* ipc = IPCThreadState::self();
+        const int calling_pid = ipc->getCallingPid();
+        const int calling_uid = ipc->getCallingUid();
+        if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+            return PERMISSION_DENIED;
+        }
+
+        // can't verify if we're missing either param
+        if ((enrolled_password_handle_length | provided_password_length) == 0)
+            return -EINVAL;
+
+        int ret = device->verify(device, uid, challenge,
+                enrolled_password_handle, enrolled_password_handle_length,
+                provided_password, provided_password_length, auth_token, auth_token_length);
+
+        if (ret >= 0 && *auth_token != NULL && *auth_token_length > 0) {
+            // TODO: cache service?
+            sp<IServiceManager> sm = defaultServiceManager();
+            sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+            sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+            if (service != NULL) {
+                status_t ret = service->addAuthToken(*auth_token, *auth_token_length);
+                if (ret != ResponseCode::NO_ERROR) {
+                    ALOGE("Falure sending auth token to KeyStore: %d", ret);
+                }
+            } else {
+                ALOGE("Unable to communicate with KeyStore");
+            }
+        }
+
+        if (ret >= 0) {
+            maybe_store_sid(uid, reinterpret_cast<const gatekeeper::password_handle_t *>(
+                        enrolled_password_handle)->user_id);
+            return NO_ERROR;
+        }
+
+        return UNKNOWN_ERROR;
+    }
+
+    virtual uint64_t getSecureUserId(uint32_t uid) {
+        return read_sid(uid);
+    }
+
+    virtual void clearSecureUserId(uint32_t uid) {
+        IPCThreadState* ipc = IPCThreadState::self();
+        const int calling_pid = ipc->getCallingPid();
+        const int calling_uid = ipc->getCallingUid();
+        if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
+            ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
+            return;
+        }
+        clear_sid(uid);
+    }
+
+    virtual status_t dump(int fd, const Vector<String16> &) {
+        IPCThreadState* ipc = IPCThreadState::self();
+        const int pid = ipc->getCallingPid();
+        const int uid = ipc->getCallingUid();
+        if (!PermissionCache::checkPermission(DUMP_PERMISSION, pid, uid)) {
+            return PERMISSION_DENIED;
+        }
+
+        if (device == NULL) {
+            const char *result = "Device not available";
+            write(fd, result, strlen(result) + 1);
+        } else {
+            const char *result = "OK";
+            write(fd, result, strlen(result) + 1);
+        }
+
+        return NO_ERROR;
+    }
+
+private:
+    gatekeeper_device_t *device;
+    const hw_module_t *module;
+};
+}// namespace android
+
+int main(int argc, char* argv[]) {
+    ALOGI("Starting gatekeeperd...");
+    if (argc < 2) {
+        ALOGE("A directory must be specified!");
+        return 1;
+    }
+    if (chdir(argv[1]) == -1) {
+        ALOGE("chdir: %s: %s", argv[1], strerror(errno));
+        return 1;
+    }
+
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
+    android::status_t ret = sm->addService(
+            android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
+    if (ret != android::OK) {
+        ALOGE("Couldn't register binder service!");
+        return -1;
+    }
+
+    /*
+     * We're the only thread in existence, so we're just going to process
+     * Binder transaction as a single-threaded program.
+     */
+    android::IPCThreadState::self()->joinThreadPool();
+    return 0;
+}
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index 1fee855..b0002cc 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -53,6 +53,7 @@
     .batteryCurrentAvgPath = String8(String8::kEmptyString),
     .batteryChargeCounterPath = String8(String8::kEmptyString),
     .energyCounter = NULL,
+    .boot_min_cap = 0,
     .screen_on = NULL,
 };
 
diff --git a/healthd/healthd.h b/healthd/healthd.h
index 4704f0b..84b6d76 100644
--- a/healthd/healthd.h
+++ b/healthd/healthd.h
@@ -67,6 +67,7 @@
     android::String8 batteryChargeCounterPath;
 
     int (*energyCounter)(int64_t *);
+    int boot_min_cap;
     bool (*screen_on)(android::BatteryProperties *props);
 };
 
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 78f8403..6800ad2 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -116,6 +116,7 @@
 
     struct animation *batt_anim;
     GRSurface* surf_unknown;
+    int boot_min_cap;
 };
 
 static struct frame batt_anim_frames[] = {
@@ -520,19 +521,29 @@
                     LOGW("[%" PRId64 "] booting from charger mode\n", now);
                     property_set("sys.boot_from_charger_mode", "1");
                 } else {
-                    LOGW("[%" PRId64 "] rebooting\n", now);
-                    android_reboot(ANDROID_RB_RESTART, 0, 0);
+                    if (charger->batt_anim->capacity >= charger->boot_min_cap) {
+                        LOGW("[%" PRId64 "] rebooting\n", now);
+                        android_reboot(ANDROID_RB_RESTART, 0, 0);
+                    } else {
+                        LOGV("[%" PRId64 "] ignore power-button press, battery level "
+                            "less than minimum\n", now);
+                    }
                 }
             } else {
                 /* if the key is pressed but timeout hasn't expired,
                  * make sure we wake up at the right-ish time to check
                  */
                 set_next_key_check(charger, key, POWER_ON_KEY_TIME);
+
+               /* Turn on the display and kick animation on power-key press
+                * rather than on key release
+                */
+                kick_animation(charger->batt_anim);
+                request_suspend(false);
             }
         } else {
             /* if the power key got released, force screen state cycle */
             if (key->pending) {
-                request_suspend(false);
                 kick_animation(charger->batt_anim);
             }
         }
@@ -555,6 +566,11 @@
         return;
 
     if (!charger->charger_connected) {
+
+        /* Last cycle would have stopped at the extreme top of battery-icon
+         * Need to show the correct level corresponding to capacity.
+         */
+        kick_animation(charger->batt_anim);
         request_suspend(false);
         if (charger->next_pwr_check == -1) {
             charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
@@ -705,4 +721,5 @@
     charger->next_key_check = -1;
     charger->next_pwr_check = -1;
     healthd_config = config;
+    charger->boot_min_cap = config->boot_min_cap;
 }
diff --git a/include/backtrace/BacktraceMap.h b/include/backtrace/BacktraceMap.h
index da96307..784bc03 100644
--- a/include/backtrace/BacktraceMap.h
+++ b/include/backtrace/BacktraceMap.h
@@ -37,6 +37,8 @@
 
   uintptr_t start;
   uintptr_t end;
+  uintptr_t offset;
+  uintptr_t load_base;
   int flags;
   std::string name;
 };
@@ -82,6 +84,14 @@
     return map.end > 0;
   }
 
+  static uintptr_t GetRelativePc(const backtrace_map_t& map, uintptr_t pc) {
+    if (IsValid(map)) {
+      return pc - map.start + map.load_base;
+    } else {
+      return pc;
+    }
+  }
+
 protected:
   BacktraceMap(pid_t pid);
 
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/netutils/dhcp.h b/include/netutils/dhcp.h
index de6bc82..008dbd8 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -23,26 +23,18 @@
 __BEGIN_DECLS
 
 extern int do_dhcp(char *iname);
-extern int dhcp_do_request(const char *ifname,
-                          char *ipaddr,
-                          char *gateway,
-                          uint32_t *prefixLength,
-                          char *dns[],
-                          char *server,
-                          uint32_t *lease,
-                          char *vendorInfo,
-                          char *domain,
-                          char *mtu);
-extern int dhcp_do_request_renew(const char *ifname,
-                                char *ipaddr,
-                                char *gateway,
-                                uint32_t *prefixLength,
-                                char *dns[],
-                                char *server,
-                                uint32_t *lease,
-                                char *vendorInfo,
-                                char *domain,
-                                char *mtu);
+extern int dhcp_start(const char *ifname);
+extern int dhcp_start_renew(const char *ifname);
+extern int dhcp_get_results(const char *ifname,
+                            char *ipaddr,
+                            char *gateway,
+                            uint32_t *prefixLength,
+                            char *dns[],
+                            char *server,
+                            uint32_t *lease,
+                            char *vendorInfo,
+                            char *domain,
+                            char *mtu);
 extern int dhcp_stop(const char *ifname);
 extern int dhcp_release_lease(const char *ifname);
 extern char *dhcp_get_errmsg();
diff --git a/include/system/audio.h b/include/system/audio.h
deleted file mode 100644
index 181a171..0000000
--- a/include/system/audio.h
+++ /dev/null
@@ -1,1373 +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.
- */
-
-
-#ifndef ANDROID_AUDIO_CORE_H
-#define ANDROID_AUDIO_CORE_H
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <cutils/bitops.h>
-
-__BEGIN_DECLS
-
-/* The enums were moved here mostly from
- * frameworks/base/include/media/AudioSystem.h
- */
-
-/* device address used to refer to the standard remote submix */
-#define AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS "0"
-
-/* AudioFlinger and AudioPolicy services use I/O handles to identify audio sources and sinks */
-typedef int audio_io_handle_t;
-#define AUDIO_IO_HANDLE_NONE    0
-
-/* Audio stream types */
-typedef enum {
-    /* These values must kept in sync with
-     * frameworks/base/media/java/android/media/AudioSystem.java
-     */
-    AUDIO_STREAM_DEFAULT          = -1,
-    AUDIO_STREAM_MIN              = 0,
-    AUDIO_STREAM_VOICE_CALL       = 0,
-    AUDIO_STREAM_SYSTEM           = 1,
-    AUDIO_STREAM_RING             = 2,
-    AUDIO_STREAM_MUSIC            = 3,
-    AUDIO_STREAM_ALARM            = 4,
-    AUDIO_STREAM_NOTIFICATION     = 5,
-    AUDIO_STREAM_BLUETOOTH_SCO    = 6,
-    AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user
-                                        * and must be routed to speaker
-                                        */
-    AUDIO_STREAM_DTMF             = 8,
-    AUDIO_STREAM_TTS              = 9,  /* Transmitted Through Speaker.
-                                         * Plays over speaker only, silent on other devices.
-                                         */
-    AUDIO_STREAM_ACCESSIBILITY    = 10, /* For accessibility talk back prompts */
-    AUDIO_STREAM_REROUTING        = 11, /* For dynamic policy output mixes */
-    AUDIO_STREAM_PATCH            = 12, /* For internal audio flinger tracks. Fixed volume */
-    AUDIO_STREAM_PUBLIC_CNT       = AUDIO_STREAM_TTS + 1,
-    AUDIO_STREAM_CNT              = AUDIO_STREAM_PATCH + 1,
-} audio_stream_type_t;
-
-/* Do not change these values without updating their counterparts
- * in frameworks/base/media/java/android/media/AudioAttributes.java
- */
-typedef enum {
-    AUDIO_CONTENT_TYPE_UNKNOWN      = 0,
-    AUDIO_CONTENT_TYPE_SPEECH       = 1,
-    AUDIO_CONTENT_TYPE_MUSIC        = 2,
-    AUDIO_CONTENT_TYPE_MOVIE        = 3,
-    AUDIO_CONTENT_TYPE_SONIFICATION = 4,
-
-    AUDIO_CONTENT_TYPE_CNT,
-    AUDIO_CONTENT_TYPE_MAX          = AUDIO_CONTENT_TYPE_CNT - 1,
-} audio_content_type_t;
-
-/* Do not change these values without updating their counterparts
- * in frameworks/base/media/java/android/media/AudioAttributes.java
- */
-typedef enum {
-    AUDIO_USAGE_UNKNOWN                            = 0,
-    AUDIO_USAGE_MEDIA                              = 1,
-    AUDIO_USAGE_VOICE_COMMUNICATION                = 2,
-    AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING     = 3,
-    AUDIO_USAGE_ALARM                              = 4,
-    AUDIO_USAGE_NOTIFICATION                       = 5,
-    AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE    = 6,
-    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7,
-    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8,
-    AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9,
-    AUDIO_USAGE_NOTIFICATION_EVENT                 = 10,
-    AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY           = 11,
-    AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE     = 12,
-    AUDIO_USAGE_ASSISTANCE_SONIFICATION            = 13,
-    AUDIO_USAGE_GAME                               = 14,
-    AUDIO_USAGE_VIRTUAL_SOURCE                     = 15,
-
-    AUDIO_USAGE_CNT,
-    AUDIO_USAGE_MAX                                = AUDIO_USAGE_CNT - 1,
-} audio_usage_t;
-
-typedef uint32_t audio_flags_mask_t;
-
-/* Do not change these values without updating their counterparts
- * in frameworks/base/media/java/android/media/AudioAttributes.java
- */
-enum {
-    AUDIO_FLAG_AUDIBILITY_ENFORCED = 0x1,
-    AUDIO_FLAG_SECURE              = 0x2,
-    AUDIO_FLAG_SCO                 = 0x4,
-    AUDIO_FLAG_BEACON              = 0x8,
-    AUDIO_FLAG_HW_AV_SYNC          = 0x10,
-    AUDIO_FLAG_HW_HOTWORD          = 0x20,
-};
-
-/* Do not change these values without updating their counterparts
- * in frameworks/base/media/java/android/media/MediaRecorder.java,
- * frameworks/av/services/audiopolicy/AudioPolicyService.cpp,
- * and system/media/audio_effects/include/audio_effects/audio_effects_conf.h!
- */
-typedef enum {
-    AUDIO_SOURCE_DEFAULT             = 0,
-    AUDIO_SOURCE_MIC                 = 1,
-    AUDIO_SOURCE_VOICE_UPLINK        = 2,
-    AUDIO_SOURCE_VOICE_DOWNLINK      = 3,
-    AUDIO_SOURCE_VOICE_CALL          = 4,
-    AUDIO_SOURCE_CAMCORDER           = 5,
-    AUDIO_SOURCE_VOICE_RECOGNITION   = 6,
-    AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
-    AUDIO_SOURCE_REMOTE_SUBMIX       = 8, /* Source for the mix to be presented remotely.      */
-                                          /* An example of remote presentation is Wifi Display */
-                                          /*  where a dongle attached to a TV can be used to   */
-                                          /*  play the mix captured by this audio source.      */
-    AUDIO_SOURCE_CNT,
-    AUDIO_SOURCE_MAX                 = AUDIO_SOURCE_CNT - 1,
-    AUDIO_SOURCE_FM_TUNER            = 1998,
-    AUDIO_SOURCE_HOTWORD             = 1999, /* A low-priority, preemptible audio source for
-                                                for background software hotword detection.
-                                                Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
-                                                Used only internally to the framework. Not exposed
-                                                at the audio HAL. */
-} audio_source_t;
-
-/* Audio attributes */
-#define AUDIO_ATTRIBUTES_TAGS_MAX_SIZE 256
-typedef struct {
-    audio_content_type_t content_type;
-    audio_usage_t        usage;
-    audio_source_t       source;
-    audio_flags_mask_t   flags;
-    char                 tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; /* UTF8 */
-} audio_attributes_t;
-
-/* special audio session values
- * (XXX: should this be living in the audio effects land?)
- */
-typedef enum {
-    /* session for effects attached to a particular output stream
-     * (value must be less than 0)
-     */
-    AUDIO_SESSION_OUTPUT_STAGE = -1,
-
-    /* session for effects applied to output mix. These effects can
-     * be moved by audio policy manager to another output stream
-     * (value must be 0)
-     */
-    AUDIO_SESSION_OUTPUT_MIX = 0,
-
-    /* application does not specify an explicit session ID to be used,
-     * and requests a new session ID to be allocated
-     * TODO use unique values for AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE,
-     * after all uses have been updated from 0 to the appropriate symbol, and have been tested.
-     */
-    AUDIO_SESSION_ALLOCATE = 0,
-} audio_session_t;
-
-/* a unique ID allocated by AudioFlinger for use as a audio_io_handle_t or audio_session_t */
-typedef int audio_unique_id_t;
-
-#define AUDIO_UNIQUE_ID_ALLOCATE AUDIO_SESSION_ALLOCATE
-
-/* Audio sub formats (see enum audio_format). */
-
-/* PCM sub formats */
-typedef enum {
-    /* All of these are in native byte order */
-    AUDIO_FORMAT_PCM_SUB_16_BIT          = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */
-    AUDIO_FORMAT_PCM_SUB_8_BIT           = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */
-    AUDIO_FORMAT_PCM_SUB_32_BIT          = 0x3, /* PCM signed .31 fixed point */
-    AUDIO_FORMAT_PCM_SUB_8_24_BIT        = 0x4, /* PCM signed 7.24 fixed point */
-    AUDIO_FORMAT_PCM_SUB_FLOAT           = 0x5, /* PCM single-precision floating point */
-    AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED   = 0x6, /* PCM signed .23 fixed point packed in 3 bytes */
-} audio_format_pcm_sub_fmt_t;
-
-/* The audio_format_*_sub_fmt_t declarations are not currently used */
-
-/* MP3 sub format field definition : can use 11 LSBs in the same way as MP3
- * frame header to specify bit rate, stereo mode, version...
- */
-typedef enum {
-    AUDIO_FORMAT_MP3_SUB_NONE            = 0x0,
-} audio_format_mp3_sub_fmt_t;
-
-/* AMR NB/WB sub format field definition: specify frame block interleaving,
- * bandwidth efficient or octet aligned, encoding mode for recording...
- */
-typedef enum {
-    AUDIO_FORMAT_AMR_SUB_NONE            = 0x0,
-} audio_format_amr_sub_fmt_t;
-
-/* AAC sub format field definition: specify profile or bitrate for recording... */
-typedef enum {
-    AUDIO_FORMAT_AAC_SUB_MAIN            = 0x1,
-    AUDIO_FORMAT_AAC_SUB_LC              = 0x2,
-    AUDIO_FORMAT_AAC_SUB_SSR             = 0x4,
-    AUDIO_FORMAT_AAC_SUB_LTP             = 0x8,
-    AUDIO_FORMAT_AAC_SUB_HE_V1           = 0x10,
-    AUDIO_FORMAT_AAC_SUB_SCALABLE        = 0x20,
-    AUDIO_FORMAT_AAC_SUB_ERLC            = 0x40,
-    AUDIO_FORMAT_AAC_SUB_LD              = 0x80,
-    AUDIO_FORMAT_AAC_SUB_HE_V2           = 0x100,
-    AUDIO_FORMAT_AAC_SUB_ELD             = 0x200,
-} audio_format_aac_sub_fmt_t;
-
-/* VORBIS sub format field definition: specify quality for recording... */
-typedef enum {
-    AUDIO_FORMAT_VORBIS_SUB_NONE         = 0x0,
-} audio_format_vorbis_sub_fmt_t;
-
-/* Audio format consists of a main format field (upper 8 bits) and a sub format
- * field (lower 24 bits).
- *
- * The main format indicates the main codec type. The sub format field
- * indicates options and parameters for each format. The sub format is mainly
- * used for record to indicate for instance the requested bitrate or profile.
- * It can also be used for certain formats to give informations not present in
- * the encoded audio stream (e.g. octet alignement for AMR).
- */
-typedef enum {
-    AUDIO_FORMAT_INVALID             = 0xFFFFFFFFUL,
-    AUDIO_FORMAT_DEFAULT             = 0,
-    AUDIO_FORMAT_PCM                 = 0x00000000UL, /* DO NOT CHANGE */
-    AUDIO_FORMAT_MP3                 = 0x01000000UL,
-    AUDIO_FORMAT_AMR_NB              = 0x02000000UL,
-    AUDIO_FORMAT_AMR_WB              = 0x03000000UL,
-    AUDIO_FORMAT_AAC                 = 0x04000000UL,
-    AUDIO_FORMAT_HE_AAC_V1           = 0x05000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V1*/
-    AUDIO_FORMAT_HE_AAC_V2           = 0x06000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V2*/
-    AUDIO_FORMAT_VORBIS              = 0x07000000UL,
-    AUDIO_FORMAT_OPUS                = 0x08000000UL,
-    AUDIO_FORMAT_AC3                 = 0x09000000UL,
-    AUDIO_FORMAT_E_AC3               = 0x0A000000UL,
-    AUDIO_FORMAT_MAIN_MASK           = 0xFF000000UL,
-    AUDIO_FORMAT_SUB_MASK            = 0x00FFFFFFUL,
-
-    /* Aliases */
-    /* note != AudioFormat.ENCODING_PCM_16BIT */
-    AUDIO_FORMAT_PCM_16_BIT          = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_16_BIT),
-    /* note != AudioFormat.ENCODING_PCM_8BIT */
-    AUDIO_FORMAT_PCM_8_BIT           = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_8_BIT),
-    AUDIO_FORMAT_PCM_32_BIT          = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_32_BIT),
-    AUDIO_FORMAT_PCM_8_24_BIT        = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_8_24_BIT),
-    AUDIO_FORMAT_PCM_FLOAT           = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_FLOAT),
-    AUDIO_FORMAT_PCM_24_BIT_PACKED   = (AUDIO_FORMAT_PCM |
-                                        AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED),
-    AUDIO_FORMAT_AAC_MAIN            = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_MAIN),
-    AUDIO_FORMAT_AAC_LC              = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_LC),
-    AUDIO_FORMAT_AAC_SSR             = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_SSR),
-    AUDIO_FORMAT_AAC_LTP             = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_LTP),
-    AUDIO_FORMAT_AAC_HE_V1           = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_HE_V1),
-    AUDIO_FORMAT_AAC_SCALABLE        = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_SCALABLE),
-    AUDIO_FORMAT_AAC_ERLC            = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_ERLC),
-    AUDIO_FORMAT_AAC_LD              = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_LD),
-    AUDIO_FORMAT_AAC_HE_V2           = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_HE_V2),
-    AUDIO_FORMAT_AAC_ELD             = (AUDIO_FORMAT_AAC |
-                                        AUDIO_FORMAT_AAC_SUB_ELD),
-} audio_format_t;
-
-/* For the channel mask for position assignment representation */
-enum {
-
-/* These can be a complete audio_channel_mask_t. */
-
-    AUDIO_CHANNEL_NONE                      = 0x0,
-    AUDIO_CHANNEL_INVALID                   = 0xC0000000,
-
-/* These can be the bits portion of an audio_channel_mask_t
- * with representation AUDIO_CHANNEL_REPRESENTATION_POSITION.
- * Using these bits as a complete audio_channel_mask_t is deprecated.
- */
-
-    /* output channels */
-    AUDIO_CHANNEL_OUT_FRONT_LEFT            = 0x1,
-    AUDIO_CHANNEL_OUT_FRONT_RIGHT           = 0x2,
-    AUDIO_CHANNEL_OUT_FRONT_CENTER          = 0x4,
-    AUDIO_CHANNEL_OUT_LOW_FREQUENCY         = 0x8,
-    AUDIO_CHANNEL_OUT_BACK_LEFT             = 0x10,
-    AUDIO_CHANNEL_OUT_BACK_RIGHT            = 0x20,
-    AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER  = 0x40,
-    AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80,
-    AUDIO_CHANNEL_OUT_BACK_CENTER           = 0x100,
-    AUDIO_CHANNEL_OUT_SIDE_LEFT             = 0x200,
-    AUDIO_CHANNEL_OUT_SIDE_RIGHT            = 0x400,
-    AUDIO_CHANNEL_OUT_TOP_CENTER            = 0x800,
-    AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT        = 0x1000,
-    AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER      = 0x2000,
-    AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT       = 0x4000,
-    AUDIO_CHANNEL_OUT_TOP_BACK_LEFT         = 0x8000,
-    AUDIO_CHANNEL_OUT_TOP_BACK_CENTER       = 0x10000,
-    AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT        = 0x20000,
-
-/* TODO: should these be considered complete channel masks, or only bits? */
-
-    AUDIO_CHANNEL_OUT_MONO     = AUDIO_CHANNEL_OUT_FRONT_LEFT,
-    AUDIO_CHANNEL_OUT_STEREO   = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT),
-    AUDIO_CHANNEL_OUT_QUAD     = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT),
-    AUDIO_CHANNEL_OUT_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD,
-    /* like AUDIO_CHANNEL_OUT_QUAD_BACK with *_SIDE_* instead of *_BACK_* */
-    AUDIO_CHANNEL_OUT_QUAD_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
-    AUDIO_CHANNEL_OUT_5POINT1  = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT),
-    AUDIO_CHANNEL_OUT_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1,
-    /* like AUDIO_CHANNEL_OUT_5POINT1_BACK with *_SIDE_* instead of *_BACK_* */
-    AUDIO_CHANNEL_OUT_5POINT1_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
-    // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1
-    AUDIO_CHANNEL_OUT_7POINT1  = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT |
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT |
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT),
-    AUDIO_CHANNEL_OUT_ALL      = (AUDIO_CHANNEL_OUT_FRONT_LEFT |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_CENTER |
-                                  AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                                  AUDIO_CHANNEL_OUT_BACK_LEFT |
-                                  AUDIO_CHANNEL_OUT_BACK_RIGHT |
-                                  AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER |
-                                  AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER |
-                                  AUDIO_CHANNEL_OUT_BACK_CENTER|
-                                  AUDIO_CHANNEL_OUT_SIDE_LEFT|
-                                  AUDIO_CHANNEL_OUT_SIDE_RIGHT|
-                                  AUDIO_CHANNEL_OUT_TOP_CENTER|
-                                  AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT|
-                                  AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER|
-                                  AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT|
-                                  AUDIO_CHANNEL_OUT_TOP_BACK_LEFT|
-                                  AUDIO_CHANNEL_OUT_TOP_BACK_CENTER|
-                                  AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
-
-/* These are bits only, not complete values */
-
-    /* input channels */
-    AUDIO_CHANNEL_IN_LEFT            = 0x4,
-    AUDIO_CHANNEL_IN_RIGHT           = 0x8,
-    AUDIO_CHANNEL_IN_FRONT           = 0x10,
-    AUDIO_CHANNEL_IN_BACK            = 0x20,
-    AUDIO_CHANNEL_IN_LEFT_PROCESSED  = 0x40,
-    AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80,
-    AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100,
-    AUDIO_CHANNEL_IN_BACK_PROCESSED  = 0x200,
-    AUDIO_CHANNEL_IN_PRESSURE        = 0x400,
-    AUDIO_CHANNEL_IN_X_AXIS          = 0x800,
-    AUDIO_CHANNEL_IN_Y_AXIS          = 0x1000,
-    AUDIO_CHANNEL_IN_Z_AXIS          = 0x2000,
-    AUDIO_CHANNEL_IN_VOICE_UPLINK    = 0x4000,
-    AUDIO_CHANNEL_IN_VOICE_DNLINK    = 0x8000,
-
-/* TODO: should these be considered complete channel masks, or only bits, or deprecated? */
-
-    AUDIO_CHANNEL_IN_MONO   = AUDIO_CHANNEL_IN_FRONT,
-    AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT),
-    AUDIO_CHANNEL_IN_FRONT_BACK = (AUDIO_CHANNEL_IN_FRONT | AUDIO_CHANNEL_IN_BACK),
-    AUDIO_CHANNEL_IN_ALL    = (AUDIO_CHANNEL_IN_LEFT |
-                               AUDIO_CHANNEL_IN_RIGHT |
-                               AUDIO_CHANNEL_IN_FRONT |
-                               AUDIO_CHANNEL_IN_BACK|
-                               AUDIO_CHANNEL_IN_LEFT_PROCESSED |
-                               AUDIO_CHANNEL_IN_RIGHT_PROCESSED |
-                               AUDIO_CHANNEL_IN_FRONT_PROCESSED |
-                               AUDIO_CHANNEL_IN_BACK_PROCESSED|
-                               AUDIO_CHANNEL_IN_PRESSURE |
-                               AUDIO_CHANNEL_IN_X_AXIS |
-                               AUDIO_CHANNEL_IN_Y_AXIS |
-                               AUDIO_CHANNEL_IN_Z_AXIS |
-                               AUDIO_CHANNEL_IN_VOICE_UPLINK |
-                               AUDIO_CHANNEL_IN_VOICE_DNLINK),
-};
-
-/* A channel mask per se only defines the presence or absence of a channel, not the order.
- * But see AUDIO_INTERLEAVE_* below for the platform convention of order.
- *
- * audio_channel_mask_t is an opaque type and its internal layout should not
- * be assumed as it may change in the future.
- * Instead, always use the functions declared in this header to examine.
- *
- * These are the current representations:
- *
- *   AUDIO_CHANNEL_REPRESENTATION_POSITION
- *     is a channel mask representation for position assignment.
- *     Each low-order bit corresponds to the spatial position of a transducer (output),
- *     or interpretation of channel (input).
- *     The user of a channel mask needs to know the context of whether it is for output or input.
- *     The constants AUDIO_CHANNEL_OUT_* or AUDIO_CHANNEL_IN_* apply to the bits portion.
- *     It is not permitted for no bits to be set.
- *
- *   AUDIO_CHANNEL_REPRESENTATION_INDEX
- *     is a channel mask representation for index assignment.
- *     Each low-order bit corresponds to a selected channel.
- *     There is no platform interpretation of the various bits.
- *     There is no concept of output or input.
- *     It is not permitted for no bits to be set.
- *
- * All other representations are reserved for future use.
- *
- * Warning: current representation distinguishes between input and output, but this will not the be
- * case in future revisions of the platform. Wherever there is an ambiguity between input and output
- * that is currently resolved by checking the channel mask, the implementer should look for ways to
- * fix it with additional information outside of the mask.
- */
-typedef uint32_t audio_channel_mask_t;
-
-/* Maximum number of channels for all representations */
-#define AUDIO_CHANNEL_COUNT_MAX             30
-
-/* log(2) of maximum number of representations, not part of public API */
-#define AUDIO_CHANNEL_REPRESENTATION_LOG2   2
-
-/* Representations */
-typedef enum {
-    AUDIO_CHANNEL_REPRESENTATION_POSITION    = 0,    // must be zero for compatibility
-    // 1 is reserved for future use
-    AUDIO_CHANNEL_REPRESENTATION_INDEX       = 2,
-    // 3 is reserved for future use
-} audio_channel_representation_t;
-
-/* The return value is undefined if the channel mask is invalid. */
-static inline uint32_t audio_channel_mask_get_bits(audio_channel_mask_t channel)
-{
-    return channel & ((1 << AUDIO_CHANNEL_COUNT_MAX) - 1);
-}
-
-/* The return value is undefined if the channel mask is invalid. */
-static inline audio_channel_representation_t audio_channel_mask_get_representation(
-        audio_channel_mask_t channel)
-{
-    // The right shift should be sufficient, but also "and" for safety in case mask is not 32 bits
-    return (audio_channel_representation_t)
-            ((channel >> AUDIO_CHANNEL_COUNT_MAX) & ((1 << AUDIO_CHANNEL_REPRESENTATION_LOG2) - 1));
-}
-
-/* Returns true if the channel mask is valid,
- * or returns false for AUDIO_CHANNEL_NONE, AUDIO_CHANNEL_INVALID, and other invalid values.
- * This function is unable to determine whether a channel mask for position assignment
- * is invalid because an output mask has an invalid output bit set,
- * or because an input mask has an invalid input bit set.
- * All other APIs that take a channel mask assume that it is valid.
- */
-static inline bool audio_channel_mask_is_valid(audio_channel_mask_t channel)
-{
-    uint32_t bits = audio_channel_mask_get_bits(channel);
-    audio_channel_representation_t representation = audio_channel_mask_get_representation(channel);
-    switch (representation) {
-    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
-    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
-        break;
-    default:
-        bits = 0;
-        break;
-    }
-    return bits != 0;
-}
-
-/* Not part of public API */
-static inline audio_channel_mask_t audio_channel_mask_from_representation_and_bits(
-        audio_channel_representation_t representation, uint32_t bits)
-{
-    return (audio_channel_mask_t) ((representation << AUDIO_CHANNEL_COUNT_MAX) | bits);
-}
-
-/* Expresses the convention when stereo audio samples are stored interleaved
- * in an array.  This should improve readability by allowing code to use
- * symbolic indices instead of hard-coded [0] and [1].
- *
- * For multi-channel beyond stereo, the platform convention is that channels
- * are interleaved in order from least significant channel mask bit
- * to most significant channel mask bit, with unused bits skipped.
- * Any exceptions to this convention will be noted at the appropriate API.
- */
-enum {
-    AUDIO_INTERLEAVE_LEFT   = 0,
-    AUDIO_INTERLEAVE_RIGHT  = 1,
-};
-
-typedef enum {
-    AUDIO_MODE_INVALID          = -2,
-    AUDIO_MODE_CURRENT          = -1,
-    AUDIO_MODE_NORMAL           = 0,
-    AUDIO_MODE_RINGTONE         = 1,
-    AUDIO_MODE_IN_CALL          = 2,
-    AUDIO_MODE_IN_COMMUNICATION = 3,
-
-    AUDIO_MODE_CNT,
-    AUDIO_MODE_MAX              = AUDIO_MODE_CNT - 1,
-} audio_mode_t;
-
-/* This enum is deprecated */
-typedef enum {
-    AUDIO_IN_ACOUSTICS_NONE          = 0,
-    AUDIO_IN_ACOUSTICS_AGC_ENABLE    = 0x0001,
-    AUDIO_IN_ACOUSTICS_AGC_DISABLE   = 0,
-    AUDIO_IN_ACOUSTICS_NS_ENABLE     = 0x0002,
-    AUDIO_IN_ACOUSTICS_NS_DISABLE    = 0,
-    AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE = 0x0004,
-    AUDIO_IN_ACOUSTICS_TX_DISABLE    = 0,
-} audio_in_acoustics_t;
-
-enum {
-    AUDIO_DEVICE_NONE                          = 0x0,
-    /* reserved bits */
-    AUDIO_DEVICE_BIT_IN                        = 0x80000000,
-    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,
-    /* output devices */
-    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,
-    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,
-    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,
-    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,
-    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,
-    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,
-    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40,
-    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80,
-    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
-    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200,
-    AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400,
-    AUDIO_DEVICE_OUT_HDMI                      = AUDIO_DEVICE_OUT_AUX_DIGITAL,
-    /* uses an analog connection (multiplexed over the USB connector pins for instance) */
-    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800,
-    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000,
-    /* USB accessory mode: your Android device is a USB device and the dock is a USB host */
-    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000,
-    /* USB host mode: your Android device is a USB host and the dock is a USB device */
-    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000,
-    AUDIO_DEVICE_OUT_REMOTE_SUBMIX             = 0x8000,
-    /* Telephony voice TX path */
-    AUDIO_DEVICE_OUT_TELEPHONY_TX              = 0x10000,
-    /* Analog jack with line impedance detected */
-    AUDIO_DEVICE_OUT_LINE                      = 0x20000,
-    /* HDMI Audio Return Channel */
-    AUDIO_DEVICE_OUT_HDMI_ARC                  = 0x40000,
-    /* S/PDIF out */
-    AUDIO_DEVICE_OUT_SPDIF                     = 0x80000,
-    /* FM transmitter out */
-    AUDIO_DEVICE_OUT_FM                        = 0x100000,
-    /* Line out for av devices */
-    AUDIO_DEVICE_OUT_AUX_LINE                  = 0x200000,
-    /* limited-output speaker device for acoustic safety */
-    AUDIO_DEVICE_OUT_SPEAKER_SAFE              = 0x400000,
-    AUDIO_DEVICE_OUT_DEFAULT                   = AUDIO_DEVICE_BIT_DEFAULT,
-    AUDIO_DEVICE_OUT_ALL      = (AUDIO_DEVICE_OUT_EARPIECE |
-                                 AUDIO_DEVICE_OUT_SPEAKER |
-                                 AUDIO_DEVICE_OUT_WIRED_HEADSET |
-                                 AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
-                                 AUDIO_DEVICE_OUT_HDMI |
-                                 AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET |
-                                 AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET |
-                                 AUDIO_DEVICE_OUT_USB_ACCESSORY |
-                                 AUDIO_DEVICE_OUT_USB_DEVICE |
-                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX |
-                                 AUDIO_DEVICE_OUT_TELEPHONY_TX |
-                                 AUDIO_DEVICE_OUT_LINE |
-                                 AUDIO_DEVICE_OUT_HDMI_ARC |
-                                 AUDIO_DEVICE_OUT_SPDIF |
-                                 AUDIO_DEVICE_OUT_FM |
-                                 AUDIO_DEVICE_OUT_AUX_LINE |
-                                 AUDIO_DEVICE_OUT_SPEAKER_SAFE |
-                                 AUDIO_DEVICE_OUT_DEFAULT),
-    AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
-    AUDIO_DEVICE_OUT_ALL_SCO  = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
-                                 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT),
-    AUDIO_DEVICE_OUT_ALL_USB  = (AUDIO_DEVICE_OUT_USB_ACCESSORY |
-                                 AUDIO_DEVICE_OUT_USB_DEVICE),
-
-    /* input devices */
-    AUDIO_DEVICE_IN_COMMUNICATION         = AUDIO_DEVICE_BIT_IN | 0x1,
-    AUDIO_DEVICE_IN_AMBIENT               = AUDIO_DEVICE_BIT_IN | 0x2,
-    AUDIO_DEVICE_IN_BUILTIN_MIC           = AUDIO_DEVICE_BIT_IN | 0x4,
-    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8,
-    AUDIO_DEVICE_IN_WIRED_HEADSET         = AUDIO_DEVICE_BIT_IN | 0x10,
-    AUDIO_DEVICE_IN_AUX_DIGITAL           = AUDIO_DEVICE_BIT_IN | 0x20,
-    AUDIO_DEVICE_IN_HDMI                  = AUDIO_DEVICE_IN_AUX_DIGITAL,
-    /* Telephony voice RX path */
-    AUDIO_DEVICE_IN_VOICE_CALL            = AUDIO_DEVICE_BIT_IN | 0x40,
-    AUDIO_DEVICE_IN_TELEPHONY_RX          = AUDIO_DEVICE_IN_VOICE_CALL,
-    AUDIO_DEVICE_IN_BACK_MIC              = AUDIO_DEVICE_BIT_IN | 0x80,
-    AUDIO_DEVICE_IN_REMOTE_SUBMIX         = AUDIO_DEVICE_BIT_IN | 0x100,
-    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x200,
-    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET     = AUDIO_DEVICE_BIT_IN | 0x400,
-    AUDIO_DEVICE_IN_USB_ACCESSORY         = AUDIO_DEVICE_BIT_IN | 0x800,
-    AUDIO_DEVICE_IN_USB_DEVICE            = AUDIO_DEVICE_BIT_IN | 0x1000,
-    /* FM tuner input */
-    AUDIO_DEVICE_IN_FM_TUNER              = AUDIO_DEVICE_BIT_IN | 0x2000,
-    /* TV tuner input */
-    AUDIO_DEVICE_IN_TV_TUNER              = AUDIO_DEVICE_BIT_IN | 0x4000,
-    /* Analog jack with line impedance detected */
-    AUDIO_DEVICE_IN_LINE                  = AUDIO_DEVICE_BIT_IN | 0x8000,
-    /* S/PDIF in */
-    AUDIO_DEVICE_IN_SPDIF                 = AUDIO_DEVICE_BIT_IN | 0x10000,
-    AUDIO_DEVICE_IN_BLUETOOTH_A2DP        = AUDIO_DEVICE_BIT_IN | 0x20000,
-    AUDIO_DEVICE_IN_LOOPBACK              = AUDIO_DEVICE_BIT_IN | 0x40000,
-    AUDIO_DEVICE_IN_DEFAULT               = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT,
-
-    AUDIO_DEVICE_IN_ALL     = (AUDIO_DEVICE_IN_COMMUNICATION |
-                               AUDIO_DEVICE_IN_AMBIENT |
-                               AUDIO_DEVICE_IN_BUILTIN_MIC |
-                               AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET |
-                               AUDIO_DEVICE_IN_WIRED_HEADSET |
-                               AUDIO_DEVICE_IN_HDMI |
-                               AUDIO_DEVICE_IN_TELEPHONY_RX |
-                               AUDIO_DEVICE_IN_BACK_MIC |
-                               AUDIO_DEVICE_IN_REMOTE_SUBMIX |
-                               AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET |
-                               AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET |
-                               AUDIO_DEVICE_IN_USB_ACCESSORY |
-                               AUDIO_DEVICE_IN_USB_DEVICE |
-                               AUDIO_DEVICE_IN_FM_TUNER |
-                               AUDIO_DEVICE_IN_TV_TUNER |
-                               AUDIO_DEVICE_IN_LINE |
-                               AUDIO_DEVICE_IN_SPDIF |
-                               AUDIO_DEVICE_IN_BLUETOOTH_A2DP |
-                               AUDIO_DEVICE_IN_LOOPBACK |
-                               AUDIO_DEVICE_IN_DEFAULT),
-    AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
-    AUDIO_DEVICE_IN_ALL_USB  = (AUDIO_DEVICE_IN_USB_ACCESSORY |
-                                AUDIO_DEVICE_IN_USB_DEVICE),
-};
-
-typedef uint32_t audio_devices_t;
-
-/* the audio output flags serve two purposes:
- * - when an AudioTrack is created they indicate a "wish" to be connected to an
- * output stream with attributes corresponding to the specified flags
- * - when present in an output profile descriptor listed for a particular audio
- * hardware module, they indicate that an output stream can be opened that
- * supports the attributes indicated by the flags.
- * the audio policy manager will try to match the flags in the request
- * (when getOuput() is called) to an available output stream.
- */
-typedef enum {
-    AUDIO_OUTPUT_FLAG_NONE = 0x0,       // no attributes
-    AUDIO_OUTPUT_FLAG_DIRECT = 0x1,     // this output directly connects a track
-                                        // to one output stream: no software mixer
-    AUDIO_OUTPUT_FLAG_PRIMARY = 0x2,    // this output is the primary output of
-                                        // the device. It is unique and must be
-                                        // present. It is opened by default and
-                                        // receives routing, audio mode and volume
-                                        // controls related to voice calls.
-    AUDIO_OUTPUT_FLAG_FAST = 0x4,       // output supports "fast tracks",
-                                        // defined elsewhere
-    AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers
-    AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10,  // offload playback of compressed
-                                                // streams to hardware codec
-    AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20, // use non-blocking write
-    AUDIO_OUTPUT_FLAG_HW_AV_SYNC = 0x40 // output uses a hardware A/V synchronization source
-} audio_output_flags_t;
-
-/* The audio input flags are analogous to audio output flags.
- * Currently they are used only when an AudioRecord is created,
- * to indicate a preference to be connected to an input stream with
- * attributes corresponding to the specified flags.
- */
-typedef enum {
-    AUDIO_INPUT_FLAG_NONE       = 0x0,  // no attributes
-    AUDIO_INPUT_FLAG_FAST       = 0x1,  // prefer an input that supports "fast tracks"
-    AUDIO_INPUT_FLAG_HW_HOTWORD = 0x2,  // prefer an input that captures from hw hotword source
-} audio_input_flags_t;
-
-/* Additional information about compressed streams offloaded to
- * hardware playback
- * The version and size fields must be initialized by the caller by using
- * one of the constants defined here.
- */
-typedef struct {
-    uint16_t version;                   // version of the info structure
-    uint16_t size;                      // total size of the structure including version and size
-    uint32_t sample_rate;               // sample rate in Hz
-    audio_channel_mask_t channel_mask;  // channel mask
-    audio_format_t format;              // audio format
-    audio_stream_type_t stream_type;    // stream type
-    uint32_t bit_rate;                  // bit rate in bits per second
-    int64_t duration_us;                // duration in microseconds, -1 if unknown
-    bool has_video;                     // true if stream is tied to a video stream
-    bool is_streaming;                  // true if streaming, false if local playback
-} audio_offload_info_t;
-
-#define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \
-            ((((maj) & 0xff) << 8) | ((min) & 0xff))
-
-#define AUDIO_OFFLOAD_INFO_VERSION_0_1 AUDIO_MAKE_OFFLOAD_INFO_VERSION(0, 1)
-#define AUDIO_OFFLOAD_INFO_VERSION_CURRENT AUDIO_OFFLOAD_INFO_VERSION_0_1
-
-static const audio_offload_info_t AUDIO_INFO_INITIALIZER = {
-    version: AUDIO_OFFLOAD_INFO_VERSION_CURRENT,
-    size: sizeof(audio_offload_info_t),
-    sample_rate: 0,
-    channel_mask: 0,
-    format: AUDIO_FORMAT_DEFAULT,
-    stream_type: AUDIO_STREAM_VOICE_CALL,
-    bit_rate: 0,
-    duration_us: 0,
-    has_video: false,
-    is_streaming: false
-};
-
-/* common audio stream configuration parameters
- * You should memset() the entire structure to zero before use to
- * ensure forward compatibility
- */
-struct audio_config {
-    uint32_t sample_rate;
-    audio_channel_mask_t channel_mask;
-    audio_format_t  format;
-    audio_offload_info_t offload_info;
-    size_t frame_count;
-};
-typedef struct audio_config audio_config_t;
-
-static const audio_config_t AUDIO_CONFIG_INITIALIZER = {
-    sample_rate: 0,
-    channel_mask: AUDIO_CHANNEL_NONE,
-    format: AUDIO_FORMAT_DEFAULT,
-    offload_info: {
-        version: AUDIO_OFFLOAD_INFO_VERSION_CURRENT,
-        size: sizeof(audio_offload_info_t),
-        sample_rate: 0,
-        channel_mask: 0,
-        format: AUDIO_FORMAT_DEFAULT,
-        stream_type: AUDIO_STREAM_VOICE_CALL,
-        bit_rate: 0,
-        duration_us: 0,
-        has_video: false,
-        is_streaming: false
-    },
-    frame_count: 0,
-};
-
-
-/* audio hw module handle functions or structures referencing a module */
-typedef int audio_module_handle_t;
-
-/******************************
- *  Volume control
- *****************************/
-
-/* If the audio hardware supports gain control on some audio paths,
- * the platform can expose them in the audio_policy.conf file. The audio HAL
- * will then implement gain control functions that will use the following data
- * structures. */
-
-/* Type of gain control exposed by an audio port */
-#define AUDIO_GAIN_MODE_JOINT     0x1 /* supports joint channel gain control */
-#define AUDIO_GAIN_MODE_CHANNELS  0x2 /* supports separate channel gain control */
-#define AUDIO_GAIN_MODE_RAMP      0x4 /* supports gain ramps */
-
-typedef uint32_t audio_gain_mode_t;
-
-
-/* An audio_gain struct is a representation of a gain stage.
- * A gain stage is always attached to an audio port. */
-struct audio_gain  {
-    audio_gain_mode_t    mode;          /* e.g. AUDIO_GAIN_MODE_JOINT */
-    audio_channel_mask_t channel_mask;  /* channels which gain an be controlled.
-                                           N/A if AUDIO_GAIN_MODE_CHANNELS is not supported */
-    int                  min_value;     /* minimum gain value in millibels */
-    int                  max_value;     /* maximum gain value in millibels */
-    int                  default_value; /* default gain value in millibels */
-    unsigned int         step_value;    /* gain step in millibels */
-    unsigned int         min_ramp_ms;   /* minimum ramp duration in ms */
-    unsigned int         max_ramp_ms;   /* maximum ramp duration in ms */
-};
-
-/* The gain configuration structure is used to get or set the gain values of a
- * given port */
-struct audio_gain_config  {
-    int                  index;             /* index of the corresponding audio_gain in the
-                                               audio_port gains[] table */
-    audio_gain_mode_t    mode;              /* mode requested for this command */
-    audio_channel_mask_t channel_mask;      /* channels which gain value follows.
-                                               N/A in joint mode */
-    int                  values[sizeof(audio_channel_mask_t) * 8]; /* gain values in millibels
-                                               for each channel ordered from LSb to MSb in
-                                               channel mask. The number of values is 1 in joint
-                                               mode or popcount(channel_mask) */
-    unsigned int         ramp_duration_ms; /* ramp duration in ms */
-};
-
-/******************************
- *  Routing control
- *****************************/
-
-/* Types defined here are used to describe an audio source or sink at internal
- * framework interfaces (audio policy, patch panel) or at the audio HAL.
- * Sink and sources are grouped in a concept of “audio port” representing an
- * audio end point at the edge of the system managed by the module exposing
- * the interface. */
-
-/* Audio port role: either source or sink */
-typedef enum {
-    AUDIO_PORT_ROLE_NONE,
-    AUDIO_PORT_ROLE_SOURCE,
-    AUDIO_PORT_ROLE_SINK,
-} audio_port_role_t;
-
-/* Audio port type indicates if it is a session (e.g AudioTrack),
- * a mix (e.g PlaybackThread output) or a physical device
- * (e.g AUDIO_DEVICE_OUT_SPEAKER) */
-typedef enum {
-    AUDIO_PORT_TYPE_NONE,
-    AUDIO_PORT_TYPE_DEVICE,
-    AUDIO_PORT_TYPE_MIX,
-    AUDIO_PORT_TYPE_SESSION,
-} audio_port_type_t;
-
-/* Each port has a unique ID or handle allocated by policy manager */
-typedef int audio_port_handle_t;
-#define AUDIO_PORT_HANDLE_NONE 0
-
-
-/* maximum audio device address length */
-#define AUDIO_DEVICE_MAX_ADDRESS_LEN 32
-
-/* extension for audio port configuration structure when the audio port is a
- * hardware device */
-struct audio_port_config_device_ext {
-    audio_module_handle_t hw_module;                /* module the device is attached to */
-    audio_devices_t       type;                     /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
-    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; /* device address. "" if N/A */
-};
-
-/* extension for audio port configuration structure when the audio port is a
- * sub mix */
-struct audio_port_config_mix_ext {
-    audio_module_handle_t hw_module;    /* module the stream is attached to */
-    audio_io_handle_t handle;           /* I/O handle of the input/output stream */
-    union {
-        //TODO: change use case for output streams: use strategy and mixer attributes
-        audio_stream_type_t stream;
-        audio_source_t      source;
-    } usecase;
-};
-
-/* extension for audio port configuration structure when the audio port is an
- * audio session */
-struct audio_port_config_session_ext {
-    audio_session_t   session; /* audio session */
-};
-
-/* Flags indicating which fields are to be considered in struct audio_port_config */
-#define AUDIO_PORT_CONFIG_SAMPLE_RATE  0x1
-#define AUDIO_PORT_CONFIG_CHANNEL_MASK 0x2
-#define AUDIO_PORT_CONFIG_FORMAT       0x4
-#define AUDIO_PORT_CONFIG_GAIN         0x8
-#define AUDIO_PORT_CONFIG_ALL (AUDIO_PORT_CONFIG_SAMPLE_RATE | \
-                               AUDIO_PORT_CONFIG_CHANNEL_MASK | \
-                               AUDIO_PORT_CONFIG_FORMAT | \
-                               AUDIO_PORT_CONFIG_GAIN)
-
-/* audio port configuration structure used to specify a particular configuration of
- * an audio port */
-struct audio_port_config {
-    audio_port_handle_t      id;           /* port unique ID */
-    audio_port_role_t        role;         /* sink or source */
-    audio_port_type_t        type;         /* device, mix ... */
-    unsigned int             config_mask;  /* e.g AUDIO_PORT_CONFIG_ALL */
-    unsigned int             sample_rate;  /* sampling rate in Hz */
-    audio_channel_mask_t     channel_mask; /* channel mask if applicable */
-    audio_format_t           format;       /* format if applicable */
-    struct audio_gain_config gain;         /* gain to apply if applicable */
-    union {
-        struct audio_port_config_device_ext  device;  /* device specific info */
-        struct audio_port_config_mix_ext     mix;     /* mix specific info */
-        struct audio_port_config_session_ext session; /* session specific info */
-    } ext;
-};
-
-
-/* max number of sampling rates in audio port */
-#define AUDIO_PORT_MAX_SAMPLING_RATES 16
-/* max number of channel masks in audio port */
-#define AUDIO_PORT_MAX_CHANNEL_MASKS 16
-/* max number of audio formats in audio port */
-#define AUDIO_PORT_MAX_FORMATS 16
-/* max number of gain controls in audio port */
-#define AUDIO_PORT_MAX_GAINS 16
-
-/* extension for audio port structure when the audio port is a hardware device */
-struct audio_port_device_ext {
-    audio_module_handle_t hw_module;    /* module the device is attached to */
-    audio_devices_t       type;         /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
-    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
-};
-
-/* Latency class of the audio mix */
-typedef enum {
-    AUDIO_LATENCY_LOW,
-    AUDIO_LATENCY_NORMAL,
-} audio_mix_latency_class_t;
-
-/* extension for audio port structure when the audio port is a sub mix */
-struct audio_port_mix_ext {
-    audio_module_handle_t     hw_module;     /* module the stream is attached to */
-    audio_io_handle_t         handle;        /* I/O handle of the input.output stream */
-    audio_mix_latency_class_t latency_class; /* latency class */
-    // other attributes: routing strategies
-};
-
-/* extension for audio port structure when the audio port is an audio session */
-struct audio_port_session_ext {
-    audio_session_t   session; /* audio session */
-};
-
-
-struct audio_port {
-    audio_port_handle_t      id;                /* port unique ID */
-    audio_port_role_t        role;              /* sink or source */
-    audio_port_type_t        type;              /* device, mix ... */
-    unsigned int             num_sample_rates;  /* number of sampling rates in following array */
-    unsigned int             sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES];
-    unsigned int             num_channel_masks; /* number of channel masks in following array */
-    audio_channel_mask_t     channel_masks[AUDIO_PORT_MAX_CHANNEL_MASKS];
-    unsigned int             num_formats;       /* number of formats in following array */
-    audio_format_t           formats[AUDIO_PORT_MAX_FORMATS];
-    unsigned int             num_gains;         /* number of gains in following array */
-    struct audio_gain        gains[AUDIO_PORT_MAX_GAINS];
-    struct audio_port_config active_config;     /* current audio port configuration */
-    union {
-        struct audio_port_device_ext  device;
-        struct audio_port_mix_ext     mix;
-        struct audio_port_session_ext session;
-    } ext;
-};
-
-/* An audio patch represents a connection between one or more source ports and
- * one or more sink ports. Patches are connected and disconnected by audio policy manager or by
- * applications via framework APIs.
- * Each patch is identified by a handle at the interface used to create that patch. For instance,
- * when a patch is created by the audio HAL, the HAL allocates and returns a handle.
- * This handle is unique to a given audio HAL hardware module.
- * But the same patch receives another system wide unique handle allocated by the framework.
- * This unique handle is used for all transactions inside the framework.
- */
-typedef int audio_patch_handle_t;
-#define AUDIO_PATCH_HANDLE_NONE 0
-
-#define AUDIO_PATCH_PORTS_MAX   16
-
-struct audio_patch {
-    audio_patch_handle_t id;            /* patch unique ID */
-    unsigned int      num_sources;      /* number of sources in following array */
-    struct audio_port_config sources[AUDIO_PATCH_PORTS_MAX];
-    unsigned int      num_sinks;        /* number of sinks in following array */
-    struct audio_port_config sinks[AUDIO_PATCH_PORTS_MAX];
-};
-
-
-
-/* a HW synchronization source returned by the audio HAL */
-typedef uint32_t audio_hw_sync_t;
-
-/* an invalid HW synchronization source indicating an error */
-#define AUDIO_HW_SYNC_INVALID 0
-
-static inline bool audio_is_output_device(audio_devices_t device)
-{
-    if (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
-            (popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0))
-        return true;
-    else
-        return false;
-}
-
-static inline bool audio_is_input_device(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
-        device &= ~AUDIO_DEVICE_BIT_IN;
-        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0))
-            return true;
-    }
-    return false;
-}
-
-static inline bool audio_is_output_devices(audio_devices_t device)
-{
-    return (device & AUDIO_DEVICE_BIT_IN) == 0;
-}
-
-static inline bool audio_is_a2dp_in_device(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
-        device &= ~AUDIO_DEVICE_BIT_IN;
-        if ((popcount(device) == 1) && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP))
-            return true;
-    }
-    return false;
-}
-
-static inline bool audio_is_a2dp_out_device(audio_devices_t device)
-{
-    if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_A2DP))
-        return true;
-    else
-        return false;
-}
-
-// Deprecated - use audio_is_a2dp_out_device() instead
-static inline bool audio_is_a2dp_device(audio_devices_t device)
-{
-    return audio_is_a2dp_out_device(device);
-}
-
-static inline bool audio_is_bluetooth_sco_device(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_BIT_IN) == 0) {
-        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL_SCO) == 0))
-            return true;
-    } else {
-        device &= ~AUDIO_DEVICE_BIT_IN;
-        if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) == 0))
-            return true;
-    }
-
-    return false;
-}
-
-static inline bool audio_is_usb_out_device(audio_devices_t device)
-{
-    return ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_USB));
-}
-
-static inline bool audio_is_usb_in_device(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
-        device &= ~AUDIO_DEVICE_BIT_IN;
-        if (popcount(device) == 1 && (device & AUDIO_DEVICE_IN_ALL_USB) != 0)
-            return true;
-    }
-    return false;
-}
-
-/* OBSOLETE - use audio_is_usb_out_device() instead. */
-static inline bool audio_is_usb_device(audio_devices_t device)
-{
-    return audio_is_usb_out_device(device);
-}
-
-static inline bool audio_is_remote_submix_device(audio_devices_t device)
-{
-    if ((device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-            || (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX)
-        return true;
-    else
-        return false;
-}
-
-/* Returns true if:
- *  representation is valid, and
- *  there is at least one channel bit set which _could_ correspond to an input channel, and
- *  there are no channel bits set which could _not_ correspond to an input channel.
- * Otherwise returns false.
- */
-static inline bool audio_is_input_channel(audio_channel_mask_t channel)
-{
-    uint32_t bits = audio_channel_mask_get_bits(channel);
-    switch (audio_channel_mask_get_representation(channel)) {
-    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
-        if (bits & ~AUDIO_CHANNEL_IN_ALL) {
-            bits = 0;
-        }
-        // fall through
-    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
-        return bits != 0;
-    default:
-        return false;
-    }
-}
-
-/* Returns true if:
- *  representation is valid, and
- *  there is at least one channel bit set which _could_ correspond to an output channel, and
- *  there are no channel bits set which could _not_ correspond to an output channel.
- * Otherwise returns false.
- */
-static inline bool audio_is_output_channel(audio_channel_mask_t channel)
-{
-    uint32_t bits = audio_channel_mask_get_bits(channel);
-    switch (audio_channel_mask_get_representation(channel)) {
-    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
-        if (bits & ~AUDIO_CHANNEL_OUT_ALL) {
-            bits = 0;
-        }
-        // fall through
-    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
-        return bits != 0;
-    default:
-        return false;
-    }
-}
-
-/* Returns the number of channels from an input channel mask,
- * used in the context of audio input or recording.
- * If a channel bit is set which could _not_ correspond to an input channel,
- * it is excluded from the count.
- * Returns zero if the representation is invalid.
- */
-static inline uint32_t audio_channel_count_from_in_mask(audio_channel_mask_t channel)
-{
-    uint32_t bits = audio_channel_mask_get_bits(channel);
-    switch (audio_channel_mask_get_representation(channel)) {
-    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
-        // TODO: We can now merge with from_out_mask and remove anding
-        bits &= AUDIO_CHANNEL_IN_ALL;
-        // fall through
-    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
-        return popcount(bits);
-    default:
-        return 0;
-    }
-}
-
-/* Returns the number of channels from an output channel mask,
- * used in the context of audio output or playback.
- * If a channel bit is set which could _not_ correspond to an output channel,
- * it is excluded from the count.
- * Returns zero if the representation is invalid.
- */
-static inline uint32_t audio_channel_count_from_out_mask(audio_channel_mask_t channel)
-{
-    uint32_t bits = audio_channel_mask_get_bits(channel);
-    switch (audio_channel_mask_get_representation(channel)) {
-    case AUDIO_CHANNEL_REPRESENTATION_POSITION:
-        // TODO: We can now merge with from_in_mask and remove anding
-        bits &= AUDIO_CHANNEL_OUT_ALL;
-        // fall through
-    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
-        return popcount(bits);
-    default:
-        return 0;
-    }
-}
-
-/* Derive an output channel mask for position assignment from a channel count.
- * This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel
- * cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad,
- * and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC
- * for continuity with stereo.
- * Returns the matching channel mask,
- * or AUDIO_CHANNEL_NONE if the channel count is zero,
- * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
- * configurations for which a default output channel mask is defined.
- */
-static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count)
-{
-    uint32_t bits;
-    switch (channel_count) {
-    case 0:
-        return AUDIO_CHANNEL_NONE;
-    case 1:
-        bits = AUDIO_CHANNEL_OUT_MONO;
-        break;
-    case 2:
-        bits = AUDIO_CHANNEL_OUT_STEREO;
-        break;
-    case 3:
-        bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER;
-        break;
-    case 4: // 4.0
-        bits = AUDIO_CHANNEL_OUT_QUAD;
-        break;
-    case 5: // 5.0
-        bits = AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER;
-        break;
-    case 6: // 5.1
-        bits = AUDIO_CHANNEL_OUT_5POINT1;
-        break;
-    case 7: // 6.1
-        bits = AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER;
-        break;
-    case 8:
-        bits = AUDIO_CHANNEL_OUT_7POINT1;
-        break;
-    default:
-        return AUDIO_CHANNEL_INVALID;
-    }
-    return audio_channel_mask_from_representation_and_bits(
-            AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
-}
-
-/* Derive an input channel mask for position assignment from a channel count.
- * Currently handles only mono and stereo.
- * Returns the matching channel mask,
- * or AUDIO_CHANNEL_NONE if the channel count is zero,
- * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the
- * configurations for which a default input channel mask is defined.
- */
-static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count)
-{
-    uint32_t bits;
-    switch (channel_count) {
-    case 0:
-        return AUDIO_CHANNEL_NONE;
-    case 1:
-        bits = AUDIO_CHANNEL_IN_MONO;
-        break;
-    case 2:
-        bits = AUDIO_CHANNEL_IN_STEREO;
-        break;
-    default:
-        return AUDIO_CHANNEL_INVALID;
-    }
-    return audio_channel_mask_from_representation_and_bits(
-            AUDIO_CHANNEL_REPRESENTATION_POSITION, bits);
-}
-
-/* Derive a channel mask for index assignment from a channel count.
- * Returns the matching channel mask,
- * or AUDIO_CHANNEL_NONE if the channel count is zero,
- * or AUDIO_CHANNEL_INVALID if the channel count exceeds AUDIO_CHANNEL_COUNT_MAX.
- */
-static inline audio_channel_mask_t audio_channel_mask_for_index_assignment_from_count(
-        uint32_t channel_count)
-{
-    if (channel_count == 0) {
-        return AUDIO_CHANNEL_NONE;
-    }
-    if (channel_count > AUDIO_CHANNEL_COUNT_MAX) {
-        return AUDIO_CHANNEL_INVALID;
-    }
-    uint32_t bits = (1 << channel_count) - 1;
-    return audio_channel_mask_from_representation_and_bits(
-            AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
-}
-
-static inline bool audio_is_valid_format(audio_format_t format)
-{
-    switch (format & AUDIO_FORMAT_MAIN_MASK) {
-    case AUDIO_FORMAT_PCM:
-        switch (format) {
-        case AUDIO_FORMAT_PCM_16_BIT:
-        case AUDIO_FORMAT_PCM_8_BIT:
-        case AUDIO_FORMAT_PCM_32_BIT:
-        case AUDIO_FORMAT_PCM_8_24_BIT:
-        case AUDIO_FORMAT_PCM_FLOAT:
-        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
-            return true;
-        default:
-            return false;
-        }
-        /* not reached */
-    case AUDIO_FORMAT_MP3:
-    case AUDIO_FORMAT_AMR_NB:
-    case AUDIO_FORMAT_AMR_WB:
-    case AUDIO_FORMAT_AAC:
-    case AUDIO_FORMAT_HE_AAC_V1:
-    case AUDIO_FORMAT_HE_AAC_V2:
-    case AUDIO_FORMAT_VORBIS:
-    case AUDIO_FORMAT_OPUS:
-    case AUDIO_FORMAT_AC3:
-    case AUDIO_FORMAT_E_AC3:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static inline bool audio_is_linear_pcm(audio_format_t format)
-{
-    return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM);
-}
-
-static inline size_t audio_bytes_per_sample(audio_format_t format)
-{
-    size_t size = 0;
-
-    switch (format) {
-    case AUDIO_FORMAT_PCM_32_BIT:
-    case AUDIO_FORMAT_PCM_8_24_BIT:
-        size = sizeof(int32_t);
-        break;
-    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
-        size = sizeof(uint8_t) * 3;
-        break;
-    case AUDIO_FORMAT_PCM_16_BIT:
-        size = sizeof(int16_t);
-        break;
-    case AUDIO_FORMAT_PCM_8_BIT:
-        size = sizeof(uint8_t);
-        break;
-    case AUDIO_FORMAT_PCM_FLOAT:
-        size = sizeof(float);
-        break;
-    default:
-        break;
-    }
-    return size;
-}
-
-/* converts device address to string sent to audio HAL via set_parameters */
-static char *audio_device_address_to_parameter(audio_devices_t device, const char *address)
-{
-    const size_t kSize = AUDIO_DEVICE_MAX_ADDRESS_LEN + sizeof("a2dp_sink_address=");
-    char param[kSize];
-
-    if (device & AUDIO_DEVICE_OUT_ALL_A2DP)
-        snprintf(param, kSize, "%s=%s", "a2dp_sink_address", address);
-    else if (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
-        snprintf(param, kSize, "%s=%s", "mix", address);
-    else
-        snprintf(param, kSize, "%s", address);
-
-    return strdup(param);
-}
-
-
-__END_DECLS
-
-#endif  // ANDROID_AUDIO_CORE_H
diff --git a/include/system/audio_policy.h b/include/system/audio_policy.h
deleted file mode 100644
index 2881104..0000000
--- a/include/system/audio_policy.h
+++ /dev/null
@@ -1,103 +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.
- */
-
-
-#ifndef ANDROID_AUDIO_POLICY_CORE_H
-#define ANDROID_AUDIO_POLICY_CORE_H
-
-#include <stdint.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <cutils/bitops.h>
-
-__BEGIN_DECLS
-
-/* The enums were moved here mostly from
- * frameworks/base/include/media/AudioSystem.h
- */
-
-/* device categories used for audio_policy->set_force_use() */
-typedef enum {
-    AUDIO_POLICY_FORCE_NONE,
-    AUDIO_POLICY_FORCE_SPEAKER,
-    AUDIO_POLICY_FORCE_HEADPHONES,
-    AUDIO_POLICY_FORCE_BT_SCO,
-    AUDIO_POLICY_FORCE_BT_A2DP,
-    AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
-    AUDIO_POLICY_FORCE_BT_CAR_DOCK,
-    AUDIO_POLICY_FORCE_BT_DESK_DOCK,
-    AUDIO_POLICY_FORCE_ANALOG_DOCK,
-    AUDIO_POLICY_FORCE_DIGITAL_DOCK,
-    AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
-    AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
-    AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED,
-
-    AUDIO_POLICY_FORCE_CFG_CNT,
-    AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,
-
-    AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
-} audio_policy_forced_cfg_t;
-
-/* usages used for audio_policy->set_force_use() */
-typedef enum {
-    AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
-    AUDIO_POLICY_FORCE_FOR_MEDIA,
-    AUDIO_POLICY_FORCE_FOR_RECORD,
-    AUDIO_POLICY_FORCE_FOR_DOCK,
-    AUDIO_POLICY_FORCE_FOR_SYSTEM,
-    AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO,
-
-    AUDIO_POLICY_FORCE_USE_CNT,
-    AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
-} audio_policy_force_use_t;
-
-/* device connection states used for audio_policy->set_device_connection_state()
- */
-typedef enum {
-    AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-    AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-
-    AUDIO_POLICY_DEVICE_STATE_CNT,
-    AUDIO_POLICY_DEVICE_STATE_MAX = AUDIO_POLICY_DEVICE_STATE_CNT - 1,
-} audio_policy_dev_state_t;
-
-typedef enum {
-    /* Used to generate a tone to notify the user of a
-     * notification/alarm/ringtone while they are in a call. */
-    AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION = 0,
-
-    AUDIO_POLICY_TONE_CNT,
-    AUDIO_POLICY_TONE_MAX                  = AUDIO_POLICY_TONE_CNT - 1,
-} audio_policy_tone_t;
-
-
-static inline bool audio_is_low_visibility(audio_stream_type_t stream)
-{
-    switch (stream) {
-    case AUDIO_STREAM_SYSTEM:
-    case AUDIO_STREAM_NOTIFICATION:
-    case AUDIO_STREAM_RING:
-        return true;
-    default:
-        return false;
-    }
-}
-
-
-__END_DECLS
-
-#endif  // ANDROID_AUDIO_POLICY_CORE_H
diff --git a/include/system/camera.h b/include/system/camera.h
index 7a4dd53..09c915d 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -194,7 +194,12 @@
     /** The facing of the camera is opposite to that of the screen. */
     CAMERA_FACING_BACK = 0,
     /** The facing of the camera is the same as that of the screen. */
-    CAMERA_FACING_FRONT = 1
+    CAMERA_FACING_FRONT = 1,
+    /**
+     * The facing of the camera is not fixed relative to the screen.
+     * The cameras with this facing are external cameras, e.g. USB cameras.
+     */
+    CAMERA_FACING_EXTERNAL = 2
 };
 
 enum {
diff --git a/include/system/graphics.h b/include/system/graphics.h
index efd48cb..da24fb8 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -58,11 +58,6 @@
     HAL_PIXEL_FORMAT_RGB_565            = 4,
     HAL_PIXEL_FORMAT_BGRA_8888          = 5,
 
-    // Deprecated sRGB formats for source code compatibility
-    // Not for use in new code
-    HAL_PIXEL_FORMAT_sRGB_A_8888        = 0xC,
-    HAL_PIXEL_FORMAT_sRGB_X_8888        = 0xD,
-
     /*
      * 0x100 - 0x1FF
      *
@@ -194,9 +189,6 @@
      */
     HAL_PIXEL_FORMAT_RAW16 = 0x20,
 
-    // Temporary alias for source code compatibility; do not use in new code
-    HAL_PIXEL_FORMAT_RAW_SENSOR = HAL_PIXEL_FORMAT_RAW16,
-
     /*
      * Android RAW10 format:
      *
@@ -252,6 +244,56 @@
     HAL_PIXEL_FORMAT_RAW10 = 0x25,
 
     /*
+     * Android RAW12 format:
+     *
+     * This format is exposed outside of camera HAL to applications.
+     *
+     * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
+     * and second byte contains the top 8 bits of first and second pixel. The third
+     * byte contains the 4 least significant bits of the two pixels, the exact layout
+     * data for each two consecutive pixels is illustrated below (Pi[j] stands for
+     * the jth bit of the ith pixel):
+     *
+     *           bit 7                                            bit 0
+     *          ======|======|======|======|======|======|======|======|
+     * Byte 0: |P0[11]|P0[10]|P0[ 9]|P0[ 8]|P0[ 7]|P0[ 6]|P0[ 5]|P0[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 1: |P1[11]|P1[10]|P1[ 9]|P1[ 8]|P1[ 7]|P1[ 6]|P1[ 5]|P1[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 2: |P1[ 3]|P1[ 2]|P1[ 1]|P1[ 0]|P0[ 3]|P0[ 2]|P0[ 1]|P0[ 0]|
+     *          =======================================================
+     *
+     * This format assumes:
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (12 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (12 / 8), padding bytes will be present at the end of
+     * each row (including the last row).
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    HAL_PIXEL_FORMAT_RAW12 = 0x26,
+
+    /*
      * Android opaque RAW format:
      *
      * This format is exposed outside of the camera HAL to applications.
@@ -316,11 +358,11 @@
     HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22,
 
     /*
-     * Android flexible YCbCr formats
+     * Android flexible YCbCr 4:2:0 formats
      *
-     * This format allows platforms to use an efficient YCbCr/YCrCb buffer
-     * layout, while still describing the buffer layout in a way accessible to
-     * the CPU in a device-independent manner.  While called YCbCr, it can be
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:0
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
      * used to describe formats with either chromatic ordering, as well as
      * whole planar or semiplanar layouts.
      *
@@ -337,6 +379,62 @@
      */
     HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
 
+    /*
+     * Android flexible YCbCr 4:2:2 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:2
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_YCbCr_422_888 = 0x27,
+
+    /*
+     * Android flexible YCbCr 4:4:4 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:4:4
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_YCbCr_444_888 = 0x28,
+
+    /*
+     * Android flexible RGB 888 formats
+     *
+     * This format allows platforms to use an efficient RGB/BGR/RGBX/BGRX
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called RGB, it can be
+     * used to describe formats with either color ordering and optional
+     * padding, as well as whole planar layout.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_FLEX_RGB_888 = 0x29,
+
+    /*
+     * Android flexible RGBA 8888 formats
+     *
+     * This format allows platforms to use an efficient RGBA/BGRA/ARGB/ABGR
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called RGBA, it can be
+     * used to describe formats with any of the component orderings, as
+     * well as whole planar layout.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    HAL_PIXEL_FORMAT_FLEX_RGBA_8888 = 0x2A,
+
     /* Legacy formats (deprecated), used by ImageFormat.java */
     HAL_PIXEL_FORMAT_YCbCr_422_SP       = 0x10, // NV16
     HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11, // NV21
diff --git a/include/system/radio.h b/include/system/radio.h
new file mode 100644
index 0000000..a088526
--- /dev/null
+++ b/include/system/radio.h
@@ -0,0 +1,247 @@
+/*
+ * 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 ANDROID_RADIO_H
+#define ANDROID_RADIO_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+
+#define RADIO_NUM_BANDS_MAX     16
+#define RADIO_NUM_SPACINGS_MAX  16
+#define RADIO_STRING_LEN_MAX    128
+
+/*
+ * Radio hardware module class. A given radio hardware module HAL is of one class
+ * only. The platform can not have more than one hardware module of each class.
+ * Current version of the framework only supports RADIO_CLASS_AM_FM.
+ */
+typedef enum {
+    RADIO_CLASS_AM_FM = 0,  /* FM (including HD radio) and AM */
+    RADIO_CLASS_SAT   = 1,  /* Satellite Radio */
+    RADIO_CLASS_DT    = 2,  /* Digital Radio (DAB) */
+} radio_class_t;
+
+/* value for field "type" of radio band described in struct radio_hal_band_config */
+typedef enum {
+    RADIO_BAND_AM     = 0,  /* Amplitude Modulation band: LW, MW, SW */
+    RADIO_BAND_FM     = 1,  /* Frequency Modulation band: FM */
+    RADIO_BAND_FM_HD  = 2,  /* FM HD Radio / DRM (IBOC) */
+    RADIO_BAND_AM_HD  = 3,  /* AM HD Radio / DRM (IBOC) */
+} radio_band_t;
+
+/* RDS variant implemented. A struct radio_hal_fm_band_config can list none or several. */
+enum {
+    RADIO_RDS_NONE   = 0x0,
+    RADIO_RDS_WORLD  = 0x01,
+    RADIO_RDS_US     = 0x02,
+};
+typedef unsigned int radio_rds_t;
+
+/* FM deemphasis variant implemented. A struct radio_hal_fm_band_config can list one or more. */
+enum {
+    RADIO_DEEMPHASIS_50   = 0x1,
+    RADIO_DEEMPHASIS_75   = 0x2,
+};
+typedef unsigned int radio_deemphasis_t;
+
+/* Region a particular radio band configuration corresponds to. Not used at the HAL.
+ * Derived by the framework when converting the band descriptors retrieved from the HAL to
+ * individual band descriptors for each supported region. */
+typedef enum {
+    RADIO_REGION_NONE  = -1,
+    RADIO_REGION_ITU_1 = 0,
+    RADIO_REGION_ITU_2 = 1,
+    RADIO_REGION_OIRT  = 2,
+    RADIO_REGION_JAPAN = 3,
+    RADIO_REGION_KOREA = 4,
+} radio_region_t;
+
+/* scanning direction for scan() and step() tuner APIs */
+typedef enum {
+    RADIO_DIRECTION_UP,
+    RADIO_DIRECTION_DOWN
+} radio_direction_t;
+
+/* unique handle allocated to a radio module */
+typedef unsigned int radio_handle_t;
+
+/* Opaque meta data structure used by radio meta data API (see system/radio_metadata.h) */
+typedef struct radio_medtadata radio_metadata_t;
+
+
+/* Additional attributes for an FM band configuration */
+typedef struct radio_hal_fm_band_config {
+    radio_deemphasis_t  deemphasis; /* deemphasis variant */
+    bool                stereo;     /* stereo supported */
+    radio_rds_t         rds;        /* RDS variants supported */
+    bool                ta;         /* Traffic Announcement supported */
+    bool                af;         /* Alternate Frequency supported */
+} radio_hal_fm_band_config_t;
+
+/* Additional attributes for an AM band configuration */
+typedef struct radio_hal_am_band_config {
+    bool                stereo;     /* stereo supported */
+} radio_hal_am_band_config_t;
+
+/* Radio band configuration. Describes a given band supported by the radio module.
+ * The HAL can expose only one band per type with the the maximum range supported and all options.
+ * THe framework will derive the actual regions were this module can operate and expose separate
+ * band configurations for applications to chose from. */
+typedef struct radio_hal_band_config {
+    radio_band_t type;
+    bool         antenna_connected;
+    unsigned int lower_limit;
+    unsigned int upper_limit;
+    unsigned int num_spacings;
+    unsigned int spacings[RADIO_NUM_SPACINGS_MAX];
+    union {
+        radio_hal_fm_band_config_t fm;
+        radio_hal_am_band_config_t am;
+    };
+} radio_hal_band_config_t;
+
+/* Used internally by the framework to represent a band for s specific region */
+typedef struct radio_band_config {
+    radio_region_t  region;
+    radio_hal_band_config_t band;
+} radio_band_config_t;
+
+
+/* Exposes properties of a given hardware radio module.
+ * NOTE: current framework implementation supports only one audio source (num_audio_sources = 1).
+ * The source corresponds to AUDIO_DEVICE_IN_FM_TUNER.
+ * If more than one tuner is supported (num_tuners > 1), only one can be connected to the audio
+ * source. */
+typedef struct radio_hal_properties {
+    radio_class_t   class_id;   /* Class of this module. E.g RADIO_CLASS_AM_FM */
+    char            implementor[RADIO_STRING_LEN_MAX];  /* implementor name */
+    char            product[RADIO_STRING_LEN_MAX];  /* product name */
+    char            version[RADIO_STRING_LEN_MAX];  /* product version */
+    char            serial[RADIO_STRING_LEN_MAX];  /* serial number (for subscription services) */
+    unsigned int    num_tuners;     /* number of tuners controllable independently */
+    unsigned int    num_audio_sources; /* number of audio sources driven simultaneously */
+    bool            supports_capture; /* the hardware supports capture of audio source audio HAL */
+    unsigned int    num_bands;      /* number of band descriptors */
+    radio_hal_band_config_t bands[RADIO_NUM_BANDS_MAX]; /* band descriptors */
+} radio_hal_properties_t;
+
+/* Used internally by the framework. Same information as in struct radio_hal_properties plus a
+ * unique handle and one band configuration per region. */
+typedef struct radio_properties {
+    radio_handle_t      handle;
+    radio_class_t       class_id;
+    char                implementor[RADIO_STRING_LEN_MAX];
+    char                product[RADIO_STRING_LEN_MAX];
+    char                version[RADIO_STRING_LEN_MAX];
+    char                serial[RADIO_STRING_LEN_MAX];
+    unsigned int        num_tuners;
+    unsigned int        num_audio_sources;
+    bool                supports_capture;
+    unsigned int        num_bands;
+    radio_band_config_t bands[RADIO_NUM_BANDS_MAX];
+} radio_properties_t;
+
+/* Radio program information. Returned by the HAL with event RADIO_EVENT_TUNED.
+ * Contains information on currently tuned channel.
+ */
+typedef struct radio_program_info {
+    unsigned int     channel;   /* current channel. (e.g kHz for band type RADIO_BAND_FM) */
+    unsigned int     sub_channel; /* current sub channel. (used for RADIO_BAND_FM_HD) */
+    bool             tuned;     /* tuned to a program or not */
+    bool             stereo;    /* program is stereo or not */
+    bool             digital;   /* digital program or not (e.g HD Radio program) */
+    unsigned int     signal_strength; /* signal strength from 0 to 100 */
+    radio_metadata_t *metadata; /* non null if meta data are present (e.g PTY, song title ...) */
+} radio_program_info_t;
+
+
+/* Events sent to the framework via the HAL callback. An event can notify the completion of an
+ * asynchronous command (configuration, tune, scan ...) or a spontaneous change (antenna connection,
+ * failure, AF switching, meta data reception... */
+enum {
+    RADIO_EVENT_HW_FAILURE  = 0,  /* hardware module failure. Requires reopening the tuner */
+    RADIO_EVENT_CONFIG      = 1,  /* configuration change completed */
+    RADIO_EVENT_ANTENNA     = 2,  /* Antenna connected, disconnected */
+    RADIO_EVENT_TUNED       = 3,  /* tune, step, scan completed */
+    RADIO_EVENT_METADATA    = 4,  /* New meta data received */
+    RADIO_EVENT_TA          = 5,  /* Traffic announcement start or stop */
+    RADIO_EVENT_AF_SWITCH   = 6,  /* Switch to Alternate Frequency */
+    // begin framework only events
+    RADIO_EVENT_CONTROL     = 100, /* loss/gain of tuner control */
+    RADIO_EVENT_SERVER_DIED = 101, /* radio service died */
+};
+typedef unsigned int radio_event_type_t;
+
+/* Event passed to the framework by the HAL callback */
+typedef struct radio_hal_event {
+    radio_event_type_t  type;       /* event type */
+    int                 status;     /* used by RADIO_EVENT_CONFIG, RADIO_EVENT_TUNED */
+    union {
+        bool                    on;     /* RADIO_EVENT_ANTENNA, RADIO_EVENT_TA */
+        radio_hal_band_config_t config; /* RADIO_EVENT_CONFIG */
+        radio_program_info_t    info;   /* RADIO_EVENT_TUNED, RADIO_EVENT_AF_SWITCH */
+        radio_metadata_t        *metadata; /* RADIO_EVENT_METADATA */
+    };
+} radio_hal_event_t;
+
+/* Used internally by the framework. Same information as in struct radio_hal_event */
+typedef struct radio_event {
+    radio_event_type_t  type;
+    int                 status;
+    union {
+        bool                    on;
+        radio_band_config_t     config;
+        radio_program_info_t    info;
+        radio_metadata_t        *metadata; /* offset from start of struct when in shared memory */
+    };
+} radio_event_t;
+
+
+static radio_rds_t radio_rds_for_region(bool rds, radio_region_t region) {
+    if (!rds)
+        return RADIO_RDS_NONE;
+    switch(region) {
+        case RADIO_REGION_ITU_1:
+        case RADIO_REGION_OIRT:
+        case RADIO_REGION_JAPAN:
+        case RADIO_REGION_KOREA:
+            return RADIO_RDS_WORLD;
+        case RADIO_REGION_ITU_2:
+            return RADIO_RDS_US;
+        default:
+            return RADIO_REGION_NONE;
+    }
+}
+
+static radio_deemphasis_t radio_demephasis_for_region(radio_region_t region) {
+    switch(region) {
+        case RADIO_REGION_KOREA:
+        case RADIO_REGION_ITU_2:
+            return RADIO_DEEMPHASIS_75;
+        case RADIO_REGION_ITU_1:
+        case RADIO_REGION_OIRT:
+        case RADIO_REGION_JAPAN:
+        default:
+            return RADIO_DEEMPHASIS_50;
+    }
+}
+
+#endif  // ANDROID_RADIO_H
diff --git a/include/system/sound_trigger.h b/include/system/sound_trigger.h
deleted file mode 100644
index 773e4f7..0000000
--- a/include/system/sound_trigger.h
+++ /dev/null
@@ -1,223 +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 ANDROID_SOUND_TRIGGER_H
-#define ANDROID_SOUND_TRIGGER_H
-
-#include <stdbool.h>
-#include <system/audio.h>
-
-#define SOUND_TRIGGER_MAX_STRING_LEN 64 /* max length of strings in properties or
-                                           descriptor structs */
-#define SOUND_TRIGGER_MAX_LOCALE_LEN 6  /* max length of locale string. e.g en_US */
-#define SOUND_TRIGGER_MAX_USERS 10      /* max number of concurrent users */
-#define SOUND_TRIGGER_MAX_PHRASES 10    /* max number of concurrent phrases */
-
-typedef enum {
-    SOUND_TRIGGER_STATE_NO_INIT = -1,   /* The sound trigger service is not initialized */
-    SOUND_TRIGGER_STATE_ENABLED = 0,    /* The sound trigger service is enabled */
-    SOUND_TRIGGER_STATE_DISABLED = 1    /* The sound trigger service is disabled */
-} sound_trigger_service_state_t;
-
-#define RECOGNITION_MODE_VOICE_TRIGGER 0x1       /* simple voice trigger */
-#define RECOGNITION_MODE_USER_IDENTIFICATION 0x2 /* trigger only if one user in model identified */
-#define RECOGNITION_MODE_USER_AUTHENTICATION 0x4 /* trigger only if one user in mode
-                                                    authenticated */
-#define RECOGNITION_STATUS_SUCCESS 0
-#define RECOGNITION_STATUS_ABORT 1
-#define RECOGNITION_STATUS_FAILURE 2
-
-#define SOUND_MODEL_STATUS_UPDATED 0
-
-typedef enum {
-    SOUND_MODEL_TYPE_UNKNOWN = -1,    /* use for unspecified sound model type */
-    SOUND_MODEL_TYPE_KEYPHRASE = 0    /* use for key phrase sound models */
-} sound_trigger_sound_model_type_t;
-
-typedef struct sound_trigger_uuid_s {
-    unsigned int   timeLow;
-    unsigned short timeMid;
-    unsigned short timeHiAndVersion;
-    unsigned short clockSeq;
-    unsigned char  node[6];
-} sound_trigger_uuid_t;
-
-/*
- * sound trigger implementation descriptor read by the framework via get_properties().
- * Used by SoundTrigger service to report to applications and manage concurrency and policy.
- */
-struct sound_trigger_properties {
-    char                 implementor[SOUND_TRIGGER_MAX_STRING_LEN]; /* implementor name */
-    char                 description[SOUND_TRIGGER_MAX_STRING_LEN]; /* implementation description */
-    unsigned int         version;               /* implementation version */
-    sound_trigger_uuid_t uuid;                  /* unique implementation ID.
-                                                   Must change with version each version */
-    unsigned int         max_sound_models;      /* maximum number of concurrent sound models
-                                                   loaded */
-    unsigned int         max_key_phrases;       /* maximum number of key phrases */
-    unsigned int         max_users;             /* maximum number of concurrent users detected */
-    unsigned int         recognition_modes;     /* all supported modes.
-                                                   e.g RECOGNITION_MODE_VOICE_TRIGGER */
-    bool                 capture_transition;    /* supports seamless transition from detection
-                                                   to capture */
-    unsigned int         max_buffer_ms;         /* maximum buffering capacity in ms if
-                                                   capture_transition is true*/
-    bool                 concurrent_capture;    /* supports capture by other use cases while
-                                                   detection is active */
-    bool                 trigger_in_event;      /* returns the trigger capture in event */
-    unsigned int         power_consumption_mw;  /* Rated power consumption when detection is active
-                                                   with TDB silence/sound/speech ratio */
-};
-
-typedef int sound_trigger_module_handle_t;
-
-struct sound_trigger_module_descriptor {
-    sound_trigger_module_handle_t   handle;
-    struct sound_trigger_properties properties;
-};
-
-typedef int sound_model_handle_t;
-
-/*
- * Generic sound model descriptor. This struct is the header of a larger block passed to
- * load_sound_model() and containing the binary data of the sound model.
- * Proprietary representation of users in binary data must match information indicated
- * by users field
- */
-struct sound_trigger_sound_model {
-    sound_trigger_sound_model_type_t type;        /* model type. e.g. SOUND_MODEL_TYPE_KEYPHRASE */
-    sound_trigger_uuid_t             uuid;        /* unique sound model ID. */
-    sound_trigger_uuid_t             vendor_uuid; /* unique vendor ID. Identifies the engine the
-                                                  sound model was build for */
-    unsigned int                     data_size;   /* size of opaque model data */
-    unsigned int                     data_offset; /* offset of opaque data start from head of struct
-                                                    (e.g sizeof struct sound_trigger_sound_model) */
-};
-
-/* key phrase descriptor */
-struct sound_trigger_phrase {
-    unsigned int id;                /* keyphrase ID */
-    unsigned int recognition_mode;  /* recognition modes supported by this key phrase */
-    unsigned int num_users;         /* number of users in the key phrase */
-    unsigned int users[SOUND_TRIGGER_MAX_USERS]; /* users ids: (not uid_t but sound trigger
-                                                 specific IDs */
-    char         locale[SOUND_TRIGGER_MAX_LOCALE_LEN]; /* locale - JAVA Locale style (e.g. en_US) */
-    char         text[SOUND_TRIGGER_MAX_STRING_LEN];   /* phrase text in UTF-8 format. */
-};
-
-/*
- * Specialized sound model for key phrase detection.
- * Proprietary representation of key phrases in binary data must match information indicated
- * by phrases field
- */
-struct sound_trigger_phrase_sound_model {
-    struct sound_trigger_sound_model common;
-    unsigned int                     num_phrases;   /* number of key phrases in model */
-    struct sound_trigger_phrase      phrases[SOUND_TRIGGER_MAX_PHRASES];
-};
-
-
-/*
- * Generic recognition event sent via recognition callback
- */
-struct sound_trigger_recognition_event {
-    int                              status;            /* recognition status e.g.
-                                                           RECOGNITION_STATUS_SUCCESS */
-    sound_trigger_sound_model_type_t type;              /* event type, same as sound model type.
-                                                           e.g. SOUND_MODEL_TYPE_KEYPHRASE */
-    sound_model_handle_t             model;             /* loaded sound model that triggered the
-                                                           event */
-    bool                             capture_available; /* it is possible to capture audio from this
-                                                           utterance buffered by the
-                                                           implementation */
-    int                              capture_session;   /* audio session ID. framework use */
-    int                              capture_delay_ms;  /* delay in ms between end of model
-                                                           detection and start of audio available
-                                                           for capture. A negative value is possible
-                                                           (e.g. if key phrase is also available for
-                                                           capture */
-    int                              capture_preamble_ms; /* duration in ms of audio captured
-                                                            before the start of the trigger.
-                                                            0 if none. */
-    bool                             trigger_in_data; /* the opaque data is the capture of
-                                                            the trigger sound */
-    audio_config_t                   audio_config;        /* audio format of either the trigger in
-                                                             event data or to use for capture of the
-                                                             rest of the utterance */
-    unsigned int                     data_size;         /* size of opaque event data */
-    unsigned int                     data_offset;       /* offset of opaque data start from start of
-                                                          this struct (e.g sizeof struct
-                                                          sound_trigger_phrase_recognition_event) */
-};
-
-/*
- * Confidence level for each user in struct sound_trigger_phrase_recognition_extra
- */
-struct sound_trigger_confidence_level {
-    unsigned int user_id;   /* user ID */
-    unsigned int level;     /* confidence level in percent (0 - 100).
-                               - min level for recognition configuration
-                               - detected level for recognition event */
-};
-
-/*
- * Specialized recognition event for key phrase detection
- */
-struct sound_trigger_phrase_recognition_extra {
-    unsigned int id;                /* keyphrase ID */
-    unsigned int recognition_modes; /* recognition modes used for this keyphrase */
-    unsigned int confidence_level;  /* confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER */
-    unsigned int num_levels;        /* number of user confidence levels */
-    struct sound_trigger_confidence_level levels[SOUND_TRIGGER_MAX_USERS];
-};
-
-struct sound_trigger_phrase_recognition_event {
-    struct sound_trigger_recognition_event common;
-    unsigned int                           num_phrases;
-    struct sound_trigger_phrase_recognition_extra phrase_extras[SOUND_TRIGGER_MAX_PHRASES];
-};
-
-/*
- * configuration for sound trigger capture session passed to start_recognition()
- */
-struct sound_trigger_recognition_config {
-    audio_io_handle_t    capture_handle;    /* IO handle that will be used for capture.
-                                            N/A if capture_requested is false */
-    audio_devices_t      capture_device;    /* input device requested for detection capture */
-    bool                 capture_requested; /* capture and buffer audio for this recognition
-                                            instance */
-    unsigned int         num_phrases;   /* number of key phrases recognition extras */
-    struct sound_trigger_phrase_recognition_extra phrases[SOUND_TRIGGER_MAX_PHRASES];
-                                           /* configuration for each key phrase */
-    unsigned int        data_size;         /* size of opaque capture configuration data */
-    unsigned int        data_offset;       /* offset of opaque data start from start of this struct
-                                           (e.g sizeof struct sound_trigger_recognition_config) */
-};
-
-/*
- * Event sent via load sound model callback
- */
-struct sound_trigger_model_event {
-    int                  status;      /* sound model status e.g. SOUND_MODEL_STATUS_UPDATED */
-    sound_model_handle_t model;       /* loaded sound model that triggered the event */
-    unsigned int         data_size;   /* size of event data if any. Size of updated sound model if
-                                       status is SOUND_MODEL_STATUS_UPDATED */
-    unsigned int         data_offset; /* offset of data start from start of this struct
-                                       (e.g sizeof struct sound_trigger_model_event) */
-};
-
-
-#endif  // ANDROID_SOUND_TRIGGER_H
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/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index 4fa49c5..b80f3ea 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -21,25 +21,29 @@
 #define NL_PARAMS_MAX 32
 
 class NetlinkEvent {
+public:
+    enum class Action {
+        kUnknown = 0,
+        kAdd = 1,
+        kRemove = 2,
+        kChange = 3,
+        kLinkUp = 4,
+        kLinkDown = 5,
+        kAddressUpdated = 6,
+        kAddressRemoved = 7,
+        kRdnss = 8,
+        kRouteUpdated = 9,
+        kRouteRemoved = 10,
+    };
+
+private:
     int  mSeq;
     char *mPath;
-    int  mAction;
+    Action mAction;
     char *mSubsystem;
     char *mParams[NL_PARAMS_MAX];
 
 public:
-    const static int NlActionUnknown;
-    const static int NlActionAdd;
-    const static int NlActionRemove;
-    const static int NlActionChange;
-    const static int NlActionLinkDown;
-    const static int NlActionLinkUp;
-    const static int NlActionAddressUpdated;
-    const static int NlActionAddressRemoved;
-    const static int NlActionRdnss;
-    const static int NlActionRouteUpdated;
-    const static int NlActionRouteRemoved;
-
     NetlinkEvent();
     virtual ~NetlinkEvent();
 
@@ -47,7 +51,7 @@
     const char *findParam(const char *paramName);
 
     const char *getSubsystem() { return mSubsystem; }
-    int getAction() { return mAction; }
+    Action getAction() { return mAction; }
 
     void dump();
 
diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h
index d26e931..4350ec1 100644
--- a/include/usbhost/usbhost.h
+++ b/include/usbhost/usbhost.h
@@ -156,6 +156,10 @@
  */
 char* usb_device_get_product_name(struct usb_device *device);
 
+/* Returns the version number for the USB device.
+ */
+int usb_device_get_version(struct usb_device *device);
+
 /* Returns the USB serial number for the USB device.
  * Call free() to free the result when you are done with it.
  */
diff --git a/include/utils/LinearAllocator.h b/include/utils/LinearAllocator.h
deleted file mode 100644
index 4772bc8..0000000
--- a/include/utils/LinearAllocator.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * 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 ``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.
- */
-
-#ifndef ANDROID_LINEARALLOCATOR_H
-#define ANDROID_LINEARALLOCATOR_H
-
-#include <stddef.h>
-
-namespace android {
-
-/**
- * A memory manager that internally allocates multi-kbyte buffers for placing objects in. It avoids
- * the overhead of malloc when many objects are allocated. It is most useful when creating many
- * small objects with a similar lifetime, and doesn't add significant overhead for large
- * allocations.
- */
-class LinearAllocator {
-public:
-    LinearAllocator();
-    ~LinearAllocator();
-
-    /**
-     * Reserves and returns a region of memory of at least size 'size', aligning as needed.
-     * Typically this is used in an object's overridden new() method or as a replacement for malloc.
-     *
-     * The lifetime of the returned buffers is tied to that of the LinearAllocator. If calling
-     * delete() on an object stored in a buffer is needed, it should be overridden to use
-     * rewindIfLastAlloc()
-     */
-    void* alloc(size_t size);
-
-    /**
-     * Attempt to deallocate the given buffer, with the LinearAllocator attempting to rewind its
-     * state if possible. No destructors are called.
-     */
-    void rewindIfLastAlloc(void* ptr, size_t allocSize);
-
-    /**
-     * Dump memory usage statistics to the log (allocated and wasted space)
-     */
-    void dumpMemoryStats(const char* prefix = "");
-
-    /**
-     * The number of bytes used for buffers allocated in the LinearAllocator (does not count space
-     * wasted)
-     */
-    size_t usedSize() const { return mTotalAllocated - mWastedSpace; }
-
-private:
-    LinearAllocator(const LinearAllocator& other);
-
-    class Page;
-
-    Page* newPage(size_t pageSize);
-    bool fitsInCurrentPage(size_t size);
-    void ensureNext(size_t size);
-    void* start(Page *p);
-    void* end(Page* p);
-
-    size_t mPageSize;
-    size_t mMaxAllocSize;
-    void* mNext;
-    Page* mCurrentPage;
-    Page* mPages;
-
-    // Memory usage tracking
-    size_t mTotalAllocated;
-    size_t mWastedSpace;
-    size_t mPageCount;
-    size_t mDedicatedPageCount;
-};
-
-}; // namespace android
-
-#endif // ANDROID_LINEARALLOCATOR_H
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index 15c9891..da2d5f2 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -386,11 +386,12 @@
     void removeMessages(const sp<MessageHandler>& handler, int what);
 
     /**
-     * Return whether this looper's thread is currently idling -- that is, whether it
-     * stopped waiting for more work to do.  Note that this is intrinsically racy, since
-     * its state can change before you get the result back.
+     * Returns whether this looper's thread is currently polling for more work to do.
+     * This is a good signal that the loop is still alive rather than being stuck
+     * handling a callback.  Note that this method is intrinsically racy, since the
+     * state of the loop can change before you get the result back.
      */
-    bool isIdling() const;
+    bool isPolling() const;
 
     /**
      * Prepares a looper associated with the calling thread, and returns it.
@@ -419,8 +420,12 @@
     struct Request {
         int fd;
         int ident;
+        int events;
+        int seq;
         sp<LooperCallback> callback;
         void* data;
+
+        void initEventItem(struct epoll_event* eventItem) const;
     };
 
     struct Response {
@@ -442,8 +447,7 @@
 
     const bool mAllowNonCallbacks; // immutable
 
-    int mWakeReadPipeFd;  // immutable
-    int mWakeWritePipeFd; // immutable
+    int mWakeEventFd;  // immutable
     Mutex mLock;
 
     Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
@@ -451,12 +455,14 @@
 
     // Whether we are currently waiting for work.  Not protected by a lock,
     // any use of it is racy anyway.
-    volatile bool mIdling;
+    volatile bool mPolling;
 
-    int mEpollFd; // immutable
+    int mEpollFd; // guarded by mLock but only modified on the looper thread
+    bool mEpollRebuildRequired; // guarded by mLock
 
     // Locked list of file descriptor monitoring requests.
     KeyedVector<int, Request> mRequests;  // guarded by mLock
+    int mNextRequestSeq;
 
     // This state is only used privately by pollOnce and does not require a lock since
     // it runs on a single thread.
@@ -465,11 +471,15 @@
     nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
 
     int pollInner(int timeoutMillis);
+    int removeFd(int fd, int seq);
     void awoken();
     void pushResponse(int events, const Request& request);
+    void rebuildEpollLocked();
+    void scheduleEpollRebuildLocked();
 
     static void initTLSKey();
     static void threadDestructor(void *st);
+    static void initEpollEvent(struct epoll_event* eventItem);
 };
 
 } // namespace android
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 91ca8b7..d75c210 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -97,12 +97,7 @@
     map_name = "<unknown>";
   }
 
-  uintptr_t relative_pc;
-  if (BacktraceMap::IsValid(frame->map)) {
-    relative_pc = frame->pc - frame->map.start;
-  } else {
-    relative_pc = frame->pc;
-  }
+  uintptr_t relative_pc = BacktraceMap::GetRelativePc(frame->map, frame->pc);
 
   std::string line(StringPrintf("#%02zu pc %" PRIPTR "  %s", frame->num, relative_pc, map_name));
   if (!frame->func_name.empty()) {
diff --git a/libbacktrace/BacktracePtrace.cpp b/libbacktrace/BacktracePtrace.cpp
index 6134438..e10cce1 100644
--- a/libbacktrace/BacktracePtrace.cpp
+++ b/libbacktrace/BacktracePtrace.cpp
@@ -83,13 +83,12 @@
     if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) {
       return 0;
     }
-    align_bytes = sizeof(word_t) - align_bytes;
-    memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + sizeof(word_t) - align_bytes,
-           align_bytes);
-    addr += align_bytes;
-    buffer += align_bytes;
-    bytes -= align_bytes;
-    bytes_read += align_bytes;
+    size_t copy_bytes = MIN(sizeof(word_t) - align_bytes, bytes);
+    memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + align_bytes, copy_bytes);
+    addr += copy_bytes;
+    buffer += copy_bytes;
+    bytes -= copy_bytes;
+    bytes_read += copy_bytes;
   }
 
   size_t num_words = bytes / sizeof(word_t);
diff --git a/libbacktrace/UnwindMap.cpp b/libbacktrace/UnwindMap.cpp
index fa59d07..879fea5 100644
--- a/libbacktrace/UnwindMap.cpp
+++ b/libbacktrace/UnwindMap.cpp
@@ -51,6 +51,8 @@
 
     map.start = unw_map.start;
     map.end = unw_map.end;
+    map.offset = unw_map.offset;
+    map.load_base = unw_map.load_base;
     map.flags = unw_map.flags;
     map.name = unw_map.path;
 
@@ -91,6 +93,8 @@
 
       map.start = unw_map.start;
       map.end = unw_map.end;
+      map.offset = unw_map.offset;
+      map.load_base = unw_map.load_base;
       map.flags = unw_map.flags;
       map.name = unw_map.path;
 
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 4af6592..ba3cbb5 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -771,6 +771,7 @@
   // Check map name empty, but exists.
   frame.map.start = 1;
   frame.map.end = 1;
+  frame.map.load_base = 0;
 #if defined(__LP64__)
   EXPECT_EQ("#01 pc 0000000000000001  <unknown>",
 #else
@@ -808,6 +809,16 @@
   EXPECT_EQ("#01 pc 12345678  MapFake (ProcFake+645)",
 #endif
             backtrace->FormatFrameData(&frame));
+
+  // Check func_name is set, func offset is non-zero, and load_base is non-zero.
+  frame.func_offset = 645;
+  frame.map.load_base = 100;
+#if defined(__LP64__)
+  EXPECT_EQ("#01 pc 00000000123456dc  MapFake (ProcFake+645)",
+#else
+  EXPECT_EQ("#01 pc 123456dc  MapFake (ProcFake+645)",
+#endif
+            backtrace->FormatFrameData(&frame));
 }
 
 struct map_test_t {
@@ -871,6 +882,17 @@
   ASSERT_EQ(waitpid(pid, nullptr, 0), pid);
 }
 
+void InitMemory(uint8_t* memory, size_t bytes) {
+  for (size_t i = 0; i < bytes; i++) {
+    memory[i] = i;
+    if (memory[i] == '\0') {
+      // Don't use '\0' in our data so we can verify that an overread doesn't
+      // occur by using a '\0' as the character after the read data.
+      memory[i] = 23;
+    }
+  }
+}
+
 void* ThreadReadTest(void* data) {
   thread_t* thread_data = reinterpret_cast<thread_t*>(data);
 
@@ -889,9 +911,7 @@
   }
 
   // Set up a simple pattern in memory.
-  for (size_t i = 0; i < pagesize; i++) {
-    memory[i] = i;
-  }
+  InitMemory(memory, pagesize);
 
   thread_data->data = memory;
 
@@ -919,9 +939,8 @@
 
   // Create a page of data to use to do quick compares.
   uint8_t* expected = new uint8_t[pagesize];
-  for (size_t i = 0; i < pagesize; i++) {
-    expected[i] = i;
-  }
+  InitMemory(expected, pagesize);
+
   uint8_t* data = new uint8_t[2*pagesize];
   // Verify that we can only read one page worth of data.
   size_t bytes_read = backtrace->Read(read_addr, data, 2 * pagesize);
@@ -935,6 +954,20 @@
     ASSERT_TRUE(memcmp(data, &expected[i], 2 * sizeof(word_t)) == 0)
         << "Offset at " << i << " failed";
   }
+
+  // Verify small unaligned reads.
+  for (size_t i = 1; i < sizeof(word_t); i++) {
+    for (size_t j = 1; j < sizeof(word_t); j++) {
+      // Set one byte past what we expect to read, to guarantee we don't overread.
+      data[j] = '\0';
+      bytes_read = backtrace->Read(read_addr + i, data, j);
+      ASSERT_EQ(j, bytes_read);
+      ASSERT_TRUE(memcmp(data, &expected[i], j) == 0)
+          << "Offset at " << i << " length " << j << " miscompared";
+      ASSERT_EQ('\0', data[j])
+          << "Offset at " << i << " length " << j << " wrote too much data";
+    }
+  }
   delete data;
   delete expected;
 }
@@ -978,9 +1011,7 @@
   }
 
   // Set up a simple pattern in memory.
-  for (size_t i = 0; i < pagesize; i++) {
-    memory[i] = i;
-  }
+  InitMemory(memory, pagesize);
 
   g_addr = reinterpret_cast<uintptr_t>(memory);
   g_ready = 1;
diff --git a/libion/ion.c b/libion/ion.c
index 4908932..d1984bd 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -91,6 +91,7 @@
             int flags, off_t offset, unsigned char **ptr, int *map_fd)
 {
     int ret;
+    unsigned char *tmp_ptr;
     struct ion_fd_data data = {
         .handle = handle,
     };
@@ -103,16 +104,17 @@
     ret = ion_ioctl(fd, ION_IOC_MAP, &data);
     if (ret < 0)
         return ret;
-    *map_fd = data.fd;
-    if (*map_fd < 0) {
+    if (data.fd < 0) {
         ALOGE("map ioctl returned negative fd\n");
         return -EINVAL;
     }
-    *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
-    if (*ptr == MAP_FAILED) {
+    tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset);
+    if (tmp_ptr == MAP_FAILED) {
         ALOGE("mmap failed: %s\n", strerror(errno));
         return -errno;
     }
+    *map_fd = data.fd;
+    *ptr = tmp_ptr;
     return ret;
 }
 
@@ -129,11 +131,11 @@
     ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
     if (ret < 0)
         return ret;
-    *share_fd = data.fd;
-    if (*share_fd < 0) {
+    if (data.fd < 0) {
         ALOGE("share ioctl returned negative fd\n");
         return -EINVAL;
     }
+    *share_fd = data.fd;
     return ret;
 }
 
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/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 70e37c6..c6b9fe4 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -1,16 +1,16 @@
 /*
  * Copyright 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 
+ * 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 
+ *     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 
+ * 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.
  */
 
@@ -33,7 +33,7 @@
 static const int NAP_TIME = 200;   /* wait for 200ms at a time */
                                   /* when polling for property values */
 static const char DAEMON_NAME_RENEW[]  = "iprenew";
-static char errmsg[100];
+static char errmsg[100] = "\0";
 /* interface length for dhcpcd daemon start (dhcpcd_<interface> as defined in init.rc file)
  * or for filling up system properties dhcpcd.<interface>.ipaddress, dhcpcd.<interface>.dns1
  * and other properties on a successful bind
@@ -74,7 +74,7 @@
 
     while (maxnaps-- >= 0) {
         if (property_get(name, value, NULL)) {
-            if (desired_value == NULL || 
+            if (desired_value == NULL ||
                     strcmp(value, desired_value) == 0) {
                 return 0;
             }
@@ -169,6 +169,47 @@
 }
 
 /*
+ * Get any available DHCP results.
+ */
+int dhcp_get_results(const char *interface,
+                     char *ipaddr,
+                     char *gateway,
+                     uint32_t *prefixLength,
+                     char *dns[],
+                     char *server,
+                     uint32_t *lease,
+                     char *vendorInfo,
+                     char *domain,
+                     char *mtu)
+{
+    char result_prop_name[PROPERTY_KEY_MAX];
+    char prop_value[PROPERTY_VALUE_MAX];
+
+    /* Interface name after converting p2p0-p2p0-X to p2p to reuse system properties */
+    char p2p_interface[MAX_INTERFACE_LENGTH];
+    get_p2p_interface_replacement(interface, p2p_interface);
+    snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
+            DHCP_PROP_NAME_PREFIX,
+            p2p_interface);
+
+    memset(prop_value, '\0', PROPERTY_VALUE_MAX);
+    if (!property_get(result_prop_name, prop_value, NULL)) {
+        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set");
+        return -1;
+    }
+    if (strcmp(prop_value, "ok") == 0) {
+        if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+                server, lease, vendorInfo, domain, mtu) == -1) {
+            return -1;
+        }
+        return 0;
+    } else {
+        snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
+        return -1;
+    }
+}
+
+/*
  * Start the dhcp client daemon, and wait for it to finish
  * configuring the interface.
  *
@@ -177,16 +218,7 @@
  * Example:
  * service dhcpcd_<interface> /system/bin/dhcpcd -ABKL -f dhcpcd.conf
  */
-int dhcp_do_request(const char *interface,
-                    char *ipaddr,
-                    char *gateway,
-                    uint32_t *prefixLength,
-                    char *dns[],
-                    char *server,
-                    uint32_t *lease,
-                    char *vendorInfo,
-                    char *domain,
-                    char *mtu)
+int dhcp_start(const char *interface)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char daemon_prop_name[PROPERTY_KEY_MAX];
@@ -230,21 +262,7 @@
         return -1;
     }
 
-    if (!property_get(result_prop_name, prop_value, NULL)) {
-        /* shouldn't ever happen, given the success of wait_for_property() */
-        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set");
-        return -1;
-    }
-    if (strcmp(prop_value, "ok") == 0) {
-        if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
-                server, lease, vendorInfo, domain, mtu) == -1) {
-            return -1;
-        }
-        return 0;
-    } else {
-        snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
-        return -1;
-    }
+    return 0;
 }
 
 /**
@@ -320,16 +338,7 @@
  * service iprenew_<interface> /system/bin/dhcpcd -n
  *
  */
-int dhcp_do_request_renew(const char *interface,
-                    char *ipaddr,
-                    char *gateway,
-                    uint32_t *prefixLength,
-                    char *dns[],
-                    char *server,
-                    uint32_t *lease,
-                    char *vendorInfo,
-                    char *domain,
-                    char *mtu)
+int dhcp_start_renew(const char *interface)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
@@ -359,16 +368,5 @@
         return -1;
     }
 
-    if (!property_get(result_prop_name, prop_value, NULL)) {
-        /* shouldn't ever happen, given the success of wait_for_property() */
-        snprintf(errmsg, sizeof(errmsg), "%s", "DHCP Renew result property was not set");
-        return -1;
-    }
-    if (strcmp(prop_value, "ok") == 0) {
-        return fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
-                server, lease, vendorInfo, domain, mtu);
-    } else {
-        snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
-        return -1;
-    }
+    return 0;
 }
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 909df86..ef30017 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -47,20 +47,8 @@
 #include <netlink/handlers.h>
 #include <netlink/msg.h>
 
-const int NetlinkEvent::NlActionUnknown = 0;
-const int NetlinkEvent::NlActionAdd = 1;
-const int NetlinkEvent::NlActionRemove = 2;
-const int NetlinkEvent::NlActionChange = 3;
-const int NetlinkEvent::NlActionLinkUp = 4;
-const int NetlinkEvent::NlActionLinkDown = 5;
-const int NetlinkEvent::NlActionAddressUpdated = 6;
-const int NetlinkEvent::NlActionAddressRemoved = 7;
-const int NetlinkEvent::NlActionRdnss = 8;
-const int NetlinkEvent::NlActionRouteUpdated = 9;
-const int NetlinkEvent::NlActionRouteRemoved = 10;
-
 NetlinkEvent::NetlinkEvent() {
-    mAction = NlActionUnknown;
+    mAction = Action::kUnknown;
     memset(mParams, 0, sizeof(mParams));
     mPath = NULL;
     mSubsystem = NULL;
@@ -154,8 +142,8 @@
         switch(rta->rta_type) {
             case IFLA_IFNAME:
                 asprintf(&mParams[0], "INTERFACE=%s", (char *) RTA_DATA(rta));
-                mAction = (ifi->ifi_flags & IFF_LOWER_UP) ?  NlActionLinkUp :
-                                                             NlActionLinkDown;
+                mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? Action::kLinkUp :
+                                                            Action::kLinkDown;
                 mSubsystem = strdup("net");
                 return true;
         }
@@ -244,8 +232,8 @@
     }
 
     // Fill in netlink event information.
-    mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated :
-                                      NlActionAddressRemoved;
+    mAction = (type == RTM_NEWADDR) ? Action::kAddressUpdated :
+                                      Action::kAddressRemoved;
     mSubsystem = strdup("net");
     asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr,
              ifaddr->ifa_prefixlen);
@@ -276,7 +264,7 @@
     asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix);
     asprintf(&mParams[1], "INTERFACE=%s", devname);
     mSubsystem = strdup("qlog");
-    mAction = NlActionChange;
+    mAction = Action::kChange;
     return true;
 }
 
@@ -311,7 +299,7 @@
     asprintf(&mParams[0], "UID=%d", uid);
     mParams[1] = hex;
     mSubsystem = strdup("strict");
-    mAction = NlActionChange;
+    mAction = Action::kChange;
     return true;
 }
 
@@ -397,8 +385,8 @@
         return false;
 
     // Fill in netlink event information.
-    mAction = (type == RTM_NEWROUTE) ? NlActionRouteUpdated :
-                                       NlActionRouteRemoved;
+    mAction = (type == RTM_NEWROUTE) ? Action::kRouteUpdated :
+                                       Action::kRouteRemoved;
     mSubsystem = strdup("net");
     asprintf(&mParams[0], "ROUTE=%s/%d", dst, prefixLength);
     asprintf(&mParams[1], "GATEWAY=%s", (*gw) ? gw : "");
@@ -497,7 +485,7 @@
         }
         buf[pos] = '\0';
 
-        mAction = NlActionRdnss;
+        mAction = Action::kRdnss;
         mSubsystem = strdup("net");
         asprintf(&mParams[0], "INTERFACE=%s", ifname);
         asprintf(&mParams[1], "LIFETIME=%u", lifetime);
@@ -617,11 +605,11 @@
             const char* a;
             if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) {
                 if (!strcmp(a, "add"))
-                    mAction = NlActionAdd;
+                    mAction = Action::kAdd;
                 else if (!strcmp(a, "remove"))
-                    mAction = NlActionRemove;
+                    mAction = Action::kRemove;
                 else if (!strcmp(a, "change"))
-                    mAction = NlActionChange;
+                    mAction = Action::kChange;
             } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) {
                 mSeq = atoi(a);
             } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) {
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 527a6a0..3011ed7 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -86,6 +86,7 @@
             return -1;
         }
         SLOGV("got mSock = %d for %s", mSock, mSocketName);
+        fcntl(mSock, F_SETFD, FD_CLOEXEC);
     }
 
     if (mListen && listen(mSock, backlog) < 0) {
@@ -212,6 +213,7 @@
                 sleep(1);
                 continue;
             }
+            fcntl(c, F_SETFD, FD_CLOEXEC);
             pthread_mutex_lock(&mClientsLock);
             mClients->push_back(new SocketClient(c, true, mUseCmdNum));
             pthread_mutex_unlock(&mClientsLock);
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index 684f401..40b8b9f 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -498,6 +498,12 @@
     return usb_device_get_string(device, desc->iProduct);
 }
 
+int usb_device_get_version(struct usb_device *device)
+{
+    struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
+    return desc->bcdUSB;
+}
+
 char* usb_device_get_serial(struct usb_device *device)
 {
     struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
diff --git a/libutils/Android.mk b/libutils/Android.mk
index e9c5f89..f675a94 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -20,7 +20,6 @@
 	CallStack.cpp \
 	FileMap.cpp \
 	JenkinsHash.cpp \
-	LinearAllocator.cpp \
 	LinearTransform.cpp \
 	Log.cpp \
 	NativeHandle.cpp \
diff --git a/libutils/LinearAllocator.cpp b/libutils/LinearAllocator.cpp
deleted file mode 100644
index 8b90696..0000000
--- a/libutils/LinearAllocator.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * 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 ``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.
- */
-
-#define LOG_TAG "LinearAllocator"
-#define LOG_NDEBUG 1
-
-#include <stdlib.h>
-#include <utils/LinearAllocator.h>
-#include <utils/Log.h>
-
-
-// The ideal size of a page allocation (these need to be multiples of 8)
-#define INITIAL_PAGE_SIZE ((size_t)4096) // 4kb
-#define MAX_PAGE_SIZE ((size_t)131072) // 128kb
-
-// The maximum amount of wasted space we can have per page
-// Allocations exceeding this will have their own dedicated page
-// If this is too low, we will malloc too much
-// Too high, and we may waste too much space
-// Must be smaller than INITIAL_PAGE_SIZE
-#define MAX_WASTE_SIZE ((size_t)1024)
-
-#if ALIGN_DOUBLE
-#define ALIGN_SZ (sizeof(double))
-#else
-#define ALIGN_SZ (sizeof(int))
-#endif
-
-#define ALIGN(x) ((x + ALIGN_SZ - 1 ) & ~(ALIGN_SZ - 1))
-#define ALIGN_PTR(p) ((void*)(ALIGN((size_t)p)))
-
-#if LOG_NDEBUG
-#define ADD_ALLOCATION(size)
-#define RM_ALLOCATION(size)
-#else
-#include <utils/Thread.h>
-#include <utils/Timers.h>
-static size_t s_totalAllocations = 0;
-static nsecs_t s_nextLog = 0;
-static android::Mutex s_mutex;
-
-static void _logUsageLocked() {
-    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    if (now > s_nextLog) {
-        s_nextLog = now + milliseconds_to_nanoseconds(10);
-        ALOGV("Total memory usage: %zu kb", s_totalAllocations / 1024);
-    }
-}
-
-static void _addAllocation(size_t size) {
-    android::AutoMutex lock(s_mutex);
-    s_totalAllocations += size;
-    _logUsageLocked();
-}
-
-#define ADD_ALLOCATION(size) _addAllocation(size);
-#define RM_ALLOCATION(size) _addAllocation(-size);
-#endif
-
-#define min(x,y) (((x) < (y)) ? (x) : (y))
-
-namespace android {
-
-class LinearAllocator::Page {
-public:
-    Page* next() { return mNextPage; }
-    void setNext(Page* next) { mNextPage = next; }
-
-    Page()
-        : mNextPage(0)
-    {}
-
-    void* operator new(size_t /*size*/, void* buf) { return buf; }
-
-    void* start() {
-        return (void*) (((size_t)this) + sizeof(Page));
-    }
-
-    void* end(int pageSize) {
-        return (void*) (((size_t)start()) + pageSize);
-    }
-
-private:
-    Page(const Page& /*other*/) {}
-    Page* mNextPage;
-};
-
-LinearAllocator::LinearAllocator()
-    : mPageSize(INITIAL_PAGE_SIZE)
-    , mMaxAllocSize(MAX_WASTE_SIZE)
-    , mNext(0)
-    , mCurrentPage(0)
-    , mPages(0)
-    , mTotalAllocated(0)
-    , mWastedSpace(0)
-    , mPageCount(0)
-    , mDedicatedPageCount(0) {}
-
-LinearAllocator::~LinearAllocator(void) {
-    Page* p = mPages;
-    while (p) {
-        Page* next = p->next();
-        p->~Page();
-        free(p);
-        RM_ALLOCATION(mPageSize);
-        p = next;
-    }
-}
-
-void* LinearAllocator::start(Page* p) {
-    return ALIGN_PTR(((size_t*)p) + sizeof(Page));
-}
-
-void* LinearAllocator::end(Page* p) {
-    return ((char*)p) + mPageSize;
-}
-
-bool LinearAllocator::fitsInCurrentPage(size_t size) {
-    return mNext && ((char*)mNext + size) <= end(mCurrentPage);
-}
-
-void LinearAllocator::ensureNext(size_t size) {
-    if (fitsInCurrentPage(size)) return;
-
-    if (mCurrentPage && mPageSize < MAX_PAGE_SIZE) {
-        mPageSize = min(MAX_PAGE_SIZE, mPageSize * 2);
-        mPageSize = ALIGN(mPageSize);
-    }
-    mWastedSpace += mPageSize;
-    Page* p = newPage(mPageSize);
-    if (mCurrentPage) {
-        mCurrentPage->setNext(p);
-    }
-    mCurrentPage = p;
-    if (!mPages) {
-        mPages = mCurrentPage;
-    }
-    mNext = start(mCurrentPage);
-}
-
-void* LinearAllocator::alloc(size_t size) {
-    size = ALIGN(size);
-    if (size > mMaxAllocSize && !fitsInCurrentPage(size)) {
-        ALOGV("Exceeded max size %zu > %zu", size, mMaxAllocSize);
-        // Allocation is too large, create a dedicated page for the allocation
-        Page* page = newPage(size);
-        mDedicatedPageCount++;
-        page->setNext(mPages);
-        mPages = page;
-        if (!mCurrentPage)
-            mCurrentPage = mPages;
-        return start(page);
-    }
-    ensureNext(size);
-    void* ptr = mNext;
-    mNext = ((char*)mNext) + size;
-    mWastedSpace -= size;
-    return ptr;
-}
-
-void LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize) {
-    // Don't bother rewinding across pages
-    allocSize = ALIGN(allocSize);
-    if (ptr >= start(mCurrentPage) && ptr < end(mCurrentPage)
-            && ptr == ((char*)mNext - allocSize)) {
-        mTotalAllocated -= allocSize;
-        mWastedSpace += allocSize;
-        mNext = ptr;
-    }
-}
-
-LinearAllocator::Page* LinearAllocator::newPage(size_t pageSize) {
-    pageSize = ALIGN(pageSize + sizeof(LinearAllocator::Page));
-    ADD_ALLOCATION(pageSize);
-    mTotalAllocated += pageSize;
-    mPageCount++;
-    void* buf = malloc(pageSize);
-    return new (buf) Page();
-}
-
-static const char* toSize(size_t value, float& result) {
-    if (value < 2000) {
-        result = value;
-        return "B";
-    }
-    if (value < 2000000) {
-        result = value / 1024.0f;
-        return "KB";
-    }
-    result = value / 1048576.0f;
-    return "MB";
-}
-
-void LinearAllocator::dumpMemoryStats(const char* prefix) {
-    float prettySize;
-    const char* prettySuffix;
-    prettySuffix = toSize(mTotalAllocated, prettySize);
-    ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix);
-    prettySuffix = toSize(mWastedSpace, prettySize);
-    ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix,
-          (float) mWastedSpace / (float) mTotalAllocated * 100.0f);
-    ALOGD("%sPages %zu (dedicated %zu)", prefix, mPageCount, mDedicatedPageCount);
-}
-
-}; // namespace android
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 9a2dd6c..e69784d 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -20,6 +20,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <inttypes.h>
+#include <sys/eventfd.h>
 
 
 namespace android {
@@ -68,41 +70,20 @@
 
 Looper::Looper(bool allowNonCallbacks) :
         mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
-        mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
-    int wakeFds[2];
-    int result = pipe(wakeFds);
-    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
+        mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
+        mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
+    mWakeEventFd = eventfd(0, EFD_NONBLOCK);
+    LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd.  errno=%d", errno);
 
-    mWakeReadPipeFd = wakeFds[0];
-    mWakeWritePipeFd = wakeFds[1];
-
-    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
-    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
-            errno);
-
-    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
-    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
-            errno);
-
-    mIdling = false;
-
-    // Allocate the epoll instance and register the wake pipe.
-    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
-    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
-
-    struct epoll_event eventItem;
-    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
-    eventItem.events = EPOLLIN;
-    eventItem.data.fd = mWakeReadPipeFd;
-    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
-    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
-            errno);
+    AutoMutex _l(mLock);
+    rebuildEpollLocked();
 }
 
 Looper::~Looper() {
-    close(mWakeReadPipeFd);
-    close(mWakeWritePipeFd);
-    close(mEpollFd);
+    close(mWakeEventFd);
+    if (mEpollFd >= 0) {
+        close(mEpollFd);
+    }
 }
 
 void Looper::initTLSKey() {
@@ -156,6 +137,50 @@
     return mAllowNonCallbacks;
 }
 
+void Looper::rebuildEpollLocked() {
+    // Close old epoll instance if we have one.
+    if (mEpollFd >= 0) {
+#if DEBUG_CALLBACKS
+        ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
+#endif
+        close(mEpollFd);
+    }
+
+    // Allocate the new epoll instance and register the wake pipe.
+    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
+    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
+
+    struct epoll_event eventItem;
+    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+    eventItem.events = EPOLLIN;
+    eventItem.data.fd = mWakeEventFd;
+    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance.  errno=%d",
+            errno);
+
+    for (size_t i = 0; i < mRequests.size(); i++) {
+        const Request& request = mRequests.valueAt(i);
+        struct epoll_event eventItem;
+        request.initEventItem(&eventItem);
+
+        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
+        if (epollResult < 0) {
+            ALOGE("Error adding epoll events for fd %d while rebuilding epoll set, errno=%d",
+                    request.fd, errno);
+        }
+    }
+}
+
+void Looper::scheduleEpollRebuildLocked() {
+    if (!mEpollRebuildRequired) {
+#if DEBUG_CALLBACKS
+        ALOGD("%p ~ scheduleEpollRebuildLocked - scheduling epoll set rebuild", this);
+#endif
+        mEpollRebuildRequired = true;
+        wake();
+    }
+}
+
 int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
     int result = 0;
     for (;;) {
@@ -206,7 +231,7 @@
             timeoutMillis = messageTimeoutMillis;
         }
 #if DEBUG_POLL_AND_WAKE
-        ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
+        ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d",
                 this, mNextMessageUptime - now, timeoutMillis);
 #endif
     }
@@ -217,17 +242,24 @@
     mResponseIndex = 0;
 
     // We are about to idle.
-    mIdling = true;
+    mPolling = true;
 
     struct epoll_event eventItems[EPOLL_MAX_EVENTS];
     int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
 
     // No longer idling.
-    mIdling = false;
+    mPolling = false;
 
     // Acquire lock.
     mLock.lock();
 
+    // Rebuild epoll set if needed.
+    if (mEpollRebuildRequired) {
+        mEpollRebuildRequired = false;
+        rebuildEpollLocked();
+        goto Done;
+    }
+
     // Check for poll error.
     if (eventCount < 0) {
         if (errno == EINTR) {
@@ -255,11 +287,11 @@
     for (int i = 0; i < eventCount; i++) {
         int fd = eventItems[i].data.fd;
         uint32_t epollEvents = eventItems[i].events;
-        if (fd == mWakeReadPipeFd) {
+        if (fd == mWakeEventFd) {
             if (epollEvents & EPOLLIN) {
                 awoken();
             } else {
-                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
+                ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
             }
         } else {
             ssize_t requestIndex = mRequests.indexOfKey(fd);
@@ -326,10 +358,14 @@
             ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
                     this, response.request.callback.get(), fd, events, data);
 #endif
+            // Invoke the callback.  Note that the file descriptor may be closed by
+            // the callback (and potentially even reused) before the function returns so
+            // we need to be a little careful when removing the file descriptor afterwards.
             int callbackResult = response.request.callback->handleEvent(fd, events, data);
             if (callbackResult == 0) {
-                removeFd(fd);
+                removeFd(fd, response.request.seq);
             }
+
             // Clear the callback reference in the response structure promptly because we
             // will not clear the response vector itself until the next poll.
             response.request.callback.clear();
@@ -370,12 +406,9 @@
     ALOGD("%p ~ wake", this);
 #endif
 
-    ssize_t nWrite;
-    do {
-        nWrite = write(mWakeWritePipeFd, "W", 1);
-    } while (nWrite == -1 && errno == EINTR);
-
-    if (nWrite != 1) {
+    uint64_t inc = 1;
+    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, errno=%d", errno);
         }
@@ -387,11 +420,8 @@
     ALOGD("%p ~ awoken", this);
 #endif
 
-    char buffer[16];
-    ssize_t nRead;
-    do {
-        nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
-    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
+    uint64_t counter;
+    TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t)));
 }
 
 void Looper::pushResponse(int events, const Request& request) {
@@ -425,23 +455,20 @@
         ident = POLL_CALLBACK;
     }
 
-    int epollEvents = 0;
-    if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
-    if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
-
     { // acquire lock
         AutoMutex _l(mLock);
 
         Request request;
         request.fd = fd;
         request.ident = ident;
+        request.events = events;
+        request.seq = mNextRequestSeq++;
         request.callback = callback;
         request.data = data;
+        if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
 
         struct epoll_event eventItem;
-        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
-        eventItem.events = epollEvents;
-        eventItem.data.fd = fd;
+        request.initEventItem(&eventItem);
 
         ssize_t requestIndex = mRequests.indexOfKey(fd);
         if (requestIndex < 0) {
@@ -454,8 +481,36 @@
         } else {
             int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
             if (epollResult < 0) {
-                ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
-                return -1;
+                if (errno == ENOENT) {
+                    // Tolerate ENOENT because it means that an older file descriptor was
+                    // closed before its callback was unregistered and meanwhile a new
+                    // file descriptor with the same number has been created and is now
+                    // being registered for the first time.  This error may occur naturally
+                    // when a callback has the side-effect of closing the file descriptor
+                    // before returning and unregistering itself.  Callback sequence number
+                    // checks further ensure that the race is benign.
+                    //
+                    // Unfortunately due to kernel limitations we need to rebuild the epoll
+                    // set from scratch because it may contain an old file handle that we are
+                    // now unable to remove since its file descriptor is no longer valid.
+                    // No such problem would have occurred if we were using the poll system
+                    // call instead, but that approach carries others disadvantages.
+#if DEBUG_CALLBACKS
+                    ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor "
+                            "being recycled, falling back on EPOLL_CTL_ADD, errno=%d",
+                            this, errno);
+#endif
+                    epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
+                    if (epollResult < 0) {
+                        ALOGE("Error modifying or adding epoll events for fd %d, errno=%d",
+                                fd, errno);
+                        return -1;
+                    }
+                    scheduleEpollRebuildLocked();
+                } else {
+                    ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
+                    return -1;
+                }
             }
             mRequests.replaceValueAt(requestIndex, request);
         }
@@ -464,8 +519,12 @@
 }
 
 int Looper::removeFd(int fd) {
+    return removeFd(fd, -1);
+}
+
+int Looper::removeFd(int fd, int seq) {
 #if DEBUG_CALLBACKS
-    ALOGD("%p ~ removeFd - fd=%d", this, fd);
+    ALOGD("%p ~ removeFd - fd=%d, seq=%d", this, fd, seq);
 #endif
 
     { // acquire lock
@@ -475,13 +534,43 @@
             return 0;
         }
 
-        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
-        if (epollResult < 0) {
-            ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
-            return -1;
+        // Check the sequence number if one was given.
+        if (seq != -1 && mRequests.valueAt(requestIndex).seq != seq) {
+#if DEBUG_CALLBACKS
+            ALOGD("%p ~ removeFd - sequence number mismatch, oldSeq=%d",
+                    this, mRequests.valueAt(requestIndex).seq);
+#endif
+            return 0;
         }
 
+        // Always remove the FD from the request map even if an error occurs while
+        // updating the epoll set so that we avoid accidentally leaking callbacks.
         mRequests.removeItemsAt(requestIndex);
+
+        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
+        if (epollResult < 0) {
+            if (seq != -1 && (errno == EBADF || errno == ENOENT)) {
+                // Tolerate EBADF or ENOENT when the sequence number is known because it
+                // means that the file descriptor was closed before its callback was
+                // unregistered.  This error may occur naturally when a callback has the
+                // side-effect of closing the file descriptor before returning and
+                // unregistering itself.
+                //
+                // Unfortunately due to kernel limitations we need to rebuild the epoll
+                // set from scratch because it may contain an old file handle that we are
+                // now unable to remove since its file descriptor is no longer valid.
+                // No such problem would have occurred if we were using the poll system
+                // call instead, but that approach carries others disadvantages.
+#if DEBUG_CALLBACKS
+                ALOGD("%p ~ removeFd - EPOLL_CTL_DEL failed due to file descriptor "
+                        "being closed, errno=%d", this, errno);
+#endif
+                scheduleEpollRebuildLocked();
+            } else {
+                ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
+                return -1;
+            }
+        }
     } // release lock
     return 1;
 }
@@ -500,7 +589,7 @@
 void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
         const Message& message) {
 #if DEBUG_CALLBACKS
-    ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
+    ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d",
             this, uptime, handler.get(), message.what);
 #endif
 
@@ -566,8 +655,18 @@
     } // release lock
 }
 
-bool Looper::isIdling() const {
-    return mIdling;
+bool Looper::isPolling() const {
+    return mPolling;
+}
+
+void Looper::Request::initEventItem(struct epoll_event* eventItem) const {
+    int epollEvents = 0;
+    if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
+    if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
+
+    memset(eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+    eventItem->events = epollEvents;
+    eventItem->data.fd = fd;
 }
 
 } // namespace android
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..b6c6196 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -25,18 +25,25 @@
 #include <log/log.h>
 #include <log/log_read.h>
 
+// Hijack this header as a common include file used by most all sources
+// to report some utilities defined here and there.
+
 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 +59,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 +86,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..10f7255 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");
@@ -70,21 +70,7 @@
     mSizes[log_id] += size;
     ++mElements[log_id];
 
-    uid_t uid = e->getUid();
-    unsigned short dropped = e->getDropped();
-    android::hash_t hash = android::hash_type(uid);
-    uidTable_t &table = uidTable[log_id];
-    ssize_t index = table.find(-1, hash, uid);
-    if (index == -1) {
-        UidEntry initEntry(uid);
-        initEntry.add(size);
-        initEntry.add_dropped(dropped);
-        table.add(hash, initEntry);
-    } else {
-        UidEntry &entry = table.editEntryAt(index);
-        entry.add(size);
-        entry.add_dropped(dropped);
-    }
+    uidTable[log_id].add(e->getUid(), e);
 
     mSizesTotal[log_id] += size;
     ++mElementsTotal[log_id];
@@ -93,28 +79,7 @@
         return;
     }
 
-    pid_t pid = e->getPid();
-    hash = android::hash_type(pid);
-    index = pidTable.find(-1, hash, pid);
-    if (index == -1) {
-        PidEntry initEntry(pid, uid, android::pidToName(pid));
-        initEntry.add(size);
-        initEntry.add_dropped(dropped);
-        pidTable.add(hash, initEntry);
-    } else {
-        PidEntry &entry = pidTable.editEntryAt(index);
-        if (entry.getUid() != uid) {
-            entry.setUid(uid);
-            entry.setName(android::pidToName(pid));
-        } else if (!entry.getName()) {
-            char *name = android::pidToName(pid);
-            if (name) {
-                entry.setName(name);
-            }
-        }
-        entry.add(size);
-        entry.add_dropped(dropped);
-    }
+    pidTable.add(e->getPid(), e);
 }
 
 void LogStatistics::subtract(LogBufferElement *e) {
@@ -123,31 +88,13 @@
     mSizes[log_id] -= size;
     --mElements[log_id];
 
-    uid_t uid = e->getUid();
-    unsigned short dropped = e->getDropped();
-    android::hash_t hash = android::hash_type(uid);
-    uidTable_t &table = uidTable[log_id];
-    ssize_t index = table.find(-1, hash, uid);
-    if (index != -1) {
-        UidEntry &entry = table.editEntryAt(index);
-        if (entry.subtract(size) || entry.subtract_dropped(dropped)) {
-            table.removeAt(index);
-        }
-    }
+    uidTable[log_id].subtract(e->getUid(), e);
 
     if (!enable) {
         return;
     }
 
-    pid_t pid = e->getPid();
-    hash = android::hash_type(pid);
-    index = pidTable.find(-1, hash, pid);
-    if (index != -1) {
-        PidEntry &entry = pidTable.editEntryAt(index);
-        if (entry.subtract(size) || entry.subtract_dropped(dropped)) {
-            pidTable.removeAt(index);
-        }
-    }
+    pidTable.subtract(e->getPid(), e);
 }
 
 // Atomically set an entry to drop
@@ -157,28 +104,13 @@
     unsigned short size = e->getMsgLen();
     mSizes[log_id] -= size;
 
-    uid_t uid = e->getUid();
-    android::hash_t hash = android::hash_type(uid);
-    typeof uidTable[0] &table = uidTable[log_id];
-    ssize_t index = table.find(-1, hash, uid);
-    if (index != -1) {
-        UidEntry &entry = table.editEntryAt(index);
-        entry.subtract(size);
-        entry.add_dropped(1);
-    }
+    uidTable[log_id].drop(e->getUid(), e);
 
     if (!enable) {
         return;
     }
 
-    pid_t pid = e->getPid();
-    hash = android::hash_type(pid);
-    index = pidTable.find(-1, hash, pid);
-    if (index != -1) {
-        PidEntry &entry = pidTable.editEntryAt(index);
-        entry.subtract(size);
-        entry.add_dropped(1);
-    }
+    pidTable.drop(e->getPid(), e);
 }
 
 // caller must own and free character string
@@ -379,6 +311,7 @@
     }
 
     if (enable) {
+        // Pid table
         bool headerPrinted = false;
         std::unique_ptr<const PidEntry *[]> sorted = pidTable.sort(maximum_sorted_entries);
         ssize_t index = -1;
@@ -460,48 +393,14 @@
 }
 
 uid_t LogStatistics::pidToUid(pid_t pid) {
-    uid_t uid;
-    android::hash_t hash = android::hash_type(pid);
-    ssize_t index = pidTable.find(-1, hash, pid);
-    if (index == -1) {
-        uid = android::pidToUid(pid);
-        PidEntry initEntry(pid, uid, android::pidToName(pid));
-        pidTable.add(hash, initEntry);
-    } else {
-        PidEntry &entry = pidTable.editEntryAt(index);
-        if (!entry.getName()) {
-            char *name = android::pidToName(pid);
-            if (name) {
-                entry.setName(name);
-            }
-        }
-        uid = entry.getUid();
-    }
-    return uid;
+    return pidTable.entryAt(pidTable.add(pid)).getUid();
 }
 
 // caller must free character string
 char *LogStatistics::pidToName(pid_t pid) {
-    char *name;
-
-    android::hash_t hash = android::hash_type(pid);
-    ssize_t index = pidTable.find(-1, hash, pid);
-    if (index == -1) {
-        name = android::pidToName(pid);
-        PidEntry initEntry(pid, android::pidToUid(pid), name ? strdup(name) : NULL);
-        pidTable.add(hash, initEntry);
-    } else {
-        PidEntry &entry = pidTable.editEntryAt(index);
-        const char *n = entry.getName();
-        if (n) {
-            name = strdup(n);
-        } else {
-            name = android::pidToName(pid);
-            if (name) {
-                entry.setName(strdup(name));
-            }
-        }
+    const char *name = pidTable.entryAt(pidTable.add(pid)).getName();
+    if (!name) {
+        return NULL;
     }
-
-    return name;
+    return strdup(name);
 }
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index f3110d7..a935c27 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -73,52 +73,139 @@
     ssize_t next(ssize_t index) {
         return android::BasicHashtable<TKey, TEntry>::next(index);
     }
+
+    size_t add(TKey key, LogBufferElement *e) {
+        android::hash_t hash = android::hash_type(key);
+        ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, hash, key);
+        if (index == -1) {
+            return android::BasicHashtable<TKey, TEntry>::add(hash, TEntry(e));
+        }
+        android::BasicHashtable<TKey, TEntry>::editEntryAt(index).add(e);
+        return index;
+    }
+
+    inline size_t add(TKey key) {
+        android::hash_t hash = android::hash_type(key);
+        ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, hash, key);
+        if (index == -1) {
+            return android::BasicHashtable<TKey, TEntry>::add(hash, TEntry(key));
+        }
+        android::BasicHashtable<TKey, TEntry>::editEntryAt(index).add(key);
+        return index;
+    }
+
+    void subtract(TKey key, LogBufferElement *e) {
+        ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, android::hash_type(key), key);
+        if ((index != -1)
+         && android::BasicHashtable<TKey, TEntry>::editEntryAt(index).subtract(e)) {
+            android::BasicHashtable<TKey, TEntry>::removeAt(index);
+        }
+    }
+
+    inline void drop(TKey key, LogBufferElement *e) {
+        ssize_t index = android::BasicHashtable<TKey, TEntry>::find(-1, android::hash_type(key), key);
+        if (index != -1) {
+            android::BasicHashtable<TKey, TEntry>::editEntryAt(index).drop(e);
+        }
+    }
+
 };
 
-struct UidEntry {
-    const uid_t uid;
+struct EntryBase {
     size_t size;
+
+    EntryBase():size(0) { }
+    EntryBase(LogBufferElement *e):size(e->getMsgLen()) { }
+
+    size_t getSizes() const { return size; }
+
+    inline void add(LogBufferElement *e) { size += e->getMsgLen(); }
+    inline bool subtract(LogBufferElement *e) { size -= e->getMsgLen(); return !size; }
+};
+
+struct EntryBaseDropped : public EntryBase {
     size_t dropped;
 
-    UidEntry(uid_t uid):uid(uid),size(0),dropped(0) { }
+    EntryBaseDropped():dropped(0) { }
+    EntryBaseDropped(LogBufferElement *e):EntryBase(e),dropped(e->getDropped()){ }
 
-    inline const uid_t&getKey() const { return uid; }
-    size_t getSizes() const { return size; }
     size_t getDropped() const { return dropped; }
 
-    inline void add(size_t s) { size += s; }
-    inline void add_dropped(size_t d) { dropped += d; }
-    inline bool subtract(size_t s) { size -= s; return !dropped && !size; }
-    inline bool subtract_dropped(size_t d) { dropped -= d; return !dropped && !size; }
+    inline void add(LogBufferElement *e) {
+        dropped += e->getDropped();
+        EntryBase::add(e);
+    }
+    inline bool subtract(LogBufferElement *e) {
+        dropped -= e->getDropped();
+        return EntryBase::subtract(e) && !dropped;
+    }
+    inline void drop(LogBufferElement *e) {
+        dropped += 1;
+        EntryBase::subtract(e);
+    }
 };
 
-struct PidEntry {
+struct UidEntry : public EntryBaseDropped {
+    const uid_t uid;
+
+    UidEntry(LogBufferElement *e):EntryBaseDropped(e),uid(e->getUid()) { }
+
+    inline const uid_t&getKey() const { return uid; }
+};
+
+namespace android {
+// caller must own and free character string
+char *pidToName(pid_t pid);
+uid_t pidToUid(pid_t pid);
+}
+
+struct PidEntry : public EntryBaseDropped {
     const pid_t pid;
     uid_t uid;
     char *name;
-    size_t size;
-    size_t dropped;
 
-    PidEntry(pid_t p, uid_t u, char *n):pid(p),uid(u),name(n),size(0),dropped(0) { }
+    PidEntry(pid_t p):
+        EntryBaseDropped(),
+        pid(p),
+        uid(android::pidToUid(p)),
+        name(android::pidToName(pid)) { }
+    PidEntry(LogBufferElement *e):
+        EntryBaseDropped(e),
+        pid(e->getPid()),
+        uid(e->getUid()),
+        name(android::pidToName(e->getPid())) { }
     PidEntry(const PidEntry &c):
+        EntryBaseDropped(c),
         pid(c.pid),
         uid(c.uid),
-        name(c.name ? strdup(c.name) : NULL),
-        size(c.size),
-        dropped(c.dropped) { }
+        name(c.name ? strdup(c.name) : NULL) { }
     ~PidEntry() { free(name); }
 
     const pid_t&getKey() const { return pid; }
     const uid_t&getUid() const { return uid; }
-    uid_t&setUid(uid_t u) { return uid = u; }
     const char*getName() const { return name; }
-    char *setName(char *n) { free(name); return name = n; }
-    size_t getSizes() const { return size; }
-    size_t getDropped() const { return dropped; }
-    inline void add(size_t s) { size += s; }
-    inline void add_dropped(size_t d) { dropped += d; }
-    inline bool subtract(size_t s) { size -= s; return !dropped && !size; }
-    inline bool subtract_dropped(size_t d) { dropped -= d; return !dropped && !size; }
+
+    inline void add(pid_t p) {
+        if (!name) {
+            char *n = android::pidToName(p);
+            if (n) {
+                name = n;
+            }
+        }
+    }
+
+    inline void add(LogBufferElement *e) {
+        uid_t u = e->getUid();
+        if (getUid() != u) {
+            uid = u;
+            free(name);
+            name = android::pidToName(e->getPid());
+        } else {
+            add(e->getPid());
+        }
+        EntryBaseDropped::add(e);
+    }
+
 };
 
 // Log Statistics
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;
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 3a6276e..83576fb 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -325,7 +325,7 @@
 
     if (log_target & LOG_KLOG) {
         snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
-                 "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag);
+                 "<6>%.*s: %%s\n", MAX_KLOG_TAG, log_info.btag);
     }
 
     if ((log_target & LOG_FILE) && !file_path) {
diff --git a/mkbootimg/mkbootimg.c b/mkbootimg/mkbootimg.c
index fc92b4d..a4ab7e1 100644
--- a/mkbootimg/mkbootimg.c
+++ b/mkbootimg/mkbootimg.c
@@ -59,7 +59,7 @@
 {
     fprintf(stderr,"usage: mkbootimg\n"
             "       --kernel <filename>\n"
-            "       --ramdisk <filename>\n"
+            "       [ --ramdisk <filename> ]\n"
             "       [ --second <2ndbootloader-filename> ]\n"
             "       [ --cmdline <kernel-commandline> ]\n"
             "       [ --board <boardname> ]\n"
@@ -179,11 +179,6 @@
         return usage();
     }
 
-    if(ramdisk_fn == 0) {
-        fprintf(stderr,"error: no ramdisk image specified\n");
-        return usage();
-    }
-
     if(strlen(board) >= BOOT_NAME_SIZE) {
         fprintf(stderr,"error: board name too large\n");
         return usage();
@@ -213,7 +208,7 @@
         return 1;
     }
 
-    if(!strcmp(ramdisk_fn,"NONE")) {
+    if(ramdisk_fn == 0) {
         ramdisk_data = 0;
         hdr.ramdisk_size = 0;
     } else {
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 3ecb1db..7ab76b8 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -26,7 +26,7 @@
 #
 # create some directories (some are mount points)
 LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
-    sbin dev proc sys system data)
+    sbin dev proc sys system data oem)
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 0064790..b34ea01 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -5,7 +5,7 @@
     export ANDROID_ASSETS /system/app
     export ANDROID_DATA /data
     export ANDROID_STORAGE /storage
+    export EXTERNAL_STORAGE /sdcard
     export ASEC_MOUNTPOINT /mnt/asec
-    export LOOP_MOUNTPOINT /mnt/obb
     export BOOTCLASSPATH %BOOTCLASSPATH%
     export SYSTEMSERVERCLASSPATH %SYSTEMSERVERCLASSPATH%
diff --git a/rootdir/init.rc b/rootdir/init.rc
index c00c590..d44f98b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -19,9 +19,6 @@
 
     start ueventd
 
-    # create mountpoints
-    mkdir /mnt 0775 root system
-
 on init
     sysclktz 0
 
@@ -55,28 +52,30 @@
     mkdir /cache 0770 system cache
     mkdir /config 0500 root root
 
+    # Mount staging areas for devices managed by vold
     # See storage config details at http://source.android.com/tech/storage/
-    mkdir /mnt/shell 0700 shell shell
-    mkdir /mnt/media_rw 0700 media_rw media_rw
-    mkdir /storage 0751 root sdcard_r
+    mkdir /mnt 0755 root system
+    mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=1000
+    restorecon_recursive /mnt
 
-    # Directory for putting things only root should see.
     mkdir /mnt/secure 0700 root root
+    mkdir /mnt/secure/asec 0700 root root
+    mkdir /mnt/asec 0755 root system
+    mkdir /mnt/obb 0755 root system
+    mkdir /mnt/media_rw 0750 root media_rw
+    mkdir /mnt/user 0755 root root
+    mkdir /mnt/user/0 0755 root root
+    mkdir /mnt/expand 0771 system system
 
-    # Directory for staging bindmounts
-    mkdir /mnt/secure/staging 0700 root root
+    # sdcard_r is GID 1028
+    mkdir /storage 0751 root sdcard_r
+    mount tmpfs tmpfs /storage mode=0751,uid=0,gid=1028
+    restorecon_recursive /storage
 
-    # Directory-target for where the secure container
-    # imagefile directory will be bind-mounted
-    mkdir /mnt/secure/asec  0700 root root
-
-    # Secure container public mount points.
-    mkdir /mnt/asec  0700 root system
-    mount tmpfs tmpfs /mnt/asec mode=0755,gid=1000
-
-    # Filesystem image public mount points.
-    mkdir /mnt/obb 0700 root system
-    mount tmpfs tmpfs /mnt/obb mode=0755,gid=1000
+    # Symlink to keep legacy apps working in multi-user world
+    mkdir /storage/self 0751 root sdcard_r
+    symlink /storage/self/primary /sdcard
+    symlink /mnt/user/0/primary /storage/self/primary
 
     # memory control cgroup
     mkdir /dev/memcg 0700 root system
@@ -104,6 +103,10 @@
     # set fwmark on accepted sockets
     write /proc/sys/net/ipv4/tcp_fwmark_accept 1
 
+    # disable icmp redirects
+    write /proc/sys/net/ipv4/conf/all/accept_redirects 0
+    write /proc/sys/net/ipv6/conf/all/accept_redirects 0
+
     # Create cgroup mount points for process groups
     mkdir /dev/cpuctl
     mount cgroup none /dev/cpuctl cpu
@@ -228,6 +231,9 @@
     # We restorecon /data in case the userdata partition has been reset.
     restorecon /data
 
+    # Emulated internal storage area
+    mkdir /data/media 0770 media_rw media_rw
+
     # Start bootcharting as soon as possible after the data partition is
     # mounted to collect more data.
     mkdir /data/bootchart 0755 shell shell
@@ -257,10 +263,12 @@
     mkdir /data/misc/ethernet 0770 system system
     mkdir /data/misc/dhcp 0770 dhcp dhcp
     mkdir /data/misc/user 0771 root root
+    mkdir /data/misc/perfprofd 0775 root root
     # give system access to wpa_supplicant.conf for backup and restore
     chmod 0660 /data/misc/wifi/wpa_supplicant.conf
     mkdir /data/local 0751 root root
     mkdir /data/misc/media 0700 media media
+    mkdir /data/misc/vold 0700 root root
 
     # For security reasons, /data/local/tmp should always be empty.
     # Do not place files or directories in /data/local/tmp
@@ -340,9 +348,9 @@
     write /proc/sys/vm/overcommit_memory 1
     write /proc/sys/vm/min_free_order_shift 4
     chown root system /sys/module/lowmemorykiller/parameters/adj
-    chmod 0220 /sys/module/lowmemorykiller/parameters/adj
+    chmod 0664 /sys/module/lowmemorykiller/parameters/adj
     chown root system /sys/module/lowmemorykiller/parameters/minfree
-    chmod 0220 /sys/module/lowmemorykiller/parameters/minfree
+    chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
 
     # Tweak background writeout
     write /proc/sys/vm/dirty_expire_centisecs 200
@@ -531,7 +539,9 @@
     onrestart restart surfaceflinger
     onrestart restart drm
 
-service vold /system/bin/vold
+service vold /system/bin/vold \
+        --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
+        --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
     class core
     socket vold stream 0660 root mount
     ioprio be 2
@@ -552,6 +562,7 @@
 service ril-daemon /system/bin/rild
     class main
     socket rild stream 660 root radio
+    socket sap_uim_socket1 stream 660 bluetooth bluetooth
     socket rild-debug stream 660 radio system
     user root
     group radio cache inet misc audio log
@@ -594,6 +605,10 @@
     disabled
     oneshot
 
+service gatekeeperd /system/bin/gatekeeperd /data/misc/gatekeeper
+    class main
+    user system
+
 service installd /system/bin/installd
     class main
     socket installd stream 600 system system
@@ -641,3 +656,11 @@
     class main
     disabled
     oneshot
+
+on property:ro.debuggable=1
+    start perfprofd
+
+service perfprofd /system/xbin/perfprofd
+    disabled
+    user root
+    oneshot
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 893c0dc..f8b23a3 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -146,8 +146,6 @@
     PERM_ANDROID_OBB,
     /* This node is "/Android/media" */
     PERM_ANDROID_MEDIA,
-    /* This node is "/Android/user" */
-    PERM_ANDROID_USER,
 } perm_t;
 
 /* Permissions structure to derive */
@@ -252,7 +250,7 @@
     __u32 inode_ctr;
 
     Hashmap* package_to_appid;
-    Hashmap* appid_with_rw;
+    Hashmap* uid_with_rw;
 };
 
 /* Private data used by a single fuse handler. */
@@ -474,6 +472,8 @@
         /* Legacy internal layout places users at top level */
         node->perm = PERM_ROOT;
         node->userid = strtoul(node->name, NULL, 10);
+        node->gid = multiuser_get_uid(node->userid, AID_SDCARD_R);
+        node->mode = 0771;
         break;
     case PERM_ROOT:
         /* Assume masked off by default. */
@@ -485,14 +485,14 @@
         } else if (fuse->split_perms) {
             if (!strcasecmp(node->name, "DCIM")
                     || !strcasecmp(node->name, "Pictures")) {
-                node->gid = AID_SDCARD_PICS;
+                node->gid = multiuser_get_uid(node->userid, AID_SDCARD_PICS);
             } else if (!strcasecmp(node->name, "Alarms")
                     || !strcasecmp(node->name, "Movies")
                     || !strcasecmp(node->name, "Music")
                     || !strcasecmp(node->name, "Notifications")
                     || !strcasecmp(node->name, "Podcasts")
                     || !strcasecmp(node->name, "Ringtones")) {
-                node->gid = AID_SDCARD_AV;
+                node->gid = multiuser_get_uid(node->userid, AID_SDCARD_AV);
             }
         }
         break;
@@ -512,13 +512,6 @@
             /* App-specific directories inside; let anyone traverse */
             node->perm = PERM_ANDROID_MEDIA;
             node->mode = 0771;
-        } else if (!strcasecmp(node->name, "user")) {
-            /* User directories must only be accessible to system, protected
-             * by sdcard_all. Zygote will bind mount the appropriate user-
-             * specific path. */
-            node->perm = PERM_ANDROID_USER;
-            node->gid = AID_SDCARD_ALL;
-            node->mode = 0770;
         }
         break;
     case PERM_ANDROID_DATA:
@@ -530,13 +523,6 @@
         }
         node->mode = 0770;
         break;
-    case PERM_ANDROID_USER:
-        /* Root of a secondary user */
-        node->perm = PERM_ROOT;
-        node->userid = strtoul(node->name, NULL, 10);
-        node->gid = AID_SDCARD_R;
-        node->mode = 0771;
-        break;
     }
 }
 
@@ -547,8 +533,7 @@
         return true;
     }
 
-    appid_t appid = multiuser_get_app_id(hdr->uid);
-    return hashmapContainsKey(fuse->appid_with_rw, (void*) (uintptr_t) appid);
+    return hashmapContainsKey(fuse->uid_with_rw, (void*) (uintptr_t) hdr->uid);
 }
 
 /* Kernel has already enforced everything we returned through
@@ -729,7 +714,7 @@
 }
 
 static void fuse_init(struct fuse *fuse, int fd, const char *source_path,
-        gid_t write_gid, derive_t derive, bool split_perms) {
+        gid_t write_gid, userid_t owner_user, derive_t derive, bool split_perms) {
     pthread_mutex_init(&fuse->lock, NULL);
 
     fuse->fd = fd;
@@ -761,10 +746,10 @@
          * places user_id at the top directory level, with the actual roots
          * just below that. Shared OBB path is also at top level. */
         fuse->root.perm = PERM_LEGACY_PRE_ROOT;
-        fuse->root.mode = 0771;
+        fuse->root.mode = 0711;
         fuse->root.gid = AID_SDCARD_R;
         fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals);
-        fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals);
+        fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals);
         snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/obb", source_path);
         fs_prepare_dir(fuse->obbpath, 0775, getuid(), getgid());
         break;
@@ -773,9 +758,10 @@
          * /Android/user and shared OBB path under /Android/obb. */
         fuse->root.perm = PERM_ROOT;
         fuse->root.mode = 0771;
-        fuse->root.gid = AID_SDCARD_R;
+        fuse->root.userid = owner_user;
+        fuse->root.gid = multiuser_get_uid(owner_user, AID_SDCARD_R);
         fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals);
-        fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals);
+        fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals);
         snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/Android/obb", source_path);
         break;
     }
@@ -1710,7 +1696,7 @@
     pthread_mutex_lock(&fuse->lock);
 
     hashmapForEach(fuse->package_to_appid, remove_str_to_int, fuse->package_to_appid);
-    hashmapForEach(fuse->appid_with_rw, remove_int_to_null, fuse->appid_with_rw);
+    hashmapForEach(fuse->uid_with_rw, remove_int_to_null, fuse->uid_with_rw);
 
     FILE* file = fopen(kPackagesListFile, "r");
     if (!file) {
@@ -1731,9 +1717,14 @@
 
             char* token = strtok(gids, ",");
             while (token != NULL) {
-                if (strtoul(token, NULL, 10) == fuse->write_gid) {
-                    hashmapPut(fuse->appid_with_rw, (void*) (uintptr_t) appid, (void*) (uintptr_t) 1);
-                    break;
+                // Current packages.list format is a bit funky; it blends per
+                // user GID membership into a single per-app line. Here we
+                // work backwards from the groups to build the per-user UIDs
+                // that have write permission.
+                gid_t gid = strtoul(token, NULL, 10);
+                if (multiuser_get_app_id(gid) == fuse->write_gid) {
+                    uid_t uid = multiuser_get_uid(multiuser_get_user_id(gid), appid);
+                    hashmapPut(fuse->uid_with_rw, (void*) (uintptr_t) uid, (void*) (uintptr_t) 1);
                 }
                 token = strtok(NULL, ",");
             }
@@ -1742,7 +1733,7 @@
 
     TRACE("read_package_list: found %zu packages, %zu with write_gid\n",
             hashmapSize(fuse->package_to_appid),
-            hashmapSize(fuse->appid_with_rw));
+            hashmapSize(fuse->uid_with_rw));
     fclose(file);
     pthread_mutex_unlock(&fuse->lock);
     return 0;
@@ -1867,7 +1858,7 @@
 }
 
 static int run(const char* source_path, const char* dest_path, uid_t uid,
-        gid_t gid, gid_t write_gid, int num_threads, derive_t derive,
+        gid_t gid, gid_t write_gid, userid_t owner_user, int num_threads, derive_t derive,
         bool split_perms) {
     int fd;
     char opts[256];
@@ -1912,7 +1903,7 @@
         goto error;
     }
 
-    fuse_init(&fuse, fd, source_path, write_gid, derive, split_perms);
+    fuse_init(&fuse, fd, source_path, write_gid, owner_user, derive, split_perms);
 
     umask(0);
     res = ignite_fuse(&fuse, num_threads);
@@ -1933,6 +1924,7 @@
     uid_t uid = 0;
     gid_t gid = 0;
     gid_t write_gid = AID_SDCARD_RW;
+    userid_t owner_user = 0;
     int num_threads = DEFAULT_NUM_THREADS;
     derive_t derive = DERIVE_NONE;
     bool split_perms = false;
@@ -1941,7 +1933,7 @@
     int fs_version;
 
     int opt;
-    while ((opt = getopt(argc, argv, "u:g:w:t:dls")) != -1) {
+    while ((opt = getopt(argc, argv, "u:g:w:o:t:dls")) != -1) {
         switch (opt) {
             case 'u':
                 uid = strtoul(optarg, NULL, 10);
@@ -1952,6 +1944,9 @@
             case 'w':
                 write_gid = strtoul(optarg, NULL, 10);
                 break;
+            case 'o':
+                owner_user = strtoul(optarg, NULL, 10);
+                break;
             case 't':
                 num_threads = strtoul(optarg, NULL, 10);
                 break;
@@ -2018,6 +2013,7 @@
         sleep(1);
     }
 
-    res = run(source_path, dest_path, uid, gid, write_gid, num_threads, derive, split_perms);
+    res = run(source_path, dest_path, uid, gid, write_gid, owner_user,
+            num_threads, derive, split_perms);
     return res < 0 ? 1 : 0;
 }