am 6ef0dfec: Merge "Add a new test to crasher to upset dlmalloc."

* commit '6ef0dfecca9fde5abe15ceea30e0615897d7b374':
  Add a new test to crasher to upset dlmalloc.
diff --git a/adb/Android.mk b/adb/Android.mk
index 6cd82ec..a803978 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -17,6 +17,7 @@
   USB_SRCS := usb_linux.c
   EXTRA_SRCS := get_my_path_linux.c
   LOCAL_LDLIBS += -lrt -ldl -lpthread
+  LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
 endif
 
 ifeq ($(HOST_OS),darwin)
diff --git a/adb/adb.c b/adb/adb.c
index cd7f16c..ec74b49 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -326,7 +326,7 @@
     send_packet(cp, t);
 }
 
-static void send_auth_request(atransport *t)
+void send_auth_request(atransport *t)
 {
     D("Calling send_auth_request\n");
     apacket *p;
@@ -407,6 +407,8 @@
         return "sideload";
     case CS_OFFLINE:
         return "offline";
+    case CS_UNAUTHORIZED:
+        return "unauthorized";
     default:
         return "unknown";
     }
@@ -536,6 +538,7 @@
 
     case A_AUTH:
         if (p->msg.arg0 == ADB_AUTH_TOKEN) {
+            t->connection_state = CS_UNAUTHORIZED;
             t->key = adb_auth_nextkey(t->key);
             if (t->key) {
                 send_auth_response(p->data, p->msg.data_length, t);
@@ -988,6 +991,33 @@
 #endif
 
 #if ADB_HOST
+
+#ifdef WORKAROUND_BUG6558362
+#include <sched.h>
+#define AFFINITY_ENVVAR "ADB_CPU_AFFINITY_BUG6558362"
+void adb_set_affinity(void)
+{
+   cpu_set_t cpu_set;
+   const char* cpunum_str = getenv(AFFINITY_ENVVAR);
+   char* strtol_res;
+   int cpu_num;
+
+   if (!cpunum_str || !*cpunum_str)
+       return;
+   cpu_num = strtol(cpunum_str, &strtol_res, 0);
+   if (*strtol_res != '\0')
+     fatal("bad number (%s) in env var %s. Expecting 0..n.\n", cpunum_str, AFFINITY_ENVVAR);
+
+   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+   D("orig cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+   CPU_ZERO(&cpu_set);
+   CPU_SET(cpu_num, &cpu_set);
+   sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
+   D("new cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
+}
+#endif
+
 int launch_server(int server_port)
 {
 #ifdef HAVE_WIN32_PROC
@@ -1158,6 +1188,32 @@
 }
 
 #if !ADB_HOST
+
+static void drop_capabilities_bounding_set_if_needed() {
+#ifdef ALLOW_ADBD_ROOT
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.debuggable", value, "");
+    if (strcmp(value, "1") == 0) {
+        return;
+    }
+#endif
+    int i;
+    for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+        if ((i == CAP_SETUID) || (i == CAP_SETGID)) {
+            // CAP_SETUID CAP_SETGID needed by /system/bin/run-as
+            continue;
+        }
+        int err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+
+        // Some kernels don't have file capabilities compiled in, and
+        // prctl(PR_CAPBSET_DROP) returns EINVAL. Don't automatically
+        // die when we see such misconfigured kernels.
+        if ((err < 0) && (errno != EINVAL)) {
+            exit(1);
+        }
+    }
+}
+
 static int should_drop_privileges() {
 #ifndef ALLOW_ADBD_ROOT
     return 1;
@@ -1212,6 +1268,10 @@
 
 #if ADB_HOST
     HOST = 1;
+
+#ifdef WORKAROUND_BUG6558362
+    if(is_daemon) adb_set_affinity();
+#endif
     usb_vendors_init();
     usb_init();
     local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
@@ -1248,6 +1308,8 @@
             exit(1);
         }
 
+        drop_capabilities_bounding_set_if_needed();
+
         /* add extra groups:
         ** AID_ADB to access the USB driver
         ** AID_LOG to read system logs (adb logcat)
diff --git a/adb/adb.h b/adb/adb.h
index 9da8af8..a01d460 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -468,6 +468,7 @@
 #define CS_RECOVERY   4
 #define CS_NOPERM     5 /* Insufficient permissions to communicate with the device */
 #define CS_SIDELOAD   6
+#define CS_UNAUTHORIZED 7
 
 extern int HOST;
 extern int SHELL_EXIT_NOTIFY_FD;
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 1fffa49..b24c674 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -20,6 +20,8 @@
 void adb_auth_init(void);
 void adb_auth_verified(atransport *t);
 
+void send_auth_request(atransport *t);
+
 /* AUTH packets first argument */
 /* Request */
 #define ADB_AUTH_TOKEN         1
@@ -36,7 +38,6 @@
 static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; }
 static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; }
 static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { }
-static inline void adb_auth_reload_keys(void) { }
 
 #else // !ADB_HOST
 
@@ -47,7 +48,6 @@
 int adb_auth_generate_token(void *token, size_t token_size);
 int adb_auth_verify(void *token, void *sig, int siglen);
 void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
-void adb_auth_reload_keys(void);
 
 #endif // ADB_HOST
 
diff --git a/adb/adb_auth_client.c b/adb/adb_auth_client.c
index 0b4913e..763b448 100644
--- a/adb/adb_auth_client.c
+++ b/adb/adb_auth_client.c
@@ -34,8 +34,6 @@
     RSAPublicKey key;
 };
 
-static struct listnode key_list;
-
 static char *key_paths[] = {
     "/adb_keys",
     "/data/misc/adb/adb_keys",
@@ -45,6 +43,10 @@
 static fdevent listener_fde;
 static int framework_fd = -1;
 
+static void usb_disconnected(void* unused, atransport* t);
+static struct adisconnect usb_disconnect = { usb_disconnected, 0, 0, 0 };
+static atransport* usb_transport;
+static bool needs_retry = false;
 
 static void read_keys(const char *file, struct listnode *list)
 {
@@ -102,18 +104,18 @@
     }
 }
 
-void adb_auth_reload_keys(void)
+static void load_keys(struct listnode *list)
 {
     char *path;
     char **paths = key_paths;
     struct stat buf;
 
-    free_keys(&key_list);
+    list_init(list);
 
     while ((path = *paths++)) {
         if (!stat(path, &buf)) {
             D("Loading keys from '%s'\n", path);
-            read_keys(path, &key_list);
+            read_keys(path, list);
         }
     }
 }
@@ -137,37 +139,50 @@
 {
     struct listnode *item;
     struct adb_public_key *key;
-    int ret;
+    struct listnode key_list;
+    int ret = 0;
 
     if (siglen != RSANUMBYTES)
         return 0;
 
+    load_keys(&key_list);
+
     list_for_each(item, &key_list) {
         key = node_to_item(item, struct adb_public_key, node);
         ret = RSA_verify(&key->key, sig, siglen, token);
         if (ret)
-            return 1;
+            break;
     }
 
-    return 0;
+    free_keys(&key_list);
+
+    return ret;
+}
+
+static void usb_disconnected(void* unused, atransport* t)
+{
+    D("USB disconnect\n");
+    remove_transport_disconnect(usb_transport, &usb_disconnect);
+    usb_transport = NULL;
+    needs_retry = false;
 }
 
 static void adb_auth_event(int fd, unsigned events, void *data)
 {
-    atransport *t = data;
     char response[2];
     int ret;
 
     if (events & FDE_READ) {
         ret = unix_read(fd, response, sizeof(response));
         if (ret < 0) {
-            D("Disconnect");
-            fdevent_remove(&t->auth_fde);
+            D("Framework disconnect\n");
+            if (usb_transport)
+                fdevent_remove(&usb_transport->auth_fde);
             framework_fd = -1;
         }
         else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
-            adb_auth_reload_keys();
-            adb_auth_verified(t);
+            if (usb_transport)
+                adb_auth_verified(usb_transport);
         }
     }
 }
@@ -177,8 +192,14 @@
     char msg[MAX_PAYLOAD];
     int ret;
 
+    if (!usb_transport) {
+        usb_transport = t;
+        add_transport_disconnect(t, &usb_disconnect);
+    }
+
     if (framework_fd < 0) {
         D("Client not connected\n");
+        needs_retry = true;
         return;
     }
 
@@ -219,15 +240,17 @@
     }
 
     framework_fd = s;
+
+    if (needs_retry) {
+        needs_retry = false;
+        send_auth_request(usb_transport);
+    }
 }
 
 void adb_auth_init(void)
 {
     int fd, ret;
 
-    list_init(&key_list);
-    adb_auth_reload_keys();
-
     fd = android_get_control_socket("adbd");
     if (fd < 0) {
         D("Failed to get adbd socket\n");
diff --git a/adb/commandline.c b/adb/commandline.c
index a927423..27a1754 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -144,12 +144,15 @@
         "  adb bugreport                - return all information from the device\n"
         "                                 that should be included in a bug report.\n"
         "\n"
-        "  adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
+        "  adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
         "                               - write an archive of the device's data to <file>.\n"
         "                                 If no -f option is supplied then the data is written\n"
         "                                 to \"backup.ab\" in the current directory.\n"
         "                                 (-apk|-noapk enable/disable backup of the .apks themselves\n"
         "                                    in the archive; the default is noapk.)\n"
+        "                                 (-obb|-noobb enable/disable backup of any installed apk expansion\n"
+        "                                    (aka .obb) files associated with each application; the default\n"
+        "                                    is noobb.)\n"
         "                                 (-shared|-noshared enable/disable backup of the device's\n"
         "                                    shared storage / SD card contents; the default is noshared.)\n"
         "                                 (-all means to back up all installed applications)\n"
diff --git a/adb/transport.c b/adb/transport.c
index 9fd6cc2..b4abb66 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -851,6 +851,12 @@
     adb_mutex_unlock(&transport_lock);
 
     if (result) {
+        if (result->connection_state == CS_UNAUTHORIZED) {
+            if (error_out)
+                *error_out = "device unauthorized. Please check the confirmation dialog on your device.";
+            result = NULL;
+        }
+
          /* offline devices are ignored -- they are either being born or dying */
         if (result && result->connection_state == CS_OFFLINE) {
             if (error_out)
@@ -888,6 +894,7 @@
     case CS_RECOVERY: return "recovery";
     case CS_SIDELOAD: return "sideload";
     case CS_NOPERM: return "no permissions";
+    case CS_UNAUTHORIZED: return "unauthorized";
     default: return "unknown";
     }
 }
diff --git a/charger/Android.mk b/charger/Android.mk
index 0258604..b9d3473 100644
--- a/charger/Android.mk
+++ b/charger/Android.mk
@@ -28,7 +28,7 @@
 ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
 LOCAL_STATIC_LIBRARIES += libsuspend
 endif
-LOCAL_STATIC_LIBRARIES += libz libstdc++ libcutils libm libc
+LOCAL_STATIC_LIBRARIES += libz libstdc++ libcutils liblog libm libc
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/charger/charger.c b/charger/charger.c
index 353bdf0..66ddeaf 100644
--- a/charger/charger.c
+++ b/charger/charger.c
@@ -610,7 +610,7 @@
         x = (gr_fb_width() - str_len_px) / 2;
     if (y < 0)
         y = (gr_fb_height() - char_height) / 2;
-    gr_text(x, y, str);
+    gr_text(x, y, str, 0);
 
     return y + char_height;
 }
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 3fca64f..8621e9c 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -25,6 +25,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
+	liblog \
 	libc \
 	libcorkscrew \
 	libselinux
@@ -39,7 +40,7 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_CFLAGS += -fstack-protector-all
 #LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_SHARED_LIBRARIES := libcutils libc
+LOCAL_SHARED_LIBRARIES := libcutils liblog libc
 include $(BUILD_EXECUTABLE)
 
 ifeq ($(ARCH_ARM_HAVE_VFP),true)
@@ -54,7 +55,7 @@
 LOCAL_MODULE := vfp-crasher
 LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
 LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libcutils libc
+LOCAL_SHARED_LIBRARIES := libcutils liblog libc
 include $(BUILD_EXECUTABLE)
 endif # ARCH_ARM_HAVE_VFP == true
 
diff --git a/debuggerd/arm/machine.c b/debuggerd/arm/machine.c
index 160db7b..67e3028 100644
--- a/debuggerd/arm/machine.c
+++ b/debuggerd/arm/machine.c
@@ -42,7 +42,7 @@
 #endif
 #endif
 
-static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
+static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scopeFlags) {
     char code_buffer[64];       /* actual 8+1+((8+1)*4) + 1 == 45 */
     char ascii_buffer[32];      /* actual 16 + 1 == 17 */
     uintptr_t p, end;
@@ -102,7 +102,7 @@
             p += 4;
         }
         *asc_out = '\0';
-        _LOG(log, !at_fault, "    %s %s\n", code_buffer, ascii_buffer);
+        _LOG(log, scopeFlags, "    %s %s\n", code_buffer, ascii_buffer);
     }
 }
 
@@ -117,6 +117,8 @@
         return;
     }
 
+    int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
+
     if (at_fault && DUMP_MEMORY_FOR_ALL_REGISTERS) {
         static const char REG_NAMES[] = "r0r1r2r3r4r5r6r7r8r9slfpipsp";
 
@@ -132,17 +134,18 @@
                 continue;
             }
 
-            _LOG(log, false, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
-            dump_memory(log, tid, addr, at_fault);
+            _LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
+            dump_memory(log, tid, addr, scopeFlags | SCOPE_SENSITIVE);
         }
     }
 
-    _LOG(log, !at_fault, "\ncode around pc:\n");
-    dump_memory(log, tid, (uintptr_t)regs.ARM_pc, at_fault);
+    /* explicitly allow upload of code dump logging */
+    _LOG(log, scopeFlags, "\ncode around pc:\n");
+    dump_memory(log, tid, (uintptr_t)regs.ARM_pc, scopeFlags);
 
     if (regs.ARM_pc != regs.ARM_lr) {
-        _LOG(log, !at_fault, "\ncode around lr:\n");
-        dump_memory(log, tid, (uintptr_t)regs.ARM_lr, at_fault);
+        _LOG(log, scopeFlags, "\ncode around lr:\n");
+        dump_memory(log, tid, (uintptr_t)regs.ARM_lr, scopeFlags);
     }
 }
 
@@ -150,20 +153,20 @@
         log_t* log, pid_t tid, bool at_fault)
 {
     struct pt_regs r;
-    bool only_in_tombstone = !at_fault;
+    int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
 
     if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
-        _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+        _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
         return;
     }
 
-    _LOG(log, only_in_tombstone, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
+    _LOG(log, scopeFlags, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
             (uint32_t)r.ARM_r0, (uint32_t)r.ARM_r1, (uint32_t)r.ARM_r2, (uint32_t)r.ARM_r3);
-    _LOG(log, only_in_tombstone, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
+    _LOG(log, scopeFlags, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
             (uint32_t)r.ARM_r4, (uint32_t)r.ARM_r5, (uint32_t)r.ARM_r6, (uint32_t)r.ARM_r7);
-    _LOG(log, only_in_tombstone, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",
+    _LOG(log, scopeFlags, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",
             (uint32_t)r.ARM_r8, (uint32_t)r.ARM_r9, (uint32_t)r.ARM_r10, (uint32_t)r.ARM_fp);
-    _LOG(log, only_in_tombstone, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
+    _LOG(log, scopeFlags, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
             (uint32_t)r.ARM_ip, (uint32_t)r.ARM_sp, (uint32_t)r.ARM_lr,
             (uint32_t)r.ARM_pc, (uint32_t)r.ARM_cpsr);
 
@@ -172,14 +175,14 @@
     int i;
 
     if(ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
-        _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+        _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
         return;
     }
 
     for (i = 0; i < NUM_VFP_REGS; i += 2) {
-        _LOG(log, only_in_tombstone, "    d%-2d %016llx  d%-2d %016llx\n",
+        _LOG(log, scopeFlags, "    d%-2d %016llx  d%-2d %016llx\n",
                 i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
     }
-    _LOG(log, only_in_tombstone, "    scr %08lx\n", vfp_regs.fpscr);
+    _LOG(log, scopeFlags, "    scr %08lx\n", vfp_regs.fpscr);
 #endif
 }
diff --git a/debuggerd/backtrace.c b/debuggerd/backtrace.c
index ba76e7d..f42f24c 100644
--- a/debuggerd/backtrace.c
+++ b/debuggerd/backtrace.c
@@ -51,15 +51,15 @@
     localtime_r(&t, &tm);
     char timestr[64];
     strftime(timestr, sizeof(timestr), "%F %T", &tm);
-    _LOG(log, false, "\n\n----- pid %d at %s -----\n", pid, timestr);
+    _LOG(log, SCOPE_AT_FAULT, "\n\n----- pid %d at %s -----\n", pid, timestr);
 
     if (procname) {
-        _LOG(log, false, "Cmd line: %s\n", procname);
+        _LOG(log, SCOPE_AT_FAULT, "Cmd line: %s\n", procname);
     }
 }
 
 static void dump_process_footer(log_t* log, pid_t pid) {
-    _LOG(log, false, "\n----- end %d -----\n", pid);
+    _LOG(log, SCOPE_AT_FAULT, "\n----- end %d -----\n", pid);
 }
 
 static void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool attached,
@@ -81,10 +81,11 @@
         }
     }
 
-    _LOG(log, false, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid);
+    _LOG(log, SCOPE_AT_FAULT, "\n\"%s\" sysTid=%d\n",
+            threadname ? threadname : "<unknown>", tid);
 
     if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
-        _LOG(log, false, "Could not attach to thread: %s\n", strerror(errno));
+        _LOG(log, SCOPE_AT_FAULT, "Could not attach to thread: %s\n", strerror(errno));
         return;
     }
 
@@ -93,7 +94,7 @@
     backtrace_frame_t backtrace[STACK_DEPTH];
     ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH);
     if (frames <= 0) {
-        _LOG(log, false, "Could not obtain stack trace for thread.\n");
+        _LOG(log, SCOPE_AT_FAULT, "Could not obtain stack trace for thread.\n");
     } else {
         backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
         get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
@@ -101,7 +102,7 @@
             char line[MAX_BACKTRACE_LINE_LENGTH];
             format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
                     line, MAX_BACKTRACE_LINE_LENGTH);
-            _LOG(log, false, "  %s\n", line);
+            _LOG(log, SCOPE_AT_FAULT, "  %s\n", line);
         }
         free_backtrace_symbols(backtrace_symbols, frames);
     }
@@ -112,10 +113,11 @@
     }
 }
 
-void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed,
+void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
         int* total_sleep_time_usec) {
     log_t log;
     log.tfd = fd;
+    log.amfd = amfd;
     log.quiet = true;
 
     ptrace_context_t* context = load_ptrace_context(tid);
diff --git a/debuggerd/backtrace.h b/debuggerd/backtrace.h
index ec7d20f..c5c786a 100644
--- a/debuggerd/backtrace.h
+++ b/debuggerd/backtrace.h
@@ -25,7 +25,7 @@
 
 /* Dumps a backtrace using a format similar to what Dalvik uses so that the result
  * can be intermixed in a bug report. */
-void dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed,
+void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed,
         int* total_sleep_time_usec);
 
 #endif // _DEBUGGERD_BACKTRACE_H
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 99e6f13..da2e9b0 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -203,7 +203,7 @@
     pollfds[0].revents = 0;
     status = TEMP_FAILURE_RETRY(poll(pollfds, 1, 3000));
     if (status != 1) {
-        LOG("timed out reading tid\n");
+        LOG("timed out reading tid (from pid=%d uid=%d)\n", cr.pid, cr.uid);
         return -1;
     }
 
@@ -211,13 +211,15 @@
     memset(&msg, 0, sizeof(msg));
     status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg)));
     if (status < 0) {
-        LOG("read failure? %s\n", strerror(errno));
+        LOG("read failure? %s (pid=%d uid=%d)\n",
+            strerror(errno), cr.pid, cr.uid);
         return -1;
     }
     if (status == sizeof(debugger_msg_t)) {
         XLOG("crash request of size %d abort_msg_address=%#08x\n", status, msg.abort_msg_address);
     } else {
-        LOG("invalid crash request of size %d\n", status);
+        LOG("invalid crash request of size %d (from pid=%d uid=%d)\n",
+            status, cr.pid, cr.uid);
         return -1;
     }
 
@@ -250,7 +252,7 @@
             return -1;
         }
     } else {
-        /* No one else is not allowed to dump arbitrary processes. */
+        /* No one else is allowed to dump arbitrary processes. */
         return -1;
     }
     return 0;
@@ -318,7 +320,8 @@
                                     &total_sleep_time_usec);
                         } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
                             XLOG("stopped -- dumping to fd\n");
-                            dump_backtrace(fd, request.pid, request.tid, &detach_failed,
+                            dump_backtrace(fd, -1,
+                                    request.pid, request.tid, &detach_failed,
                                     &total_sleep_time_usec);
                         } else {
                             XLOG("stopped -- continuing\n");
diff --git a/debuggerd/mips/machine.c b/debuggerd/mips/machine.c
index dba1711..65fdf02 100644
--- a/debuggerd/mips/machine.c
+++ b/debuggerd/mips/machine.c
@@ -36,7 +36,7 @@
 
 #define R(x) ((unsigned int)(x))
 
-static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
+static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, int scopeFlags) {
     char code_buffer[64];       /* actual 8+1+((8+1)*4) + 1 == 45 */
     char ascii_buffer[32];      /* actual 16 + 1 == 17 */
     uintptr_t p, end;
@@ -92,7 +92,7 @@
             p += 4;
         }
         *asc_out = '\0';
-        _LOG(log, !at_fault, "    %s %s\n", code_buffer, ascii_buffer);
+        _LOG(log, scopeFlags, "    %s %s\n", code_buffer, ascii_buffer);
     }
 }
 
@@ -107,6 +107,7 @@
         return;
     }
 
+    int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
     if (at_fault && DUMP_MEMORY_FOR_ALL_REGISTERS) {
         static const char REG_NAMES[] = "$0atv0v1a0a1a2a3t0t1t2t3t4t5t6t7s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra";
 
@@ -129,20 +130,20 @@
                 continue;
             }
 
-            _LOG(log, false, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
-            dump_memory(log, tid, addr, at_fault);
+            _LOG(log, scopeFlags | SCOPE_SENSITIVE, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
+            dump_memory(log, tid, addr, scopeFlags | SCOPE_SENSITIVE);
         }
     }
 
     unsigned int pc = R(r.cp0_epc);
     unsigned int ra = R(r.regs[31]);
 
-    _LOG(log, !at_fault, "\ncode around pc:\n");
-    dump_memory(log, tid, (uintptr_t)pc, at_fault);
+    _LOG(log, scopeFlags, "\ncode around pc:\n");
+    dump_memory(log, tid, (uintptr_t)pc, scopeFlags);
 
     if (pc != ra) {
-        _LOG(log, !at_fault, "\ncode around ra:\n");
-        dump_memory(log, tid, (uintptr_t)ra, at_fault);
+        _LOG(log, scopeFlags, "\ncode around ra:\n");
+        dump_memory(log, tid, (uintptr_t)ra, scopeFlags);
     }
 }
 
@@ -150,29 +151,29 @@
         log_t* log, pid_t tid, bool at_fault)
 {
     pt_regs_mips_t r;
-    bool only_in_tombstone = !at_fault;
+    int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
 
     if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
-        _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+        _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
         return;
     }
 
-    _LOG(log, only_in_tombstone, " zr %08x  at %08x  v0 %08x  v1 %08x\n",
+    _LOG(log, scopeFlags, " zr %08x  at %08x  v0 %08x  v1 %08x\n",
      R(r.regs[0]), R(r.regs[1]), R(r.regs[2]), R(r.regs[3]));
-    _LOG(log, only_in_tombstone, " a0 %08x  a1 %08x  a2 %08x  a3 %08x\n",
+    _LOG(log, scopeFlags, " a0 %08x  a1 %08x  a2 %08x  a3 %08x\n",
      R(r.regs[4]), R(r.regs[5]), R(r.regs[6]), R(r.regs[7]));
-    _LOG(log, only_in_tombstone, " t0 %08x  t1 %08x  t2 %08x  t3 %08x\n",
+    _LOG(log, scopeFlags, " t0 %08x  t1 %08x  t2 %08x  t3 %08x\n",
      R(r.regs[8]), R(r.regs[9]), R(r.regs[10]), R(r.regs[11]));
-    _LOG(log, only_in_tombstone, " t4 %08x  t5 %08x  t6 %08x  t7 %08x\n",
+    _LOG(log, scopeFlags, " t4 %08x  t5 %08x  t6 %08x  t7 %08x\n",
      R(r.regs[12]), R(r.regs[13]), R(r.regs[14]), R(r.regs[15]));
-    _LOG(log, only_in_tombstone, " s0 %08x  s1 %08x  s2 %08x  s3 %08x\n",
+    _LOG(log, scopeFlags, " s0 %08x  s1 %08x  s2 %08x  s3 %08x\n",
      R(r.regs[16]), R(r.regs[17]), R(r.regs[18]), R(r.regs[19]));
-    _LOG(log, only_in_tombstone, " s4 %08x  s5 %08x  s6 %08x  s7 %08x\n",
+    _LOG(log, scopeFlags, " s4 %08x  s5 %08x  s6 %08x  s7 %08x\n",
      R(r.regs[20]), R(r.regs[21]), R(r.regs[22]), R(r.regs[23]));
-    _LOG(log, only_in_tombstone, " t8 %08x  t9 %08x  k0 %08x  k1 %08x\n",
+    _LOG(log, scopeFlags, " t8 %08x  t9 %08x  k0 %08x  k1 %08x\n",
      R(r.regs[24]), R(r.regs[25]), R(r.regs[26]), R(r.regs[27]));
-    _LOG(log, only_in_tombstone, " gp %08x  sp %08x  s8 %08x  ra %08x\n",
+    _LOG(log, scopeFlags, " gp %08x  sp %08x  s8 %08x  ra %08x\n",
      R(r.regs[28]), R(r.regs[29]), R(r.regs[30]), R(r.regs[31]));
-    _LOG(log, only_in_tombstone, " hi %08x  lo %08x bva %08x epc %08x\n",
+    _LOG(log, scopeFlags, " hi %08x  lo %08x bva %08x epc %08x\n",
      R(r.hi), R(r.lo), R(r.cp0_badvaddr), R(r.cp0_epc));
 }
diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c
index da5f03c..77f6ef1 100644
--- a/debuggerd/tombstone.c
+++ b/debuggerd/tombstone.c
@@ -35,6 +35,9 @@
 #include <corkscrew/demangle.h>
 #include <corkscrew/backtrace.h>
 
+#include <sys/socket.h>
+#include <linux/un.h>
+
 #include <selinux/android.h>
 
 #include "machine.h"
@@ -47,6 +50,9 @@
 #define MAX_TOMBSTONES  10
 #define TOMBSTONE_DIR   "/data/tombstones"
 
+/* Must match the path defined in NativeCrashListener.java */
+#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
+
 #define typecheck(x,y) {    \
     typeof(x) __dummy1;     \
     typeof(y) __dummy2;     \
@@ -157,7 +163,7 @@
 
     property_get("ro.revision", revision, "unknown");
 
-    _LOG(log, false, "Revision: '%s'\n", revision);
+    _LOG(log, SCOPE_AT_FAULT, "Revision: '%s'\n", revision);
 }
 
 static void dump_build_info(log_t* log)
@@ -166,7 +172,7 @@
 
     property_get("ro.build.fingerprint", fingerprint, "unknown");
 
-    _LOG(log, false, "Build fingerprint: '%s'\n", fingerprint);
+    _LOG(log, SCOPE_AT_FAULT, "Build fingerprint: '%s'\n", fingerprint);
 }
 
 static void dump_fault_addr(log_t* log, pid_t tid, int sig)
@@ -174,15 +180,15 @@
     siginfo_t si;
 
     memset(&si, 0, sizeof(si));
-    if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
-        _LOG(log, false, "cannot get siginfo: %s\n", strerror(errno));
+    if(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
+        _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
     } else if (signal_has_address(sig)) {
-        _LOG(log, false, "signal %d (%s), code %d (%s), fault addr %08x\n",
+        _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %08x\n",
              sig, get_signame(sig),
              si.si_code, get_sigcode(sig, si.si_code),
              (uintptr_t) si.si_addr);
     } else {
-        _LOG(log, false, "signal %d (%s), code %d (%s), fault addr --------\n",
+        _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
              sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
     }
 }
@@ -215,19 +221,20 @@
             fclose(fp);
         }
 
-        _LOG(log, false, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", pid, tid,
+        _LOG(log, SCOPE_AT_FAULT, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", pid, tid,
                 threadname ? threadname : "UNKNOWN",
                 procname ? procname : "UNKNOWN");
     } else {
-        _LOG(log, true, "pid: %d, tid: %d, name: %s\n", pid, tid,
-                threadname ? threadname : "UNKNOWN");
+        _LOG(log, 0, "pid: %d, tid: %d, name: %s\n",
+                pid, tid, threadname ? threadname : "UNKNOWN");
     }
 }
 
 static void dump_backtrace(const ptrace_context_t* context __attribute((unused)),
         log_t* log, pid_t tid __attribute((unused)), bool at_fault,
         const backtrace_frame_t* backtrace, size_t frames) {
-    _LOG(log, !at_fault, "\nbacktrace:\n");
+    int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
+    _LOG(log, scopeFlags, "\nbacktrace:\n");
 
     backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
     get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
@@ -235,13 +242,13 @@
         char line[MAX_BACKTRACE_LINE_LENGTH];
         format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
                 line, MAX_BACKTRACE_LINE_LENGTH);
-        _LOG(log, !at_fault, "    %s\n", line);
+        _LOG(log, scopeFlags, "    %s\n", line);
     }
     free_backtrace_symbols(backtrace_symbols, frames);
 }
 
 static void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_t tid,
-        bool only_in_tombstone, uintptr_t* sp, size_t words, int label) {
+        int scopeFlags, uintptr_t* sp, size_t words, int label) {
     for (size_t i = 0; i < words; i++) {
         uint32_t stack_content;
         if (!try_get_word_ptrace(tid, *sp, &stack_content)) {
@@ -258,28 +265,28 @@
             uint32_t offset = stack_content - (mi->start + symbol->start);
             if (!i && label >= 0) {
                 if (offset) {
-                    _LOG(log, only_in_tombstone, "    #%02d  %08x  %08x  %s (%s+%u)\n",
+                    _LOG(log, scopeFlags, "    #%02d  %08x  %08x  %s (%s+%u)\n",
                             label, *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
                 } else {
-                    _LOG(log, only_in_tombstone, "    #%02d  %08x  %08x  %s (%s)\n",
+                    _LOG(log, scopeFlags, "    #%02d  %08x  %08x  %s (%s)\n",
                             label, *sp, stack_content, mi ? mi->name : "", symbol_name);
                 }
             } else {
                 if (offset) {
-                    _LOG(log, only_in_tombstone, "         %08x  %08x  %s (%s+%u)\n",
+                    _LOG(log, scopeFlags, "         %08x  %08x  %s (%s+%u)\n",
                             *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
                 } else {
-                    _LOG(log, only_in_tombstone, "         %08x  %08x  %s (%s)\n",
+                    _LOG(log, scopeFlags, "         %08x  %08x  %s (%s)\n",
                             *sp, stack_content, mi ? mi->name : "", symbol_name);
                 }
             }
             free(demangled_name);
         } else {
             if (!i && label >= 0) {
-                _LOG(log, only_in_tombstone, "    #%02d  %08x  %08x  %s\n",
+                _LOG(log, scopeFlags, "    #%02d  %08x  %08x  %s\n",
                         label, *sp, stack_content, mi ? mi->name : "");
             } else {
-                _LOG(log, only_in_tombstone, "         %08x  %08x  %s\n",
+                _LOG(log, scopeFlags, "         %08x  %08x  %s\n",
                         *sp, stack_content, mi ? mi->name : "");
             }
         }
@@ -305,28 +312,28 @@
         return;
     }
 
-    _LOG(log, !at_fault, "\nstack:\n");
+    int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
+    _LOG(log, scopeFlags, "\nstack:\n");
 
     // Dump a few words before the first frame.
-    bool only_in_tombstone = !at_fault;
     uintptr_t sp = backtrace[first].stack_top - STACK_WORDS * sizeof(uint32_t);
-    dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, -1);
+    dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, -1);
 
     // Dump a few words from all successive frames.
     // Only log the first 3 frames, put the rest in the tombstone.
     for (size_t i = first; i <= last; i++) {
         const backtrace_frame_t* frame = &backtrace[i];
         if (sp != frame->stack_top) {
-            _LOG(log, only_in_tombstone, "         ........  ........\n");
+            _LOG(log, scopeFlags, "         ........  ........\n");
             sp = frame->stack_top;
         }
         if (i - first == 3) {
-            only_in_tombstone = true;
+            scopeFlags &= (~SCOPE_AT_FAULT);
         }
         if (i == last) {
-            dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, i);
+            dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, i);
             if (sp < frame->stack_top + frame->stack_size) {
-                _LOG(log, only_in_tombstone, "         ........  ........\n");
+                _LOG(log, scopeFlags, "         ........  ........\n");
             }
         } else {
             size_t words = frame->stack_size / sizeof(uint32_t);
@@ -335,7 +342,7 @@
             } else if (words > STACK_WORDS) {
                 words = STACK_WORDS;
             }
-            dump_stack_segment(context, log, tid, only_in_tombstone, &sp, words, i);
+            dump_stack_segment(context, log, tid, scopeFlags, &sp, words, i);
         }
     }
 }
@@ -350,23 +357,24 @@
     }
 }
 
-static void dump_map(log_t* log, map_info_t* m, const char* what) {
+static void dump_map(log_t* log, map_info_t* m, const char* what, int scopeFlags) {
     if (m != NULL) {
-        _LOG(log, false, "    %08x-%08x %c%c%c %s\n", m->start, m->end,
+        _LOG(log, scopeFlags, "    %08x-%08x %c%c%c %s\n", m->start, m->end,
              m->is_readable ? 'r' : '-',
              m->is_writable ? 'w' : '-',
              m->is_executable ? 'x' : '-',
              m->name);
     } else {
-        _LOG(log, false, "    (no %s)\n", what);
+        _LOG(log, scopeFlags, "    (no %s)\n", what);
     }
 }
 
-static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t tid) {
+static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault) {
+    int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
     siginfo_t si;
     memset(&si, 0, sizeof(si));
     if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
-        _LOG(log, false, "cannot get siginfo for %d: %s\n",
+        _LOG(log, scopeFlags, "cannot get siginfo for %d: %s\n",
                 tid, strerror(errno));
         return;
     }
@@ -380,7 +388,7 @@
         return;
     }
 
-    _LOG(log, false, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
+    _LOG(log, scopeFlags, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
 
     /*
      * Search for a match, or for a hole where the match would be.  The list
@@ -408,9 +416,9 @@
      * Show "next" then "match" then "prev" so that the addresses appear in
      * ascending order (like /proc/pid/maps).
      */
-    dump_map(log, next, "map below");
-    dump_map(log, map, "map for address");
-    dump_map(log, prev, "map above");
+    dump_map(log, next, "map below", scopeFlags);
+    dump_map(log, map, "map for address", scopeFlags);
+    dump_map(log, prev, "map above", scopeFlags);
 }
 
 static void dump_thread(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault,
@@ -421,7 +429,7 @@
     dump_backtrace_and_stack(context, log, tid, at_fault);
     if (at_fault) {
         dump_memory_and_code(context, log, tid, at_fault);
-        dump_nearby_maps(context, log, tid);
+        dump_nearby_maps(context, log, tid, at_fault);
     }
 }
 
@@ -458,7 +466,7 @@
             continue;
         }
 
-        _LOG(log, true, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
+        _LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
         dump_thread_info(log, pid, new_tid, false);
         dump_thread(context, log, new_tid, false, total_sleep_time_usec);
 
@@ -511,12 +519,12 @@
                 /* non-blocking EOF; we're done */
                 break;
             } else {
-                _LOG(log, true, "Error while reading log: %s\n",
+                _LOG(log, 0, "Error while reading log: %s\n",
                     strerror(errno));
                 break;
             }
         } else if (actual == 0) {
-            _LOG(log, true, "Got zero bytes while reading log: %s\n",
+            _LOG(log, 0, "Got zero bytes while reading log: %s\n",
                 strerror(errno));
             break;
         }
@@ -536,7 +544,7 @@
         }
 
         if (first) {
-            _LOG(log, true, "--------- %slog %s\n",
+            _LOG(log, 0, "--------- %slog %s\n",
                 tailOnly ? "tail end of " : "", filename);
             first = false;
         }
@@ -578,7 +586,7 @@
             shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
             shortLogCount++;
         } else {
-            _LOG(log, true, "%s.%03d %5d %5d %c %-8s: %s\n",
+            _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
                 timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
                 prioChar, tag, msg);
         }
@@ -598,7 +606,7 @@
         }
 
         for (i = 0; i < shortLogCount; i++) {
-            _LOG(log, true, "%s\n", shortLog[shortLogNext]);
+            _LOG(log, 0, "%s\n", shortLog[shortLogNext]);
             shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
         }
     }
@@ -648,7 +656,7 @@
   }
   msg[sizeof(msg) - 1] = '\0';
 
-  _LOG(log, false, "Abort message: '%s'\n", msg);
+  _LOG(log, SCOPE_AT_FAULT, "Abort message: '%s'\n", msg);
 }
 
 /*
@@ -662,7 +670,19 @@
     property_get("ro.debuggable", value, "0");
     bool want_logs = (value[0] == '1');
 
-    _LOG(log, false,
+    if (log->amfd >= 0) {
+        /*
+         * Activity Manager protocol: binary 32-bit network-byte-order ints for the
+         * pid and signal number, followed by the raw text of the dump, culminating
+         * in a zero byte that marks end-of-data.
+         */
+        uint32_t datum = htonl(pid);
+        TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
+        datum = htonl(signal);
+        TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
+    }
+
+    _LOG(log, SCOPE_AT_FAULT,
             "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
     dump_build_info(log);
     dump_revision_info(log);
@@ -689,6 +709,16 @@
     if (want_logs) {
         dump_logs(log, pid, false);
     }
+
+    /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
+     * and killing the target out from under it */
+    if (log->amfd >= 0) {
+        uint8_t eodMarker = 0;
+        TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) );
+        /* 3 sec timeout reading the ack; we're fine if that happens */
+        TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) );
+    }
+
     return detach_failed;
 }
 
@@ -748,6 +778,35 @@
     return strdup(path);
 }
 
+static int activity_manager_connect() {
+    int amfd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if (amfd >= 0) {
+        struct sockaddr_un address;
+        int err;
+
+        memset(&address, 0, sizeof(address));
+        address.sun_family = AF_UNIX;
+        strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path));
+        err = TEMP_FAILURE_RETRY( connect(amfd, (struct sockaddr*) &address, sizeof(address)) );
+        if (!err) {
+            struct timeval tv;
+            memset(&tv, 0, sizeof(tv));
+            tv.tv_sec = 1;  // tight leash
+            err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+            if (!err) {
+                tv.tv_sec = 3;  // 3 seconds on handshake read
+                err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+            }
+        }
+        if (err) {
+            close(amfd);
+            amfd = -1;
+        }
+    }
+
+    return amfd;
+}
+
 char* engrave_tombstone(pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address,
         bool dump_sibling_threads, bool quiet, bool* detach_failed,
         int* total_sleep_time_usec) {
@@ -768,10 +827,12 @@
 
     log_t log;
     log.tfd = fd;
+    log.amfd = activity_manager_connect();
     log.quiet = quiet;
     *detach_failed = dump_crash(&log, pid, tid, signal, abort_msg_address, dump_sibling_threads,
             total_sleep_time_usec);
 
+    close(log.amfd);
     close(fd);
     return path;
 }
diff --git a/debuggerd/utility.c b/debuggerd/utility.c
index aabaf74..9bf3c18 100644
--- a/debuggerd/utility.c
+++ b/debuggerd/utility.c
@@ -25,27 +25,63 @@
 #include <cutils/logd.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
+#include <arpa/inet.h>
+#include <assert.h>
 
 #include "utility.h"
 
 const int sleep_time_usec = 50000;         /* 0.05 seconds */
 const int max_total_sleep_usec = 10000000; /* 10 seconds */
 
-void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...) {
+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 */
+            LOG("AM write failure (%d / %s)\n", errno, strerror(errno));
+            return -1;
+        }
+        to_write -= written;
+    }
+    return len;
+}
+
+void _LOG(log_t* log, int scopeFlags, const char *fmt, ...) {
     char buf[512];
+    bool want_tfd_write;
+    bool want_log_write;
+    bool want_amfd_write;
+    int len = 0;
 
     va_list ap;
     va_start(ap, fmt);
 
-    if (log && log->tfd >= 0) {
-        int len;
+    // where is the information going to go?
+    want_tfd_write = log && log->tfd >= 0;
+    want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
+    want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
+
+    // if we're going to need the literal string, generate it once here
+    if (want_tfd_write || want_amfd_write) {
         vsnprintf(buf, sizeof(buf), fmt, ap);
         len = strlen(buf);
+    }
+
+    if (want_tfd_write) {
         write(log->tfd, buf, len);
     }
 
-    if (!in_tombstone_only && (!log || !log->quiet)) {
+    if (want_log_write) {
+        // whatever goes to logcat also goes to the Activity Manager
         __android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
+        if (want_amfd_write && len > 0) {
+            int written = write_to_am(log->amfd, buf, len);
+            if (written <= 0) {
+                // timeout or other failure on write; stop informing the activity manager
+                log->amfd = -1;
+            }
+        }
     }
     va_end(ap);
 }
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 136f46d..1f006ed 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -24,26 +24,38 @@
 typedef struct {
     /* tombstone file descriptor */
     int tfd;
-    /* if true, does not log anything to the Android logcat */
+    /* Activity Manager socket file descriptor */
+    int amfd;
+    /* if true, does not log anything to the Android logcat or Activity Manager */
     bool quiet;
 } log_t;
 
-/* Log information onto the tombstone. */
-void _LOG(log_t* log, bool in_tombstone_only, const char *fmt, ...)
+/* Log information onto the tombstone.  scopeFlags is a bitmask of the flags defined
+ * here. */
+void _LOG(log_t* log, int scopeFlags, const char *fmt, ...)
         __attribute__ ((format(printf, 3, 4)));
 
-#define LOG(fmt...) _LOG(NULL, 0, fmt)
+/* The message pertains specifically to the faulting thread / process */
+#define SCOPE_AT_FAULT (1 << 0)
+/* The message contains sensitive information such as RAM contents */
+#define SCOPE_SENSITIVE  (1 << 1)
+
+#define IS_AT_FAULT(x)    (((x) & SCOPE_AT_FAULT) != 0)
+#define IS_SENSITIVE(x)    (((x) & SCOPE_SENSITIVE) != 0)
+
+/* Further helpful macros */
+#define LOG(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
 
 /* Set to 1 for normal debug traces */
 #if 0
-#define XLOG(fmt...) _LOG(NULL, 0, fmt)
+#define XLOG(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
 #else
 #define XLOG(fmt...) do {} while(0)
 #endif
 
 /* Set to 1 for chatty debug traces. Includes all resolved dynamic symbols */
 #if 0
-#define XLOG2(fmt...) _LOG(NULL, 0, fmt)
+#define XLOG2(fmt...) _LOG(NULL, SCOPE_AT_FAULT, fmt)
 #else
 #define XLOG2(fmt...) do {} while(0)
 #endif
diff --git a/debuggerd/x86/machine.c b/debuggerd/x86/machine.c
index 01da5fe..af79092 100644
--- a/debuggerd/x86/machine.c
+++ b/debuggerd/x86/machine.c
@@ -38,21 +38,21 @@
 void dump_registers(const ptrace_context_t* context __attribute((unused)),
         log_t* log, pid_t tid, bool at_fault) {
     struct pt_regs_x86 r;
-    bool only_in_tombstone = !at_fault;
+    int scopeFlags = (at_fault ? SCOPE_AT_FAULT : 0);
 
     if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
-        _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+        _LOG(log, scopeFlags, "cannot get registers: %s\n", strerror(errno));
         return;
     }
     //if there is no stack, no print just like arm
     if(!r.ebp)
         return;
-    _LOG(log, only_in_tombstone, "    eax %08x  ebx %08x  ecx %08x  edx %08x\n",
+    _LOG(log, scopeFlags, "    eax %08x  ebx %08x  ecx %08x  edx %08x\n",
          r.eax, r.ebx, r.ecx, r.edx);
-    _LOG(log, only_in_tombstone, "    esi %08x  edi %08x\n",
+    _LOG(log, scopeFlags, "    esi %08x  edi %08x\n",
          r.esi, r.edi);
-    _LOG(log, only_in_tombstone, "    xcs %08x  xds %08x  xes %08x  xfs %08x  xss %08x\n",
+    _LOG(log, scopeFlags, "    xcs %08x  xds %08x  xes %08x  xfs %08x  xss %08x\n",
          r.xcs, r.xds, r.xes, r.xfs, r.xss);
-    _LOG(log, only_in_tombstone, "    eip %08x  ebp %08x  esp %08x  flags %08x\n",
+    _LOG(log, scopeFlags, "    eip %08x  ebp %08x  esp %08x  flags %08x\n",
          r.eip, r.ebp, r.esp, r.eflags);
 }
diff --git a/fastboot/bootimg.c b/fastboot/bootimg.c
index 9e0e45c..240784f 100644
--- a/fastboot/bootimg.c
+++ b/fastboot/bootimg.c
@@ -37,10 +37,10 @@
     strcpy((char*) h->cmdline, cmdline);
 }
 
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
-                        void *ramdisk, unsigned ramdisk_size,
-                        void *second, unsigned second_size,
-                        unsigned page_size, unsigned base,
+boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
+                        void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
+                        void *second, unsigned second_size, unsigned second_offset,
+                        unsigned page_size, unsigned base, unsigned tags_offset,
                         unsigned *bootimg_size)
 {
     unsigned kernel_actual;
@@ -68,12 +68,15 @@
     hdr->kernel_size =  kernel_size;
     hdr->ramdisk_size = ramdisk_size;
     hdr->second_size =  second_size;
-    hdr->kernel_addr =  base + 0x00008000;
-    hdr->ramdisk_addr = base + 0x01000000;
-    hdr->second_addr =  base + 0x00F00000;
-    hdr->tags_addr =    base + 0x00000100;
+
+    hdr->kernel_addr =  base + kernel_offset;
+    hdr->ramdisk_addr = base + ramdisk_offset;
+    hdr->second_addr =  base + second_offset;
+    hdr->tags_addr =    base + tags_offset;
+
     hdr->page_size =    page_size;
 
+
     memcpy(hdr->magic + page_size,
            kernel, kernel_size);
     memcpy(hdr->magic + page_size + kernel_actual,
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 3de6d7d..447b257 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -58,10 +58,10 @@
 
 void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
 
-boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
-                        void *ramdisk, unsigned ramdisk_size,
-                        void *second, unsigned second_size,
-                        unsigned page_size, unsigned base,
+boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset,
+                        void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset,
+                        void *second, unsigned second_size, unsigned second_offset,
+                        unsigned page_size, unsigned base, unsigned tags_offset,
                         unsigned *bootimg_size);
 
 static usb_handle *usb = 0;
@@ -74,7 +74,13 @@
 static int64_t sparse_limit = -1;
 static int64_t target_sparse_limit = -1;
 
-static unsigned base_addr = 0x10000000;
+unsigned page_size = 2048;
+unsigned base_addr      = 0x10000000;
+unsigned kernel_offset  = 0x00008000;
+unsigned ramdisk_offset = 0x01000000;
+unsigned second_offset  = 0x00f00000;
+unsigned tags_offset    = 0x00000100;
+
 
 void die(const char *fmt, ...)
 {
@@ -186,11 +192,6 @@
 }
 #endif
 
-int match_fastboot(usb_ifc_info *info)
-{
-    return match_fastboot_with_serial(info, serial);
-}
-
 int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial)
 {
     if(!(vendor_id && (info->dev_vendor == vendor_id)) &&
@@ -217,6 +218,11 @@
     return 0;
 }
 
+int match_fastboot(usb_ifc_info *info)
+{
+    return match_fastboot_with_serial(info, serial);
+}
+
 int list_devices_callback(usb_ifc_info *info)
 {
     if (match_fastboot_with_serial(info, NULL) == 0) {
@@ -297,14 +303,14 @@
             "  -p <product>                             specify product name\n"
             "  -c <cmdline>                             override kernel commandline\n"
             "  -i <vendor id>                           specify a custom USB vendor id\n"
-            "  -b <base_addr>                           specify a custom kernel base address\n"
+            "  -b <base_addr>                           specify a custom kernel base address. default: 0x10000000\n"
             "  -n <page size>                           specify the nand page size. default: 2048\n"
             "  -S <size>[K|M|G]                         automatically sparse files greater than\n"
             "                                           size.  0 to disable\n"
         );
 }
 
-void *load_bootable_image(unsigned page_size, const char *kernel, const char *ramdisk,
+void *load_bootable_image(const char *kernel, const char *ramdisk,
                           unsigned *sz, const char *cmdline)
 {
     void *kdata = 0, *rdata = 0;
@@ -345,7 +351,10 @@
     }
 
     fprintf(stderr,"creating boot image...\n");
-    bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, page_size, base_addr, &bsize);
+    bdata = mkbootimg(kdata, ksize, kernel_offset,
+                      rdata, rsize, ramdisk_offset,
+                      0, 0, second_offset,
+                      page_size, base_addr, tags_offset, &bsize);
     if(bdata == 0) {
         fprintf(stderr,"failed to create boot.img\n");
         return 0;
@@ -806,53 +815,38 @@
     int erase_first = 1;
     void *data;
     unsigned sz;
-    unsigned page_size = 2048;
     int status;
     int c;
     int r;
 
-    const struct option longopts = { 0, 0, 0, 0 };
+    const struct option longopts[] = {
+        {"base", required_argument, 0, 'b'},
+        {"kernel_offset", required_argument, 0, 'k'},
+        {"page_size", required_argument, 0, 'n'},
+        {"ramdisk_offset", required_argument, 0, 'r'},
+        {"help", 0, 0, 'h'},
+        {0, 0, 0, 0}
+    };
 
     serial = getenv("ANDROID_SERIAL");
 
     while (1) {
-        c = getopt_long(argc, argv, "wub:n:s:S:lp:c:i:m:h", &longopts, NULL);
+        int option_index = 0;
+        c = getopt_long(argc, argv, "wub:k:n:r:s:S:lp:c:i:m:h", longopts, NULL);
         if (c < 0) {
             break;
         }
-
+        /* Alphabetical cases */
         switch (c) {
-        case 'w':
-            wants_wipe = 1;
-            break;
-        case 'u':
-            erase_first = 0;
-            break;
         case 'b':
             base_addr = strtoul(optarg, 0, 16);
             break;
-        case 'n':
-            page_size = (unsigned)strtoul(optarg, NULL, 0);
-            if (!page_size) die("invalid page size");
-            break;
-        case 's':
-            serial = optarg;
-            break;
-        case 'S':
-            sparse_limit = parse_num(optarg);
-            if (sparse_limit < 0) {
-                    die("invalid sparse limit");
-            }
-            break;
-        case 'l':
-            long_listing = 1;
-            break;
-        case 'p':
-            product = optarg;
-            break;
         case 'c':
             cmdline = optarg;
             break;
+        case 'h':
+            usage();
+            return 1;
         case 'i': {
                 char *endptr = NULL;
                 unsigned long val;
@@ -863,9 +857,37 @@
                 vendor_id = (unsigned short)val;
                 break;
             }
-        case 'h':
-            usage();
-            return 1;
+        case 'k':
+            kernel_offset = strtoul(optarg, 0, 16);
+            break;
+        case 'l':
+            long_listing = 1;
+            break;
+        case 'n':
+            page_size = (unsigned)strtoul(optarg, NULL, 0);
+            if (!page_size) die("invalid page size");
+            break;
+        case 'p':
+            product = optarg;
+            break;
+        case 'r':
+            ramdisk_offset = strtoul(optarg, 0, 16);
+            break;
+        case 's':
+            serial = optarg;
+            break;
+        case 'S':
+            sparse_limit = parse_num(optarg);
+            if (sparse_limit < 0) {
+                    die("invalid sparse limit");
+            }
+            break;
+        case 'u':
+            erase_first = 0;
+            break;
+        case 'w':
+            wants_wipe = 1;
+            break;
         case '?':
             return 1;
         default:
@@ -944,7 +966,7 @@
                 rname = argv[0];
                 skip(1);
             }
-            data = load_bootable_image(page_size, kname, rname, &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");
@@ -975,7 +997,7 @@
             } else {
                 skip(3);
             }
-            data = load_bootable_image(page_size, kname, rname, &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/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt
new file mode 100644
index 0000000..2248992
--- /dev/null
+++ b/fastboot/fastboot_protocol.txt
@@ -0,0 +1,173 @@
+
+FastBoot  Version  0.4
+----------------------
+
+The fastboot protocol is a mechanism for communicating with bootloaders
+over USB.  It is designed to be very straightforward to implement, to
+allow it to be used across a wide range of devices and from hosts running
+Linux, Windows, or OSX.
+
+
+Basic Requirements
+------------------
+
+* Two bulk endpoints (in, out) are required
+* Max packet size must be 64 bytes for full-speed and 512 bytes for 
+  high-speed USB
+* The protocol is entirely host-driven and synchronous (unlike the
+  multi-channel, bi-directional, asynchronous ADB protocol)
+
+
+Transport and Framing
+---------------------
+
+1. Host sends a command, which is an ascii string in a single
+   packet no greater than 64 bytes.
+
+2. Client response with a single packet no greater than 64 bytes.
+   The first four bytes of the response are "OKAY", "FAIL", "DATA", 
+   or "INFO".  Additional bytes may contain an (ascii) informative
+   message.
+
+   a. INFO -> the remaining 60 bytes are an informative message
+      (providing progress or diagnostic messages).  They should 
+      be displayed and then step #2 repeats
+
+   b. FAIL -> the requested command failed.  The remaining 60 bytes 
+      of the response (if present) provide a textual failure message 
+      to present to the user.  Stop.
+
+   c. OKAY -> the requested command completed successfully.  Go to #5
+
+   d. DATA -> the requested command is ready for the data phase.
+      A DATA response packet will be 12 bytes long, in the form of
+      DATA00000000 where the 8 digit hexidecimal number represents
+      the total data size to transfer.
+
+3. Data phase.  Depending on the command, the host or client will 
+   send the indicated amount of data.  Short packets are always 
+   acceptable and zero-length packets are ignored.  This phase continues
+   until the client has sent or received the number of bytes indicated
+   in the "DATA" response above.
+
+4. Client responds with a single packet no greater than 64 bytes.  
+   The first four bytes of the response are "OKAY", "FAIL", or "INFO".  
+   Similar to #2:
+
+   a. INFO -> display the remaining 60 bytes and return to #4
+   
+   b. FAIL -> display the remaining 60 bytes (if present) as a failure
+      reason and consider the command failed.  Stop.
+
+   c. OKAY -> success.  Go to #5
+
+5. Success.  Stop.
+
+
+Example Session
+---------------
+
+Host:    "getvar:version"        request version variable
+
+Client:  "OKAY0.4"               return version "0.4"
+
+Host:    "getvar:nonexistant"    request some undefined variable
+
+Client:  "OKAY"                  return value ""
+
+Host:    "download:00001234"     request to send 0x1234 bytes of data
+
+Client:  "DATA00001234"          ready to accept data
+
+Host:    < 0x1234 bytes >        send data
+
+Client:  "OKAY"                  success
+
+Host:    "flash:bootloader"      request to flash the data to the bootloader
+
+Client:  "INFOerasing flash"     indicate status / progress
+         "INFOwriting flash"
+         "OKAY"                  indicate success
+
+Host:    "powerdown"             send a command
+
+Client:  "FAILunknown command"   indicate failure
+
+
+Command Reference
+-----------------
+
+* Command parameters are indicated by printf-style escape sequences.
+
+* Commands are ascii strings and sent without the quotes (which are
+  for illustration only here) and without a trailing 0 byte.
+
+* Commands that begin with a lowercase letter are reserved for this
+  specification.  OEM-specific commands should not begin with a 
+  lowercase letter, to prevent incompatibilities with future specs.
+
+ "getvar:%s"           Read a config/version variable from the bootloader.
+                       The variable contents will be returned after the
+                       OKAY response.
+
+ "download:%08x"       Write data to memory which will be later used
+                       by "boot", "ramdisk", "flash", etc.  The client
+                       will reply with "DATA%08x" if it has enough 
+                       space in RAM or "FAIL" if not.  The size of
+                       the download is remembered.
+
+  "verify:%08x"        Send a digital signature to verify the downloaded
+                       data.  Required if the bootloader is "secure"
+                       otherwise "flash" and "boot" will be ignored.
+
+  "flash:%s"           Write the previously downloaded image to the
+                       named partition (if possible).
+
+  "erase:%s"           Erase the indicated partition (clear to 0xFFs)
+
+  "boot"               The previously downloaded data is a boot.img
+                       and should be booted according to the normal
+                       procedure for a boot.img
+
+  "continue"           Continue booting as normal (if possible)
+
+  "reboot"             Reboot the device.
+
+  "reboot-bootloader"  Reboot back into the bootloader.
+                       Useful for upgrade processes that require upgrading
+                       the bootloader and then upgrading other partitions
+                       using the new bootloader.
+
+  "powerdown"          Power off the device.
+
+
+
+Client Variables
+----------------
+
+The "getvar:%s" command is used to read client variables which
+represent various information about the device and the software
+on it.
+
+The various currently defined names are:
+
+  version             Version of FastBoot protocol supported.
+                      It should be "0.3" for this document.
+
+  version-bootloader  Version string for the Bootloader.
+
+  version-baseband    Version string of the Baseband Software
+
+  product             Name of the product
+
+  serialno            Product serial number
+
+  secure              If the value is "yes", this is a secure
+                      bootloader requiring a signature before
+                      it will install or boot images.
+
+Names starting with a lowercase character are reserved by this
+specification.  OEM-specific names should not start with lowercase
+characters.
+
+
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 7c66f6a..782ae99 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 
 LOCAL_MODULE:= libfs_mgr
+LOCAL_STATIC_LIBRARIES := liblogwrap
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 
 include $(BUILD_STATIC_LIBRARY)
@@ -27,7 +28,7 @@
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
 
-LOCAL_STATIC_LIBRARIES := libfs_mgr libcutils libc
+LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index e51c9cf..fecc556 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-/* TO DO:
- *   1. Re-direct fsck output to the kernel log?
- *
- */
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -36,6 +31,7 @@
 #include <private/android_filesystem_config.h>
 #include <cutils/partition_utils.h>
 #include <cutils/properties.h>
+#include <logwrap/logwrap.h>
 
 #include "fs_mgr_priv.h"
 
@@ -44,6 +40,8 @@
 
 #define E2FSCK_BIN      "/system/bin/e2fsck"
 
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
 struct flag_list {
     const char *name;
     unsigned flag;
@@ -72,6 +70,10 @@
     { "wait",        MF_WAIT },
     { "check",       MF_CHECK },
     { "encryptable=",MF_CRYPT },
+    { "nonremovable",MF_NONREMOVABLE },
+    { "voldmanaged=",MF_VOLDMANAGED},
+    { "length=",     MF_LENGTH },
+    { "recoveryonly",MF_RECOVERYONLY },
     { "defaults",    0 },
     { 0,             0 },
 };
@@ -106,7 +108,8 @@
     return ret;
 }
 
-static int parse_flags(char *flags, struct flag_list *fl, char **key_loc,
+static int parse_flags(char *flags, struct flag_list *fl,
+                       char **key_loc, long long *part_length, char **label, int *partnum,
                        char *fs_options, int fs_options_len)
 {
     int f = 0;
@@ -119,6 +122,18 @@
     if (key_loc) {
         *key_loc = NULL;
     }
+    /* initialize part_length to 0, if we find an MF_LENGTH flag,
+     * then we'll set part_length to the proper value */
+    if (part_length) {
+        *part_length = 0;
+    }
+    if (partnum) {
+        *partnum = -1;
+    }
+    if (label) {
+        *label = NULL;
+    }
+
     /* initialize fs_options to the null string */
     if (fs_options && (fs_options_len > 0)) {
         fs_options[0] = '\0';
@@ -137,6 +152,36 @@
                      * location of the keys.  Get it and return it.
                      */
                     *key_loc = strdup(strchr(p, '=') + 1);
+                } else if ((fl[i].flag == MF_LENGTH) && part_length) {
+                    /* The length flag is followed by an = and the
+                     * size of the partition.  Get it and return it.
+                     */
+                    *part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
+                } else if ((fl[i].flag == MF_VOLDMANAGED) && label && partnum) {
+                    /* The voldmanaged flag is followed by an = and the
+                     * label, a colon and the partition number or the
+                     * word "auto", e.g.
+                     *   voldmanaged=sdcard:3
+                     * Get and return them.
+                     */
+                    char *label_start;
+                    char *label_end;
+                    char *part_start;
+
+                    label_start = strchr(p, '=') + 1;
+                    label_end = strchr(p, ':');
+                    if (label_end) {
+                        *label = strndup(label_start,
+                                         (int) (label_end - label_start));
+                        part_start = strchr(p, ':') + 1;
+                        if (!strcmp(part_start, "auto")) {
+                            *partnum = -1;
+                        } else {
+                            *partnum = strtol(part_start, NULL, 0);
+                        }
+                    } else {
+                        ERROR("Warning: voldmanaged= flag malformed\n");
+                    }
                 }
                 break;
             }
@@ -227,7 +272,7 @@
     }
 }
 
-static struct fstab_rec *read_fstab(char *fstab_path)
+struct fstab *fs_mgr_read_fstab(const char *fstab_path)
 {
     FILE *fstab_file;
     int cnt, entries;
@@ -235,8 +280,12 @@
     char line[256];
     const char *delim = " \t";
     char *save_ptr, *p;
-    struct fstab_rec *fstab;
+    struct fstab *fstab;
+    struct fstab_rec *recs;
     char *key_loc;
+    long long part_length;
+    char *label;
+    int partnum;
 #define FS_OPTIONS_LEN 1024
     char tmp_fs_options[FS_OPTIONS_LEN];
 
@@ -269,7 +318,11 @@
         return 0;
     }
 
-    fstab = calloc(entries + 1, sizeof(struct fstab_rec));
+    /* Allocate and init the fstab structure */
+    fstab = calloc(1, sizeof(struct fstab));
+    fstab->num_entries = entries;
+    fstab->fstab_filename = strdup(fstab_path);
+    fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
 
     fseek(fstab_file, 0, SEEK_SET);
 
@@ -303,41 +356,48 @@
             ERROR("Error parsing mount source\n");
             return 0;
         }
-        fstab[cnt].blk_dev = strdup(p);
+        fstab->recs[cnt].blk_device = strdup(p);
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
-            ERROR("Error parsing mnt_point\n");
+            ERROR("Error parsing mount_point\n");
             return 0;
         }
-        fstab[cnt].mnt_point = strdup(p);
+        fstab->recs[cnt].mount_point = strdup(p);
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             ERROR("Error parsing fs_type\n");
             return 0;
         }
-        fstab[cnt].type = strdup(p);
+        fstab->recs[cnt].fs_type = strdup(p);
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             ERROR("Error parsing mount_flags\n");
             return 0;
         }
         tmp_fs_options[0] = '\0';
-        fstab[cnt].flags = parse_flags(p, mount_flags, 0, tmp_fs_options, FS_OPTIONS_LEN);
+        fstab->recs[cnt].flags = parse_flags(p, mount_flags,
+                                       NULL, NULL, NULL, NULL,
+                                       tmp_fs_options, FS_OPTIONS_LEN);
 
         /* fs_options are optional */
         if (tmp_fs_options[0]) {
-            fstab[cnt].fs_options = strdup(tmp_fs_options);
+            fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
         } else {
-            fstab[cnt].fs_options = NULL;
+            fstab->recs[cnt].fs_options = NULL;
         }
 
         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
             ERROR("Error parsing fs_mgr_options\n");
             return 0;
         }
-        fstab[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &key_loc, 0, 0);
-        fstab[cnt].key_loc = key_loc;
-
+        fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
+                                              &key_loc, &part_length,
+                                              &label, &partnum,
+                                              NULL, 0);
+        fstab->recs[cnt].key_loc = key_loc;
+        fstab->recs[cnt].length = part_length;
+        fstab->recs[cnt].label = label;
+        fstab->recs[cnt].partnum = partnum;
         cnt++;
     }
     fclose(fstab_file);
@@ -345,35 +405,45 @@
     return fstab;
 }
 
-static void free_fstab(struct fstab_rec *fstab)
+void fs_mgr_free_fstab(struct fstab *fstab)
 {
-    int i = 0;
+    int i;
 
-    while (fstab[i].blk_dev) {
+    for (i = 0; i < fstab->num_entries; i++) {
         /* Free the pointers return by strdup(3) */
-        free(fstab[i].blk_dev);
-        free(fstab[i].mnt_point);
-        free(fstab[i].type);
-        free(fstab[i].fs_options);
-        free(fstab[i].key_loc);
-
+        free(fstab->recs[i].blk_device);
+        free(fstab->recs[i].mount_point);
+        free(fstab->recs[i].fs_type);
+        free(fstab->recs[i].fs_options);
+        free(fstab->recs[i].key_loc);
+        free(fstab->recs[i].label);
         i++;
     }
 
-    /* Free the actual fstab array created by calloc(3) */
+    /* Free the fstab_recs array created by calloc(3) */
+    free(fstab->recs);
+
+    /* Free the fstab filename */
+    free(fstab->fstab_filename);
+
+    /* Free fstab */
     free(fstab);
 }
 
-static void check_fs(char *blk_dev, char *type, char *target)
+static void check_fs(char *blk_device, char *fs_type, char *target)
 {
-    pid_t pid;
     int status;
     int ret;
     long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
     char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro";
+    char *e2fsck_argv[] = {
+        E2FSCK_BIN,
+        "-y",
+        blk_device
+    };
 
     /* Check for the types of filesystems we know how to check */
-    if (!strcmp(type, "ext2") || !strcmp(type, "ext3") || !strcmp(type, "ext4")) {
+    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
         /*
          * First try to mount and unmount the filesystem.  We do this because
          * the kernel is more efficient than e2fsck in running the journal and
@@ -387,25 +457,19 @@
          * filesytsem due to an error, e2fsck is still run to do a full check
          * fix the filesystem.
          */
-        ret = mount(blk_dev, target, type, tmpmnt_flags, tmpmnt_opts);
-        if (! ret) {
+        ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
+        if (!ret) {
             umount(target);
         }
 
-        INFO("Running %s on %s\n", E2FSCK_BIN, blk_dev);
-        pid = fork();
-        if (pid > 0) {
-            /* Parent, wait for the child to return */
-            waitpid(pid, &status, 0);
-        } else if (pid == 0) {
-            /* child, run checker */
-            execlp(E2FSCK_BIN, E2FSCK_BIN, "-y", blk_dev, (char *)NULL);
+        INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
 
-            /* Only gets here on error */
-            ERROR("Cannot run fs_mgr binary %s\n", E2FSCK_BIN);
-        } else {
+        ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
+                                      &status, true, LOG_KLOG, true);
+
+        if (ret < 0) {
             /* No need to check for error in fork, we can't really handle it now */
-            ERROR("Fork failed trying to run %s\n", E2FSCK_BIN);
+            ERROR("Failed trying to run %s\n", E2FSCK_BIN);
         }
     }
 
@@ -443,49 +507,62 @@
     return ret;
 }
 
-int fs_mgr_mount_all(char *fstab_file)
+int fs_mgr_mount_all(struct fstab *fstab)
 {
     int i = 0;
     int encrypted = 0;
     int ret = -1;
     int mret;
-    struct fstab_rec *fstab = 0;
 
-    if (!(fstab = read_fstab(fstab_file))) {
+    if (!fstab) {
         return ret;
     }
 
-    for (i = 0; fstab[i].blk_dev; i++) {
-        if (fstab[i].fs_mgr_flags & MF_WAIT) {
-            wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT);
+    for (i = 0; i < fstab->num_entries; i++) {
+        /* Don't mount entries that are managed by vold */
+        if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) {
+            continue;
         }
 
-        if (fstab[i].fs_mgr_flags & MF_CHECK) {
-            check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point);
+        /* Skip raw partition entries such as boot, recovery, etc */
+        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
+            !strcmp(fstab->recs[i].fs_type, "mtd")) {
+            continue;
         }
 
-        mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type,
-                     fstab[i].flags, fstab[i].fs_options);
+        if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
+            wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
+        }
+
+        if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
+            check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
+                     fstab->recs[i].mount_point);
+        }
+
+        mret = mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
+                     fstab->recs[i].fs_type, fstab->recs[i].flags,
+                     fstab->recs[i].fs_options);
         if (!mret) {
             /* Success!  Go get the next one */
             continue;
         }
 
         /* mount(2) returned an error, check if it's encrypted and deal with it */
-        if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) {
+        if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) &&
+            !partition_wiped(fstab->recs[i].blk_device)) {
             /* Need to mount a tmpfs at this mountpoint for now, and set
              * properties that vold will query later for decrypting
              */
-            if (mount("tmpfs", fstab[i].mnt_point, "tmpfs",
+            if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs",
                   MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) {
                 ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n",
-                        fstab[i].mnt_point);
+                        fstab->recs[i].mount_point);
                 goto out;
             }
             encrypted = 1;
         } else {
             ERROR("Cannot mount filesystem on %s at %s\n",
-                    fstab[i].blk_dev, fstab[i].mnt_point);
+                    fstab->recs[i].blk_device, fstab->recs[i].mount_point);
             goto out;
         }
     }
@@ -497,49 +574,57 @@
     }
 
 out:
-    free_fstab(fstab);
     return ret;
 }
 
-/* If tmp_mnt_point is non-null, mount the filesystem there.  This is for the
+/* If tmp_mount_point is non-null, mount the filesystem there.  This is for the
  * tmp mount we do to check the user password
  */
-int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point)
+int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
+                    char *tmp_mount_point)
 {
     int i = 0;
     int ret = -1;
-    struct fstab_rec *fstab = 0;
     char *m;
 
-    if (!(fstab = read_fstab(fstab_file))) {
+    if (!fstab) {
         return ret;
     }
 
-    for (i = 0; fstab[i].blk_dev; i++) {
-        if (!fs_match(fstab[i].mnt_point, n_name)) {
+    for (i = 0; i < fstab->num_entries; i++) {
+        if (!fs_match(fstab->recs[i].mount_point, n_name)) {
             continue;
         }
 
         /* We found our match */
-        /* First check the filesystem if requested */
-        if (fstab[i].fs_mgr_flags & MF_WAIT) {
-            wait_for_file(n_blk_dev, WAIT_TIMEOUT);
+        /* If this is a raw partition, report an error */
+        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
+            !strcmp(fstab->recs[i].fs_type, "mtd")) {
+            ERROR("Cannot mount filesystem of type %s on %s\n",
+                  fstab->recs[i].fs_type, n_blk_device);
+            goto out;
         }
 
-        if (fstab[i].fs_mgr_flags & MF_CHECK) {
-            check_fs(n_blk_dev, fstab[i].type, fstab[i].mnt_point);
+        /* First check the filesystem if requested */
+        if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
+            wait_for_file(n_blk_device, WAIT_TIMEOUT);
+        }
+
+        if (fstab->recs[i].fs_mgr_flags & MF_CHECK) {
+            check_fs(n_blk_device, fstab->recs[i].fs_type,
+                     fstab->recs[i].mount_point);
         }
 
         /* Now mount it where requested */
-        if (tmp_mnt_point) {
-            m = tmp_mnt_point;
+        if (tmp_mount_point) {
+            m = tmp_mount_point;
         } else {
-            m = fstab[i].mnt_point;
+            m = fstab->recs[i].mount_point;
         }
-        if (mount(n_blk_dev, m, fstab[i].type,
-                  fstab[i].flags, fstab[i].fs_options)) {
+        if (mount(n_blk_device, m, fstab->recs[i].fs_type,
+                  fstab->recs[i].flags, fstab->recs[i].fs_options)) {
             ERROR("Cannot mount filesystem on %s at %s\n",
-                    n_blk_dev, m);
+                    n_blk_device, m);
             goto out;
         } else {
             ret = 0;
@@ -548,10 +633,9 @@
     }
 
     /* We didn't find a match, say so and return an error */
-    ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point);
+    ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point);
 
 out:
-    free_fstab(fstab);
     return ret;
 }
 
@@ -574,65 +658,128 @@
     return 0;
 }
 
-int fs_mgr_unmount_all(char *fstab_file)
+int fs_mgr_unmount_all(struct fstab *fstab)
 {
     int i = 0;
     int ret = 0;
-    struct fstab_rec *fstab = 0;
 
-    if (!(fstab = read_fstab(fstab_file))) {
+    if (!fstab) {
         return -1;
     }
 
-    while (fstab[i].blk_dev) {
-        if (umount(fstab[i].mnt_point)) {
-            ERROR("Cannot unmount filesystem at %s\n", fstab[i].mnt_point);
+    while (fstab->recs[i].blk_device) {
+        if (umount(fstab->recs[i].mount_point)) {
+            ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point);
             ret = -1;
         }
         i++;
     }
 
-    free_fstab(fstab);
     return ret;
 }
 /*
  * key_loc must be at least PROPERTY_VALUE_MAX bytes long
  *
- * real_blk_dev must be at least PROPERTY_VALUE_MAX bytes long
+ * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
  */
-int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size)
+int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size)
 {
     int i = 0;
-    struct fstab_rec *fstab = 0;
 
-    if (!(fstab = read_fstab(fstab_file))) {
+    if (!fstab) {
         return -1;
     }
     /* Initialize return values to null strings */
     if (key_loc) {
         *key_loc = '\0';
     }
-    if (real_blk_dev) {
-        *real_blk_dev = '\0';
+    if (real_blk_device) {
+        *real_blk_device = '\0';
     }
 
     /* Look for the encryptable partition to find the data */
-    for (i = 0; fstab[i].blk_dev; i++) {
-        if (!(fstab[i].fs_mgr_flags & MF_CRYPT)) {
+    for (i = 0; i < fstab->num_entries; i++) {
+        /* Don't deal with vold managed enryptable partitions here */
+        if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) {
+            continue;
+        }
+        if (!(fstab->recs[i].fs_mgr_flags & MF_CRYPT)) {
             continue;
         }
 
         /* We found a match */
         if (key_loc) {
-            strlcpy(key_loc, fstab[i].key_loc, size);
+            strlcpy(key_loc, fstab->recs[i].key_loc, size);
         }
-        if (real_blk_dev) {
-            strlcpy(real_blk_dev, fstab[i].blk_dev, size);
+        if (real_blk_device) {
+            strlcpy(real_blk_device, fstab->recs[i].blk_device, size);
         }
         break;
     }
 
-    free_fstab(fstab);
     return 0;
 }
 
+/* Add an entry to the fstab, and return 0 on success or -1 on error */
+int fs_mgr_add_entry(struct fstab *fstab,
+                     const char *mount_point, const char *fs_type,
+                     const char *blk_device, long long length)
+{
+    struct fstab_rec *new_fstab_recs;
+    int n = fstab->num_entries;
+
+    new_fstab_recs = (struct fstab_rec *)
+                     realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
+
+    if (!new_fstab_recs) {
+        return -1;
+    }
+
+    /* A new entry was added, so initialize it */
+     memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
+     new_fstab_recs[n].mount_point = strdup(mount_point);
+     new_fstab_recs[n].fs_type = strdup(fs_type);
+     new_fstab_recs[n].blk_device = strdup(blk_device);
+     new_fstab_recs[n].length = 0;
+
+     /* Update the fstab struct */
+     fstab->recs = new_fstab_recs;
+     fstab->num_entries++;
+
+     return 0;
+}
+
+struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
+{
+    int i;
+
+    if (!fstab) {
+        return NULL;
+    }
+
+    for (i = 0; i < fstab->num_entries; i++) {
+        int len = strlen(fstab->recs[i].mount_point);
+        if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
+            (path[len] == '\0' || path[len] == '/')) {
+            return &fstab->recs[i];
+        }
+    }
+
+    return NULL;
+}
+
+int fs_mgr_is_voldmanaged(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
+}
+
+int fs_mgr_is_nonremovable(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_NONREMOVABLE;
+}
+
+int fs_mgr_is_encryptable(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_CRYPT;
+}
+
diff --git a/fs_mgr/fs_mgr_main.c b/fs_mgr/fs_mgr_main.c
index 81febf1..4bde4a1 100644
--- a/fs_mgr/fs_mgr_main.c
+++ b/fs_mgr/fs_mgr_main.c
@@ -82,7 +82,8 @@
     int n_flag=0;
     char *n_name;
     char *n_blk_dev;
-    char *fstab;
+    char *fstab_file;
+    struct fstab *fstab;
 
     klog_init();
     klog_set_level(6);
@@ -90,7 +91,9 @@
     parse_options(argc, argv, &a_flag, &u_flag, &n_flag, &n_name, &n_blk_dev);
 
     /* The name of the fstab file is last, after the option */
-    fstab = argv[argc - 1];
+    fstab_file = argv[argc - 1];
+
+    fstab = fs_mgr_read_fstab(fstab_file);
 
     if (a_flag) {
         return fs_mgr_mount_all(fstab);
@@ -103,6 +106,8 @@
         exit(1);
     }
 
+    fs_mgr_free_fstab(fstab);
+
     /* Should not get here */
     exit(1);
 }
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 175fdab..75dad49 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -25,16 +25,6 @@
 
 #define CRYPTO_TMPFS_OPTIONS "size=128m,mode=0771,uid=1000,gid=1000"
 
-struct fstab_rec {
-    char *blk_dev;
-    char *mnt_point;
-    char *type;
-    unsigned long flags;
-    char *fs_options;
-    int fs_mgr_flags;
-    char *key_loc;
-};
-
 #define WAIT_TIMEOUT 5
 
 /* fstab has the following format:
@@ -59,8 +49,8 @@
  *                     run an fscheck program on the <source> before mounting the filesystem.
  *                     If check is specifed on a read-only filesystem, it is ignored.
  *                     Also, "encryptable" means that filesystem can be encrypted.
- *                     The "encryptable" flag _MUST_ be followed by a : and a string which
- *                     is the location of the encryption keys.  I can either be a path
+ *                     The "encryptable" flag _MUST_ be followed by a = and a string which
+ *                     is the location of the encryption keys.  It can either be a path
  *                     to a file or partition which contains the keys, or the word "footer"
  *                     which means the keys are in the last 16 Kbytes of the partition
  *                     containing the filesystem.
@@ -72,9 +62,13 @@
  *
  */
 
-#define MF_WAIT      0x1
-#define MF_CHECK     0x2
-#define MF_CRYPT     0x4
+#define MF_WAIT         0x1
+#define MF_CHECK        0x2
+#define MF_CRYPT        0x4
+#define MF_NONREMOVABLE 0x8
+#define MF_VOLDMANAGED  0x10
+#define MF_LENGTH       0x20
+#define MF_RECOVERYONLY 0x40
 
 #endif /* __CORE_FS_MGR_PRIV_H */
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 76abb83..05bcc1b 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -17,11 +17,48 @@
 #ifndef __CORE_FS_MGR_H
 #define __CORE_FS_MGR_H
 
-int fs_mgr_mount_all(char *fstab_file);
-int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct fstab {
+    int num_entries;
+    struct fstab_rec *recs;
+    char *fstab_filename;
+};
+
+struct fstab_rec {
+    char *blk_device;
+    char *mount_point;
+    char *fs_type;
+    unsigned long flags;
+    char *fs_options;
+    int fs_mgr_flags;
+    char *key_loc;
+    long long length;
+    char *label;
+    int partnum;
+};
+
+struct fstab *fs_mgr_read_fstab(const char *fstab_path);
+void fs_mgr_free_fstab(struct fstab *fstab);
+int fs_mgr_mount_all(struct fstab *fstab);
+int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
+                    char *tmp_mount_point);
 int fs_mgr_do_tmpfs_mount(char *n_name);
-int fs_mgr_unmount_all(char *fstab_file);
-int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size);
+int fs_mgr_unmount_all(struct fstab *fstab);
+int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
+                          char *real_blk_device, int size);
+int fs_mgr_add_entry(struct fstab *fstab,
+                     const char *mount_point, const char *fs_type,
+                     const char *blk_device, long long length);
+struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path);
+int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
+int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
+int fs_mgr_is_encryptable(struct fstab_rec *fstab);
+#ifdef __cplusplus
+}
+#endif
 
 #endif /* __CORE_FS_MGR_H */
 
diff --git a/include/cutils/aref.h b/include/cutils/aref.h
new file mode 100644
index 0000000..460ac02
--- /dev/null
+++ b/include/cutils/aref.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _CUTILS_AREF_H_
+#define _CUTILS_AREF_H_
+
+#include <stddef.h>
+#include <sys/cdefs.h>
+
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#endif
+
+__BEGIN_DECLS
+
+#define AREF_TO_ITEM(aref, container, member) \
+    (container *) (((char*) (aref)) - offsetof(container, member))
+
+struct aref
+{
+    volatile int32_t count;
+};
+
+static inline void aref_init(struct aref *r)
+{
+    r->count = 1;
+}
+
+static inline int32_t aref_count(struct aref *r)
+{
+    return r->count;
+}
+
+static inline void aref_get(struct aref *r)
+{
+    android_atomic_inc(&r->count);
+}
+
+static inline void aref_put(struct aref *r, void (*release)(struct aref *))
+{
+    if (android_atomic_dec(&r->count) == 1)
+        release(r);
+}
+
+__END_DECLS
+
+#endif // _CUTILS_AREF_H_
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
index 1b3b762..eb44236 100644
--- a/include/cutils/bitops.h
+++ b/include/cutils/bitops.h
@@ -17,10 +17,79 @@
 #ifndef __CUTILS_BITOPS_H
 #define __CUTILS_BITOPS_H
 
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
+/*
+ * Bitmask Operations
+ *
+ * Note this doesn't provide any locking/exclusion, and isn't atomic.
+ * Additionally no bounds checking is done on the bitmask array.
+ *
+ * Example:
+ *
+ * int num_resources;
+ * unsigned int resource_bits[BITS_TO_WORDS(num_resources)];
+ * bitmask_init(resource_bits, num_resources);
+ * ...
+ * int bit = bitmask_ffz(resource_bits, num_resources);
+ * bitmask_set(resource_bits, bit);
+ * ...
+ * if (bitmask_test(resource_bits, bit)) { ... }
+ * ...
+ * bitmask_clear(resource_bits, bit);
+ *
+ */
+
+#define BITS_PER_WORD    (sizeof(unsigned int) * 8)
+#define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD)
+#define BIT_IN_WORD(x)   ((x) % BITS_PER_WORD)
+#define BIT_WORD(x)      ((x) / BITS_PER_WORD)
+#define BIT_MASK(x)      (1 << BIT_IN_WORD(x))
+
+static inline void bitmask_init(unsigned int *bitmask, int num_bits)
+{
+    memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int));
+}
+
+static inline int bitmask_ffz(unsigned int *bitmask, int num_bits)
+{
+    int bit, result;
+    unsigned int i;
+
+    for (i = 0; i < BITS_TO_WORDS(num_bits); i++) {
+        bit = ffs(~bitmask[i]);
+        if (bit) {
+            // ffs is 1-indexed, return 0-indexed result
+            bit--;
+            result = BITS_PER_WORD * i + bit;
+            if (result >= num_bits)
+                return -1;
+            return result;
+        }
+    }
+    return -1;
+}
+
+static inline void bitmask_set(unsigned int *bitmask, int bit)
+{
+    bitmask[BIT_WORD(bit)] |= BIT_MASK(bit);
+}
+
+static inline void bitmask_clear(unsigned int *bitmask, int bit)
+{
+    bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit);
+}
+
+static inline bool bitmask_test(unsigned int *bitmask, int bit)
+{
+    return bitmask[BIT_WORD(bit)] & BIT_MASK(bit);
+}
+
 static inline int popcount(unsigned int x)
 {
     return __builtin_popcount(x);
diff --git a/include/cutils/klog.h b/include/cutils/klog.h
index 1335543..ba728ac 100644
--- a/include/cutils/klog.h
+++ b/include/cutils/klog.h
@@ -17,12 +17,18 @@
 #ifndef _CUTILS_KLOG_H_
 #define _CUTILS_KLOG_H_
 
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
 void klog_init(void);
 void klog_set_level(int level);
 void klog_close(void);
 void klog_write(int level, const char *fmt, ...)
     __attribute__ ((format(printf, 2, 3)));
 
+__END_DECLS
+
 #define KLOG_ERROR(tag,x...)   klog_write(3, "<3>" tag ": " x)
 #define KLOG_WARNING(tag,x...) klog_write(4, "<4>" tag ": " x)
 #define KLOG_NOTICE(tag,x...)  klog_write(5, "<5>" tag ": " x)
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
new file mode 100644
index 0000000..29034ca
--- /dev/null
+++ b/include/cutils/trace.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBS_CUTILS_TRACE_H
+#define _LIBS_CUTILS_TRACE_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <cutils/compiler.h>
+
+#ifdef ANDROID_SMP
+#include <cutils/atomic-inline.h>
+#else
+#include <cutils/atomic.h>
+#endif
+
+__BEGIN_DECLS
+
+/**
+ * The ATRACE_TAG macro can be defined before including this header to trace
+ * using one of the tags defined below.  It must be defined to one of the
+ * following ATRACE_TAG_* macros.  The trace tag is used to filter tracing in
+ * userland to avoid some of the runtime cost of tracing when it is not desired.
+ *
+ * Defining ATRACE_TAG to be ATRACE_TAG_ALWAYS will result in the tracing always
+ * being enabled - this should ONLY be done for debug code, as userland tracing
+ * has a performance cost even when the trace is not being recorded.  Defining
+ * ATRACE_TAG to be ATRACE_TAG_NEVER or leaving ATRACE_TAG undefined will result
+ * in the tracing always being disabled.
+ *
+ * ATRACE_TAG_HAL should be bitwise ORed with the relevant tags for tracing
+ * within a hardware module.  For example a camera hardware module would set:
+ * #define ATRACE_TAG  (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
+ *
+ * Keep these in sync with frameworks/base/core/java/android/os/Trace.java.
+ */
+#define ATRACE_TAG_NEVER            0       // This tag is never enabled.
+#define ATRACE_TAG_ALWAYS           (1<<0)  // This tag is always enabled.
+#define ATRACE_TAG_GRAPHICS         (1<<1)
+#define ATRACE_TAG_INPUT            (1<<2)
+#define ATRACE_TAG_VIEW             (1<<3)
+#define ATRACE_TAG_WEBVIEW          (1<<4)
+#define ATRACE_TAG_WINDOW_MANAGER   (1<<5)
+#define ATRACE_TAG_ACTIVITY_MANAGER (1<<6)
+#define ATRACE_TAG_SYNC_MANAGER     (1<<7)
+#define ATRACE_TAG_AUDIO            (1<<8)
+#define ATRACE_TAG_VIDEO            (1<<9)
+#define ATRACE_TAG_CAMERA           (1<<10)
+#define ATRACE_TAG_HAL              (1<<11)
+#define ATRACE_TAG_APP              (1<<12)
+#define ATRACE_TAG_RESOURCES        (1<<13)
+#define ATRACE_TAG_DALVIK           (1<<14)
+#define ATRACE_TAG_LAST             ATRACE_TAG_DALVIK
+
+// Reserved for initialization.
+#define ATRACE_TAG_NOT_READY        (1LL<<63)
+
+#define ATRACE_TAG_VALID_MASK ((ATRACE_TAG_LAST - 1) | ATRACE_TAG_LAST)
+
+#ifndef ATRACE_TAG
+#define ATRACE_TAG ATRACE_TAG_NEVER
+#elif ATRACE_TAG > ATRACE_TAG_VALID_MASK
+#error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
+#endif
+
+#ifdef HAVE_ANDROID_OS
+/**
+ * Maximum size of a message that can be logged to the trace buffer.
+ * Note this message includes a tag, the pid, and the string given as the name.
+ * Names should be kept short to get the most use of the trace buffer.
+ */
+#define ATRACE_MESSAGE_LENGTH 1024
+
+/**
+ * Opens the trace file for writing and reads the property for initial tags.
+ * The atrace.tags.enableflags property sets the tags to trace.
+ * This function should not be explicitly called, the first call to any normal
+ * trace function will cause it to be run safely.
+ */
+void atrace_setup();
+
+/**
+ * If tracing is ready, set atrace_enabled_tags to the system property
+ * debug.atrace.tags.enableflags. Can be used as a sysprop change callback.
+ */
+void atrace_update_tags();
+
+/**
+ * Set whether the process is debuggable.  By default the process is not
+ * considered debuggable.  If the process is not debuggable then application-
+ * level tracing is not allowed unless the ro.debuggable system property is
+ * set to '1'.
+ */
+void atrace_set_debuggable(bool debuggable);
+
+/**
+ * Set whether tracing is enabled for the current process.  This is used to
+ * prevent tracing within the Zygote process.
+ */
+void atrace_set_tracing_enabled(bool enabled);
+
+/**
+ * Flag indicating whether setup has been completed, initialized to 0.
+ * Nonzero indicates setup has completed.
+ * Note: This does NOT indicate whether or not setup was successful.
+ */
+extern volatile int32_t atrace_is_ready;
+
+/**
+ * Set of ATRACE_TAG flags to trace for, initialized to ATRACE_TAG_NOT_READY.
+ * A value of zero indicates setup has failed.
+ * Any other nonzero value indicates setup has succeeded, and tracing is on.
+ */
+extern uint64_t atrace_enabled_tags;
+
+/**
+ * Handle to the kernel's trace buffer, initialized to -1.
+ * Any other value indicates setup has succeeded, and is a valid fd for tracing.
+ */
+extern int atrace_marker_fd;
+
+/**
+ * atrace_init readies the process for tracing by opening the trace_marker file.
+ * Calling any trace function causes this to be run, so calling it is optional.
+ * This can be explicitly run to avoid setup delay on first trace function.
+ */
+#define ATRACE_INIT() atrace_init()
+static inline void atrace_init()
+{
+    if (CC_UNLIKELY(!android_atomic_acquire_load(&atrace_is_ready))) {
+        atrace_setup();
+    }
+}
+
+/**
+ * Get the mask of all tags currently enabled.
+ * It can be used as a guard condition around more expensive trace calculations.
+ * Every trace function calls this, which ensures atrace_init is run.
+ */
+#define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()
+static inline uint64_t atrace_get_enabled_tags()
+{
+    atrace_init();
+    return atrace_enabled_tags;
+}
+
+/**
+ * Test if a given tag is currently enabled.
+ * Returns nonzero if the tag is enabled, otherwise zero.
+ * It can be used as a guard condition around more expensive trace calculations.
+ */
+#define ATRACE_ENABLED() atrace_is_tag_enabled(ATRACE_TAG)
+static inline uint64_t atrace_is_tag_enabled(uint64_t tag)
+{
+    return atrace_get_enabled_tags() & tag;
+}
+
+/**
+ * Trace the beginning of a context.  name is used to identify the context.
+ * This is often used to time function execution.
+ */
+#define ATRACE_BEGIN(name) atrace_begin(ATRACE_TAG, name)
+static inline void atrace_begin(uint64_t tag, const char* name)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "B|%d|%s", getpid(), name);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+/**
+ * Trace the end of a context.
+ * This should match up (and occur after) a corresponding ATRACE_BEGIN.
+ */
+#define ATRACE_END() atrace_end(ATRACE_TAG)
+static inline void atrace_end(uint64_t tag)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char c = 'E';
+        write(atrace_marker_fd, &c, 1);
+    }
+}
+
+/**
+ * Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
+ * contexts, asynchronous events do not need to be nested. The name describes
+ * the event, and the cookie provides a unique identifier for distinguishing
+ * simultaneous events. The name and cookie used to begin an event must be
+ * used to end it.
+ */
+#define ATRACE_ASYNC_BEGIN(name, cookie) \
+    atrace_async_begin(ATRACE_TAG, name, cookie)
+static inline void atrace_async_begin(uint64_t tag, const char* name,
+        int32_t cookie)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "S|%d|%s|%d", getpid(),
+                name, cookie);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+/**
+ * Trace the end of an asynchronous event.
+ * This should have a corresponding ATRACE_ASYNC_BEGIN.
+ */
+#define ATRACE_ASYNC_END(name, cookie) atrace_async_end(ATRACE_TAG, name, cookie)
+static inline void atrace_async_end(uint64_t tag, const char* name,
+        int32_t cookie)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "F|%d|%s|%d", getpid(),
+                name, cookie);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+
+/**
+ * Traces an integer counter value.  name is used to identify the counter.
+ * This can be used to track how a value changes over time.
+ */
+#define ATRACE_INT(name, value) atrace_int(ATRACE_TAG, name, value)
+static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%d",
+                getpid(), name, value);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
+#else // not HAVE_ANDROID_OS
+
+#define ATRACE_INIT()
+#define ATRACE_GET_ENABLED_TAGS()
+#define ATRACE_ENABLED()
+#define ATRACE_BEGIN(name)
+#define ATRACE_END()
+#define ATRACE_ASYNC_BEGIN(name, cookie)
+#define ATRACE_ASYNC_END(name, cookie)
+#define ATRACE_INT(name, value)
+
+#endif // not HAVE_ANDROID_OS
+
+__END_DECLS
+
+#endif // _LIBS_CUTILS_TRACE_H
diff --git a/include/cutils/zygote.h b/include/cutils/zygote.h
index 22721a6..a7480d3 100644
--- a/include/cutils/zygote.h
+++ b/include/cutils/zygote.h
@@ -23,7 +23,6 @@
 
 int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
 int zygote_run(int argc, const char **argv);
-int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int));
 
 #ifdef __cplusplus
 }
diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h
index d25e58f..bd2c957 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -27,11 +27,18 @@
                           char *ipaddr,
                           char *gateway,
                           uint32_t *prefixLength,
-                          char *dns1,
-                          char *dns2,
+                          char *dns[],
                           char *server,
                           uint32_t *lease,
                           char *vendorInfo);
+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);
 extern int dhcp_stop(const char *ifname);
 extern int dhcp_release_lease(const char *ifname);
 extern char *dhcp_get_errmsg();
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 53bd166..5d363a7 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -71,6 +71,7 @@
 #define AID_SDCARD_R      1028  /* external storage read access */
 #define AID_CLAT          1029  /* clat part of nat464 */
 #define AID_LOOP_RADIO    1030  /* loop radio devices */
+#define AID_MEDIA_DRM     1031  /* MediaDrm plugins */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
 #define AID_CACHE         2001  /* cache access */
@@ -150,6 +151,7 @@
     { "misc",      AID_MISC, },
     { "nobody",    AID_NOBODY, },
     { "clat",      AID_CLAT, },
+    { "mediadrm",  AID_MEDIA_DRM, },
 };
 
 #define android_id_count \
@@ -187,6 +189,7 @@
     { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
     { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },
     { 00755, AID_ROOT,   AID_ROOT,   0, "system/etc/ppp" },
+    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },
     { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },
     { 00755, AID_ROOT,   AID_ROOT,   0, 0 },
 };
@@ -204,7 +207,6 @@
     { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
     { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.testmenu" },
     { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
-    { 00440, AID_BLUETOOTH, AID_BLUETOOTH, 0, "system/etc/dbus.conf" },
     { 00444, AID_RADIO,     AID_AUDIO,     0, "system/etc/AudioPara4.csv" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
@@ -234,6 +236,7 @@
     { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
diff --git a/include/sync/sw_sync.h b/include/sync/sw_sync.h
new file mode 100644
index 0000000..3bf4110
--- /dev/null
+++ b/include/sync/sw_sync.h
@@ -0,0 +1,37 @@
+/*
+ *  sw_sync.h
+ *
+ *   Copyright 2013 Google, Inc
+ *
+ *  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 __SYS_CORE_SW_SYNC_H
+#define __SYS_CORE_SW_SYNC_H
+
+#include "sync.h"
+
+__BEGIN_DECLS
+
+/*
+ * sw_sync is mainly intended for testing and should not be compiled into
+ * production kernels
+ */
+
+int sw_sync_timeline_create(void);
+int sw_sync_timeline_inc(int fd, unsigned count);
+int sw_sync_fence_create(int fd, const char *name, unsigned value);
+
+__END_DECLS
+
+#endif /* __SYS_CORE_SW_SYNC_H */
diff --git a/include/sync/sync.h b/include/sync/sync.h
index 918acf6..2e5d82f 100644
--- a/include/sync/sync.h
+++ b/include/sync/sync.h
@@ -49,14 +49,6 @@
                                   struct sync_pt_info *itr);
 void sync_fence_info_free(struct sync_fence_info_data *info);
 
-/* sw_sync is mainly inteded for testing and should not be complied into
- * production kernels
- */
-
-int sw_sync_timeline_create(void);
-int sw_sync_timeline_inc(int fd, unsigned count);
-int sw_sync_fence_create(int fd, const char *name, unsigned value);
-
 __END_DECLS
 
 #endif /* __SYS_CORE_SYNC_H */
diff --git a/include/system/audio.h b/include/system/audio.h
index d246070..da235dd 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -239,6 +239,7 @@
 
     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 |
diff --git a/include/system/graphics.h b/include/system/graphics.h
index 82b5fcc..ed493f5 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -17,6 +17,8 @@
 #ifndef SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
 #define SYSTEM_CORE_INCLUDE_ANDROID_GRAPHICS_H
 
+#include <stdint.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -87,6 +89,54 @@
      */
     HAL_PIXEL_FORMAT_YV12   = 0x32315659, // YCrCb 4:2:0 Planar
 
+
+    /*
+     * Android Y8 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y8 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 8 bits.
+     *
+     * It is equivalent to just the Y plane from YV12.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   size = stride * height
+     *
+     */
+    HAL_PIXEL_FORMAT_Y8     = 0x20203859,
+
+    /*
+     * Android Y16 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y16 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 16 bits.
+     *
+     * It is just like Y8, but has double the bits per pixel (little endian).
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     */
+    HAL_PIXEL_FORMAT_Y16    = 0x20363159,
+
     /*
      * Android RAW sensor format:
      *
@@ -140,12 +190,64 @@
      */
     HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22,
 
+    /*
+     * Android flexible YCbCr 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
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * struct android_ycbcr (below) is the the struct used to describe it.
+     *
+     * This format must be accepted by the gralloc module when
+     * USAGE_HW_CAMERA_WRITE and USAGE_SW_READ_* are set.
+     *
+     * This format is locked for use by gralloc's (*lock_ycbcr) method, and
+     * locking with the (*lock) method will return an error.
+     */
+    HAL_PIXEL_FORMAT_YCbCr_420_888 = 0x23,
+
     /* Legacy formats (deprecated), used by ImageFormat.java */
     HAL_PIXEL_FORMAT_YCbCr_422_SP       = 0x10, // NV16
     HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11, // NV21
     HAL_PIXEL_FORMAT_YCbCr_422_I        = 0x14, // YUY2
 };
 
+/*
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with HAL_PIXEL_FORMAT_YCbCr_*_888.
+ *
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. HAL_PIXEL_FORMAT_YCbCr_420_888 has subsampling 4:2:0.
+ *
+ * Buffers must have a 8 bit depth.
+ *
+ * @y, @cb, and @cr point to the first byte of their respective planes.
+ *
+ * Stride describes the distance in bytes from the first value of one row of
+ * the image to the first value of the next row.  It includes the width of the
+ * image plus padding.
+ * @ystride is the stride of the luma plane.
+ * @cstride is the stride of the chroma planes.
+ *
+ * @chroma_step is the distance in bytes from one chroma pixel value to the
+ * next.  This is 2 bytes for semiplanar (because chroma values are interleaved
+ * and each chroma value is one byte) and 1 for planar.
+ */
+
+struct android_ycbcr {
+    void *y;
+    void *cb;
+    void *cr;
+    size_t ystride;
+    size_t cstride;
+    size_t chroma_step;
+
+    /** reserved for future use, set to 0 by gralloc's (*lock_ycbcr)() */
+    uint32_t reserved[8];
+};
 
 /**
  * Transformation definitions
diff --git a/include/system/window.h b/include/system/window.h
index 4698fb3..b8a19c8 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -321,7 +321,6 @@
 enum {
     NATIVE_WINDOW_FRAMEBUFFER               = 0, /* FramebufferNativeWindow */
     NATIVE_WINDOW_SURFACE                   = 1, /* Surface */
-    NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT    = 2, /* SurfaceTextureClient */
 };
 
 /* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
diff --git a/init/Android.mk b/init/Android.mk
index 00d2144..ef62bce 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -35,7 +35,9 @@
 
 LOCAL_STATIC_LIBRARIES := \
 	libfs_mgr \
+	liblogwrap \
 	libcutils \
+	liblog \
 	libc \
 	libselinux
 
diff --git a/init/builtins.c b/init/builtins.c
index dc7900e..0f9f131 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -464,6 +464,7 @@
     int child_ret = -1;
     int status;
     const char *prop;
+    struct fstab *fstab;
 
     if (nargs != 2) {
         return -1;
@@ -487,7 +488,9 @@
     } else if (pid == 0) {
         /* child, call fs_mgr_mount_all() */
         klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */
-        child_ret = fs_mgr_mount_all(args[1]);
+        fstab = fs_mgr_read_fstab(args[1]);
+        child_ret = fs_mgr_mount_all(fstab);
+        fs_mgr_free_fstab(fstab);
         if (child_ret == -1) {
             ERROR("fs_mgr_mount_all returned an error\n");
         }
diff --git a/init/init.c b/init/init.c
index 39df0ff..f8b21e6 100755
--- a/init/init.c
+++ b/init/init.c
@@ -879,6 +879,7 @@
      */
     restorecon("/dev");
     restorecon("/dev/socket");
+    restorecon("/dev/__properties__");
 
     is_charger = !strcmp(bootmode, "charger");
 
diff --git a/init/init_parser.c b/init/init_parser.c
index beb9188..686640e 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -571,6 +571,7 @@
     act = calloc(1, sizeof(*act));
     act->name = name;
     list_init(&act->commands);
+    list_init(&act->qlist);
 
     cmd = calloc(1, sizeof(*cmd));
     cmd->func = func;
@@ -583,7 +584,9 @@
 
 void action_add_queue_tail(struct action *act)
 {
-    list_add_tail(&action_queue, &act->qlist);
+    if (list_empty(&act->qlist)) {
+        list_add_tail(&action_queue, &act->qlist);
+    }
 }
 
 struct action *action_remove_queue_head(void)
@@ -594,6 +597,7 @@
         struct listnode *node = list_head(&action_queue);
         struct action *act = node_to_item(node, struct action, qlist);
         list_remove(node);
+        list_init(node);
         return act;
     }
 }
@@ -825,6 +829,7 @@
     act = calloc(1, sizeof(*act));
     act->name = args[1];
     list_init(&act->commands);
+    list_init(&act->qlist);
     list_add_tail(&action_list, &act->alist);
         /* XXX add to hash */
     return act;
diff --git a/init/keychords.c b/init/keychords.c
index aab0819..061d157 100644
--- a/init/keychords.c
+++ b/init/keychords.c
@@ -100,10 +100,7 @@
     int ret;
     __u16 id;
 
-    // only handle keychords if ro.debuggable is set or adb is enabled.
-    // the logic here is that bugreports should be enabled in userdebug or eng builds
-    // and on user builds for users that are developers.
-    debuggable = property_get("ro.debuggable");
+    // Only handle keychords if adb is enabled.
     adb_enabled = property_get("init.svc.adbd");
     ret = read(keychord_fd, &id, sizeof(id));
     if (ret != sizeof(id)) {
@@ -111,8 +108,7 @@
         return;
     }
 
-    if ((debuggable && !strcmp(debuggable, "1")) ||
-        (adb_enabled && !strcmp(adb_enabled, "running"))) {
+    if ((adb_enabled && !strcmp(adb_enabled, "running"))) {
         svc = service_find_by_keychord(id);
         if (svc) {
             INFO("starting service %s from keychord\n", svc->name);
diff --git a/init/property_service.c b/init/property_service.c
index 48488be..d7740c3 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -27,6 +27,7 @@
 
 #include <cutils/misc.h>
 #include <cutils/sockets.h>
+#include <cutils/multiuser.h>
 
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
@@ -123,7 +124,7 @@
         /* dev is a tmpfs that we can use to carve a shared workspace
          * out of, so let's do that...
          */
-    fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600);
+    fd = open(PROP_FILENAME, O_RDWR | O_CREAT | O_NOFOLLOW, 0644);
     if (fd < 0)
         return -1;
 
@@ -136,12 +137,10 @@
 
     close(fd);
 
-    fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW);
+    fd = open(PROP_FILENAME, O_RDONLY | O_NOFOLLOW);
     if (fd < 0)
         return -1;
 
-    unlink("/dev/__properties__");
-
     w->data = data;
     w->size = size;
     w->fd = fd;
@@ -272,12 +271,19 @@
 static int check_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx)
 {
     int i;
+    unsigned int app_id;
+
     if(!strncmp(name, "ro.", 3))
         name +=3;
 
     if (uid == 0)
         return check_mac_perms(name, sctx);
 
+    app_id = multiuser_get_app_id(uid);
+    if (app_id == AID_BLUETOOTH) {
+        uid = app_id;
+    }
+
     for (i = 0; property_perms[i].prefix; i++) {
         if (strncmp(property_perms[i].prefix, name,
                     strlen(property_perms[i].prefix)) == 0) {
diff --git a/libcorkscrew/Android.mk b/libcorkscrew/Android.mk
index 25512e2..d62c2d5 100644
--- a/libcorkscrew/Android.mk
+++ b/libcorkscrew/Android.mk
@@ -49,7 +49,7 @@
 LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH
 endif
 
-LOCAL_SHARED_LIBRARIES += libdl libcutils libgccdemangle
+LOCAL_SHARED_LIBRARIES += libdl libcutils liblog libgccdemangle
 
 LOCAL_CFLAGS += -std=gnu99 -Werror
 LOCAL_MODULE := libcorkscrew
@@ -75,7 +75,7 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES += $(generic_src_files) $(x86_src_files)
 LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH
-LOCAL_STATIC_LIBRARIES += libcutils
+LOCAL_STATIC_LIBRARIES += libcutils liblog
 LOCAL_LDLIBS += -ldl
 ifeq ($(HOST_OS),linux)
   LOCAL_SHARED_LIBRARIES += libgccdemangle # TODO: is this even needed on Linux?
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 17b320f..5037705 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -121,6 +121,7 @@
         mq.c \
         partition_utils.c \
         qtaguid.c \
+        trace.c \
         uevent.c
 
 ifeq ($(TARGET_ARCH),arm)
@@ -145,7 +146,9 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := libcutils
-LOCAL_WHOLE_STATIC_LIBRARIES := libcutils
+# TODO: remove liblog as whole static library, once we don't have prebuilt that requires
+# liblog symbols present in libcutils.
+LOCAL_WHOLE_STATIC_LIBRARIES := libcutils liblog
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_CFLAGS += $(targetSmpFlag)
 LOCAL_C_INCLUDES := $(libcutils_c_includes)
diff --git a/libcutils/fs.c b/libcutils/fs.c
index 1226d44..116526d 100644
--- a/libcutils/fs.c
+++ b/libcutils/fs.c
@@ -26,6 +26,7 @@
 #include <errno.h>
 #include <string.h>
 #include <limits.h>
+#include <stdlib.h>
 
 #define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
 #define BUF_SIZE 64
diff --git a/libcutils/klog.c b/libcutils/klog.c
index b586a57..812af3b 100644
--- a/libcutils/klog.c
+++ b/libcutils/klog.c
@@ -35,6 +35,9 @@
 void klog_init(void)
 {
     static const char *name = "/dev/__kmsg__";
+
+    if (klog_fd >= 0) return; /* Already initialized */
+
     if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
         klog_fd = open(name, O_WRONLY);
         fcntl(klog_fd, F_SETFD, FD_CLOEXEC);
@@ -50,7 +53,7 @@
     va_list ap;
 
     if (level > klog_level) return;
-    if (klog_fd < 0) return;
+    if (klog_fd < 0) klog_init();
 
     va_start(ap, fmt);
     vsnprintf(buf, LOG_BUF_MAX, fmt, ap);
diff --git a/libcutils/trace.c b/libcutils/trace.c
new file mode 100644
index 0000000..9754a44
--- /dev/null
+++ b/libcutils/trace.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <cutils/atomic.h>
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <cutils/trace.h>
+
+#define LOG_TAG "cutils-trace"
+#include <cutils/log.h>
+
+volatile int32_t        atrace_is_ready      = 0;
+int                     atrace_marker_fd     = -1;
+uint64_t                atrace_enabled_tags  = ATRACE_TAG_NOT_READY;
+static bool             atrace_is_debuggable = false;
+static volatile int32_t atrace_is_enabled    = 1;
+static pthread_once_t   atrace_once_control  = PTHREAD_ONCE_INIT;
+static pthread_mutex_t  atrace_tags_mutex    = PTHREAD_MUTEX_INITIALIZER;
+
+// Set whether this process is debuggable, which determines whether
+// application-level tracing is allowed when the ro.debuggable system property
+// is not set to '1'.
+void atrace_set_debuggable(bool debuggable)
+{
+    atrace_is_debuggable = debuggable;
+    atrace_update_tags();
+}
+
+// Set whether tracing is enabled in this process.  This is used to prevent
+// the Zygote process from tracing.
+void atrace_set_tracing_enabled(bool enabled)
+{
+    android_atomic_release_store(enabled ? 1 : 0, &atrace_is_enabled);
+    atrace_update_tags();
+}
+
+// Check whether the given command line matches one of the comma-separated
+// values listed in the app_cmdlines property.
+static bool atrace_is_cmdline_match(const char* cmdline)
+{
+    char value[PROPERTY_VALUE_MAX];
+    char* start = value;
+
+    property_get("debug.atrace.app_cmdlines", value, "");
+
+    while (start != NULL) {
+        char* end = strchr(start, ',');
+
+        if (end != NULL) {
+            *end = '\0';
+            end++;
+        }
+
+        if (strcmp(cmdline, start) == 0) {
+            return true;
+        }
+
+        start = end;
+    }
+
+    return false;
+}
+
+// Determine whether application-level tracing is enabled for this process.
+static bool atrace_is_app_tracing_enabled()
+{
+    bool sys_debuggable = false;
+    bool proc_debuggable = false;
+    char value[PROPERTY_VALUE_MAX];
+    bool result = false;
+
+    // Check whether the system is debuggable.
+    property_get("ro.debuggable", value, "0");
+    if (value[0] == '1') {
+        sys_debuggable = true;
+    }
+
+    if (sys_debuggable || atrace_is_debuggable) {
+        // Check whether tracing is enabled for this process.
+        FILE * file = fopen("/proc/self/cmdline", "r");
+        if (file) {
+            char cmdline[4096];
+            if (fgets(cmdline, sizeof(cmdline), file)) {
+                result = atrace_is_cmdline_match(cmdline);
+            } else {
+                ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno);
+            }
+            fclose(file);
+        } else {
+            ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno),
+                    errno);
+        }
+    }
+
+    return result;
+}
+
+// Read the sysprop and return the value tags should be set to
+static uint64_t atrace_get_property()
+{
+    char value[PROPERTY_VALUE_MAX];
+    char *endptr;
+    uint64_t tags;
+
+    property_get("debug.atrace.tags.enableflags", value, "0");
+    errno = 0;
+    tags = strtoull(value, &endptr, 0);
+    if (value[0] == '\0' || *endptr != '\0') {
+        ALOGE("Error parsing trace property: Not a number: %s", value);
+        return 0;
+    } else if (errno == ERANGE || tags == ULLONG_MAX) {
+        ALOGE("Error parsing trace property: Number too large: %s", value);
+        return 0;
+    }
+
+    // Only set the "app" tag if this process was selected for app-level debug
+    // tracing.
+    if (atrace_is_app_tracing_enabled()) {
+        tags |= ATRACE_TAG_APP;
+    } else {
+        tags &= ~ATRACE_TAG_APP;
+    }
+
+    return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK;
+}
+
+// Update tags if tracing is ready. Useful as a sysprop change callback.
+void atrace_update_tags()
+{
+    uint64_t tags;
+    if (CC_UNLIKELY(android_atomic_acquire_load(&atrace_is_ready))) {
+        if (android_atomic_acquire_load(&atrace_is_enabled)) {
+            tags = atrace_get_property();
+            pthread_mutex_lock(&atrace_tags_mutex);
+            atrace_enabled_tags = tags;
+            pthread_mutex_unlock(&atrace_tags_mutex);
+        } else {
+            // Tracing is disabled for this process, so we simply don't
+            // initialize the tags.
+            pthread_mutex_lock(&atrace_tags_mutex);
+            atrace_enabled_tags = ATRACE_TAG_NOT_READY;
+            pthread_mutex_unlock(&atrace_tags_mutex);
+        }
+    }
+}
+
+static void atrace_init_once()
+{
+    atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY);
+    if (atrace_marker_fd == -1) {
+        ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
+        atrace_enabled_tags = 0;
+        goto done;
+    }
+
+    atrace_enabled_tags = atrace_get_property();
+
+done:
+    android_atomic_release_store(1, &atrace_is_ready);
+}
+
+void atrace_setup()
+{
+    pthread_once(&atrace_once_control, atrace_init_once);
+}
diff --git a/libcutils/zygote.c b/libcutils/zygote.c
index 75ce3ba..37236e8 100644
--- a/libcutils/zygote.c
+++ b/libcutils/zygote.c
@@ -159,44 +159,6 @@
 #endif /* HAVE_ANDROID_OS */
 }
 
-int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
-{
-    int fd;
-    int pid;
-    int err;
-    const char *newargv[argc + 1];
-
-    fd = socket_local_client(ZYGOTE_SOCKET, 
-            ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
-
-    if (fd < 0) {
-        return -1;
-    }
-
-    // The command socket is passed to the peer as close-on-exec
-    // and will close when the peer dies
-    newargv[0] = "--peer-wait";
-    memcpy(newargv + 1, argv, argc * sizeof(*argv)); 
-
-    pid = send_request(fd, 1, argc + 1, newargv);
-
-    if (pid > 0 && post_run_func != NULL) {
-        post_run_func(pid);
-    }
-
-    // Wait for socket to close
-    do {
-        int dummy;
-        err = read(fd, &dummy, sizeof(dummy));
-    } while ((err < 0 && errno == EINTR) || err != 0);
-
-    do {
-        err = close(fd);
-    } while (err < 0 && errno == EINTR);
-
-    return 0;
-}
-
 /**
  * Spawns a new dalvik instance via the Zygote process. The non-zygote
  * arguments are passed to com.android.internal.os.RuntimeInit(). The
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk
index 5f5849f..aba4621 100644
--- a/libnetutils/Android.mk
+++ b/libnetutils/Android.mk
@@ -9,7 +9,8 @@
         packet.c
 
 LOCAL_SHARED_LIBRARIES := \
-        libcutils
+        libcutils \
+        liblog
 
 LOCAL_MODULE:= libnetutils
 
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index b940453..da00f74 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -88,16 +88,17 @@
                      char *ipaddr,
                      char *gateway,
                      uint32_t *prefixLength,
-                     char *dns1,
-                     char *dns2,
+                     char *dns[],
                      char *server,
                      uint32_t *lease,
-                     char *vendorInfo)
+                     char *vendorInfo,
+                     char *domain)
 {
     char 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];
+    int x;
 
     get_p2p_interface_replacement(interface, p2p_interface);
 
@@ -111,7 +112,7 @@
     property_get(prop_name, server, NULL);
 
     //TODO: Handle IPv6 when we change system property usage
-    if (strcmp(gateway, "0.0.0.0") == 0) {
+    if (gateway[0] == '\0' || strncmp(gateway, "0.0.0.0", 7) == 0) {
         //DHCP server is our best bet as gateway
         strncpy(gateway, server, PROPERTY_VALUE_MAX);
     }
@@ -138,11 +139,11 @@
         }
         *prefixLength = p;
     }
-    snprintf(prop_name, sizeof(prop_name), "%s.%s.dns1", DHCP_PROP_NAME_PREFIX, p2p_interface);
-    property_get(prop_name, dns1, NULL);
 
-    snprintf(prop_name, sizeof(prop_name), "%s.%s.dns2", DHCP_PROP_NAME_PREFIX, p2p_interface);
-    property_get(prop_name, dns2, NULL);
+    for (x=0; dns[x] != NULL; x++) {
+        snprintf(prop_name, sizeof(prop_name), "%s.%s.dns%d", DHCP_PROP_NAME_PREFIX, p2p_interface, x+1);
+        property_get(prop_name, dns[x], NULL);
+    }
 
     snprintf(prop_name, sizeof(prop_name), "%s.%s.leasetime", DHCP_PROP_NAME_PREFIX, p2p_interface);
     if (property_get(prop_name, prop_value, NULL)) {
@@ -153,6 +154,10 @@
             p2p_interface);
     property_get(prop_name, vendorInfo, NULL);
 
+    snprintf(prop_name, sizeof(prop_name), "%s.%s.domain", DHCP_PROP_NAME_PREFIX,
+            p2p_interface);
+    property_get(prop_name, domain, NULL);
+
     return 0;
 }
 
@@ -177,11 +182,11 @@
                     char *ipaddr,
                     char *gateway,
                     uint32_t *prefixLength,
-                    char *dns1,
-                    char *dns2,
+                    char *dns[],
                     char *server,
                     uint32_t *lease,
-                    char *vendorInfo)
+                    char *vendorInfo,
+                    char *domain)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char daemon_prop_name[PROPERTY_KEY_MAX];
@@ -232,17 +237,10 @@
     }
     if (strcmp(prop_value, "ok") == 0) {
         char dns_prop_name[PROPERTY_KEY_MAX];
-        if (fill_ip_info(interface, ipaddr, gateway, prefixLength,
-                dns1, dns2, server, lease, vendorInfo) == -1) {
+        if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+                server, lease, vendorInfo, domain) == -1) {
             return -1;
         }
-
-        /* copy dns data to system properties - TODO - remove this after we have async
-         * notification of renewal's */
-        snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", interface);
-        property_set(dns_prop_name, *dns1 ? ipaddr_to_string(*dns1) : "");
-        snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", interface);
-        property_set(dns_prop_name, *dns2 ? ipaddr_to_string(*dns2) : "");
         return 0;
     } else {
         snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
@@ -327,11 +325,11 @@
                     char *ipaddr,
                     char *gateway,
                     uint32_t *prefixLength,
-                    char *dns1,
-                    char *dns2,
+                    char *dns[],
                     char *server,
                     uint32_t *lease,
-                    char *vendorInfo)
+                    char *vendorInfo,
+                    char *domain)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
@@ -367,8 +365,8 @@
         return -1;
     }
     if (strcmp(prop_value, "ok") == 0) {
-        return fill_ip_info(interface, ipaddr, gateway, prefixLength,
-                dns1, dns2, server, lease, vendorInfo);
+        return fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
+                server, lease, vendorInfo, domain);
     } else {
         snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
         return -1;
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 488003f..7f20e5b 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -16,8 +16,8 @@
     codeflinger/blending.cpp \
     codeflinger/texturing.cpp \
     codeflinger/disassem.c \
-	tinyutils/SharedBuffer.cpp \
-	tinyutils/VectorImpl.cpp \
+	codeflinger/tinyutils/SharedBuffer.cpp \
+	codeflinger/tinyutils/VectorImpl.cpp \
 	fixed.cpp.arm \
 	picker.cpp.arm \
 	pixelflinger.cpp.arm \
@@ -50,14 +50,7 @@
 PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
 endif
 
-LOCAL_SHARED_LIBRARIES := libcutils
-
-ifneq ($(TARGET_ARCH),arm)
-# Required to define logging functions on the simulator.
-# TODO: move the simulator logging functions into libcutils with
-# the rest of the basic log stuff.
-LOCAL_SHARED_LIBRARIES += libutils
-endif
+LOCAL_SHARED_LIBRARIES := libcutils liblog
 
 #
 # Shared library
@@ -82,7 +75,7 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE:= libpixelflinger_static
 LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
-LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) 
+LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
 include $(BUILD_STATIC_LIBRARY)
 
 
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index c4f42f5..607ed3c 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -28,9 +28,9 @@
 
 #include <private/pixelflinger/ggl_context.h>
 
-#include "codeflinger/ARMAssembler.h"
-#include "codeflinger/CodeCache.h"
-#include "codeflinger/disassem.h"
+#include "ARMAssembler.h"
+#include "CodeCache.h"
+#include "disassem.h"
 
 // ----------------------------------------------------------------------------
 
diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h
index 06c66dd..c03dd9a 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.h
+++ b/libpixelflinger/codeflinger/ARMAssembler.h
@@ -25,9 +25,8 @@
 #include "tinyutils/KeyedVector.h"
 #include "tinyutils/smartpointer.h"
 
-#include "tinyutils/smartpointer.h"
-#include "codeflinger/ARMAssemblerInterface.h"
-#include "codeflinger/CodeCache.h"
+#include "ARMAssemblerInterface.h"
+#include "CodeCache.h"
 
 namespace android {
 
diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp b/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
index 82180ee..073633c 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
+++ b/libpixelflinger/codeflinger/ARMAssemblerInterface.cpp
@@ -22,7 +22,7 @@
 #include <sys/types.h>
 
 #include <cutils/log.h>
-#include "codeflinger/ARMAssemblerInterface.h"
+#include "ARMAssemblerInterface.h"
 
 namespace android {
 
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
index 7feed62..1c7bc76 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
@@ -19,7 +19,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "codeflinger/ARMAssemblerProxy.h"
+#include "ARMAssemblerProxy.h"
 
 namespace android {
 
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.h b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
index 5e3f763..70cb464 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.h
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
@@ -22,7 +22,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "codeflinger/ARMAssemblerInterface.h"
+#include "ARMAssemblerInterface.h"
 
 namespace android {
 
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index f9ae00a..58fde7e 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -28,7 +28,7 @@
 #include <cutils/log.h>
 
 
-#include "codeflinger/CodeCache.h"
+#include "CodeCache.h"
 
 namespace android {
 
diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h
index 54fd69b..fa67dd0 100644
--- a/libpixelflinger/codeflinger/CodeCache.h
+++ b/libpixelflinger/codeflinger/CodeCache.h
@@ -28,6 +28,8 @@
 
 namespace android {
 
+using namespace tinyutils;
+
 // ----------------------------------------------------------------------------
 
 class AssemblyKeyBase {
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index 1ddf93d..0cb042e 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -24,7 +24,7 @@
 #include <sys/types.h>
 #include <cutils/log.h>
 
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
 
 namespace android {
 
diff --git a/libpixelflinger/codeflinger/GGLAssembler.h b/libpixelflinger/codeflinger/GGLAssembler.h
index dd5f48e..d993684 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.h
+++ b/libpixelflinger/codeflinger/GGLAssembler.h
@@ -24,7 +24,7 @@
 
 #include <private/pixelflinger/ggl_context.h>
 
-#include "codeflinger/ARMAssemblerProxy.h"
+#include "ARMAssemblerProxy.h"
 
 
 namespace android {
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index 7888a0e..a88d2fe 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -61,9 +61,9 @@
 
 #include <private/pixelflinger/ggl_context.h>
 
-#include "codeflinger/MIPSAssembler.h"
-#include "codeflinger/CodeCache.h"
-#include "codeflinger/mips_disassem.h"
+#include "MIPSAssembler.h"
+#include "CodeCache.h"
+#include "mips_disassem.h"
 
 // Choose MIPS arch variant following gcc flags
 #if defined(__mips__) && __mips==32 && __mips_isa_rev>=2
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.h b/libpixelflinger/codeflinger/MIPSAssembler.h
index d8e8165..430ab06 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.h
+++ b/libpixelflinger/codeflinger/MIPSAssembler.h
@@ -21,12 +21,12 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-
+#include "tinyutils/KeyedVector.h"
+#include "tinyutils/Vector.h"
 #include "tinyutils/smartpointer.h"
-#include "codeflinger/ARMAssemblerInterface.h"
-#include "codeflinger/CodeCache.h"
+
+#include "ARMAssemblerInterface.h"
+#include "CodeCache.h"
 
 namespace android {
 
diff --git a/libpixelflinger/codeflinger/blending.cpp b/libpixelflinger/codeflinger/blending.cpp
index c90eaa0..b20219c 100644
--- a/libpixelflinger/codeflinger/blending.cpp
+++ b/libpixelflinger/codeflinger/blending.cpp
@@ -23,7 +23,7 @@
 
 #include <cutils/log.h>
 
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
 
 
 namespace android {
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index 146fa52..0a46eaa 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -18,7 +18,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <cutils/log.h>
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
 
 #ifdef __ARM_ARCH__
 #include <machine/cpu-features.h>
diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp
index 4d5a50f..9e3d217 100644
--- a/libpixelflinger/codeflinger/texturing.cpp
+++ b/libpixelflinger/codeflinger/texturing.cpp
@@ -23,7 +23,7 @@
 
 #include <cutils/log.h>
 
-#include "codeflinger/GGLAssembler.h"
+#include "GGLAssembler.h"
 
 #ifdef __ARM_ARCH__
 #include <machine/cpu-features.h>
diff --git a/libpixelflinger/tinyutils/Errors.h b/libpixelflinger/codeflinger/tinyutils/Errors.h
similarity index 60%
rename from libpixelflinger/tinyutils/Errors.h
rename to libpixelflinger/codeflinger/tinyutils/Errors.h
index b9fd5f4..47ae9d7 100644
--- a/libpixelflinger/tinyutils/Errors.h
+++ b/libpixelflinger/codeflinger/tinyutils/Errors.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright 2007 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_ERRORS_H
-#define ANDROID_ERRORS_H
+#ifndef ANDROID_PIXELFLINGER_ERRORS_H
+#define ANDROID_PIXELFLINGER_ERRORS_H
 
 #include <sys/types.h>
 #include <errno.h>
 
 namespace android {
+namespace tinyutils {
 
 // use this type to return error codes
 typedef int32_t     status_t;
@@ -31,32 +32,17 @@
  */
 
 enum {
-    OK                = 0,    // Everything's swell.
     NO_ERROR          = 0,    // No errors.
-    
-    UNKNOWN_ERROR       = 0x80000000,
-
     NO_MEMORY           = -ENOMEM,
-    INVALID_OPERATION   = -ENOSYS,
     BAD_VALUE           = -EINVAL,
-    BAD_TYPE            = 0x80000001,
-    NAME_NOT_FOUND      = -ENOENT,
-    PERMISSION_DENIED   = -EPERM,
-    NO_INIT             = -ENODEV,
-    ALREADY_EXISTS      = -EEXIST,
-    DEAD_OBJECT         = -EPIPE,
-    FAILED_TRANSACTION  = 0x80000002,
-    JPARKS_BROKE_IT     = -EPIPE,
     BAD_INDEX           = -EOVERFLOW,
-    NOT_ENOUGH_DATA     = -ENODATA,
-    WOULD_BLOCK         = -EWOULDBLOCK, 
-    TIMED_OUT           = -ETIME,
-    UNKNOWN_TRANSACTION = -EBADMSG,
+    NAME_NOT_FOUND      = -ENOENT,
 };
 
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
     
 // ---------------------------------------------------------------------------
     
-#endif // ANDROID_ERRORS_H
+#endif // ANDROID_PIXELFLINGER_ERRORS_H
diff --git a/libpixelflinger/tinyutils/KeyedVector.h b/libpixelflinger/codeflinger/tinyutils/KeyedVector.h
similarity index 85%
rename from libpixelflinger/tinyutils/KeyedVector.h
rename to libpixelflinger/codeflinger/tinyutils/KeyedVector.h
index 1be2094..9d8668b 100644
--- a/libpixelflinger/tinyutils/KeyedVector.h
+++ b/libpixelflinger/codeflinger/tinyutils/KeyedVector.h
@@ -1,25 +1,34 @@
 /*
- *  keyed_vector.h
- *  Android  
+ * Copyright 2005 The Android Open Source Project
  *
- *  Created on 11/18/05.
- *  Copyright 2005 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_KEYED_VECTOR_H
-#define ANDROID_KEYED_VECTOR_H
+#ifndef ANDROID_PIXELFLINGER_KEYED_VECTOR_H
+#define ANDROID_PIXELFLINGER_KEYED_VECTOR_H
 
 #include <assert.h>
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "tinyutils/SortedVector.h"
-#include "tinyutils/TypeHelpers.h"
+#include "Errors.h"
+#include "SortedVector.h"
+#include "TypeHelpers.h"
 
 // ---------------------------------------------------------------------------
 
 namespace android {
+namespace tinyutils {
 
 template <typename KEY, typename VALUE>
 class KeyedVector
@@ -186,8 +195,9 @@
     return i >= 0 ? KeyedVector<KEY,VALUE>::valueAt(i) : mDefault;
 }
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
 // ---------------------------------------------------------------------------
 
-#endif // ANDROID_KEYED_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_KEYED_VECTOR_H
diff --git a/libpixelflinger/tinyutils/SharedBuffer.cpp b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.cpp
similarity index 75%
rename from libpixelflinger/tinyutils/SharedBuffer.cpp
rename to libpixelflinger/codeflinger/tinyutils/SharedBuffer.cpp
index ef781a7..ef453fa 100644
--- a/libpixelflinger/tinyutils/SharedBuffer.cpp
+++ b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.cpp
@@ -1,9 +1,17 @@
 /*
- *  SharedBuffer.cpp
- *  Android  
+ * Copyright 2005 The Android Open Source Project
  *
- *  Copyright 2005 The Android Open Source Project
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
 #include <stdlib.h>
@@ -11,11 +19,12 @@
 
 #include <cutils/atomic.h>
 
-#include "tinyutils/SharedBuffer.h"
+#include "SharedBuffer.h"
 
 // ---------------------------------------------------------------------------
 
 namespace android {
+namespace tinyutils {
 
 SharedBuffer* SharedBuffer::alloc(size_t size)
 {
@@ -102,5 +111,5 @@
     return prev;
 }
 
-
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
diff --git a/libpixelflinger/tinyutils/SharedBuffer.h b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.h
similarity index 82%
rename from libpixelflinger/tinyutils/SharedBuffer.h
rename to libpixelflinger/codeflinger/tinyutils/SharedBuffer.h
index 9f63121..d69b417 100644
--- a/libpixelflinger/tinyutils/SharedBuffer.h
+++ b/libpixelflinger/codeflinger/tinyutils/SharedBuffer.h
@@ -1,13 +1,21 @@
 /*
- *  SharedBuffer.h
- *  Android  
+ * Copyright 2005 The Android Open Source Project
  *
- *  Copyright 2005 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_SHARED_BUFFER_H
-#define ANDROID_SHARED_BUFFER_H
+#ifndef ANDROID_PIXELFLINGER_SHARED_BUFFER_H
+#define ANDROID_PIXELFLINGER_SHARED_BUFFER_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -15,6 +23,7 @@
 // ---------------------------------------------------------------------------
 
 namespace android {
+namespace tinyutils {
 
 class SharedBuffer
 {
@@ -131,8 +140,9 @@
     return (mRefs == 1);
 }
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
 // ---------------------------------------------------------------------------
 
-#endif // ANDROID_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_SHARED_BUFFER_H
diff --git a/libpixelflinger/tinyutils/SortedVector.h b/libpixelflinger/codeflinger/tinyutils/SortedVector.h
similarity index 96%
rename from libpixelflinger/tinyutils/SortedVector.h
rename to libpixelflinger/codeflinger/tinyutils/SortedVector.h
index 7a6b443..a2b7005 100644
--- a/libpixelflinger/tinyutils/SortedVector.h
+++ b/libpixelflinger/codeflinger/tinyutils/SortedVector.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 The Android Open Source Project
+ * Copyright 2005 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,20 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_SORTED_VECTOR_H
-#define ANDROID_SORTED_VECTOR_H
+#ifndef ANDROID_PIXELFLINGER_SORTED_VECTOR_H
+#define ANDROID_PIXELFLINGER_SORTED_VECTOR_H
 
 #include <assert.h>
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "tinyutils/Vector.h"
-#include "tinyutils/VectorImpl.h"
-#include "tinyutils/TypeHelpers.h"
+#include "Vector.h"
+#include "VectorImpl.h"
+#include "TypeHelpers.h"
 
 // ---------------------------------------------------------------------------
 
 namespace android {
+namespace tinyutils {
 
 template <class TYPE>
 class SortedVector : private SortedVectorImpl
@@ -274,9 +275,10 @@
     return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
 }
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
 
 // ---------------------------------------------------------------------------
 
-#endif // ANDROID_SORTED_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_SORTED_VECTOR_H
diff --git a/libpixelflinger/tinyutils/TypeHelpers.h b/libpixelflinger/codeflinger/tinyutils/TypeHelpers.h
similarity index 89%
rename from libpixelflinger/tinyutils/TypeHelpers.h
rename to libpixelflinger/codeflinger/tinyutils/TypeHelpers.h
index 9500c90..7abff07 100644
--- a/libpixelflinger/tinyutils/TypeHelpers.h
+++ b/libpixelflinger/codeflinger/tinyutils/TypeHelpers.h
@@ -1,12 +1,21 @@
 /*
- *  TypeHelpers.h
- *  
- *  Copyright 2005 The Android Open Source Project
+ * Copyright 2005 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_TYPE_HELPERS_H
-#define ANDROID_TYPE_HELPERS_H
+#ifndef ANDROID_PIXELFLINGER_TYPE_HELPERS_H
+#define ANDROID_PIXELFLINGER_TYPE_HELPERS_H
 
 #include <new>
 #include <stdint.h>
@@ -16,6 +25,7 @@
 // ---------------------------------------------------------------------------
 
 namespace android {
+namespace tinyutils {
 
 /*
  * Types traits
@@ -238,8 +248,9 @@
 
 // ---------------------------------------------------------------------------
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
 // ---------------------------------------------------------------------------
 
-#endif // ANDROID_TYPE_HELPERS_H
+#endif // ANDROID_PIXELFLINGER_TYPE_HELPERS_H
diff --git a/libpixelflinger/tinyutils/Vector.h b/libpixelflinger/codeflinger/tinyutils/Vector.h
similarity index 92%
rename from libpixelflinger/tinyutils/Vector.h
rename to libpixelflinger/codeflinger/tinyutils/Vector.h
index 14cf99a..c07a17a 100644
--- a/libpixelflinger/tinyutils/Vector.h
+++ b/libpixelflinger/codeflinger/tinyutils/Vector.h
@@ -1,13 +1,21 @@
 /*
- *  vector.h
- *  Android  
+ * Copyright 2005 The Android Open Source Project
  *
- *  Copyright 2005 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_VECTOR_H
-#define ANDROID_VECTOR_H
+#ifndef ANDROID_PIXELFLINGER_VECTOR_H
+#define ANDROID_PIXELFLINGER_VECTOR_H
 
 #include <new>
 #include <stdint.h>
@@ -15,13 +23,14 @@
 
 #include <cutils/log.h>
 
-#include "tinyutils/Errors.h"
-#include "tinyutils/VectorImpl.h"
-#include "tinyutils/TypeHelpers.h"
+#include "Errors.h"
+#include "VectorImpl.h"
+#include "TypeHelpers.h"
 
 // ---------------------------------------------------------------------------
 
 namespace android {
+namespace tinyutils {
 
 /*!
  * The main templated vector class ensuring type safety
@@ -335,9 +344,10 @@
     move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
 }
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
 
 // ---------------------------------------------------------------------------
 
-#endif // ANDROID_VECTOR_H
+#endif // ANDROID_PIXELFLINGER_VECTOR_H
diff --git a/libpixelflinger/tinyutils/VectorImpl.cpp b/libpixelflinger/codeflinger/tinyutils/VectorImpl.cpp
similarity index 94%
rename from libpixelflinger/tinyutils/VectorImpl.cpp
rename to libpixelflinger/codeflinger/tinyutils/VectorImpl.cpp
index 05c4945..689129a 100644
--- a/libpixelflinger/tinyutils/VectorImpl.cpp
+++ b/libpixelflinger/codeflinger/tinyutils/VectorImpl.cpp
@@ -1,9 +1,17 @@
 /*
- *  vector_impl.cpp
- *  Android  
+ * Copyright 2005 The Android Open Source Project
  *
- *  Copyright 2005 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 "Vector"
@@ -15,21 +23,15 @@
 
 #include <cutils/log.h>
 
-#include "tinyutils/SharedBuffer.h"
-#include "tinyutils/VectorImpl.h"
+#include "Errors.h"
+#include "SharedBuffer.h"
+#include "VectorImpl.h"
 
 /*****************************************************************************/
 
 
 namespace android {
-
-enum {
-    NO_ERROR          = 0,    // No errors.
-    NO_MEMORY           = -ENOMEM,
-    BAD_VALUE           = -EINVAL,
-    BAD_INDEX           = -EOVERFLOW,
-    NAME_NOT_FOUND      = -ENOENT,
-};
+namespace tinyutils {
 
 // ----------------------------------------------------------------------------
 
@@ -548,5 +550,6 @@
 
 /*****************************************************************************/
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
diff --git a/libpixelflinger/tinyutils/VectorImpl.h b/libpixelflinger/codeflinger/tinyutils/VectorImpl.h
similarity index 89%
rename from libpixelflinger/tinyutils/VectorImpl.h
rename to libpixelflinger/codeflinger/tinyutils/VectorImpl.h
index e868eca..56089b3 100644
--- a/libpixelflinger/tinyutils/VectorImpl.h
+++ b/libpixelflinger/codeflinger/tinyutils/VectorImpl.h
@@ -1,13 +1,21 @@
 /*
- *  vector_impl.h
- *  Android  
+ * Copyright 2005 The Android Open Source Project
  *
- *  Copyright 2005 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_VECTOR_IMPL_H
-#define ANDROID_VECTOR_IMPL_H
+#ifndef ANDROID_PIXELFLINGER_VECTOR_IMPL_H
+#define ANDROID_PIXELFLINGER_VECTOR_IMPL_H
 
 #include <assert.h>
 #include <stdint.h>
@@ -18,6 +26,7 @@
 // ---------------------------------------------------------------------------
 
 namespace android {
+namespace tinyutils {
 
 /*!
  * Implementation of the guts of the vector<> class
@@ -177,9 +186,10 @@
             ssize_t         replaceAt(const void* item, size_t index);
 };
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
 
 // ---------------------------------------------------------------------------
 
-#endif // ANDROID_VECTOR_IMPL_H
+#endif // ANDROID_PIXELFLINGER_VECTOR_IMPL_H
diff --git a/libpixelflinger/tinyutils/smartpointer.h b/libpixelflinger/codeflinger/tinyutils/smartpointer.h
similarity index 82%
rename from libpixelflinger/tinyutils/smartpointer.h
rename to libpixelflinger/codeflinger/tinyutils/smartpointer.h
index 88032d7..9d0a16e 100644
--- a/libpixelflinger/tinyutils/smartpointer.h
+++ b/libpixelflinger/codeflinger/tinyutils/smartpointer.h
@@ -1,13 +1,21 @@
 /*
- *  smartpointer.h
- *  Android  
+ * Copyright 2005 The Android Open Source Project
  *
- *  Copyright 2005 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_SMART_POINTER_H
-#define ANDROID_SMART_POINTER_H
+#ifndef ANDROID_PIXELFLINGER_SMART_POINTER_H
+#define ANDROID_PIXELFLINGER_SMART_POINTER_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -15,6 +23,7 @@
 
 // ---------------------------------------------------------------------------
 namespace android {
+namespace tinyutils {
 
 // ---------------------------------------------------------------------------
 
@@ -163,8 +172,9 @@
 
 // ---------------------------------------------------------------------------
 
-}; // namespace android
+} // namespace tinyutils
+} // namespace android
 
 // ---------------------------------------------------------------------------
 
-#endif // ANDROID_SMART_POINTER_H
+#endif // ANDROID_PIXELFLINGER_SMART_POINTER_H
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk
index 57cc313..1d396b2 100644
--- a/libsysutils/Android.mk
+++ b/libsysutils/Android.mk
@@ -16,11 +16,11 @@
 
 LOCAL_MODULE:= libsysutils
 
-LOCAL_C_INCLUDES := $(KERNEL_HEADERS) 
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
 
-LOCAL_CFLAGS := 
+LOCAL_CFLAGS :=
 
-LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SHARED_LIBRARIES := libcutils liblog
 
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index 167fa60..b967342 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -223,56 +223,61 @@
     char event_buf[512];
     char path[100];
     int i, ret, done = 0;
-    int j, event_size;
+    int offset = 0;
     int wd;
 
     ret = read(context->fd, event_buf, sizeof(event_buf));
     if (ret >= (int)sizeof(struct inotify_event)) {
-        event = (struct inotify_event *)event_buf;
-        wd = event->wd;
-        if (wd == context->wdd) {
-            if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
-                watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
-                done = find_existing_devices(context->cb_added, context->data);
-            } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
-                for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
-                    if (context->wds[i] >= 0) {
+        while (offset < ret) {
+            event = (struct inotify_event*)&event_buf[offset];
+            done = 0;
+            wd = event->wd;
+            if (wd == context->wdd) {
+                if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
+                    watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
+                    done = find_existing_devices(context->cb_added, context->data);
+                } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
+                    for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
+                        if (context->wds[i] >= 0) {
+                            inotify_rm_watch(context->fd, context->wds[i]);
+                            context->wds[i] = -1;
+                        }
+                    }
+                }
+            } else if (wd == context->wds[0]) {
+                i = atoi(event->name);
+                snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
+                D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
+                        "new" : "gone", path, i);
+                if (i > 0 && i < MAX_USBFS_WD_COUNT) {
+                    if (event->mask & IN_CREATE) {
+                        ret = inotify_add_watch(context->fd, path,
+                                IN_CREATE | IN_DELETE);
+                        if (ret >= 0)
+                            context->wds[i] = ret;
+                        done = find_existing_devices_bus(path, context->cb_added,
+                                context->data);
+                    } else if (event->mask & IN_DELETE) {
                         inotify_rm_watch(context->fd, context->wds[i]);
                         context->wds[i] = -1;
                     }
                 }
-            }
-        } else if (wd == context->wds[0]) {
-            i = atoi(event->name);
-            snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
-            D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
-                    "new" : "gone", path, i);
-            if (i > 0 && i < MAX_USBFS_WD_COUNT) {
-                if (event->mask & IN_CREATE) {
-                    ret = inotify_add_watch(context->fd, path,
-                            IN_CREATE | IN_DELETE);
-                    if (ret >= 0)
-                        context->wds[i] = ret;
-                    done = find_existing_devices_bus(path, context->cb_added,
-                            context->data);
-                } else if (event->mask & IN_DELETE) {
-                    inotify_rm_watch(context->fd, context->wds[i]);
-                    context->wds[i] = -1;
-                }
-            }
-        } else {
-            for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {
-                if (wd == context->wds[i]) {
-                    snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
-                    if (event->mask == IN_CREATE) {
-                        D("new device %s\n", path);
-                        done = context->cb_added(path, context->data);
-                    } else if (event->mask == IN_DELETE) {
-                        D("gone device %s\n", path);
-                        done = context->cb_removed(path, context->data);
+            } else {
+                for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {
+                    if (wd == context->wds[i]) {
+                        snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
+                        if (event->mask == IN_CREATE) {
+                            D("new device %s\n", path);
+                            done = context->cb_added(path, context->data);
+                        } else if (event->mask == IN_DELETE) {
+                            D("gone device %s\n", path);
+                            done = context->cb_removed(path, context->data);
+                        }
                     }
                 }
             }
+
+            offset += sizeof(struct inotify_event) + event->len;
         }
     }
 
diff --git a/logwrapper/Android.mk b/logwrapper/Android.mk
index 5fd6356..917bf37 100644
--- a/logwrapper/Android.mk
+++ b/logwrapper/Android.mk
@@ -1,7 +1,34 @@
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
+
+# ========================================================
+# Static library
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := liblogwrap
+LOCAL_SRC_FILES := logwrap.c
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+include $(BUILD_STATIC_LIBRARY)
+
+# ========================================================
+# Shared library
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := liblogwrap
+LOCAL_SHARED_LIBRARIES := libcutils liblog
+LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+include $(BUILD_SHARED_LIBRARY)
+
+# ========================================================
+# Executable
+# ========================================================
+include $(CLEAR_VARS)
 LOCAL_SRC_FILES:= logwrapper.c
 LOCAL_MODULE := logwrapper
-LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_STATIC_LIBRARIES := liblog liblogwrap libcutils
 include $(BUILD_EXECUTABLE)
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
new file mode 100644
index 0000000..8087f0a
--- /dev/null
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -0,0 +1,83 @@
+/* system/core/include/logwrap/logwrap.h
+ *
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LIBS_LOGWRAP_H
+#define __LIBS_LOGWRAP_H
+
+#include <stdbool.h>
+
+__BEGIN_DECLS
+
+/*
+ * Run a command while logging its stdout and stderr
+ *
+ * WARNING: while this function is running it will clear all SIGCHLD handlers
+ * if you rely on SIGCHLD in the caller there is a chance zombies will be
+ * created if you're not calling waitpid after calling this. This function will
+ * log a warning when it clears SIGCHLD for processes other than the child it
+ * created.
+ *
+ * Arguments:
+ *   argc:   the number of elements in argv
+ *   argv:   an array of strings containing the command to be executed and its
+ *           arguments as separate strings. argv does not need to be
+ *           NULL-terminated
+ *   status: the equivalent child status as populated by wait(status). This
+ *           value is only valid when logwrap successfully completes. If NULL
+ *           the return value of the child will be the function's return value.
+ *   ignore_int_quit: set to true if you want to completely ignore SIGINT and
+ *           SIGQUIT while logwrap is running. This may force the end-user to
+ *           send a signal twice to signal the caller (once for the child, and
+ *           once for the caller)
+ *   log_target: Specify where to log the output of the child, either LOG_NONE,
+ *           LOG_ALOG (for the Android system log) or LOG_KLOG (for the kernel
+ *           log).
+ *   abbreviated: If true, capture up to the first 100 lines and last 4K of
+ *           output from the child.  The abbreviated output is not dumped to
+ *           the specified log until the child has exited.
+ *
+ * Return value:
+ *   0 when logwrap successfully run the child process and captured its status
+ *   -1 when an internal error occurred
+ *   -ECHILD if status is NULL and the child didn't exit properly
+ *   the return value of the child if it exited properly and status is NULL
+ *
+ */
+
+/* Values for the log_target parameter android_fork_exec_ext() */
+#define LOG_NONE        0
+#define LOG_ALOG        1
+#define LOG_KLOG        2
+
+int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
+        int log_target, bool abbreviated);
+
+/* Similar to above, except abbreviated logging is not available, and if logwrap
+ * is true, logging is to the Android system log, and if false, there is no
+ * logging.
+ */
+static inline int android_fork_execvp(int argc, char* argv[], int *status,
+                                     bool ignore_int_quit, bool logwrap)
+{
+    return android_fork_execvp_ext(argc, argv, status, ignore_int_quit,
+                                   (logwrap ? LOG_ALOG : LOG_NONE), false);
+}
+
+
+__END_DECLS
+
+#endif /* __LIBS_LOGWRAP_H */
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
new file mode 100644
index 0000000..01cc9a1
--- /dev/null
+++ b/logwrapper/logwrap.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <poll.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include <logwrap/logwrap.h>
+#include "private/android_filesystem_config.h"
+#include "cutils/log.h"
+#include <cutils/klog.h>
+
+#define ARRAY_SIZE(x)   (sizeof(x) / sizeof(*(x)))
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define ERROR(fmt, args...)                                                   \
+do {                                                                          \
+    fprintf(stderr, fmt, ## args);                                            \
+    ALOG(LOG_ERROR, "logwrapper", fmt, ## args);                              \
+} while(0)
+
+#define FATAL_CHILD(fmt, args...)                                             \
+do {                                                                          \
+    ERROR(fmt, ## args);                                                      \
+    _exit(-1);                                                                \
+} while(0)
+
+#define MAX_KLOG_TAG 16
+
+/* This is a simple buffer that holds up to the first beginning_buf->buf_size
+ * bytes of output from a command.
+ */
+#define BEGINNING_BUF_SIZE 0x1000
+struct beginning_buf {
+    char *buf;
+    size_t alloc_len;
+    /* buf_size is the usable space, which is one less than the allocated size */
+    size_t buf_size;
+    size_t used_len;
+};
+
+/* This is a circular buf that holds up to the last ending_buf->buf_size bytes
+ * of output from a command after the first beginning_buf->buf_size bytes
+ * (which are held in beginning_buf above).
+ */
+#define ENDING_BUF_SIZE 0x1000
+struct ending_buf {
+    char *buf;
+    ssize_t alloc_len;
+    /* buf_size is the usable space, which is one less than the allocated size */
+    ssize_t buf_size;
+    ssize_t used_len;
+    /* read and write offsets into the circular buffer */
+    int read;
+    int write;
+};
+
+ /* A structure to hold all the abbreviated buf data */
+struct abbr_buf {
+    struct beginning_buf b_buf;
+    struct ending_buf e_buf;
+    int beginning_buf_full;
+};
+
+/* Collect all the various bits of info needed for logging in one place. */
+struct log_info {
+    int log_target;
+    char klog_fmt[MAX_KLOG_TAG * 2];
+    char *btag;
+    bool abbreviated;
+    struct abbr_buf a_buf;
+};
+
+/* Forware declaration */
+static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen);
+
+/* Return 0 on success, and 1 when full */
+static int add_line_to_linear_buf(struct beginning_buf *b_buf,
+                                   char *line, ssize_t line_len)
+{
+    size_t new_len;
+    char *new_buf;
+    int full = 0;
+
+    if ((line_len + b_buf->used_len) > b_buf->buf_size) {
+        full = 1;
+    } else {
+        /* Add to the end of the buf */
+        memcpy(b_buf->buf + b_buf->used_len, line, line_len);
+        b_buf->used_len += line_len;
+    }
+
+    return full;
+}
+
+static void add_line_to_circular_buf(struct ending_buf *e_buf,
+                                     char *line, ssize_t line_len)
+{
+    ssize_t free_len;
+    ssize_t needed_space;
+    char *new_buf;
+    int cnt;
+
+    if (e_buf->buf == NULL) {
+        return;
+    }
+
+   if (line_len > e_buf->buf_size) {
+       return;
+   }
+
+    free_len = e_buf->buf_size - e_buf->used_len;
+
+    if (line_len > free_len) {
+        /* remove oldest entries at read, and move read to make
+         * room for the new string */
+        needed_space = line_len - free_len;
+        e_buf->read = (e_buf->read + needed_space) % e_buf->buf_size;
+        e_buf->used_len -= needed_space;
+    }
+
+    /* Copy the line into the circular buffer, dealing with possible
+     * wraparound.
+     */
+    cnt = MIN(line_len, e_buf->buf_size - e_buf->write);
+    memcpy(e_buf->buf + e_buf->write, line, cnt);
+    if (cnt < line_len) {
+        memcpy(e_buf->buf, line + cnt, line_len - cnt);
+    }
+    e_buf->used_len += line_len;
+    e_buf->write = (e_buf->write + line_len) % e_buf->buf_size;
+}
+
+/* Log directly to the specified log */
+static void do_log_line(struct log_info *log_info, char *line) {
+    if (log_info->log_target == LOG_KLOG) {
+        klog_write(6, log_info->klog_fmt, line);
+    } else if (log_info->log_target == LOG_ALOG) {
+        ALOG(LOG_INFO, log_info->btag, "%s", line);
+    }
+}
+
+/* Log to either the abbreviated buf, or directly to the specified log
+ * via do_log_line() above.
+ */
+static void log_line(struct log_info *log_info, char *line, int len) {
+    if (log_info->abbreviated) {
+        add_line_to_abbr_buf(&log_info->a_buf, line, len);
+    } else {
+        do_log_line(log_info, line);
+    }
+}
+
+/*
+ * The kernel will take a maximum of 1024 bytes in any single write to
+ * the kernel logging device file, so find and print each line one at
+ * a time.  The allocated size for buf should be at least 1 byte larger
+ * than buf_size (the usable size of the buffer) to make sure there is
+ * room to temporarily stuff a null byte to terminate a line for logging.
+ */
+static void print_buf_lines(struct log_info *log_info, char *buf, int buf_size)
+{
+    char *line_start;
+    char c;
+    int line_len;
+    int i;
+
+    line_start = buf;
+    for (i = 0; i < buf_size; i++) {
+        if (*(buf + i) == '\n') {
+            /* Found a line ending, print the line and compute new line_start */
+            /* Save the next char and replace with \0 */
+            c = *(buf + i + 1);
+            *(buf + i + 1) = '\0';
+            do_log_line(log_info, line_start);
+            /* Restore the saved char */
+            *(buf + i + 1) = c;
+            line_start = buf + i + 1;
+        } else if (*(buf + i) == '\0') {
+            /* The end of the buffer, print the last bit */
+            do_log_line(log_info, line_start);
+            break;
+        }
+    }
+    /* If the buffer was completely full, and didn't end with a newline, just
+     * ignore the partial last line.
+     */
+}
+
+static void init_abbr_buf(struct abbr_buf *a_buf) {
+    char *new_buf;
+
+    memset(a_buf, 0, sizeof(struct abbr_buf));
+    new_buf = malloc(BEGINNING_BUF_SIZE);
+    if (new_buf) {
+        a_buf->b_buf.buf = new_buf;
+        a_buf->b_buf.alloc_len = BEGINNING_BUF_SIZE;
+        a_buf->b_buf.buf_size = BEGINNING_BUF_SIZE - 1;
+    }
+    new_buf = malloc(ENDING_BUF_SIZE);
+    if (new_buf) {
+        a_buf->e_buf.buf = new_buf;
+        a_buf->e_buf.alloc_len = ENDING_BUF_SIZE;
+        a_buf->e_buf.buf_size = ENDING_BUF_SIZE - 1;
+    }
+}
+
+static void free_abbr_buf(struct abbr_buf *a_buf) {
+    free(a_buf->b_buf.buf);
+    free(a_buf->e_buf.buf);
+}
+
+static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen) {
+    if (!a_buf->beginning_buf_full) {
+        a_buf->beginning_buf_full =
+            add_line_to_linear_buf(&a_buf->b_buf, linebuf, linelen);
+    }
+    if (a_buf->beginning_buf_full) {
+        add_line_to_circular_buf(&a_buf->e_buf, linebuf, linelen);
+    }
+}
+
+static void print_abbr_buf(struct log_info *log_info) {
+    struct abbr_buf *a_buf = &log_info->a_buf;
+
+    /* Add the abbreviated output to the kernel log */
+    if (a_buf->b_buf.alloc_len) {
+        print_buf_lines(log_info, a_buf->b_buf.buf, a_buf->b_buf.used_len);
+    }
+
+    /* Print an ellipsis to indicate that the buffer has wrapped or
+     * is full, and some data was not logged.
+     */
+    if (a_buf->e_buf.used_len == a_buf->e_buf.buf_size) {
+        do_log_line(log_info, "...\n");
+    }
+
+    if (a_buf->e_buf.used_len == 0) {
+        return;
+    }
+
+    /* Simplest way to print the circular buffer is allocate a second buf
+     * of the same size, and memcpy it so it's a simple linear buffer,
+     * and then cal print_buf_lines on it */
+    if (a_buf->e_buf.read < a_buf->e_buf.write) {
+        /* no wrap around, just print it */
+        print_buf_lines(log_info, a_buf->e_buf.buf + a_buf->e_buf.read,
+                        a_buf->e_buf.used_len);
+    } else {
+        /* The circular buffer will always have at least 1 byte unused,
+         * so by allocating alloc_len here we will have at least
+         * 1 byte of space available as required by print_buf_lines().
+         */
+        char * nbuf = malloc(a_buf->e_buf.alloc_len);
+        if (!nbuf) {
+            return;
+        }
+        int first_chunk_len = a_buf->e_buf.buf_size - a_buf->e_buf.read;
+        memcpy(nbuf, a_buf->e_buf.buf + a_buf->e_buf.read, first_chunk_len);
+        /* copy second chunk */
+        memcpy(nbuf + first_chunk_len, a_buf->e_buf.buf, a_buf->e_buf.write);
+        print_buf_lines(log_info, nbuf, first_chunk_len + a_buf->e_buf.write);
+        free(nbuf);
+    }
+}
+
+static int parent(const char *tag, int parent_read, pid_t pid,
+        int *chld_sts, int log_target, bool abbreviated) {
+    int status = 0;
+    char buffer[4096];
+    struct pollfd poll_fds[] = {
+        [0] = {
+            .fd = parent_read,
+            .events = POLLIN,
+        },
+    };
+    int rc = 0;
+
+    struct log_info log_info;
+
+    int a = 0;  // start index of unprocessed data
+    int b = 0;  // end index of unprocessed data
+    int sz;
+    bool found_child = false;
+    char tmpbuf[256];
+
+    log_info.log_target = log_target;
+    log_info.abbreviated = abbreviated;
+    log_info.btag = basename(tag);
+    if (!log_info.btag) {
+        log_info.btag = (char*) tag;
+    }
+
+    if (abbreviated && (log_target == LOG_NONE)) {
+        abbreviated = 0;
+    }
+    if (abbreviated) {
+        init_abbr_buf(&log_info.a_buf);
+    }
+
+    if (log_target == LOG_KLOG) {
+        snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
+                 "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag);
+    }
+
+    while (!found_child) {
+        if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
+            ERROR("poll failed\n");
+            rc = -1;
+            goto err_poll;
+        }
+
+        if (poll_fds[0].revents & POLLIN) {
+            sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b);
+
+            sz += b;
+            // Log one line at a time
+            for (b = 0; b < sz; b++) {
+                if (buffer[b] == '\r') {
+                    if (abbreviated) {
+                        /* The abbreviated logging code uses newline as
+                         * the line separator.  Lucikly, the pty layer
+                         * helpfully cooks the output of the command
+                         * being run and inserts a CR before NL.  So
+                         * I just change it to NL here when doing
+                         * abbreviated logging.
+                         */
+                        buffer[b] = '\n';
+                    } else {
+                        buffer[b] = '\0';
+                    }
+                } else if (buffer[b] == '\n') {
+                    buffer[b] = '\0';
+                    log_line(&log_info, &buffer[a], b - a);
+                    a = b + 1;
+                }
+            }
+
+            if (a == 0 && b == sizeof(buffer) - 1) {
+                // buffer is full, flush
+                buffer[b] = '\0';
+                log_line(&log_info, &buffer[a], b - a);
+                b = 0;
+            } else if (a != b) {
+                // Keep left-overs
+                b -= a;
+                memmove(buffer, &buffer[a], b);
+                a = 0;
+            } else {
+                a = 0;
+                b = 0;
+            }
+        }
+
+        if (poll_fds[0].revents & POLLHUP) {
+            int ret;
+
+            ret = waitpid(pid, &status, WNOHANG);
+            if (ret < 0) {
+                rc = errno;
+                ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
+                goto err_waitpid;
+            }
+            if (ret > 0) {
+                found_child = true;
+            }
+        }
+    }
+
+    if (chld_sts != NULL) {
+        *chld_sts = status;
+    } else {
+      if (WIFEXITED(status))
+        rc = WEXITSTATUS(status);
+      else
+        rc = -ECHILD;
+    }
+
+    // Flush remaining data
+    if (a != b) {
+      buffer[b] = '\0';
+      log_line(&log_info, &buffer[a], b - a);
+    }
+
+    /* All the output has been processed, time to dump the abbreviated output */
+    if (abbreviated) {
+        print_abbr_buf(&log_info);
+    }
+
+    if (WIFEXITED(status)) {
+      if (WEXITSTATUS(status)) {
+        snprintf(tmpbuf, sizeof(tmpbuf),
+                 "%s terminated by exit(%d)\n", log_info.btag, WEXITSTATUS(status));
+        do_log_line(&log_info, tmpbuf);
+      }
+    } else {
+      if (WIFSIGNALED(status)) {
+        snprintf(tmpbuf, sizeof(tmpbuf),
+                       "%s terminated by signal %d\n", log_info.btag, WTERMSIG(status));
+        do_log_line(&log_info, tmpbuf);
+      } else if (WIFSTOPPED(status)) {
+        snprintf(tmpbuf, sizeof(tmpbuf),
+                       "%s stopped by signal %d\n", log_info.btag, WSTOPSIG(status));
+        do_log_line(&log_info, tmpbuf);
+      }
+    }
+
+err_waitpid:
+err_poll:
+    if (abbreviated) {
+        free_abbr_buf(&log_info.a_buf);
+    }
+    return rc;
+}
+
+static void child(int argc, char* argv[]) {
+    // create null terminated argv_child array
+    char* argv_child[argc + 1];
+    memcpy(argv_child, argv, argc * sizeof(char *));
+    argv_child[argc] = NULL;
+
+    if (execvp(argv_child[0], argv_child)) {
+        FATAL_CHILD("executing %s failed: %s\n", argv_child[0],
+                strerror(errno));
+    }
+}
+
+int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
+        int log_target, bool abbreviated) {
+    pid_t pid;
+    int parent_ptty;
+    int child_ptty;
+    char *child_devname = NULL;
+    struct sigaction intact;
+    struct sigaction quitact;
+    sigset_t blockset;
+    sigset_t oldset;
+    int rc = 0;
+
+    rc = pthread_mutex_lock(&fd_mutex);
+    if (rc) {
+        ERROR("failed to lock signal_fd mutex\n");
+        goto err_lock;
+    }
+
+    /* Use ptty instead of socketpair so that STDOUT is not buffered */
+    parent_ptty = open("/dev/ptmx", O_RDWR);
+    if (parent_ptty < 0) {
+        ERROR("Cannot create parent ptty\n");
+        rc = -1;
+        goto err_open;
+    }
+
+    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
+            ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
+        ERROR("Problem with /dev/ptmx\n");
+        rc = -1;
+        goto err_ptty;
+    }
+
+    child_ptty = open(child_devname, O_RDWR);
+    if (child_ptty < 0) {
+        ERROR("Cannot open child_ptty\n");
+        rc = -1;
+        goto err_child_ptty;
+    }
+
+    sigemptyset(&blockset);
+    sigaddset(&blockset, SIGINT);
+    sigaddset(&blockset, SIGQUIT);
+    pthread_sigmask(SIG_BLOCK, &blockset, &oldset);
+
+    pid = fork();
+    if (pid < 0) {
+        close(child_ptty);
+        ERROR("Failed to fork\n");
+        rc = -1;
+        goto err_fork;
+    } else if (pid == 0) {
+        pthread_mutex_unlock(&fd_mutex);
+        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+        close(parent_ptty);
+
+        // redirect stdout and stderr
+        dup2(child_ptty, 1);
+        dup2(child_ptty, 2);
+        close(child_ptty);
+
+        child(argc, argv);
+    } else {
+        close(child_ptty);
+        if (ignore_int_quit) {
+            struct sigaction ignact;
+
+            memset(&ignact, 0, sizeof(ignact));
+            ignact.sa_handler = SIG_IGN;
+            sigaction(SIGINT, &ignact, &intact);
+            sigaction(SIGQUIT, &ignact, &quitact);
+        }
+
+        rc = parent(argv[0], parent_ptty, pid, status, log_target, abbreviated);
+    }
+
+    if (ignore_int_quit) {
+        sigaction(SIGINT, &intact, NULL);
+        sigaction(SIGQUIT, &quitact, NULL);
+    }
+err_fork:
+    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+err_child_ptty:
+err_ptty:
+    close(parent_ptty);
+err_open:
+    pthread_mutex_unlock(&fd_mutex);
+err_lock:
+    return rc;
+}
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index dd777c0..d1c6240 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -14,17 +14,14 @@
  * limitations under the License.
  */
 
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/wait.h>
 #include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
 
-#include "private/android_filesystem_config.h"
+#include <logwrap/logwrap.h>
+#include <cutils/klog.h>
+
 #include "cutils/log.h"
 
 void fatal(const char *msg) {
@@ -35,152 +32,65 @@
 
 void usage() {
     fatal(
-        "Usage: logwrapper [-d] BINARY [ARGS ...]\n"
+        "Usage: logwrapper [-a] [-d] [-k] BINARY [ARGS ...]\n"
         "\n"
         "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
         "the Android logging system. Tag is set to BINARY, priority is\n"
         "always LOG_INFO.\n"
         "\n"
+        "-a: Causes logwrapper to do abbreviated logging.\n"
+        "    This logs up to the first 4K and last 4K of the command\n"
+        "    being run, and logs the output when the command exits\n"
         "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n"
-        "    fault address is set to the status of wait()\n");
-}
-
-void parent(const char *tag, int seg_fault_on_exit, int parent_read) {
-    int status;
-    char buffer[4096];
-
-    int a = 0;  // start index of unprocessed data
-    int b = 0;  // end index of unprocessed data
-    int sz;
-
-    char *btag = basename(tag);
-    if (!btag) btag = (char*) tag;
-
-    while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
-
-        sz += b;
-        // Log one line at a time
-        for (b = 0; b < sz; b++) {
-            if (buffer[b] == '\r') {
-                buffer[b] = '\0';
-            } else if (buffer[b] == '\n') {
-                buffer[b] = '\0';
-                ALOG(LOG_INFO, btag, "%s", &buffer[a]);
-                a = b + 1;
-            }
-        }
-
-        if (a == 0 && b == sizeof(buffer) - 1) {
-            // buffer is full, flush
-            buffer[b] = '\0';
-            ALOG(LOG_INFO, btag, "%s", &buffer[a]);
-            b = 0;
-        } else if (a != b) {
-            // Keep left-overs
-            b -= a;
-            memmove(buffer, &buffer[a], b);
-            a = 0;
-        } else {
-            a = 0;
-            b = 0;
-        }
-
-    }
-    // Flush remaining data
-    if (a != b) {
-        buffer[b] = '\0';
-        ALOG(LOG_INFO, btag, "%s", &buffer[a]);
-    }
-    status = 0xAAAA;
-    if (wait(&status) != -1) {  // Wait for child
-        if (WIFEXITED(status) && WEXITSTATUS(status))
-            ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
-                    WEXITSTATUS(status));
-        else if (WIFSIGNALED(status))
-            ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
-                    WTERMSIG(status));
-        else if (WIFSTOPPED(status))
-            ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
-                    WSTOPSIG(status));
-    } else
-        ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
-                strerror(errno), errno);
-    if (seg_fault_on_exit)
-        *(int *)status = 0;  // causes SIGSEGV with fault_address = status
-}
-
-void child(int argc, char* argv[]) {
-    // create null terminated argv_child array
-    char* argv_child[argc + 1];
-    memcpy(argv_child, argv, argc * sizeof(char *));
-    argv_child[argc] = NULL;
-
-    if (execvp(argv_child[0], argv_child)) {
-        ALOG(LOG_ERROR, "logwrapper",
-            "executing %s failed: %s\n", argv_child[0], strerror(errno));
-        exit(-1);
-    }
+        "    fault address is set to the status of wait()\n"
+        "-k: Causes logwrapper to log to the kernel log instead of\n"
+        "    the Android system log\n");
 }
 
 int main(int argc, char* argv[]) {
-    pid_t pid;
     int seg_fault_on_exit = 0;
+    int log_target = LOG_ALOG;
+    bool abbreviated = false;
+    int ch;
+    int status = 0xAAAA;
+    int rc;
 
-    int parent_ptty;
-    int child_ptty;
-    char *child_devname = NULL;
-
-    if (argc < 2) {
-        usage();
-    }
-
-    if (strncmp(argv[1], "-d", 2) == 0) {
-        seg_fault_on_exit = 1;
-        argc--;
-        argv++;
-    }
-
-    if (argc < 2) {
-        usage();
-    }
-
-    /* Use ptty instead of socketpair so that STDOUT is not buffered */
-    parent_ptty = open("/dev/ptmx", O_RDWR);
-    if (parent_ptty < 0) {
-        fatal("Cannot create parent ptty\n");
-    }
-
-    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
-            ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
-        fatal("Problem with /dev/ptmx\n");
-    }
-
-    pid = fork();
-    if (pid < 0) {
-        fatal("Failed to fork\n");
-    } else if (pid == 0) {
-        child_ptty = open(child_devname, O_RDWR);
-        if (child_ptty < 0) {
-            fatal("Problem with child ptty\n");
+    while ((ch = getopt(argc, argv, "adk")) != -1) {
+        switch (ch) {
+            case 'a':
+                abbreviated = true;
+                break;
+            case 'd':
+                seg_fault_on_exit = 1;
+                break;
+            case 'k':
+                log_target = LOG_KLOG;
+                klog_set_level(6);
+                break;
+            case '?':
+            default:
+              usage();
         }
+    }
+    argc -= optind;
+    argv += optind;
 
-        // redirect stdout and stderr
-        close(parent_ptty);
-        dup2(child_ptty, 1);
-        dup2(child_ptty, 2);
-        close(child_ptty);
-
-        child(argc - 1, &argv[1]);
-
-    } else {
-        // switch user and group to "log"
-        // this may fail if we are not root, 
-        // but in that case switching user/group is unnecessary 
-        setgid(AID_LOG);
-        setuid(AID_LOG);
-
-        parent(argv[1], seg_fault_on_exit, parent_ptty);
+    if (argc < 1) {
+        usage();
     }
 
-    return 0;
+    rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
+                                 log_target, abbreviated);
+    if (!rc) {
+        if (WIFEXITED(status))
+            rc = WEXITSTATUS(status);
+        else
+            rc = -ECHILD;
+    }
+
+    if (seg_fault_on_exit) {
+        *(int *)status = 0;  // causes SIGSEGV with fault_address = status
+    }
+
+    return rc;
 }
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 64ff522..3417f54 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -4,28 +4,8 @@
 # files that live under /system/etc/...
 
 copy_from := \
-	etc/dbus.conf \
 	etc/hosts
 
-ifeq ($(TARGET_PRODUCT),full)
-copy_from += etc/vold.fstab
-endif
-
-ifeq ($(TARGET_PRODUCT),full_x86)
-copy_from += etc/vold.fstab
-endif
-
-ifeq ($(TARGET_PRODUCT),full_mips)
-copy_from += etc/vold.fstab
-endif
-
-# the /system/etc/init.goldfish.sh is needed to enable emulator support
-# in the system image. In theory, we don't need these for -user builds
-# which are device-specific. However, these builds require at the moment
-# to run the dex pre-optimization *in* the emulator. So keep the file until
-# we are capable of running dex preopt on the host.
-#
-copy_from += etc/init.goldfish.sh
 
 copy_to := $(addprefix $(TARGET_OUT)/,$(copy_from))
 copy_from := $(addprefix $(LOCAL_PATH)/,$(copy_from))
@@ -56,20 +36,6 @@
 
 # init.usb.rc is handled by build/target/product/core.rc
 
-# Just like /system/etc/init.goldfish.sh, the /init.godlfish.rc is here
-# to allow -user builds to properly run the dex pre-optimization pass in
-# the emulator.
-file := $(TARGET_ROOT_OUT)/init.goldfish.rc
-$(file) : $(LOCAL_PATH)/etc/init.goldfish.rc | $(ACP)
-	$(transform-prebuilt-to-target)
-ALL_PREBUILT += $(file)
-$(INSTALLED_RAMDISK_TARGET): $(file)
-
-file := $(TARGET_ROOT_OUT)/ueventd.goldfish.rc
-$(file) : $(LOCAL_PATH)/etc/ueventd.goldfish.rc | $(ACP)
-	$(transform-prebuilt-to-target)
-ALL_PREBUILT += $(file)
-$(INSTALLED_RAMDISK_TARGET): $(file)
 
 # create some directories (some are mount points)
 DIRS := $(addprefix $(TARGET_ROOT_OUT)/, \
diff --git a/rootdir/etc/dbus.conf b/rootdir/etc/dbus.conf
deleted file mode 100644
index 75586b9..0000000
--- a/rootdir/etc/dbus.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
-
-  <!-- Our well-known bus type, do not change this -->
-  <type>system</type>
-
-  <!-- Only allow socket-credentials-based authentication -->
-  <auth>EXTERNAL</auth>
-
-  <!-- Only listen on a local socket. (abstract=/path/to/socket 
-       means use abstract namespace, don't really create filesystem 
-       file; only Linux supports this. Use path=/whatever on other 
-       systems.) -->
-  <listen>unix:path=/dev/socket/dbus</listen>
-
-  <!-- Allow everything, D-Bus socket is protected by unix filesystem
-       permissions -->
-  <policy context="default">
-    <allow send_interface="*"/>
-    <allow receive_interface="*"/>
-    <allow own="*"/>
-    <allow user="*"/>
-    <allow send_requested_reply="true"/>
-    <allow receive_requested_reply="true"/>
-  </policy>
-</busconfig>
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
deleted file mode 100644
index 1373be8..0000000
--- a/rootdir/etc/init.goldfish.rc
+++ /dev/null
@@ -1,83 +0,0 @@
-on early-init
-    export EXTERNAL_STORAGE /mnt/sdcard
-    mkdir /mnt/sdcard 0000 system system
-    # for backwards compatibility
-    symlink /mnt/sdcard /sdcard
-    mount debugfs debugfs /sys/kernel/debug
-
-on boot
-    setsebool in_qemu 1
-    restorecon /sys/qemu_trace/process_name
-    restorecon /sys/qemu_trace/state
-    restorecon /sys/qemu_trace/symbol
-    setprop ARGH ARGH
-    setprop net.eth0.gw 10.0.2.2
-    setprop net.eth0.dns1 10.0.2.3
-    setprop net.gprs.local-ip 10.0.2.15
-    setprop ro.radio.use-ppp no
-    setprop ro.build.product generic
-    setprop ro.product.device generic
-
-# fake some battery state
-    setprop status.battery.state Slow
-    setprop status.battery.level 5
-    setprop status.battery.level_raw  50
-    setprop status.battery.level_scale 9
-
-# disable some daemons the emulator doesn't want
-    stop dund
-    stop akmd
-
-# start essential services
-    start qemud
-    start goldfish-logcat
-    start goldfish-setup
-
-    setprop ro.setupwizard.mode EMULATOR
-
-# enable Google-specific location features,
-# like NetworkLocationProvider and LocationCollector
-    setprop ro.com.google.locationfeatures 1
-
-# For the emulator, which bypasses Setup Wizard, you can specify
-# account info for the device via these two properties.  Google
-# Login Service will insert these accounts into the database when
-# it is created (ie, after a data wipe).
-#
-#   setprop ro.config.hosted_account username@hosteddomain.org:password
-#   setprop ro.config.google_account username@gmail.com:password
-#
-# You MUST have a Google account on the device, and you MAY
-# additionally have a hosted account.  No other configuration is
-# supported, and arbitrary breakage may result if you specify
-# something else.
-
-service goldfish-setup /system/etc/init.goldfish.sh
-    user root
-    group root
-    oneshot
-
-# The qemu-props program is used to set various system
-# properties on boot. It must be run early during the boot
-# process to avoid race conditions with other daemons that
-# might read them (e.g. surface flinger), so define it in
-# class 'core'
-#
-service qemu-props /system/bin/qemu-props
-    class core
-    user root
-    group root
-    oneshot
-
-service qemud /system/bin/qemud
-    socket qemud    stream 666
-    oneshot
-
-# -Q is a special logcat option that forces the
-# program to check wether it runs on the emulator
-# if it does, it redirects its output to the device
-# named by the androidboot.console kernel option
-# if not, is simply exits immediately
-
-service goldfish-logcat /system/bin/logcat -Q
-    oneshot
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
deleted file mode 100755
index ece75b4..0000000
--- a/rootdir/etc/init.goldfish.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/system/bin/sh
-
-# Setup networking when boot starts
-ifconfig eth0 10.0.2.15 netmask 255.255.255.0 up
-route add default gw 10.0.2.2 dev eth0
-
-# ro.kernel.android.qemud is normally set when we
-# want the RIL (radio interface layer) to talk to
-# the emulated modem through qemud.
-#
-# However, this will be undefined in two cases:
-#
-# - When we want the RIL to talk directly to a guest
-#   serial device that is connected to a host serial
-#   device by the emulator.
-#
-# - We don't want to use the RIL but the VM-based
-#   modem emulation that runs inside the guest system
-#   instead.
-#
-# The following detects the latter case and sets up the
-# system for it.
-#
-qemud=`getprop ro.kernel.android.qemud`
-case "$qemud" in
-    "")
-    radio_ril=`getprop ro.kernel.android.ril`
-    case "$radio_ril" in
-        "")
-        # no need for the radio interface daemon
-        # telephony is entirely emulated in Java
-        setprop ro.radio.noril yes
-        stop ril-daemon
-        ;;
-    esac
-    ;;
-esac
-
-# Setup additionnal DNS servers if needed
-num_dns=`getprop ro.kernel.ndns`
-case "$num_dns" in
-    2) setprop net.eth0.dns2 10.0.2.4
-       ;;
-    3) setprop net.eth0.dns2 10.0.2.4
-       setprop net.eth0.dns3 10.0.2.5
-       ;;
-    4) setprop net.eth0.dns2 10.0.2.4
-       setprop net.eth0.dns3 10.0.2.5
-       setprop net.eth0.dns4 10.0.2.6
-       ;;
-esac
-
-# disable boot animation for a faster boot sequence when needed
-boot_anim=`getprop ro.kernel.android.bootanim`
-case "$boot_anim" in
-    0)  setprop debug.sf.nobootanimation 1
-    ;;
-esac
-
-# set up the second interface (for inter-emulator connections)
-# if required
-my_ip=`getprop net.shared_net_ip`
-case "$my_ip" in
-    "")
-    ;;
-    *) ifconfig eth1 "$my_ip" netmask 255.255.255.0 up
-    ;;
-esac
diff --git a/rootdir/etc/ueventd.goldfish.rc b/rootdir/etc/ueventd.goldfish.rc
deleted file mode 100644
index 8de7049..0000000
--- a/rootdir/etc/ueventd.goldfish.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-# These settings are specific to running under the Android emulator
-/dev/qemu_trace           0666   system     system
-/dev/qemu_pipe            0666   system     system
-/dev/ttyS*                0666   system     system
-/proc                     0666   system     system
diff --git a/rootdir/etc/vold.fstab b/rootdir/etc/vold.fstab
deleted file mode 100644
index 4aad8dc..0000000
--- a/rootdir/etc/vold.fstab
+++ /dev/null
@@ -1,24 +0,0 @@
-## Vold 2.0 Generic fstab
-## - San Mehat (san@android.com)
-## 
-
-#######################
-## Regular device mount
-##
-## Format: dev_mount <label> <mount_point> <part> <sysfs_path1...> 
-## label        - Label for the volume
-## mount_point  - Where the volume will be mounted
-## part         - Partition # (1 based), or 'auto' for first usable partition.
-## <sysfs_path> - List of sysfs paths to source devices
-######################
-
-## Example of a standard sdcard mount for the emulator / Dream
-# Mounts the first usable partition of the specified device
-dev_mount sdcard /mnt/sdcard auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
-
-## Example of a dual card setup
-# dev_mount left_sdcard  /sdcard1  auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
-# dev_mount right_sdcard /sdcard2  auto /devices/platform/goldfish_mmc.1 /devices/platform/msm_sdcc.3/mmc_host/mmc1
-
-## Example of specifying a specific partition for mounts
-# dev_mount sdcard /sdcard 2 /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 5206cd1..18fc007 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -37,7 +37,7 @@
     export ANDROID_STORAGE /storage
     export ASEC_MOUNTPOINT /mnt/asec
     export LOOP_MOUNTPOINT /mnt/obb
-    export BOOTCLASSPATH /system/framework/core.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar
+    export BOOTCLASSPATH /system/framework/core.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar
 
 # Backward compatibility
     symlink /system/etc /etc
@@ -214,6 +214,7 @@
     mkdir /data/misc/wifi 0770 wifi wifi
     chmod 0660 /data/misc/wifi/wpa_supplicant.conf
     mkdir /data/local 0751 root root
+    mkdir /data/misc/media 0700 media media
 
     # For security reasons, /data/local/tmp should always be empty.
     # Do not place files or directories in /data/local/tmp
@@ -242,6 +243,13 @@
     # the following directory.
     mkdir /data/drm 0770 drm drm
 
+    # create directory for MediaDrm plug-ins - give drm the read/write access to
+    # the following directory.
+    mkdir /data/mediadrm 0770 mediadrm mediadrm
+
+    # symlink to bugreport storage location
+    symlink /data/data/com.android.shell/files/bugreports /data/bugreports
+
     # Separate location for storing security policy files on data
     mkdir /data/security 0711 system system
 
@@ -291,10 +299,14 @@
 
     chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate
     chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate
+    chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_slack
+    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_slack
     chown system system /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
     chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/min_sample_time
     chown system system /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
     chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq
+    chown system system /sys/devices/system/cpu/cpufreq/interactive/target_loads
+    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/target_loads
     chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
     chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
     chown system system /sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay
@@ -306,6 +318,8 @@
     chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/input_boost
     chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration
     chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration
+    chown system system /sys/devices/system/cpu/cpufreq/interactive/io_is_busy
+    chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/io_is_busy
 
     # Assume SMP uses shared cpufreq policy for all CPUs
     chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
@@ -332,6 +346,10 @@
     chown system system /sys/kernel/ipv4/tcp_rmem_max
     chown root radio /proc/cmdline
 
+# Set these so we can remotely update SELinux policy
+    chown system system /sys/fs/selinux/load
+    chown system system /sys/fs/selinux/enforce
+
 # Define TCP buffer sizes for various networks
 #   ReadMin, ReadInitial, ReadMax, WriteMin, WriteInitial, WriteMax,
     setprop net.tcp.buffersize.default 4096,87380,110208,4096,16384,110208
@@ -463,7 +481,7 @@
 service media /system/bin/mediaserver
     class main
     user media
-    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc
+    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
     ioprio rt 4
 
 service bootanim /system/bin/bootanimation
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index f37b630..15467cc 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -88,5 +88,4 @@
 # Used to set USB configuration at boot and to switch the configuration
 # when changing the default configuration
 on property:persist.sys.usb.config=*
-    setprop sys.usb.config none
     setprop sys.usb.config ${persist.sys.usb.config}
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 8d87ee9..bff6e67 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -28,6 +28,8 @@
 #include <limits.h>
 #include <ctype.h>
 #include <pthread.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -1305,6 +1307,7 @@
     gid_t gid = 0;
     int num_threads = DEFAULT_NUM_THREADS;
     int i;
+    struct rlimit rlim;
 
     for (i = 1; i < argc; i++) {
         char* arg = argv[i];
@@ -1353,6 +1356,12 @@
         return usage();
     }
 
+    rlim.rlim_cur = 8192;
+    rlim.rlim_max = 8192;
+    if (setrlimit(RLIMIT_NOFILE, &rlim)) {
+        ERROR("Error setting RLIMIT_NOFILE, errno = %d\n", errno);
+    }
+
     res = run(source_path, dest_path, uid, gid, num_threads);
     return res < 0 ? 1 : 0;
 }
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index dbbce06..c764690 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -58,6 +58,7 @@
 	lsof \
 	du \
 	md5 \
+	clear \
 	getenforce \
 	setenforce \
 	chcon \
@@ -87,6 +88,7 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
+	liblog \
 	libc \
 	libusbhost \
 	libselinux
diff --git a/toolbox/clear.c b/toolbox/clear.c
new file mode 100644
index 0000000..df46ad2
--- /dev/null
+++ b/toolbox/clear.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+int clear_main(int argc, char **argv) {
+    /* This prints the clear screen and move cursor to top-left corner control
+     * characters for VT100 terminals. This means it will not work on
+     * non-VT100 compliant terminals, namely Windows' cmd.exe, but should
+     * work on anything unix-y. */
+    fputs("\x1b[2J\x1b[H", stdout);
+    return 0;
+}
diff --git a/toolbox/du.c b/toolbox/du.c
index 06374a4..fc7c943 100644
--- a/toolbox/du.c
+++ b/toolbox/du.c
@@ -62,7 +62,7 @@
 
 int	linkchk(dev_t, ino_t);
 void	prstat(const char *, int64_t);
-void	usage(void);
+static void	usage(void);
 
 long blocksize;
 
@@ -312,7 +312,7 @@
 	return 0;
 }
 
-void
+static void
 usage(void)
 {
 
diff --git a/toolbox/renice.c b/toolbox/renice.c
index 978b329..9dfeb51 100644
--- a/toolbox/renice.c
+++ b/toolbox/renice.c
@@ -35,11 +35,12 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sched.h>
+#include <getopt.h>
 
 static void
 usage(const char *s)
 {
-    fprintf(stderr, "USAGE: %s [[-r] priority pids ...] [-g pid]\n", s);
+    fprintf(stderr, "USAGE: %s [[-r] [-t TYPE] priority pids ...] [-g pid]\n", s);
     exit(EXIT_FAILURE);
 }
 
@@ -74,32 +75,49 @@
            sched_get_priority_min(sched), sched_get_priority_max(sched));
 }
 
+int get_sched(char *str)
+{
+    if (strcasecmp(str, "RR") == 0)
+        return SCHED_RR;
+    else if (strcasecmp(str, "FIFO") == 0)
+        return SCHED_FIFO;
+    else if (strcasecmp(str, "NORMAL") == 0)
+        return SCHED_OTHER;
+    else if (strcasecmp(str, "OTHER") == 0)
+        return SCHED_OTHER;
+    return SCHED_RR;
+}
+
 int renice_main(int argc, char *argv[])
 {
     int prio;
     int realtime = 0;
+    int opt;
+    int sched = SCHED_RR;
     char *cmd = argv[0];
 
-    // consume command name
-    argc--;
-    argv++;
-
-    if (argc < 1)
-        usage(cmd);
-
-    if(strcmp("-r", argv[0]) == 0) {
-        // do realtime priority adjustment
-        realtime = 1;
-        argc--;
-        argv++;
-    }
-
-	if(strcmp("-g", argv[0]) == 0) {
-        if (argc < 2)
+    do {
+        opt = getopt(argc, argv, "rt:g:");
+        if (opt == -1)
+            break;
+        switch (opt) {
+        case 'r':
+            // do realtime priority adjustment
+            realtime = 1;
+            break;
+        case 't':
+            sched = get_sched(optarg);
+            break;
+        case 'g':
+            print_prio(atoi(optarg));
+            return 0;
+        default:
             usage(cmd);
-        print_prio(atoi(argv[1]));
-        return 0;
-    }
+        }
+    } while (1);
+
+    argc -= optind;
+    argv += optind;
 
     if (argc < 1)
         usage(cmd);
@@ -122,7 +140,7 @@
             struct sched_param sp = { .sched_priority = prio };
             int ret;
 
-            ret = sched_setscheduler(pid, SCHED_RR, &sp);
+            ret = sched_setscheduler(pid, sched, &sp);
             if (ret) {
                 perror("sched_set_scheduler");
                 exit(EXIT_FAILURE);
@@ -137,8 +155,6 @@
             }
         }
     }
-   
+
     return 0;
 }
-
-