Merge "libsparse: allow including from C++"
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index 6fc55df..0c46a0c 100755
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -140,6 +140,8 @@
 #define VENDOR_ID_PMC           0x04DA
 // Positivo's USB Vendor ID
 #define VENDOR_ID_POSITIVO      0x1662
+// Prestigio's USB Vendor ID
+#define VENDOR_ID_PRESTIGIO     0x29e4
 // Qisda's USB Vendor ID
 #define VENDOR_ID_QISDA         0x1D45
 // Qualcomm's USB Vendor ID
@@ -237,6 +239,7 @@
     VENDOR_ID_PHILIPS,
     VENDOR_ID_PMC,
     VENDOR_ID_POSITIVO,
+    VENDOR_ID_PRESTIGIO,
     VENDOR_ID_QISDA,
     VENDOR_ID_QUALCOMM,
     VENDOR_ID_QUANTA,
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index 9b20914..d4c252f 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -24,6 +24,7 @@
 #include <sys/wait.h>
 
 #include <backtrace/Backtrace.h>
+#include <log/log.h>
 #include <log/logd.h>
 
 const int sleep_time_usec = 50000;         // 0.05 seconds
@@ -64,7 +65,7 @@
   }
 
   if (want_log_write) {
-    __android_log_write(ANDROID_LOG_INFO, "DEBUG", buf);
+    __android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_INFO, "DEBUG", buf);
     if (want_amfd_write) {
       int written = write_to_am(log->amfd, buf, len);
       if (written <= 0) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 6145771..45bbfdc 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -337,7 +337,7 @@
 /* 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)
+                     const char *blk_device)
 {
     struct fstab_rec *new_fstab_recs;
     int n = fstab->num_entries;
diff --git a/fs_mgr/fs_mgr_main.c b/fs_mgr/fs_mgr_main.c
index 4bde4a1..e5a00d5 100644
--- a/fs_mgr/fs_mgr_main.c
+++ b/fs_mgr/fs_mgr_main.c
@@ -80,10 +80,10 @@
     int a_flag=0;
     int u_flag=0;
     int n_flag=0;
-    char *n_name;
-    char *n_blk_dev;
-    char *fstab_file;
-    struct fstab *fstab;
+    char *n_name=NULL;
+    char *n_blk_dev=NULL;
+    char *fstab_file=NULL;
+    struct fstab *fstab=NULL;
 
     klog_init();
     klog_set_level(6);
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 0f90c32..835cf64 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -57,7 +57,7 @@
                           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);
+                     const char *blk_device);
 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);
diff --git a/healthd/healthd_board_default.cpp b/healthd/healthd_board_default.cpp
index b2bb516..ed4ddb4 100644
--- a/healthd/healthd_board_default.cpp
+++ b/healthd/healthd_board_default.cpp
@@ -16,13 +16,13 @@
 
 #include <healthd.h>
 
-void healthd_board_init(struct healthd_config *config)
+void healthd_board_init(struct healthd_config*)
 {
     // use defaults
 }
 
 
-int healthd_board_battery_update(struct android::BatteryProperties *props)
+int healthd_board_battery_update(struct android::BatteryProperties*)
 {
     // return 0 to log periodic polled battery status to kernel log
     return 0;
diff --git a/include/log/log.h b/include/log/log.h
index d469f40..5b76c1a 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -550,6 +550,7 @@
     LOG_ID_RADIO = 1,
     LOG_ID_EVENTS = 2,
     LOG_ID_SYSTEM = 3,
+    LOG_ID_CRASH = 4,
 
     LOG_ID_MAX
 } log_id_t;
diff --git a/include/log/logger.h b/include/log/logger.h
index 3c6ea30..ed39c4f 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -142,9 +142,7 @@
 
 int android_logger_clear(struct logger *logger);
 long android_logger_get_log_size(struct logger *logger);
-#ifdef USERDEBUG_BUILD
 int android_logger_set_log_size(struct logger *logger, unsigned long size);
-#endif
 long android_logger_get_log_readable_size(struct logger *logger);
 int android_logger_get_log_version(struct logger *logger);
 
@@ -152,12 +150,10 @@
 
 ssize_t android_logger_get_statistics(struct logger_list *logger_list,
                                       char *buf, size_t len);
-#ifdef USERDEBUG_BUILD
 ssize_t android_logger_get_prune_list(struct logger_list *logger_list,
                                       char *buf, size_t len);
 int android_logger_set_prune_list(struct logger_list *logger_list,
                                   char *buf, size_t len);
-#endif
 
 struct logger_list *android_logger_list_alloc(int mode,
                                               unsigned int tail,
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 9c26baf..d662107 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -251,6 +251,7 @@
 
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
+    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/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/*" },
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
index f1a4b43..18049cd 100644
--- a/include/sysutils/FrameworkListener.h
+++ b/include/sysutils/FrameworkListener.h
@@ -36,6 +36,7 @@
 public:
     FrameworkListener(const char *socketName);
     FrameworkListener(const char *socketName, bool withSeq);
+    FrameworkListener(int sock);
     virtual ~FrameworkListener() {}
 
 protected:
diff --git a/init/property_service.c b/init/property_service.c
index fe7cbb5..eb19f93 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -269,6 +269,7 @@
         return;
     }
     write(fd, value, strlen(value));
+    fsync(fd);
     close(fd);
 
     snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
index 034b73c..67d372a 100755
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -42,7 +42,7 @@
     BACK_LOGW("unw_getcontext failed %d", ret);
     return false;
   }
-  return UnwindFromContext(num_ignore_frames, true);
+  return UnwindFromContext(num_ignore_frames, false);
 }
 
 std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
@@ -57,12 +57,14 @@
   return "";
 }
 
-bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) {
+bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool within_handler) {
   // The cursor structure is pretty large, do not put it on the stack.
   unw_cursor_t* cursor = new unw_cursor_t;
   int ret = unw_init_local(cursor, &context_);
   if (ret < 0) {
-    BACK_LOGW("unw_init_local failed %d", ret);
+    if (!within_handler) {
+      BACK_LOGW("unw_init_local failed %d", ret);
+    }
     delete cursor;
     return false;
   }
@@ -74,13 +76,17 @@
     unw_word_t pc;
     ret = unw_get_reg(cursor, UNW_REG_IP, &pc);
     if (ret < 0) {
-      BACK_LOGW("Failed to read IP %d", ret);
+      if (!within_handler) {
+        BACK_LOGW("Failed to read IP %d", ret);
+      }
       break;
     }
     unw_word_t sp;
     ret = unw_get_reg(cursor, UNW_REG_SP, &sp);
     if (ret < 0) {
-      BACK_LOGW("Failed to read SP %d", ret);
+      if (!within_handler) {
+        BACK_LOGW("Failed to read SP %d", ret);
+      }
       break;
     }
 
@@ -98,7 +104,7 @@
         prev->stack_size = frame->sp - prev->sp;
       }
 
-      if (resolve) {
+      if (!within_handler) {
         frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
         frame->map = FindMap(frame->pc);
       } else {
@@ -154,7 +160,7 @@
 void UnwindThread::ThreadUnwind(
     siginfo_t* /*siginfo*/, void* sigcontext, size_t num_ignore_frames) {
   ExtractContext(sigcontext);
-  UnwindFromContext(num_ignore_frames, false);
+  UnwindFromContext(num_ignore_frames, true);
 }
 
 //-------------------------------------------------------------------------
diff --git a/libbacktrace/UnwindCurrent.h b/libbacktrace/UnwindCurrent.h
index acce110..41080c7 100644
--- a/libbacktrace/UnwindCurrent.h
+++ b/libbacktrace/UnwindCurrent.h
@@ -34,7 +34,7 @@
 
   virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
 
-  bool UnwindFromContext(size_t num_ignore_frames, bool resolve);
+  bool UnwindFromContext(size_t num_ignore_frames, bool within_handler);
 
   void ExtractContext(void* sigcontext);
 
diff --git a/liblog/Android.mk b/liblog/Android.mk
index a23de2d..5e01903 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -22,10 +22,6 @@
 liblog_sources := logd_write_kern.c
 endif
 
-ifneq ($(filter userdebug eng,$(TARGET_BUILD_VARIANT)),)
-liblog_cflags := -DUSERDEBUG_BUILD=1
-endif
-
 # some files must not be compiled when building against Mingw
 # they correspond to features not used by our host development tools
 # which are also hard or even impossible to port to native Win32
diff --git a/liblog/log_read.c b/liblog/log_read.c
index 2dd07e6..0ff94bf 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -196,7 +196,8 @@
     [LOG_ID_MAIN] = "main",
     [LOG_ID_RADIO] = "radio",
     [LOG_ID_EVENTS] = "events",
-    [LOG_ID_SYSTEM] = "system"
+    [LOG_ID_SYSTEM] = "system",
+    [LOG_ID_CRASH] = "crash",
 };
 
 const char *android_log_id_to_name(log_id_t log_id)
@@ -340,8 +341,6 @@
     return atol(buf);
 }
 
-#ifdef USERDEBUG_BUILD
-
 int android_logger_set_log_size(struct logger *logger, unsigned long size)
 {
     char buf[512];
@@ -352,8 +351,6 @@
     return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
 }
 
-#endif /* USERDEBUG_BUILD */
-
 /*
  * returns the readable size of the log's ring buffer (that is, amount of the
  * log consumed)
@@ -408,8 +405,6 @@
     return send_log_msg(NULL, NULL, buf, len);
 }
 
-#ifdef USERDEBUG_BUILD
-
 ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
                                       char *buf, size_t len)
 {
@@ -432,8 +427,6 @@
     return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
 }
 
-#endif /* USERDEBUG_BUILD */
-
 struct logger_list *android_logger_list_alloc(int mode,
                                               unsigned int tail,
                                               pid_t pid)
diff --git a/liblog/log_read_kern.c b/liblog/log_read_kern.c
index 9cccb1d..021fe47 100644
--- a/liblog/log_read_kern.c
+++ b/liblog/log_read_kern.c
@@ -58,7 +58,8 @@
     [LOG_ID_MAIN] = "main",
     [LOG_ID_RADIO] = "radio",
     [LOG_ID_EVENTS] = "events",
-    [LOG_ID_SYSTEM] = "system"
+    [LOG_ID_SYSTEM] = "system",
+    [LOG_ID_CRASH] = "crash"
 };
 
 const char *android_log_id_to_name(log_id_t log_id)
@@ -232,16 +233,12 @@
     return logger_ioctl(logger, LOGGER_GET_LOG_BUF_SIZE, O_RDWR);
 }
 
-#ifdef USERDEBUG_BUILD
-
 int android_logger_set_log_size(struct logger *logger UNUSED,
                                 unsigned long size UNUSED)
 {
     return -ENOTSUP;
 }
 
-#endif /* USERDEBUG_BUILD */
-
 /*
  * returns the readable size of the log's ring buffer (that is, amount of the
  * log consumed)
@@ -272,8 +269,6 @@
     return -ENOTSUP;
 }
 
-#ifdef USERDEBUG_BUILD
-
 ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
                                       char *buf, size_t len)
 {
@@ -289,8 +284,6 @@
     return -ENOTSUP;
 }
 
-#endif /* USERDEBUG_BUILD */
-
 struct logger_list *android_logger_list_alloc(int mode,
                                               unsigned int tail,
                                               pid_t pid)
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 9c73dad..94722d3 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -54,7 +54,7 @@
 static int logd_fd = -1;
 #if FAKE_LOG_DEVICE
 #define WEAK __attribute__((weak))
-static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
+static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
 #endif
 
 /*
@@ -243,7 +243,8 @@
     [LOG_ID_MAIN] = "main",
     [LOG_ID_RADIO] = "radio",
     [LOG_ID_EVENTS] = "events",
-    [LOG_ID_SYSTEM] = "system"
+    [LOG_ID_SYSTEM] = "system",
+    [LOG_ID_CRASH] = "crash"
 };
 
 const WEAK char *android_log_id_to_name(log_id_t log_id)
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index 5ef349b..c29c28f 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -93,6 +93,9 @@
     int log_fd;
 
     if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
+        if (log_id == LOG_ID_CRASH) {
+            log_id = LOG_ID_MAIN;
+        }
         log_fd = log_fds[(int)log_id];
     } else {
         return -EBADF;
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index d726f2d..24ae738 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -484,7 +484,7 @@
 
     EXPECT_EQ(true, matches);
 
-    EXPECT_LE(sizeof(max_payload_buf), max_len);
+    EXPECT_LE(sizeof(max_payload_buf), static_cast<size_t>(max_len));
 
     android_logger_list_close(logger_list);
 }
diff --git a/libpixelflinger/codeflinger/disassem.c b/libpixelflinger/codeflinger/disassem.c
index aeb8034..39dd614 100644
--- a/libpixelflinger/codeflinger/disassem.c
+++ b/libpixelflinger/codeflinger/disassem.c
@@ -301,19 +301,14 @@
 static void disassemble_printaddr(u_int address);
 
 u_int
-disasm(const disasm_interface_t *di, u_int loc, int altfmt)
+disasm(const disasm_interface_t *di, u_int loc, int __unused altfmt)
 {
 	const struct arm32_insn *i_ptr = &arm32_i[0];
-
-	u_int insn;
-	int matchp;
+	u_int insn = di->di_readword(loc);
+	int matchp = 0;
 	int branch;
 	char* f_ptr;
-	int fmt;
-
-	fmt = 0;
-	matchp = 0;
-	insn = di->di_readword(loc);
+	int fmt = 0;
 
 /*	di->di_printf("loc=%08x insn=%08x : ", loc, insn);*/
 
@@ -670,7 +665,7 @@
 }
 
 static void
-disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int loc)
+disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int __unused loc)
 {
 	if (((insn >> 8) & 0xf) == 1)
 		di->di_printf("f%d, ", (insn >> 12) & 0x07);
diff --git a/libpixelflinger/codeflinger/disassem.h b/libpixelflinger/codeflinger/disassem.h
index 02747cd..c7c60b6 100644
--- a/libpixelflinger/codeflinger/disassem.h
+++ b/libpixelflinger/codeflinger/disassem.h
@@ -49,8 +49,8 @@
 
 typedef struct {
 	u_int	(*di_readword)(u_int);
-	void	(*di_printaddr)(u_int);	
-	void	(*di_printf)(const char *, ...);
+	void	(*di_printaddr)(u_int);
+	int	(*di_printf)(const char *, ...);
 } disasm_interface_t;
 
 /* Prototypes for callable functions */
diff --git a/libsuspend/autosuspend_earlysuspend.c b/libsuspend/autosuspend_earlysuspend.c
index 1df8c6a..2bece4c 100644
--- a/libsuspend/autosuspend_earlysuspend.c
+++ b/libsuspend/autosuspend_earlysuspend.c
@@ -75,13 +75,8 @@
     return err < 0 ? err : 0;
 }
 
-static void *earlysuspend_thread_func(void *arg)
+static void *earlysuspend_thread_func(void __unused *arg)
 {
-    char buf[80];
-    char wakeup_count[20];
-    int wakeup_count_len;
-    int ret;
-
     while (1) {
         if (wait_for_fb_sleep()) {
             ALOGE("Failed reading wait_for_fb_sleep, exiting earlysuspend thread\n");
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index a5ffda2..01ed54e 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -39,6 +39,11 @@
     init(socketName, false);
 }
 
+FrameworkListener::FrameworkListener(int sock) :
+                            SocketListener(sock, true) {
+    init(NULL, false);
+}
+
 void FrameworkListener::init(const char *socketName UNUSED, bool withSeq) {
     mCommands = new FrameworkCommandCollection();
     errorRate = 0;
diff --git a/libutils/BlobCache.cpp b/libutils/BlobCache.cpp
index 0fb1d8e..660917b 100644
--- a/libutils/BlobCache.cpp
+++ b/libutils/BlobCache.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "BlobCache"
 //#define LOG_NDEBUG 0
 
+#include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -54,18 +55,18 @@
 void BlobCache::set(const void* key, size_t keySize, const void* value,
         size_t valueSize) {
     if (mMaxKeySize < keySize) {
-        ALOGV("set: not caching because the key is too large: %d (limit: %d)",
+        ALOGV("set: not caching because the key is too large: %zu (limit: %zu)",
                 keySize, mMaxKeySize);
         return;
     }
     if (mMaxValueSize < valueSize) {
-        ALOGV("set: not caching because the value is too large: %d (limit: %d)",
+        ALOGV("set: not caching because the value is too large: %zu (limit: %zu)",
                 valueSize, mMaxValueSize);
         return;
     }
     if (mMaxTotalSize < keySize + valueSize) {
         ALOGV("set: not caching because the combined key/value size is too "
-                "large: %d (limit: %d)", keySize + valueSize, mMaxTotalSize);
+                "large: %zu (limit: %zu)", keySize + valueSize, mMaxTotalSize);
         return;
     }
     if (keySize == 0) {
@@ -94,15 +95,15 @@
                     continue;
                 } else {
                     ALOGV("set: not caching new key/value pair because the "
-                            "total cache size limit would be exceeded: %d "
-                            "(limit: %d)",
+                            "total cache size limit would be exceeded: %zu "
+                            "(limit: %zu)",
                             keySize + valueSize, mMaxTotalSize);
                     break;
                 }
             }
             mCacheEntries.add(CacheEntry(keyBlob, valueBlob));
             mTotalSize = newTotalSize;
-            ALOGV("set: created new cache entry with %d byte key and %d byte value",
+            ALOGV("set: created new cache entry with %zu byte key and %zu byte value",
                     keySize, valueSize);
         } else {
             // Update the existing cache entry.
@@ -116,14 +117,14 @@
                     continue;
                 } else {
                     ALOGV("set: not caching new value because the total cache "
-                            "size limit would be exceeded: %d (limit: %d)",
+                            "size limit would be exceeded: %zu (limit: %zu)",
                             keySize + valueSize, mMaxTotalSize);
                     break;
                 }
             }
             mCacheEntries.editItemAt(index).setValue(valueBlob);
             mTotalSize = newTotalSize;
-            ALOGV("set: updated existing cache entry with %d byte key and %d byte "
+            ALOGV("set: updated existing cache entry with %zu byte key and %zu byte "
                     "value", keySize, valueSize);
         }
         break;
@@ -133,7 +134,7 @@
 size_t BlobCache::get(const void* key, size_t keySize, void* value,
         size_t valueSize) {
     if (mMaxKeySize < keySize) {
-        ALOGV("get: not searching because the key is too large: %d (limit %d)",
+        ALOGV("get: not searching because the key is too large: %zu (limit %zu)",
                 keySize, mMaxKeySize);
         return 0;
     }
@@ -141,7 +142,7 @@
     CacheEntry dummyEntry(dummyKey, NULL);
     ssize_t index = mCacheEntries.indexOf(dummyEntry);
     if (index < 0) {
-        ALOGV("get: no cache entry found for key of size %d", keySize);
+        ALOGV("get: no cache entry found for key of size %zu", keySize);
         return 0;
     }
 
@@ -150,10 +151,10 @@
     sp<Blob> valueBlob(mCacheEntries[index].getValue());
     size_t valueBlobSize = valueBlob->getSize();
     if (valueBlobSize <= valueSize) {
-        ALOGV("get: copying %d bytes to caller's buffer", valueBlobSize);
+        ALOGV("get: copying %zu bytes to caller's buffer", valueBlobSize);
         memcpy(value, valueBlob->getData(), valueBlobSize);
     } else {
-        ALOGV("get: caller's buffer is too small for value: %d (needs %d)",
+        ALOGV("get: caller's buffer is too small for value: %zu (needs %zu)",
                 valueSize, valueBlobSize);
     }
     return valueBlobSize;
@@ -229,7 +230,7 @@
     }
     const Header* header = reinterpret_cast<const Header*>(buffer);
     if (header->mMagicNumber != blobCacheMagic) {
-        ALOGE("unflatten: bad magic number: %d", header->mMagicNumber);
+        ALOGE("unflatten: bad magic number: %" PRIu32, header->mMagicNumber);
         return BAD_VALUE;
     }
     if (header->mBlobCacheVersion != blobCacheVersion ||
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index 9ce370e..933e7aa 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -23,6 +23,7 @@
 #include <utils/FileMap.h>
 #include <utils/Log.h>
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -39,37 +40,32 @@
 
 /*static*/ long FileMap::mPageSize = -1;
 
-
-/*
- * Constructor.  Create an empty object.
- */
+// Constructor.  Create an empty object.
 FileMap::FileMap(void)
     : mRefCount(1), mFileName(NULL), mBasePtr(NULL), mBaseLength(0),
       mDataPtr(NULL), mDataLength(0)
 {
 }
 
-/*
- * Destructor.
- */
+// Destructor.
 FileMap::~FileMap(void)
 {
     assert(mRefCount == 0);
 
-    //printf("+++ removing FileMap %p %u\n", mDataPtr, mDataLength);
+    //printf("+++ removing FileMap %p %zu\n", mDataPtr, mDataLength);
 
     mRefCount = -100;       // help catch double-free
     if (mFileName != NULL) {
         free(mFileName);
     }
-#ifdef HAVE_POSIX_FILEMAP    
+#ifdef HAVE_POSIX_FILEMAP
     if (mBasePtr && munmap(mBasePtr, mBaseLength) != 0) {
-        ALOGD("munmap(%p, %d) failed\n", mBasePtr, (int) mBaseLength);
+        ALOGD("munmap(%p, %zu) failed\n", mBasePtr, mBaseLength);
     }
 #endif
 #ifdef HAVE_WIN32_FILEMAP
     if (mBasePtr && UnmapViewOfFile(mBasePtr) == 0) {
-        ALOGD("UnmapViewOfFile(%p) failed, error = %ld\n", mBasePtr,
+        ALOGD("UnmapViewOfFile(%p) failed, error = %" PRId32 "\n", mBasePtr,
               GetLastError() );
     }
     if (mFileMapping != INVALID_HANDLE_VALUE) {
@@ -80,14 +76,12 @@
 }
 
 
-/*
- * Create a new mapping on an open file.
- *
- * Closing the file descriptor does not unmap the pages, so we don't
- * claim ownership of the fd.
- *
- * Returns "false" on failure.
- */
+// Create a new mapping on an open file.
+//
+// Closing the file descriptor does not unmap the pages, so we don't
+// claim ownership of the fd.
+//
+// Returns "false" on failure.
 bool FileMap::create(const char* origFileName, int fd, off64_t offset, size_t length,
         bool readOnly)
 {
@@ -98,32 +92,32 @@
 
     if (mPageSize == -1) {
         SYSTEM_INFO  si;
-        
+
         GetSystemInfo( &si );
         mPageSize = si.dwAllocationGranularity;
     }
 
     DWORD  protect = readOnly ? PAGE_READONLY : PAGE_READWRITE;
-    
+
     mFileHandle  = (HANDLE) _get_osfhandle(fd);
     mFileMapping = CreateFileMapping( mFileHandle, NULL, protect, 0, 0, NULL);
     if (mFileMapping == NULL) {
-        ALOGE("CreateFileMapping(%p, %lx) failed with error %ld\n",
+        ALOGE("CreateFileMapping(%p, %" PRIx32 ") failed with error %" PRId32 "\n",
               mFileHandle, protect, GetLastError() );
         return false;
     }
-    
+
     adjust    = offset % mPageSize;
     adjOffset = offset - adjust;
     adjLength = length + adjust;
-    
-    mBasePtr = MapViewOfFile( mFileMapping, 
+
+    mBasePtr = MapViewOfFile( mFileMapping,
                               readOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
                               0,
                               (DWORD)(adjOffset),
                               adjLength );
     if (mBasePtr == NULL) {
-        ALOGE("MapViewOfFile(%ld, %ld) failed with error %ld\n",
+        ALOGE("MapViewOfFile(%" PRId64 ", %zu) failed with error %" PRId32 "\n",
               adjOffset, adjLength, GetLastError() );
         CloseHandle(mFileMapping);
         mFileMapping = INVALID_HANDLE_VALUE;
@@ -142,7 +136,7 @@
     assert(offset >= 0);
     assert(length > 0);
 
-    /* init on first use */
+    // init on first use
     if (mPageSize == -1) {
 #if NOT_USING_KLIBC
         mPageSize = sysconf(_SC_PAGESIZE);
@@ -151,7 +145,7 @@
             return false;
         }
 #else
-        /* this holds for Linux, Darwin, Cygwin, and doesn't pain the ARM */
+        // this holds for Linux, Darwin, Cygwin, and doesn't pain the ARM
         mPageSize = 4096;
 #endif
     }
@@ -168,19 +162,19 @@
 
     ptr = mmap(NULL, adjLength, prot, flags, fd, adjOffset);
     if (ptr == MAP_FAILED) {
-    	// Cygwin does not seem to like file mapping files from an offset.
-    	// So if we fail, try again with offset zero
-    	if (adjOffset > 0) {
-    		adjust = offset;
-    		goto try_again;
-    	}
-    
-        ALOGE("mmap(%ld,%ld) failed: %s\n",
-            (long) adjOffset, (long) adjLength, strerror(errno));
+        // Cygwin does not seem to like file mapping files from an offset.
+        // So if we fail, try again with offset zero
+        if (adjOffset > 0) {
+            adjust = offset;
+            goto try_again;
+        }
+
+        ALOGE("mmap(%" PRId64 ",%zu) failed: %s\n",
+            adjOffset, adjLength, strerror(errno));
         return false;
     }
     mBasePtr = ptr;
-#endif /* HAVE_POSIX_FILEMAP */
+#endif // HAVE_POSIX_FILEMAP
 
     mFileName = origFileName != NULL ? strdup(origFileName) : NULL;
     mBaseLength = adjLength;
@@ -190,15 +184,13 @@
 
     assert(mBasePtr != NULL);
 
-    ALOGV("MAP: base %p/%d data %p/%d\n",
-        mBasePtr, (int) mBaseLength, mDataPtr, (int) mDataLength);
+    ALOGV("MAP: base %p/%zu data %p/%zu\n",
+        mBasePtr, mBaseLength, mDataPtr, mDataLength);
 
     return true;
 }
 
-/*
- * Provide guidance to the system.
- */
+// Provide guidance to the system.
 int FileMap::advise(MapAdvice advice)
 {
 #if HAVE_MADVISE
@@ -220,6 +212,6 @@
         ALOGW("madvise(%d) failed: %s\n", sysAdvice, strerror(errno));
     return cc;
 #else
-	return -1;
+    return -1;
 #endif // HAVE_MADVISE
 }
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
index 5293cd2..a431e92 100644
--- a/libutils/Timers.cpp
+++ b/libutils/Timers.cpp
@@ -34,7 +34,7 @@
 
 nsecs_t systemTime(int clock)
 {
-#if defined(HAVE_POSIX_CLOCKS)
+#if defined(HAVE_ANDROID_OS)
     static const clockid_t clocks[] = {
             CLOCK_REALTIME,
             CLOCK_MONOTONIC,
@@ -47,7 +47,9 @@
     clock_gettime(clocks[clock], &t);
     return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
 #else
-    // we don't support the clocks here.
+    // Clock support varies widely across hosts. Mac OS doesn't support
+    // posix clocks, older glibcs don't support CLOCK_BOOTTIME and Windows
+    // is windows.
     struct timeval t;
     t.tv_sec = t.tv_usec = 0;
     gettimeofday(&t, NULL);
diff --git a/libutils/tests/BasicHashtable_test.cpp b/libutils/tests/BasicHashtable_test.cpp
index 7dcf750..a61b1e1 100644
--- a/libutils/tests/BasicHashtable_test.cpp
+++ b/libutils/tests/BasicHashtable_test.cpp
@@ -397,7 +397,7 @@
         const SimpleEntry& entry = h.entryAt(index);
         ASSERT_GE(entry.key, 0);
         ASSERT_LT(entry.key, N);
-        ASSERT_EQ(false, set[entry.key]);
+        ASSERT_FALSE(set[entry.key]);
         ASSERT_EQ(entry.key * 10, entry.value);
 
         set[entry.key] = true;
diff --git a/libutils/tests/LruCache_test.cpp b/libutils/tests/LruCache_test.cpp
index e573952..bcbea32 100644
--- a/libutils/tests/LruCache_test.cpp
+++ b/libutils/tests/LruCache_test.cpp
@@ -184,7 +184,7 @@
 
     for (size_t i = 0; i < kNumKeys; i++) {
         strings[i] = (char *)malloc(16);
-        sprintf(strings[i], "%d", i);
+        sprintf(strings[i], "%zu", i);
     }
 
     srandom(12345);
diff --git a/logcat/Android.mk b/logcat/Android.mk
index dd15cb3..b5e27eb 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -3,10 +3,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-ifneq ($(filter userdebug eng,$(TARGET_BUILD_VARIANT)),)
-LOCAL_CFLAGS += -DUSERDEBUG_BUILD=1
-endif
-
 LOCAL_SRC_FILES:= logcat.cpp event.logtags
 
 LOCAL_SHARED_LIBRARIES := liblog
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 5a80efe..995a42e 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -227,22 +227,20 @@
                     "  -T <count>      print only the most recent <count> lines (does not imply -d)\n"
                     "  -g              get the size of the log's ring buffer and exit\n"
                     "  -b <buffer>     Request alternate ring buffer, 'main', 'system', 'radio',\n"
-                    "                  'events' or 'all'. Multiple -b parameters are allowed and\n"
-                    "                  results are interleaved. The default is -b main -b system.\n"
+                    "                  'events', 'crash' or 'all'. Multiple -b parameters are\n"
+                    "                  allowed and results are interleaved. The default is\n"
+                    "                  -b main -b system -b crash.\n"
                     "  -B              output the log in binary.\n"
-                    "  -S              output statistics.\n");
-
-#ifdef USERDEBUG_BUILD
-
-    fprintf(stderr, "--------------------- eng & userdebug builds only ---------------------------\n"
-                    "  -G <count>      set size of log's ring buffer and exit\n"
-                    "  -p              output prune white and ~black list\n"
-                    "  -P '<list> ...' set prune white and ~black list; UID, /PID or !(worst UID)\n"
-                    "                  default is ~!, prune worst UID.\n"
-                    "-----------------------------------------------------------------------------\n"
-    );
-
-#endif
+                    "  -S              output statistics.\n"
+                    "  -G <size>       set size of log ring buffer, may suffix with K or M.\n"
+                    "  -p              print prune white and ~black list. Service is specified as\n"
+                    "                  UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n"
+                    "                  with ~, otherwise weighed for longevity if unadorned. All\n"
+                    "                  other pruning activity is oldest first. Special case ~!\n"
+                    "                  represents an automatic quicker pruning for the noisiest\n"
+                    "                  UID as determined by the current statistics.\n"
+                    "  -P '<list> ...' set prune white and ~black list, using same format as\n"
+                    "                  printed above. Must be quoted.\n");
 
     fprintf(stderr,"\nfilterspecs are a series of \n"
                    "  <tag>[:priority]\n\n"
@@ -291,11 +289,9 @@
     int hasSetLogFormat = 0;
     int clearLog = 0;
     int getLogSize = 0;
-#ifdef USERDEBUG_BUILD
     unsigned long setLogSize = 0;
     int getPruneList = 0;
     char *setPruneList = NULL;
-#endif
     int printStatistics = 0;
     int mode = O_RDONLY;
     const char *forceFilters = NULL;
@@ -323,13 +319,7 @@
     for (;;) {
         int ret;
 
-        ret = getopt(argc, argv,
-#ifdef USERDEBUG_BUILD
-            "cdt:T:gG:sQf:r::n:v:b:BSpP:"
-#else
-            "cdt:T:gsQf:r::n:v:b:BS"
-#endif
-        );
+        ret = getopt(argc, argv, "cdt:T:gG:sQf:r::n:v:b:BSpP:");
 
         if (ret < 0) {
             break;
@@ -386,8 +376,6 @@
                 getLogSize = 1;
             break;
 
-#ifdef USERDEBUG_BUILD
-
             case 'G': {
                 // would use atol if not for the multiplier
                 char *cp = optarg;
@@ -433,8 +421,6 @@
                 setPruneList = optarg;
             break;
 
-#endif
-
             case 'b': {
                 if (strcmp(optarg, "all") == 0) {
                     while (devices) {
@@ -462,10 +448,17 @@
                     if (android_name_to_log_id("events") == LOG_ID_EVENTS) {
                         dev->next = new log_device_t("events", true, 'e');
                         if (dev->next) {
+                            dev = dev->next;
                             android::g_devCount++;
                             needBinary = true;
                         }
                     }
+                    if (android_name_to_log_id("crash") == LOG_ID_CRASH) {
+                        dev->next = new log_device_t("crash", false, 'c');
+                        if (dev->next) {
+                            android::g_devCount++;
+                        }
+                    }
                     break;
                 }
 
@@ -622,6 +615,14 @@
             devices->next = new log_device_t("system", false, 's');
             android::g_devCount++;
         }
+        if (android_name_to_log_id("crash") == LOG_ID_CRASH) {
+            if (devices->next) {
+                devices->next->next = new log_device_t("crash", false, 'c');
+            } else {
+                devices->next = new log_device_t("crash", false, 'c');
+            }
+            android::g_devCount++;
+        }
     }
 
     if (android::g_logRotateSizeKBytes != 0
@@ -704,15 +705,11 @@
             }
         }
 
-#ifdef USERDEBUG_BUILD
-
         if (setLogSize && android_logger_set_log_size(dev->logger, setLogSize)) {
             perror("failed to set the log size");
             exit(EXIT_FAILURE);
         }
 
-#endif
-
         if (getLogSize) {
             long size, readable;
 
@@ -737,8 +734,6 @@
         dev = dev->next;
     }
 
-#ifdef USERDEBUG_BUILD
-
     if (setPruneList) {
         size_t len = strlen(setPruneList) + 32; // margin to allow rc
         char *buf = (char *) malloc(len);
@@ -753,30 +748,18 @@
         }
     }
 
-#endif
-
-    if (
-#ifdef USERDEBUG_BUILD
-        printStatistics || getPruneList
-#else
-        printStatistics
-#endif
-    ) {
+    if (printStatistics || getPruneList) {
         size_t len = 8192;
         char *buf;
 
         for(int retry = 32;
                 (retry >= 0) && ((buf = new char [len]));
                 delete [] buf, --retry) {
-#ifdef USERDEBUG_BUILD
             if (getPruneList) {
                 android_logger_get_prune_list(logger_list, buf, len);
             } else {
                 android_logger_get_statistics(logger_list, buf, len);
             }
-#else
-            android_logger_get_statistics(logger_list, buf, len);
-#endif
             buf[len-1] = '\0';
             size_t ret = atol(buf) + 1;
             if (ret < 4) {
@@ -824,11 +807,9 @@
     if (getLogSize) {
         exit(0);
     }
-#ifdef USERDEBUG_BUILD
     if (setLogSize || setPruneList) {
         exit(0);
     }
-#endif
     if (clearLog) {
         exit(0);
     }
diff --git a/logcat/tests/Android.mk b/logcat/tests/Android.mk
index 733af31..d42b3d0 100644
--- a/logcat/tests/Android.mk
+++ b/logcat/tests/Android.mk
@@ -30,10 +30,6 @@
     -Werror \
     -fno-builtin
 
-ifneq ($(filter userdebug eng,$(TARGET_BUILD_VARIANT)),)
-test_c_flags += -DUSERDEBUG_BUILD=1
-endif
-
 test_src_files := \
     logcat_test.cpp \
 
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 0165073..b07cc8b 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -609,7 +609,6 @@
     EXPECT_EQ(1, signals);
 }
 
-#ifdef USERDEBUG_BUILD
 static bool get_white_black(char **list) {
     FILE *fp;
 
@@ -705,4 +704,3 @@
     free(list);
     list = NULL;
 }
-#endif // USERDEBUG_BUILD
diff --git a/logd/Android.mk b/logd/Android.mk
index 61895c4..0235478 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -4,10 +4,6 @@
 
 LOCAL_MODULE:= logd
 
-ifneq ($(filter userdebug eng,$(TARGET_BUILD_VARIANT)),)
-LOCAL_CFLAGS += -DUSERDEBUG_BUILD=1
-endif
-
 LOCAL_SRC_FILES := \
     main.cpp \
     LogCommand.cpp \
@@ -32,3 +28,5 @@
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index 12b10ca..a7bf92b 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -24,6 +24,7 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 
+#include <cutils/sockets.h>
 #include <private/android_filesystem_config.h>
 #include <sysutils/SocketClient.h>
 
@@ -32,20 +33,16 @@
 
 CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
                                  LogListener * /*swl*/)
-        : FrameworkListener("logd")
+        : FrameworkListener(getLogSocket())
         , mBuf(*buf) {
     // registerCmd(new ShutdownCmd(buf, writer, swl));
     registerCmd(new ClearCmd(buf));
     registerCmd(new GetBufSizeCmd(buf));
-#ifdef USERDEBUG_BUILD
     registerCmd(new SetBufSizeCmd(buf));
-#endif
     registerCmd(new GetBufSizeUsedCmd(buf));
     registerCmd(new GetStatisticsCmd(buf));
-#ifdef USERDEBUG_BUILD
     registerCmd(new SetPruneListCmd(buf));
     registerCmd(new GetPruneListCmd(buf));
-#endif
 }
 
 CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader,
@@ -117,8 +114,6 @@
     return 0;
 }
 
-#ifdef USERDEBUG_BUILD
-
 CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer *buf)
         : LogCommand("setLogSize")
         , mBuf(*buf)
@@ -152,8 +147,6 @@
     return 0;
 }
 
-#endif // USERDEBUG_BUILD
-
 CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer *buf)
         : LogCommand("getLogSizeUsed")
         , mBuf(*buf)
@@ -236,8 +229,6 @@
     return 0;
 }
 
-#ifdef USERDEBUG_BUILD
-
 CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer *buf)
         : LogCommand("getPruneList")
         , mBuf(*buf)
@@ -294,4 +285,15 @@
     return 0;
 }
 
-#endif // USERDEBUG_BUILD
+int CommandListener::getLogSocket() {
+    static const char socketName[] = "logd";
+    int sock = android_get_control_socket(socketName);
+
+    if (sock < 0) {
+        sock = socket_local_server(socketName,
+                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                   SOCK_STREAM);
+    }
+
+    return sock;
+}
diff --git a/logd/CommandListener.h b/logd/CommandListener.h
index de1dcb9..cd1c306 100644
--- a/logd/CommandListener.h
+++ b/logd/CommandListener.h
@@ -31,6 +31,8 @@
     virtual ~CommandListener() {}
 
 private:
+    static int getLogSocket();
+
     class ShutdownCmd : public LogCommand {
         LogBuffer &mBuf;
         LogReader &mReader;
@@ -53,15 +55,11 @@
 
     LogBufferCmd(Clear)
     LogBufferCmd(GetBufSize)
-#ifdef USERDEBUG_BUILD
     LogBufferCmd(SetBufSize)
-#endif
     LogBufferCmd(GetBufSizeUsed)
     LogBufferCmd(GetStatistics)
-#ifdef USERDEBUG_BUILD
     LogBufferCmd(GetPruneList)
     LogBufferCmd(SetPruneList)
-#endif
 };
 
 #endif
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 81eb091..8dcab87 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -28,22 +28,16 @@
 
 // Default
 #define LOG_BUFFER_SIZE (256 * 1024) // Tuned on a per-platform basis here?
-#ifdef USERDEBUG_BUILD
 #define log_buffer_size(id) mMaxSize[id]
-#else
-#define log_buffer_size(id) LOG_BUFFER_SIZE
-#endif
 
 LogBuffer::LogBuffer(LastLogTimes *times)
         : mTimes(*times) {
     pthread_mutex_init(&mLogElementsLock, NULL);
     dgram_qlen_statistics = false;
 
-#ifdef USERDEBUG_BUILD
     log_id_for_each(i) {
         mMaxSize[i] = LOG_BUFFER_SIZE;
     }
-#endif
 }
 
 void LogBuffer::log(log_id_t log_id, log_time realtime,
@@ -171,10 +165,7 @@
         size_t worst_sizes = 0;
         size_t second_worst_sizes = 0;
 
-#ifdef USERDEBUG_BUILD
-        if (mPrune.worstUidEnabled())
-#endif
-        {
+        if ((id != LOG_ID_CRASH) && mPrune.worstUidEnabled()) {
             LidStatistics &l = stats.id(id);
             UidStatisticsCollection::iterator iu;
             for (iu = l.begin(); iu != l.end(); ++iu) {
@@ -217,9 +208,7 @@
                     break;
                 }
                 worst_sizes -= len;
-            }
-#ifdef USERDEBUG_BUILD
-            else if (mPrune.naughty(e)) { // BlackListed
+            } else if (mPrune.naughty(e)) { // BlackListed
                 it = mLogElements.erase(it);
                 stats.subtract(e->getMsgLen(), id, uid, e->getPid());
                 delete e;
@@ -227,34 +216,23 @@
                 if (pruneRows == 0) {
                     break;
                 }
-            }
-#endif
-            else {
+            } else {
                 ++it;
             }
         }
 
-        if (!kick
-#ifdef USERDEBUG_BUILD
-                || !mPrune.worstUidEnabled()
-#endif
-        ) {
+        if (!kick || !mPrune.worstUidEnabled()) {
             break; // the following loop will ask bad clients to skip/drop
         }
     }
 
-#ifdef USERDEBUG_BUILD
     bool whitelist = false;
-#endif
     it = mLogElements.begin();
     while((pruneRows > 0) && (it != mLogElements.end())) {
         LogBufferElement *e = *it;
         if (e->getLogId() == id) {
             if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
-#ifdef USERDEBUG_BUILD
-                if (!whitelist)
-#endif
-                {
+                if (!whitelist) {
                     if (stats.sizes(id) > (2 * log_buffer_size(id))) {
                         // kick a misbehaving log reader client off the island
                         oldest->release_Locked();
@@ -264,13 +242,13 @@
                 }
                 break;
             }
-#ifdef USERDEBUG_BUILD
+
             if (mPrune.nice(e)) { // WhiteListed
                 whitelist = true;
                 it++;
                 continue;
             }
-#endif
+
             it = mLogElements.erase(it);
             stats.subtract(e->getMsgLen(), id, e->getUid(), e->getPid());
             delete e;
@@ -280,7 +258,6 @@
         }
     }
 
-#ifdef USERDEBUG_BUILD
     if (whitelist && (pruneRows > 0)) {
         it = mLogElements.begin();
         while((it != mLogElements.end()) && (pruneRows > 0)) {
@@ -304,7 +281,6 @@
             }
         }
     }
-#endif
 
     LogTimeEntry::unlock();
 }
@@ -324,8 +300,6 @@
     return retval;
 }
 
-#ifdef USERDEBUG_BUILD
-
 // set the total space allocated to "id"
 int LogBuffer::setSize(log_id_t id, unsigned long size) {
     // Reasonable limits ...
@@ -346,15 +320,6 @@
     return retval;
 }
 
-#else // ! USERDEBUG_BUILD
-
-// get the total space allocated to "id"
-unsigned long LogBuffer::getSize(log_id_t /*id*/) {
-    return log_buffer_size(id);
-}
-
-#endif
-
 log_time LogBuffer::flushTo(
         SocketClient *reader, const log_time start, bool privileged,
         bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index bdb3179..b8a54b9 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -38,11 +38,9 @@
 
     bool dgram_qlen_statistics;
 
-#ifdef USERDEBUG_BUILD
     PruneList mPrune;
 
     unsigned long mMaxSize[LOG_ID_MAX];
-#endif
 
 public:
     LastLogTimes &mTimes;
@@ -59,9 +57,7 @@
 
     void clear(log_id_t id);
     unsigned long getSize(log_id_t id);
-#ifdef USERDEBUG_BUILD
     int setSize(log_id_t id, unsigned long size);
-#endif
     unsigned long getSizeUsed(log_id_t id);
     // *strp uses malloc, use free to release.
     void formatStatistics(char **strp, uid_t uid, unsigned int logMask);
@@ -71,11 +67,9 @@
         dgram_qlen_statistics = true;
     }
 
-#ifdef USERDEBUG_BUILD
     int initPrune(char *cp) { return mPrune.init(cp); }
     // *strp uses malloc, use free to release.
     void formatPrune(char **strp) { mPrune.format(strp); }
-#endif
 
     // helper
     char *pidToName(pid_t pid) { return stats.pidToName(pid); }
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index b835b4f..ed5b391 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -107,7 +107,15 @@
 }
 
 int LogListener::getLogSocket() {
-    int sock = android_get_control_socket("logdw");
+    static const char socketName[] = "logdw";
+    int sock = android_get_control_socket(socketName);
+
+    if (sock < 0) {
+        sock = socket_local_server(socketName,
+                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                   SOCK_DGRAM);
+    }
+
     int on = 1;
     if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
         return -1;
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 60a3507..51aa2ad 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -17,13 +17,14 @@
 #include <ctype.h>
 #include <poll.h>
 #include <sys/socket.h>
+
 #include <cutils/sockets.h>
 
 #include "LogReader.h"
 #include "FlushCommand.h"
 
 LogReader::LogReader(LogBuffer *logbuf)
-        : SocketListener("logdr", true)
+        : SocketListener(getLogSocket(), true)
         , mLogbuf(*logbuf)
 { }
 
@@ -167,3 +168,16 @@
     }
     LogTimeEntry::unlock();
 }
+
+int LogReader::getLogSocket() {
+    static const char socketName[] = "logdr";
+    int sock = android_get_control_socket(socketName);
+
+    if (sock < 0) {
+        sock = socket_local_server(socketName,
+                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                   SOCK_SEQPACKET);
+    }
+
+    return sock;
+}
diff --git a/logd/LogReader.h b/logd/LogReader.h
index b267c75..91559a3 100644
--- a/logd/LogReader.h
+++ b/logd/LogReader.h
@@ -34,6 +34,8 @@
     virtual bool onDataAvailable(SocketClient *cli);
 
 private:
+    static int getLogSocket();
+
     void doSocketDelete(SocketClient *cli);
 
 };
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index fc6e6b2..5146030 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -63,7 +63,7 @@
 bool PidStatistics::subtract(unsigned short size) {
     mSizes -= size;
     --mElements;
-    return mElements == 0 && kill(pid, 0);
+    return (mElements == 0) && kill(pid, 0) && (errno != EPERM);
 }
 
 void PidStatistics::addTotal(size_t size, size_t element) {
@@ -508,6 +508,107 @@
         spaces += spaces_total;
     }
 
+    // Construct list of worst spammers by Pid
+    static const unsigned char num_spammers = 10;
+    bool header = false;
+
+    log_id_for_each(i) {
+        if (!(logMask & (1 << i))) {
+            continue;
+        }
+
+        PidStatisticsCollection pids;
+        pids.clear();
+
+        LidStatistics &l = id(i);
+        UidStatisticsCollection::iterator iu;
+        for (iu = l.begin(); iu != l.end(); ++iu) {
+            UidStatistics &u = *(*iu);
+            PidStatisticsCollection::iterator ip;
+            for (ip = u.begin(); ip != u.end(); ++ip) {
+                PidStatistics *p = (*ip);
+                if (p->getPid() == p->gone) {
+                    break;
+                }
+
+                size_t mySizes = p->sizes();
+
+                PidStatisticsCollection::iterator q;
+                unsigned char num = 0;
+                for (q = pids.begin(); q != pids.end(); ++q) {
+                    if (mySizes > (*q)->sizes()) {
+                        pids.insert(q, p);
+                        break;
+                    }
+                    // do we need to traverse deeper in the list?
+                    if (++num > num_spammers) {
+                        break;
+                    }
+                }
+                if (q == pids.end()) {
+                   pids.push_back(p);
+                }
+            }
+        }
+
+        size_t threshold = sizes(i);
+        if (threshold < 65536) {
+            threshold = 65536;
+        }
+        threshold /= 100;
+
+        PidStatisticsCollection::iterator pt = pids.begin();
+
+        for(int line = 0;
+                (pt != pids.end()) && (line < num_spammers);
+                ++line, pt = pids.erase(pt)) {
+            PidStatistics *p = *pt;
+
+            size_t sizes = p->sizes();
+            if (sizes < threshold) {
+                break;
+            }
+
+            char *name = p->getName();
+            pid_t pid = p->getPid();
+            if (!name || !*name) {
+                name = pidToName(pid);
+                if (name) {
+                    if (*name) {
+                        p->setName(name);
+                    } else {
+                        free(name);
+                        name = NULL;
+                    }
+                }
+            }
+
+            if (!header) {
+                string.appendFormat("\n\nChattiest clients:\n"
+                                    "log id %-*s PID[?] name",
+                                    spaces_total, "size/total");
+                header = true;
+            }
+
+            size_t sizesTotal = p->sizesTotal();
+
+            android::String8 sz("");
+            sz.appendFormat((sizes != sizesTotal) ? "%zu/%zu" : "%zu",
+                            sizes, sizesTotal);
+
+            android::String8 pd("");
+            pd.appendFormat("%u%c", pid,
+                            (kill(pid, 0) && (errno != EPERM)) ? '?' : ' ');
+
+            string.appendFormat("\n%-7s%-*s %-7s%s",
+                                line ? "" : android_log_id_to_name(i),
+                                spaces_total, sz.string(), pd.string(),
+                                name ? name : "");
+        }
+
+        pids.clear();
+    }
+
     if (dgram_qlen_statistics) {
         const unsigned short spaces_time = 6;
         const unsigned long long max_seconds = 100000;
@@ -562,7 +663,7 @@
             continue;
         }
 
-        bool header = false;
+        header = false;
         bool first = true;
 
         UidStatisticsCollection::iterator ut;
@@ -610,7 +711,7 @@
                                                  : "%d/%d")
                                              : "%d",
                                          u, p);
-            string.appendFormat((first) ? "\n%-12s" : "%-12s",
+            string.appendFormat(first ? "\n%-12s" : "%-12s",
                                 intermediate.string());
             intermediate.clear();
 
@@ -659,7 +760,7 @@
                     continue;
                 }
                 els = pp->elements();
-                bool gone = kill(p, 0);
+                bool gone = kill(p, 0) && (errno != EPERM);
                 if (gone && (els == 0)) {
                     // ToDo: garbage collection: move this statistical bucket
                     //       from its current UID/PID to UID/? (races and
@@ -676,8 +777,8 @@
                 }
                 spaces = 0;
 
-                intermediate = string.format((gone) ? "%d/%d?" : "%d/%d", u, p);
-                string.appendFormat((first) ? "\n%-12s" : "%-12s",
+                intermediate = string.format(gone ? "%d/%d?" : "%d/%d", u, p);
+                string.appendFormat(first ? "\n%-12s" : "%-12s",
                                     intermediate.string());
                 intermediate.clear();
 
@@ -711,7 +812,7 @@
                 }
 
                 intermediate = string.format("%d/?", u);
-                string.appendFormat((first) ? "\n%-12s" : "%-12s",
+                string.appendFormat(first ? "\n%-12s" : "%-12s",
                                     intermediate.string());
                 intermediate.clear();
 
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index 2c10861..f739865 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#ifdef USERDEBUG_BUILD
-
 #include <ctype.h>
 
 #include <utils/String8.h>
@@ -239,5 +237,3 @@
     }
     return false;
 }
-
-#endif // USERDEBUG_BUILD
diff --git a/logd/main.cpp b/logd/main.cpp
index 7346e2f..04eef4a 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -36,6 +36,35 @@
 #include "LogListener.h"
 #include "LogAudit.h"
 
+//
+//  The service is designed to be run by init, it does not respond well
+// to starting up manually. When starting up manually the sockets will
+// fail to open typically for one of the following reasons:
+//     EADDRINUSE if logger is running.
+//     EACCESS if started without precautions (below)
+//
+// Here is a cookbook procedure for starting up logd manually assuming
+// init is out of the way, pedantically all permissions and selinux
+// security is put back in place:
+//
+//    setenforce 0
+//    rm /dev/socket/logd*
+//    chmod 777 /dev/socket
+//        # here is where you would attach the debugger or valgrind for example
+//    runcon u:r:logd:s0 /system/bin/logd </dev/null >/dev/null 2>&1 &
+//    sleep 1
+//    chmod 755 /dev/socket
+//    chown logd.logd /dev/socket/logd*
+//    restorecon /dev/socket/logd*
+//    setenforce 1
+//
+// If minimalism prevails, typical for debugging and security is not a concern:
+//
+//    setenforce 0
+//    chmod 777 /dev/socket
+//    logd
+//
+
 static int drop_privs() {
     struct sched_param param;
     memset(&param, 0, sizeof(param));
diff --git a/logd/tests/Android.mk b/logd/tests/Android.mk
new file mode 100644
index 0000000..123e317
--- /dev/null
+++ b/logd/tests/Android.mk
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# -----------------------------------------------------------------------------
+# Benchmarks. (see ../../liblog/tests)
+# -----------------------------------------------------------------------------
+
+test_module_prefix := logd-
+test_tags := tests
+
+# -----------------------------------------------------------------------------
+# Unit tests.
+# -----------------------------------------------------------------------------
+
+test_c_flags := \
+    -fstack-protector-all \
+    -g \
+    -Wall -Wextra \
+    -Werror \
+    -fno-builtin \
+
+ifeq ($(TARGET_USES_LOGD),true)
+test_c_flags += -DTARGET_USES_LOGD=1
+endif
+
+test_src_files := \
+    logd_test.cpp
+
+# Build tests for the logger. Run with:
+#   adb shell /data/nativetest/logd-unit-tests/logd-unit-tests
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(test_module_prefix)unit-tests
+LOCAL_MODULE_TAGS := $(test_tags)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_CFLAGS += $(test_c_flags)
+LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SRC_FILES := $(test_src_files)
+include $(BUILD_NATIVE_TEST)
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
new file mode 100644
index 0000000..9ad8973
--- /dev/null
+++ b/logd/tests/logd_test.cpp
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+#include "cutils/sockets.h"
+#include "log/logger.h"
+
+#define __unused __attribute__((__unused__))
+
+/*
+ * returns statistics
+ */
+static void my_android_logger_get_statistics(char *buf, size_t len)
+{
+    snprintf(buf, len, "getStatistics 0 1 2 3 4");
+    int sock = socket_local_client("logd",
+                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                   SOCK_STREAM);
+    if (sock >= 0) {
+        if (write(sock, buf, strlen(buf) + 1) > 0) {
+            read(sock, buf, len);
+        }
+        close(sock);
+    }
+}
+
+static void alloc_statistics(char **buffer, size_t *length)
+{
+    size_t len = 8192;
+    char *buf;
+
+    for(int retry = 32; (retry >= 0); delete [] buf, --retry) {
+        buf = new char [len];
+        my_android_logger_get_statistics(buf, len);
+
+        buf[len-1] = '\0';
+        size_t ret = atol(buf) + 1;
+        if (ret < 4) {
+            delete [] buf;
+            buf = NULL;
+            break;
+        }
+        bool check = ret <= len;
+        len = ret;
+        if (check) {
+            break;
+        }
+        len += len / 8; // allow for some slop
+    }
+    *buffer = buf;
+    *length = len;
+}
+
+static char *find_benchmark_spam(char *cp)
+{
+    // liblog_benchmarks has been run designed to SPAM.  The signature of
+    // a noisiest UID statistics is one of the following:
+    //
+    // main: UID/PID Total size/num   Now          UID/PID[?]  Total
+    // 0           7500306/304207     71608/3183   0/4225?     7454388/303656
+    // -or-
+    // 0/gone      7454388/303656
+    //
+    // basically if we see a *large* number of 0/????? entries
+    unsigned long value;
+    do {
+        char *benchmark = strstr(cp, " 0/");
+        char *benchmark_newline = strstr(cp, "\n0/");
+        if (!benchmark) {
+            benchmark = benchmark_newline;
+        }
+        if (benchmark_newline && (benchmark > benchmark_newline)) {
+            benchmark = benchmark_newline;
+        }
+        cp = benchmark;
+        if (!cp) {
+            break;
+        }
+        cp += 3;
+        while (isdigit(*cp) || (*cp == 'g') || (*cp == 'o') || (*cp == 'n')) {
+            ++cp;
+        }
+        value = 0;
+        // ###? or gone
+        if ((*cp == '?') || (*cp == 'e')) {
+            while (*++cp == ' ');
+            while (isdigit(*cp)) {
+                value = value * 10ULL + *cp - '0';
+                ++cp;
+            }
+        }
+    } while ((value < 900000ULL) && *cp);
+    return cp;
+}
+
+TEST(logd, statistics) {
+    size_t len;
+    char *buf;
+
+    alloc_statistics(&buf, &len);
+
+#ifdef TARGET_USES_LOGD
+    ASSERT_TRUE(NULL != buf);
+#else
+    if (!buf) {
+        return;
+    }
+#endif
+
+    // remove trailing FF
+    char *cp = buf + len - 1;
+    *cp = '\0';
+    bool truncated = *--cp != '\f';
+    if (!truncated) {
+        *cp = '\0';
+    }
+
+    // squash out the byte count
+    cp = buf;
+    if (!truncated) {
+        while (isdigit(*cp) || (*cp == '\n')) {
+            ++cp;
+        }
+    }
+
+    fprintf(stderr, "%s", cp);
+
+    EXPECT_LT((size_t)64, strlen(cp));
+
+    EXPECT_EQ(0, truncated);
+
+#ifdef TARGET_USES_LOGD
+    char *main_logs = strstr(cp, "\nmain:");
+    EXPECT_TRUE(NULL != main_logs);
+
+    char *radio_logs = strstr(cp, "\nradio:");
+    EXPECT_TRUE(NULL != radio_logs);
+
+    char *system_logs = strstr(cp, "\nsystem:");
+    EXPECT_TRUE(NULL != system_logs);
+
+    char *events_logs = strstr(cp, "\nevents:");
+    EXPECT_TRUE(NULL != events_logs);
+#endif
+
+    // Parse timing stats
+
+    cp = strstr(cp, "Minimum time between log events per dgram_qlen:");
+
+    char *log_events_per_span = cp;
+
+    if (cp) {
+        while (*cp && (*cp != '\n')) {
+            ++cp;
+        }
+        if (*cp == '\n') {
+            ++cp;
+        }
+
+        char *list_of_spans = cp;
+        EXPECT_NE('\0', *list_of_spans);
+
+        unsigned short number_of_buckets = 0;
+        unsigned short *dgram_qlen = NULL;
+        unsigned short bucket = 0;
+        while (*cp && (*cp != '\n')) {
+            bucket = 0;
+            while (isdigit(*cp)) {
+                bucket = bucket * 10 + *cp - '0';
+                ++cp;
+            }
+            while (*cp == ' ') {
+                ++cp;
+            }
+            if (!bucket) {
+                break;
+            }
+            unsigned short *new_dgram_qlen = new unsigned short[number_of_buckets + 1];
+            EXPECT_TRUE(new_dgram_qlen != NULL);
+            if (dgram_qlen) {
+                memcpy(new_dgram_qlen, dgram_qlen, sizeof(*dgram_qlen) * number_of_buckets);
+                delete [] dgram_qlen;
+            }
+
+            dgram_qlen = new_dgram_qlen;
+            dgram_qlen[number_of_buckets++] = bucket;
+        }
+
+        char *end_of_spans = cp;
+        EXPECT_NE('\0', *end_of_spans);
+
+        EXPECT_LT(5, number_of_buckets);
+
+        unsigned long long *times = new unsigned long long [number_of_buckets];
+        ASSERT_TRUE(times != NULL);
+
+        memset(times, 0, sizeof(*times) * number_of_buckets);
+
+        while (*cp == '\n') {
+            ++cp;
+        }
+
+        unsigned short number_of_values = 0;
+        unsigned long long value;
+        while (*cp && (*cp != '\n')) {
+            EXPECT_GE(number_of_buckets, number_of_values);
+
+            value = 0;
+            while (isdigit(*cp)) {
+                value = value * 10ULL + *cp - '0';
+                ++cp;
+            }
+
+            switch(*cp) {
+            case ' ':
+            case '\n':
+                value *= 1000ULL;
+                /* FALLTHRU */
+            case 'm':
+                value *= 1000ULL;
+                /* FALLTHRU */
+            case 'u':
+                value *= 1000ULL;
+                /* FALLTHRU */
+            case 'n':
+            default:
+                break;
+            }
+            while (*++cp == ' ');
+
+            if (!value) {
+                break;
+            }
+
+            times[number_of_values] = value;
+            ++number_of_values;
+        }
+
+#ifdef TARGET_USES_LOGD
+        EXPECT_EQ(number_of_values, number_of_buckets);
+#endif
+
+        FILE *fp;
+        ASSERT_TRUE(NULL != (fp = fopen("/proc/sys/net/unix/max_dgram_qlen", "r")));
+
+        unsigned max_dgram_qlen = 0;
+        fscanf(fp, "%u", &max_dgram_qlen);
+
+        fclose(fp);
+
+        // Find launch point
+        unsigned short launch = 0;
+        unsigned long long total = 0;
+        do {
+            total += times[launch];
+        } while (((++launch < number_of_buckets)
+                && ((total / launch) >= (times[launch] / 8ULL)))
+            || (launch == 1)); // too soon
+
+        bool failure = number_of_buckets <= launch;
+        if (!failure) {
+            unsigned short l = launch;
+            if (l >= number_of_buckets) {
+                l = number_of_buckets - 1;
+            }
+            failure = max_dgram_qlen < dgram_qlen[l];
+        }
+
+        // We can get failure if at any time liblog_benchmarks has been run
+        // because designed to overload /proc/sys/net/unix/max_dgram_qlen even
+        // at excessive values like 20000. It does so to measure the raw processing
+        // performance of logd.
+        if (failure) {
+            cp = find_benchmark_spam(cp);
+        }
+
+        if (cp) {
+            // Fake a failure, but without the failure code
+            if (number_of_buckets <= launch) {
+                printf ("Expected: number_of_buckets > launch, actual: %u vs %u\n",
+                        number_of_buckets, launch);
+            }
+            if (launch >= number_of_buckets) {
+                launch = number_of_buckets - 1;
+            }
+            if (max_dgram_qlen < dgram_qlen[launch]) {
+                printf ("Expected: max_dgram_qlen >= dgram_qlen[%d],"
+                            " actual: %u vs %u\n",
+                        launch, max_dgram_qlen, dgram_qlen[launch]);
+            }
+        } else
+#ifndef TARGET_USES_LOGD
+        if (total)
+#endif
+        {
+            EXPECT_GT(number_of_buckets, launch);
+            if (launch >= number_of_buckets) {
+                launch = number_of_buckets - 1;
+            }
+            EXPECT_GE(max_dgram_qlen, dgram_qlen[launch]);
+        }
+
+        delete [] dgram_qlen;
+        delete [] times;
+    }
+    delete [] buf;
+}
+
+static void caught_signal(int signum __unused) { }
+
+static void dump_log_msg(const char *prefix,
+                         log_msg *msg, unsigned int version, int lid) {
+    switch(msg->entry.hdr_size) {
+    case 0:
+        version = 1;
+        break;
+
+    case sizeof(msg->entry_v2):
+        if (version == 0) {
+            version = 2;
+        }
+        break;
+    }
+
+    fprintf(stderr, "%s: v%u[%u] ", prefix, version, msg->len());
+    if (version != 1) {
+        fprintf(stderr, "hdr_size=%u ", msg->entry.hdr_size);
+    }
+    fprintf(stderr, "pid=%u tid=%u %u.%09u ",
+            msg->entry.pid, msg->entry.tid, msg->entry.sec, msg->entry.nsec);
+    switch(version) {
+    case 1:
+         break;
+    case 2:
+        fprintf(stderr, "euid=%u ", msg->entry_v2.euid);
+        break;
+    case 3:
+    default:
+        lid = msg->entry.lid;
+        break;
+    }
+
+    switch(lid) {
+    case 0:
+        fprintf(stderr, "lid=main ");
+        break;
+    case 1:
+        fprintf(stderr, "lid=radio ");
+        break;
+    case 2:
+        fprintf(stderr, "lid=events ");
+        break;
+    case 3:
+        fprintf(stderr, "lid=system ");
+        break;
+    default:
+        if (lid >= 0) {
+            fprintf(stderr, "lid=%d ", lid);
+        }
+    }
+
+    unsigned int len = msg->entry.len;
+    fprintf(stderr, "msg[%u]={", len);
+    unsigned char *cp = reinterpret_cast<unsigned char *>(msg->msg());
+    while(len) {
+        unsigned char *p = cp;
+        while (*p && (((' ' <= *p) && (*p < 0x7F)) || (*p == '\n'))) {
+            ++p;
+        }
+        if (((p - cp) > 3) && !*p && ((unsigned int)(p - cp) < len)) {
+            fprintf(stderr, "\"");
+            while (*cp) {
+                fprintf(stderr, (*cp != '\n') ? "%c" : "\\n", *cp);
+                ++cp;
+                --len;
+            }
+            fprintf(stderr, "\"");
+        } else {
+            fprintf(stderr, "%02x", *cp);
+        }
+        ++cp;
+        if (--len) {
+            fprintf(stderr, ", ");
+        }
+    }
+    fprintf(stderr, "}\n");
+}
+
+TEST(logd, both) {
+    log_msg msg;
+
+    // check if we can read any logs from logd
+    bool user_logger_available = false;
+    bool user_logger_content = false;
+
+    int fd = socket_local_client("logdr",
+                                 ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                 SOCK_SEQPACKET);
+    if (fd >= 0) {
+        struct sigaction ignore, old_sigaction;
+        memset(&ignore, 0, sizeof(ignore));
+        ignore.sa_handler = caught_signal;
+        sigemptyset(&ignore.sa_mask);
+        sigaction(SIGALRM, &ignore, &old_sigaction);
+        unsigned int old_alarm = alarm(10);
+
+        static const char ask[] = "dumpAndClose lids=0,1,2,3";
+        user_logger_available = write(fd, ask, sizeof(ask)) == sizeof(ask);
+
+        user_logger_content = recv(fd, msg.buf, sizeof(msg), 0) > 0;
+
+        if (user_logger_content) {
+            dump_log_msg("user", &msg, 3, -1);
+        }
+
+        alarm(0);
+        sigaction(SIGALRM, &old_sigaction, NULL);
+
+        close(fd);
+    }
+
+    // check if we can read any logs from kernel logger
+    bool kernel_logger_available = false;
+    bool kernel_logger_content = false;
+
+    static const char *loggers[] = {
+        "/dev/log/main",   "/dev/log_main",
+        "/dev/log/radio",  "/dev/log_radio",
+        "/dev/log/events", "/dev/log_events",
+        "/dev/log/system", "/dev/log_system",
+    };
+
+    for (unsigned int i = 0; i < (sizeof(loggers) / sizeof(loggers[0])); ++i) {
+        fd = open(loggers[i], O_RDONLY);
+        if (fd < 0) {
+            continue;
+        }
+        kernel_logger_available = true;
+        fcntl(fd, F_SETFL, O_RDONLY | O_NONBLOCK);
+        int result = TEMP_FAILURE_RETRY(read(fd, msg.buf, sizeof(msg)));
+        if (result > 0) {
+            kernel_logger_content = true;
+            dump_log_msg("kernel", &msg, 0, i / 2);
+        }
+        close(fd);
+    }
+
+    static const char yes[] = "\xE2\x9C\x93";
+    static const char no[] = "\xE2\x9c\x98";
+    fprintf(stderr,
+            "LOGGER  Available  Content\n"
+            "user    %-13s%s\n"
+            "kernel  %-13s%s\n"
+            " status %-11s%s\n",
+            (user_logger_available)   ? yes : no,
+            (user_logger_content)     ? yes : no,
+            (kernel_logger_available) ? yes : no,
+            (kernel_logger_content)   ? yes : no,
+            (user_logger_available && kernel_logger_available) ? "WARNING" : "ok",
+            (user_logger_content && kernel_logger_content) ? "ERROR" : "ok");
+
+    if (user_logger_available && kernel_logger_available) {
+        printf("WARNING: kernel & user logger; both consuming resources!!!\n");
+    }
+
+    EXPECT_EQ(0, user_logger_content && kernel_logger_content);
+    EXPECT_EQ(0, !user_logger_content && !kernel_logger_content);
+}
+
+// BAD ROBOT
+//   Benchmark threshold are generally considered bad form unless there is
+//   is some human love applied to the continued maintenance and whether the
+//   thresholds are tuned on a per-target basis. Here we check if the values
+//   are more than double what is expected. Doubling will not prevent failure
+//   on busy or low-end systems that could have a tendency to stretch values.
+//
+//   The primary goal of this test is to simulate a spammy app (benchmark
+//   being the worst) and check to make sure the logger can deal with it
+//   appropriately by checking all the statistics are in an expected range.
+//
+TEST(logd, benchmark) {
+    size_t len;
+    char *buf;
+
+    alloc_statistics(&buf, &len);
+    bool benchmark_already_run = buf && find_benchmark_spam(buf);
+    delete [] buf;
+
+    if (benchmark_already_run) {
+        fprintf(stderr, "WARNING: spam already present and too much history\n"
+                        "         false OK for prune by worst UID check\n");
+    }
+
+    FILE *fp;
+
+    // Introduce some extreme spam for the worst UID filter
+    ASSERT_TRUE(NULL != (fp = popen(
+        "/data/nativetest/liblog-benchmarks/liblog-benchmarks",
+        "r")));
+
+    char buffer[5120];
+
+    static const char *benchmarks[] = {
+        "BM_log_maximum_retry ",
+        "BM_log_maximum ",
+        "BM_clock_overhead ",
+        "BM_log_overhead ",
+        "BM_log_latency ",
+        "BM_log_delay "
+    };
+    static const unsigned int log_maximum_retry = 0;
+    static const unsigned int log_maximum = 1;
+    static const unsigned int clock_overhead = 2;
+    static const unsigned int log_overhead = 3;
+    static const unsigned int log_latency = 4;
+    static const unsigned int log_delay = 5;
+
+    unsigned long ns[sizeof(benchmarks) / sizeof(benchmarks[0])];
+
+    memset(ns, 0, sizeof(ns));
+
+    while (fgets(buffer, sizeof(buffer), fp)) {
+        for (unsigned i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
+            if (strncmp(benchmarks[i], buffer, strlen(benchmarks[i]))) {
+                continue;
+            }
+            sscanf(buffer, "%*s %lu %lu", &ns[i], &ns[i]);
+            fprintf(stderr, "%-22s%8lu\n", benchmarks[i], ns[i]);
+        }
+    }
+    int ret = pclose(fp);
+
+    if (!WIFEXITED(ret) || (WEXITSTATUS(ret) == 127)) {
+        fprintf(stderr,
+                "WARNING: "
+                "/data/nativetest/liblog-benchmarks/liblog-benchmarks missing\n"
+                "         can not perform test\n");
+        return;
+    }
+
+#ifdef TARGET_USES_LOGD
+    EXPECT_GE(100000UL, ns[log_maximum_retry]); // 42777 user
+#else
+    EXPECT_GE(10000UL, ns[log_maximum_retry]); // 5636 kernel
+#endif
+
+#ifdef TARGET_USES_LOGD
+    EXPECT_GE(25000UL, ns[log_maximum]); // 14055 user
+#else
+    EXPECT_GE(10000UL, ns[log_maximum]); // 5637 kernel
+#endif
+
+    EXPECT_GE(4000UL, ns[clock_overhead]); // 2008
+
+#ifdef TARGET_USES_LOGD
+    EXPECT_GE(250000UL, ns[log_overhead]); // 113219 user
+#else
+    EXPECT_GE(100000UL, ns[log_overhead]); // 50945 kernel
+#endif
+
+#ifdef TARGET_USES_LOGD
+    EXPECT_GE(7500UL, ns[log_latency]); // 3718 user space
+#else
+    EXPECT_GE(500000UL, ns[log_latency]); // 254200 kernel
+#endif
+
+#ifdef TARGET_USES_LOGD
+    EXPECT_GE(20000000UL, ns[log_delay]); // 9542541 user
+#else
+    EXPECT_GE(55000UL, ns[log_delay]); // 27341 kernel
+#endif
+
+    for (unsigned i = 0; i < sizeof(ns) / sizeof(ns[0]); ++i) {
+        EXPECT_NE(0UL, ns[i]);
+    }
+
+    alloc_statistics(&buf, &len);
+
+#ifdef TARGET_USES_LOGD
+    bool collected_statistics = !!buf;
+    EXPECT_EQ(true, collected_statistics);
+#else
+    if (!buf) {
+        return;
+    }
+#endif
+
+    ASSERT_TRUE(NULL != buf);
+    EXPECT_TRUE(find_benchmark_spam(buf) != NULL);
+
+    delete [] buf;
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a07790a..0ef097c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -177,6 +177,9 @@
     chown system log /proc/last_kmsg
     chmod 0440 /proc/last_kmsg
 
+    # make the selinux kernel policy world-readable
+    chmod 0444 /sys/fs/selinux/policy
+
     # create the lost+found directories, so as to enforce our permissions
     mkdir /cache/lost+found 0770 root root
 
@@ -369,13 +372,13 @@
     setprop net.tcp.buffersize.wifi     524288,1048576,2097152,262144,524288,1048576
     setprop net.tcp.buffersize.ethernet 524288,1048576,3145728,524288,1048576,2097152
     setprop net.tcp.buffersize.lte      524288,1048576,2097152,262144,524288,1048576
-    setprop net.tcp.buffersize.umts     4094,87380,110208,4096,16384,110208
-    setprop net.tcp.buffersize.hspa     4094,87380,262144,4096,16384,262144
-    setprop net.tcp.buffersize.hsupa    4094,87380,262144,4096,16384,262144
-    setprop net.tcp.buffersize.hsdpa    4094,87380,262144,4096,16384,262144
-    setprop net.tcp.buffersize.hspap    4094,87380,1220608,4096,16384,1220608
-    setprop net.tcp.buffersize.edge     4093,26280,35040,4096,16384,35040
-    setprop net.tcp.buffersize.gprs     4092,8760,11680,4096,8760,11680
+    setprop net.tcp.buffersize.umts     58254,349525,1048576,58254,349525,1048576
+    setprop net.tcp.buffersize.hspa     40778,244668,734003,16777,100663,301990
+    setprop net.tcp.buffersize.hsupa    40778,244668,734003,16777,100663,301990
+    setprop net.tcp.buffersize.hsdpa    61167,367002,1101005,8738,52429,262114
+    setprop net.tcp.buffersize.hspap    122334,734003,2202010,32040,192239,576717
+    setprop net.tcp.buffersize.edge     4093,26280,70800,4096,16384,70800
+    setprop net.tcp.buffersize.gprs     4092,8760,48000,4096,8760,48000
     setprop net.tcp.buffersize.evdo     4094,87380,262144,4096,16384,262144
 
     class_start core
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
new file mode 100644
index 0000000..3d60a31
--- /dev/null
+++ b/rootdir/init.zygote32_64.rc
@@ -0,0 +1,12 @@
+service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
+    class main
+    socket zygote stream 660 root system
+    onrestart write /sys/android_power/request_state wake
+    onrestart write /sys/power/state on
+    onrestart restart media
+    onrestart restart netd
+
+service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
+    class main
+    socket zygote_secondary stream 660 root system
+    onrestart restart zygote
diff --git a/toolbox/syren.c b/toolbox/syren.c
index 06e329e..47c2460 100644
--- a/toolbox/syren.c
+++ b/toolbox/syren.c
@@ -123,7 +123,11 @@
 
 	r = find_reg(argv[2]);
 	if (r == NULL) {
-		strcpy(name, argv[2]);
+		if(strlen(argv[2]) >= sizeof(name)){
+			fprintf(stderr, "REGNAME too long\n");
+			return 0;
+		}
+		strlcpy(name, argv[2], sizeof(name));
 		char *addr_str = strchr(argv[2], ':');
 		if (addr_str == NULL)
 			return usage();
@@ -131,7 +135,7 @@
 		sio.page = strtoul(argv[2], 0, 0);
 		sio.addr = strtoul(addr_str, 0, 0);
 	} else {
-		strcpy(name, r->name);
+		strlcpy(name, r->name, sizeof(name));
 		sio.page = r->page;
 		sio.addr = r->addr;
 	}