Merge "Give adb a proper progress bar."
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 6800ad2..46bad4e 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -699,7 +699,10 @@
 
     GRSurface** scale_frames;
     int scale_count;
-    ret = res_create_multi_display_surface("charger/battery_scale", &scale_count, &scale_frames);
+    int scale_fps;  // Not in use (charger/battery_scale doesn't have FPS text
+                    // chunk). We are using hard-coded frame.disp_time instead.
+    ret = res_create_multi_display_surface("charger/battery_scale", &scale_count, &scale_fps,
+                                           &scale_frames);
     if (ret < 0) {
         LOGE("Cannot load battery_scale image\n");
         charger->batt_anim->num_frames = 0;
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index e2133e9..d236938 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -81,6 +81,8 @@
 #define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */
 #define AID_DBUS          1038  /* dbus-daemon IPC broker process */
 #define AID_TLSDATE       1039  /* tlsdate unprivileged user */
+#define AID_MEDIA_EX      1040  /* mediaextractor process */
+#define AID_AUDIOSERVER   1041  /* audioserver process */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
 #define AID_CACHE         2001  /* cache access */
@@ -179,6 +181,8 @@
     { "shared_relro",  AID_SHARED_RELRO, },
     { "dbus",          AID_DBUS, },
     { "tlsdate",       AID_TLSDATE, },
+    { "mediaex",       AID_MEDIA_EX, },
+    { "audioserver",   AID_AUDIOSERVER, },
 
     { "shell",         AID_SHELL, },
     { "cache",         AID_CACHE, },
diff --git a/liblog/log_read.c b/liblog/log_read.c
index 8aa887b..1aff272 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -501,6 +501,14 @@
         remaining -= n;
         cp += n;
     }
+
+    if (logger_list->pid) {
+        n = snprintf(cp, remaining, " pid=%u", logger_list->pid);
+        n = min(n, remaining);
+        remaining -= n;
+        cp += n;
+    }
+
     return send_log_msg(NULL, NULL, buf, len);
 }
 
@@ -880,18 +888,10 @@
             sigaction(SIGALRM, &old_sigaction, NULL);
         }
 
-        if (ret <= 0) {
-            if ((ret == -1) && e) {
-                return -e;
-            }
-            return ret;
+        if ((ret == -1) && e) {
+            return -e;
         }
-
-        logger_for_each(logger, logger_list) {
-            if (log_msg->entry.lid == logger->id) {
-                return ret;
-            }
-        }
+        return ret;
     }
     /* NOTREACH */
     return ret;
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index b594634..9f29a09 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -14,11 +14,17 @@
  * limitations under the License.
  */
 
+#include <fcntl.h>
+#include <sys/endian.h>
 #include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 #include <cutils/sockets.h>
 #include <log/log.h>
 #include <log/logger.h>
 #include <log/log_read.h>
+#include <private/android_logger.h>
 
 #include "benchmark.h"
 
@@ -85,6 +91,380 @@
 BENCHMARK(BM_clock_overhead);
 
 /*
+ * Measure the time it takes to submit the android logging data to pstore
+ */
+static void BM_pmsg_short(int iters) {
+
+    int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+    if (pstore_fd < 0) {
+        return;
+    }
+
+    /*
+     *  struct {
+     *      // what we provide to pstore
+     *      android_pmsg_log_header_t pmsg_header;
+     *      // what we provide to socket
+     *      android_log_header_t header;
+     *      // caller provides
+     *      union {
+     *          struct {
+     *              char     prio;
+     *              char     payload[];
+     *          } string;
+     *          struct {
+     *              uint32_t tag
+     *              char     payload[];
+     *          } binary;
+     *      };
+     *  };
+     */
+
+    struct timespec ts;
+    clock_gettime(android_log_clockid(), &ts);
+
+    android_pmsg_log_header_t pmsg_header;
+    pmsg_header.magic = LOGGER_MAGIC;
+    pmsg_header.len = sizeof(android_pmsg_log_header_t)
+                    + sizeof(android_log_header_t);
+    pmsg_header.uid = getuid();
+    pmsg_header.pid = getpid();
+
+    android_log_header_t header;
+    header.tid = gettid();
+    header.realtime.tv_sec = ts.tv_sec;
+    header.realtime.tv_nsec = ts.tv_nsec;
+
+    static const unsigned nr = 1;
+    static const unsigned header_length = 2;
+    struct iovec newVec[nr + header_length];
+
+    newVec[0].iov_base   = (unsigned char *) &pmsg_header;
+    newVec[0].iov_len    = sizeof(pmsg_header);
+    newVec[1].iov_base   = (unsigned char *) &header;
+    newVec[1].iov_len    = sizeof(header);
+
+    android_log_event_int_t buffer;
+
+    header.id = LOG_ID_EVENTS;
+    buffer.header.tag = 0;
+    buffer.payload.type = EVENT_TYPE_INT;
+    uint32_t snapshot = 0;
+    buffer.payload.data = htole32(snapshot);
+
+    newVec[2].iov_base = &buffer;
+    newVec[2].iov_len  = sizeof(buffer);
+
+    StartBenchmarkTiming();
+    for (int i = 0; i < iters; ++i) {
+        ++snapshot;
+        buffer.payload.data = htole32(snapshot);
+        writev(pstore_fd, newVec, nr);
+    }
+    StopBenchmarkTiming();
+    close(pstore_fd);
+}
+BENCHMARK(BM_pmsg_short);
+
+/*
+ * Measure the time it takes to submit the android logging data to pstore
+ * best case aligned single block.
+ */
+static void BM_pmsg_short_aligned(int iters) {
+
+    int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+    if (pstore_fd < 0) {
+        return;
+    }
+
+    /*
+     *  struct {
+     *      // what we provide to pstore
+     *      android_pmsg_log_header_t pmsg_header;
+     *      // what we provide to socket
+     *      android_log_header_t header;
+     *      // caller provides
+     *      union {
+     *          struct {
+     *              char     prio;
+     *              char     payload[];
+     *          } string;
+     *          struct {
+     *              uint32_t tag
+     *              char     payload[];
+     *          } binary;
+     *      };
+     *  };
+     */
+
+    struct timespec ts;
+    clock_gettime(android_log_clockid(), &ts);
+
+    struct packet {
+        android_pmsg_log_header_t pmsg_header;
+        android_log_header_t header;
+        android_log_event_int_t payload;
+    };
+    char buf[sizeof(struct packet) + 8] __aligned(8);
+    memset(buf, 0, sizeof(buf));
+    struct packet *buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
+    if (((uintptr_t)&buffer->pmsg_header) & 7) {
+        fprintf (stderr, "&buffer=0x%p iters=%d\n", &buffer->pmsg_header, iters);
+    }
+
+    buffer->pmsg_header.magic = LOGGER_MAGIC;
+    buffer->pmsg_header.len = sizeof(android_pmsg_log_header_t)
+                            + sizeof(android_log_header_t);
+    buffer->pmsg_header.uid = getuid();
+    buffer->pmsg_header.pid = getpid();
+
+    buffer->header.tid = gettid();
+    buffer->header.realtime.tv_sec = ts.tv_sec;
+    buffer->header.realtime.tv_nsec = ts.tv_nsec;
+
+    buffer->header.id = LOG_ID_EVENTS;
+    buffer->payload.header.tag = 0;
+    buffer->payload.payload.type = EVENT_TYPE_INT;
+    uint32_t snapshot = 0;
+    buffer->payload.payload.data = htole32(snapshot);
+
+    StartBenchmarkTiming();
+    for (int i = 0; i < iters; ++i) {
+        ++snapshot;
+        buffer->payload.payload.data = htole32(snapshot);
+        write(pstore_fd, &buffer->pmsg_header,
+            sizeof(android_pmsg_log_header_t) +
+            sizeof(android_log_header_t) +
+            sizeof(android_log_event_int_t));
+    }
+    StopBenchmarkTiming();
+    close(pstore_fd);
+}
+BENCHMARK(BM_pmsg_short_aligned);
+
+/*
+ * Measure the time it takes to submit the android logging data to pstore
+ * best case aligned single block.
+ */
+static void BM_pmsg_short_unaligned1(int iters) {
+
+    int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+    if (pstore_fd < 0) {
+        return;
+    }
+
+    /*
+     *  struct {
+     *      // what we provide to pstore
+     *      android_pmsg_log_header_t pmsg_header;
+     *      // what we provide to socket
+     *      android_log_header_t header;
+     *      // caller provides
+     *      union {
+     *          struct {
+     *              char     prio;
+     *              char     payload[];
+     *          } string;
+     *          struct {
+     *              uint32_t tag
+     *              char     payload[];
+     *          } binary;
+     *      };
+     *  };
+     */
+
+    struct timespec ts;
+    clock_gettime(android_log_clockid(), &ts);
+
+    struct packet {
+        android_pmsg_log_header_t pmsg_header;
+        android_log_header_t header;
+        android_log_event_int_t payload;
+    };
+    char buf[sizeof(struct packet) + 8] __aligned(8);
+    memset(buf, 0, sizeof(buf));
+    struct packet *buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
+    if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
+        fprintf (stderr, "&buffer=0x%p iters=%d\n", &buffer->pmsg_header, iters);
+    }
+
+    buffer->pmsg_header.magic = LOGGER_MAGIC;
+    buffer->pmsg_header.len = sizeof(android_pmsg_log_header_t)
+                            + sizeof(android_log_header_t);
+    buffer->pmsg_header.uid = getuid();
+    buffer->pmsg_header.pid = getpid();
+
+    buffer->header.tid = gettid();
+    buffer->header.realtime.tv_sec = ts.tv_sec;
+    buffer->header.realtime.tv_nsec = ts.tv_nsec;
+
+    buffer->header.id = LOG_ID_EVENTS;
+    buffer->payload.header.tag = 0;
+    buffer->payload.payload.type = EVENT_TYPE_INT;
+    uint32_t snapshot = 0;
+    buffer->payload.payload.data = htole32(snapshot);
+
+    StartBenchmarkTiming();
+    for (int i = 0; i < iters; ++i) {
+        ++snapshot;
+        buffer->payload.payload.data = htole32(snapshot);
+        write(pstore_fd, &buffer->pmsg_header,
+            sizeof(android_pmsg_log_header_t) +
+            sizeof(android_log_header_t) +
+            sizeof(android_log_event_int_t));
+    }
+    StopBenchmarkTiming();
+    close(pstore_fd);
+}
+BENCHMARK(BM_pmsg_short_unaligned1);
+
+/*
+ * Measure the time it takes to submit the android logging data to pstore
+ * best case aligned single block.
+ */
+static void BM_pmsg_long_aligned(int iters) {
+
+    int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+    if (pstore_fd < 0) {
+        return;
+    }
+
+    /*
+     *  struct {
+     *      // what we provide to pstore
+     *      android_pmsg_log_header_t pmsg_header;
+     *      // what we provide to socket
+     *      android_log_header_t header;
+     *      // caller provides
+     *      union {
+     *          struct {
+     *              char     prio;
+     *              char     payload[];
+     *          } string;
+     *          struct {
+     *              uint32_t tag
+     *              char     payload[];
+     *          } binary;
+     *      };
+     *  };
+     */
+
+    struct timespec ts;
+    clock_gettime(android_log_clockid(), &ts);
+
+    struct packet {
+        android_pmsg_log_header_t pmsg_header;
+        android_log_header_t header;
+        android_log_event_int_t payload;
+    };
+    char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD] __aligned(8);
+    memset(buf, 0, sizeof(buf));
+    struct packet *buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
+    if (((uintptr_t)&buffer->pmsg_header) & 7) {
+        fprintf (stderr, "&buffer=0x%p iters=%d\n", &buffer->pmsg_header, iters);
+    }
+
+    buffer->pmsg_header.magic = LOGGER_MAGIC;
+    buffer->pmsg_header.len = sizeof(android_pmsg_log_header_t)
+                            + sizeof(android_log_header_t);
+    buffer->pmsg_header.uid = getuid();
+    buffer->pmsg_header.pid = getpid();
+
+    buffer->header.tid = gettid();
+    buffer->header.realtime.tv_sec = ts.tv_sec;
+    buffer->header.realtime.tv_nsec = ts.tv_nsec;
+
+    buffer->header.id = LOG_ID_EVENTS;
+    buffer->payload.header.tag = 0;
+    buffer->payload.payload.type = EVENT_TYPE_INT;
+    uint32_t snapshot = 0;
+    buffer->payload.payload.data = htole32(snapshot);
+
+    StartBenchmarkTiming();
+    for (int i = 0; i < iters; ++i) {
+        ++snapshot;
+        buffer->payload.payload.data = htole32(snapshot);
+        write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
+    }
+    StopBenchmarkTiming();
+    close(pstore_fd);
+}
+BENCHMARK(BM_pmsg_long_aligned);
+
+/*
+ * Measure the time it takes to submit the android logging data to pstore
+ * best case aligned single block.
+ */
+static void BM_pmsg_long_unaligned1(int iters) {
+
+    int pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY));
+    if (pstore_fd < 0) {
+        return;
+    }
+
+    /*
+     *  struct {
+     *      // what we provide to pstore
+     *      android_pmsg_log_header_t pmsg_header;
+     *      // what we provide to socket
+     *      android_log_header_t header;
+     *      // caller provides
+     *      union {
+     *          struct {
+     *              char     prio;
+     *              char     payload[];
+     *          } string;
+     *          struct {
+     *              uint32_t tag
+     *              char     payload[];
+     *          } binary;
+     *      };
+     *  };
+     */
+
+    struct timespec ts;
+    clock_gettime(android_log_clockid(), &ts);
+
+    struct packet {
+        android_pmsg_log_header_t pmsg_header;
+        android_log_header_t header;
+        android_log_event_int_t payload;
+    };
+    char buf[sizeof(struct packet) + 8 + LOGGER_ENTRY_MAX_PAYLOAD] __aligned(8);
+    memset(buf, 0, sizeof(buf));
+    struct packet *buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
+    if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
+        fprintf (stderr, "&buffer=0x%p iters=%d\n", &buffer->pmsg_header, iters);
+    }
+
+    buffer->pmsg_header.magic = LOGGER_MAGIC;
+    buffer->pmsg_header.len = sizeof(android_pmsg_log_header_t)
+                            + sizeof(android_log_header_t);
+    buffer->pmsg_header.uid = getuid();
+    buffer->pmsg_header.pid = getpid();
+
+    buffer->header.tid = gettid();
+    buffer->header.realtime.tv_sec = ts.tv_sec;
+    buffer->header.realtime.tv_nsec = ts.tv_nsec;
+
+    buffer->header.id = LOG_ID_EVENTS;
+    buffer->payload.header.tag = 0;
+    buffer->payload.payload.type = EVENT_TYPE_INT;
+    uint32_t snapshot = 0;
+    buffer->payload.payload.data = htole32(snapshot);
+
+    StartBenchmarkTiming();
+    for (int i = 0; i < iters; ++i) {
+        ++snapshot;
+        buffer->payload.payload.data = htole32(snapshot);
+        write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
+    }
+    StopBenchmarkTiming();
+    close(pstore_fd);
+}
+BENCHMARK(BM_pmsg_long_unaligned1);
+
+/*
  *	Measure the time it takes to submit the android logging call using
  * discrete acquisition under light load. Expect this to be a dozen or so
  * syscall periods (40us).
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 621101c..50afc5f 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -866,13 +866,27 @@
                 continue;
             }
             fprintf(stderr, "i=%zu j=%zu\r", i, j);
+            bool android_log_is_loggable = __android_log_is_loggable(
+                levels[i].level, tag, levels[j].level);
             if ((levels[i].level < levels[j].level)
                     || (levels[j].level == -1)) {
-                EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
-                                                       levels[j].level));
+                if (android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_FALSE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_FALSE(__android_log_is_loggable(
+                        levels[i].level, tag, levels[j].level));
+                }
             } else {
-                EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
-                                                      levels[j].level));
+                if (!android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_TRUE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_TRUE(__android_log_is_loggable(
+                        levels[i].level, tag, levels[j].level));
+                }
             }
         }
     }
@@ -891,30 +905,58 @@
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key, buf);
             property_set(key, buf);
+            bool android_log_is_loggable = __android_log_is_loggable(
+                levels[i].level, tag, ANDROID_LOG_DEBUG);
             if ((levels[i].level < levels[j].level)
                     || (levels[j].level == -1)
                     || ((levels[i].level < ANDROID_LOG_DEBUG)
                         && (levels[j].level == -2))) {
-                EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
-                                                       ANDROID_LOG_DEBUG));
+                if (android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_FALSE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_FALSE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             } else {
-                EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
-                                                      ANDROID_LOG_DEBUG));
+                if (!android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_TRUE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_TRUE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             }
             property_set(key, "");
 
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key + base_offset, buf);
             property_set(key + base_offset, buf);
+            android_log_is_loggable = __android_log_is_loggable(
+                levels[i].level, tag, ANDROID_LOG_DEBUG);
             if ((levels[i].level < levels[j].level)
                     || (levels[j].level == -1)
                     || ((levels[i].level < ANDROID_LOG_DEBUG)
                         && (levels[j].level == -2))) {
-                EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
-                                                       ANDROID_LOG_DEBUG));
+                if (android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_FALSE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_FALSE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             } else {
-                EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
-                                                      ANDROID_LOG_DEBUG));
+                if (!android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_TRUE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_TRUE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             }
             property_set(key + base_offset, "");
 
@@ -923,30 +965,58 @@
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key, buf);
             property_set(key, buf);
+            android_log_is_loggable = __android_log_is_loggable(
+                levels[i].level, tag, ANDROID_LOG_DEBUG);
             if ((levels[i].level < levels[j].level)
                     || (levels[j].level == -1)
                     || ((levels[i].level < ANDROID_LOG_DEBUG)
                         && (levels[j].level == -2))) {
-                EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
-                                                       ANDROID_LOG_DEBUG));
+                if (android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_FALSE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_FALSE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             } else {
-                EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
-                                                      ANDROID_LOG_DEBUG));
+                if (!android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_TRUE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_TRUE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             }
             property_set(key, "");
 
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key + base_offset, buf);
             property_set(key + base_offset, buf);
+            android_log_is_loggable = __android_log_is_loggable(
+                levels[i].level, tag, ANDROID_LOG_DEBUG);
             if ((levels[i].level < levels[j].level)
                     || (levels[j].level == -1)
                     || ((levels[i].level < ANDROID_LOG_DEBUG)
                         && (levels[j].level == -2))) {
-                EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
-                                                       ANDROID_LOG_DEBUG));
+                if (android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_FALSE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_FALSE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             } else {
-                EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
-                                                      ANDROID_LOG_DEBUG));
+                if (!android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_TRUE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_TRUE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             }
             property_set(key + base_offset, "");
         }
@@ -969,30 +1039,58 @@
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key, buf);
             property_set(key, buf);
+            bool android_log_is_loggable = __android_log_is_loggable(
+                levels[i].level, tag, ANDROID_LOG_DEBUG);
             if ((levels[i].level < levels[j].level)
                     || (levels[j].level == -1)
                     || ((levels[i].level < ANDROID_LOG_INFO) // Yes INFO
                         && (levels[j].level == -2))) {
-                EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
-                                                       ANDROID_LOG_DEBUG));
+                if (android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_FALSE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_FALSE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             } else {
-                EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
-                                                      ANDROID_LOG_DEBUG));
+                if (!android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_TRUE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_TRUE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             }
             property_set(key, "");
 
             fprintf(stderr, "i=%zu j=%zu property_set(\"%s\",\"%s\")\r",
                     i, j, key + base_offset, buf);
             property_set(key + base_offset, buf);
+            android_log_is_loggable = __android_log_is_loggable(
+                levels[i].level, tag, ANDROID_LOG_DEBUG);
             if ((levels[i].level < levels[j].level)
                     || (levels[j].level == -1)
                     || ((levels[i].level < ANDROID_LOG_INFO) // Yes INFO
                         && (levels[j].level == -2))) {
-                EXPECT_FALSE(__android_log_is_loggable(levels[i].level, tag,
-                                                       ANDROID_LOG_DEBUG));
+                if (android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_FALSE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_FALSE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             } else {
-                EXPECT_TRUE(__android_log_is_loggable(levels[i].level, tag,
-                                                      ANDROID_LOG_DEBUG));
+                if (!android_log_is_loggable) {
+                    fprintf(stderr, "\n");
+                }
+                EXPECT_TRUE(android_log_is_loggable);
+                for(size_t k = 1000; k; --k) {
+                    EXPECT_TRUE(__android_log_is_loggable(
+                        levels[i].level, tag, ANDROID_LOG_DEBUG));
+                }
             }
             property_set(key + base_offset, "");
         }
diff --git a/libsparse/append2simg.c b/libsparse/append2simg.c
index 1cf827c..eef8764 100644
--- a/libsparse/append2simg.c
+++ b/libsparse/append2simg.c
@@ -82,7 +82,7 @@
         exit(-1);
     }
 
-    sparse_output = sparse_file_import_auto(output, true, true);
+    sparse_output = sparse_file_import_auto(output, false, true);
     if (!sparse_output) {
         fprintf(stderr, "Couldn't import output file\n");
         exit(-1);
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index b14884b..952c992 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -74,7 +74,7 @@
         mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
         mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
         mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
-    mWakeEventFd = eventfd(0, EFD_NONBLOCK);
+    mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
     LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd: %s",
                         strerror(errno));
 
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 50bf6a4..aa3db8a 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -230,7 +230,7 @@
 }
 
 static void writefilestring(char *path, char *s) {
-    int fd = open(path, O_WRONLY);
+    int fd = open(path, O_WRONLY | O_CLOEXEC);
     int len = strlen(s);
     int ret;
 
@@ -487,7 +487,7 @@
 
     memset(mip, 0, sizeof(struct sysmeminfo));
 
-    fd = open(ZONEINFO_PATH, O_RDONLY);
+    fd = open(ZONEINFO_PATH, O_RDONLY | O_CLOEXEC);
     if (fd == -1) {
         ALOGE("%s open: errno=%d", ZONEINFO_PATH, errno);
         return -1;
@@ -518,7 +518,7 @@
     ssize_t ret;
 
     snprintf(path, PATH_MAX, "/proc/%d/statm", pid);
-    fd = open(path, O_RDONLY);
+    fd = open(path, O_RDONLY | O_CLOEXEC);
     if (fd == -1)
         return -1;
 
@@ -541,7 +541,7 @@
     ssize_t ret;
 
     snprintf(path, PATH_MAX, "/proc/%d/cmdline", pid);
-    fd = open(path, O_RDONLY);
+    fd = open(path, O_RDONLY | O_CLOEXEC);
     if (fd == -1)
         return NULL;
     ret = read_all(fd, line, sizeof(line) - 1);
@@ -686,19 +686,19 @@
     struct epoll_event epev;
     int ret;
 
-    mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY);
+    mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC);
     if (mpfd < 0) {
         ALOGI("No kernel memory.pressure_level support (errno=%d)", errno);
         goto err_open_mpfd;
     }
 
-    evctlfd = open(MEMCG_SYSFS_PATH "cgroup.event_control", O_WRONLY);
+    evctlfd = open(MEMCG_SYSFS_PATH "cgroup.event_control", O_WRONLY | O_CLOEXEC);
     if (evctlfd < 0) {
         ALOGI("No kernel memory cgroup event control (errno=%d)", errno);
         goto err_open_evctlfd;
     }
 
-    evfd = eventfd(0, EFD_NONBLOCK);
+    evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
     if (evfd < 0) {
         ALOGE("eventfd failed for level %s; errno=%d", levelstr, errno);
         goto err_eventfd;
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 61b020c..4f517bb 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -605,7 +605,7 @@
                 char c;
 
                 if ((2 == sscanf(buffer, "%d log.tx%c", &num, &c)) &&
-                        (num <= 24)) {
+                        (num <= 40)) {
                     ++count;
                 } else if (strncmp(buffer, total, sizeof(total) - 1)) {
                     fprintf(stderr, "WARNING: Parse error: %s", buffer);
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index e103359..7394f11 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -210,9 +210,20 @@
     }
 
     unsigned int logMask = -1;
+    pid_t pid = 0;
     if (argc > 1) {
         logMask = 0;
         for (int i = 1; i < argc; ++i) {
+            static const char _pid[] = "pid=";
+            if (!strncmp(argv[i], _pid, sizeof(_pid) - 1)) {
+                pid = atol(argv[i] + sizeof(_pid) - 1);
+                if (pid == 0) {
+                    cli->sendMsg("PID Error");
+                    return 0;
+                }
+                continue;
+            }
+
             int id = atoi(argv[i]);
             if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
                 cli->sendMsg("Range Error");
@@ -222,7 +233,8 @@
         }
     }
 
-    cli->sendMsg(package_string(mBuf.formatStatistics(uid, logMask)).c_str());
+    cli->sendMsg(package_string(mBuf.formatStatistics(uid, pid,
+                                                      logMask)).c_str());
     return 0;
 }
 
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 1e4f3b0..12aa84e 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -100,6 +100,11 @@
     unsigned long default_size = property_get_size(global_tuneable);
     if (!default_size) {
         default_size = property_get_size(global_default);
+        if (!default_size) {
+            default_size = property_get_bool("ro.config.low_ram", false) ?
+                LOG_BUFFER_MIN_SIZE : // 64K
+                LOG_BUFFER_SIZE;      // 256K
+        }
     }
 
     log_id_for_each(i) {
@@ -494,7 +499,8 @@
         size_t second_worst_sizes = 0;
 
         if (worstUidEnabledForLogid(id) && mPrune.worstUidEnabled()) {
-            std::unique_ptr<const UidEntry *[]> sorted = stats.sort(2, id);
+            std::unique_ptr<const UidEntry *[]> sorted = stats.sort(
+                AID_ROOT, (pid_t)0, 2, id);
 
             if (sorted.get()) {
                 if (sorted[0] && sorted[1]) {
@@ -861,10 +867,11 @@
     return max;
 }
 
-std::string LogBuffer::formatStatistics(uid_t uid, unsigned int logMask) {
+std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
+                                        unsigned int logMask) {
     pthread_mutex_lock(&mLogElementsLock);
 
-    std::string ret = stats.format(uid, logMask);
+    std::string ret = stats.format(uid, pid, logMask);
 
     pthread_mutex_unlock(&mLogElementsLock);
 
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index c1fec73..c1614e8 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -86,7 +86,7 @@
     int setSize(log_id_t id, unsigned long size);
     unsigned long getSizeUsed(log_id_t id);
     // *strp uses malloc, use free to release.
-    std::string formatStatistics(uid_t uid, unsigned int logMask);
+    std::string formatStatistics(uid_t uid, pid_t pid, unsigned int logMask);
 
     void enableStatistics() {
         stats.enableStatistics();
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index bf0e30b..afaefc2 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -205,7 +205,7 @@
 }
 
 std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
-    uid_t uid = getKey();
+    uid_t uid = getUid();
     std::string name = android::base::StringPrintf("%u", uid);
     const char *nameTmp = stat.uidToName(uid);
     if (nameTmp) {
@@ -287,8 +287,8 @@
 
 std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
     uid_t uid = getUid();
-    std::string name = android::base::StringPrintf("%5u/%u",
-                                                   getKey(), uid);
+    pid_t pid = getPid();
+    std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
     const char *nameTmp = getName();
     if (nameTmp) {
         name += android::base::StringPrintf(
@@ -325,7 +325,7 @@
 std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
     uid_t uid = getUid();
     std::string name = android::base::StringPrintf("%5u/%u",
-                                                   getKey(), uid);
+                                                   getTid(), uid);
     const char *nameTmp = getName();
     if (nameTmp) {
         name += android::base::StringPrintf(
@@ -388,7 +388,8 @@
     return formatLine(name, size, pruned);
 }
 
-std::string LogStatistics::format(uid_t uid, unsigned int logMask) const {
+std::string LogStatistics::format(uid_t uid, pid_t pid,
+                                  unsigned int logMask) const {
     static const unsigned short spaces_total = 19;
 
     // Report on total logging, current and for all time
@@ -461,24 +462,38 @@
         name = (uid == AID_ROOT)
             ? "Chattiest UIDs in %s log buffer:"
             : "Logging for your UID in %s log buffer:";
-        output += uidTable[id].format(*this, uid, name, id);
+        output += uidTable[id].format(*this, uid, pid, name, id);
     }
 
     if (enable) {
-        name = (uid == AID_ROOT) ? "Chattiest PIDs:" : "Logging for this PID:";
-        output += pidTable.format(*this, uid, name);
-        name = "Chattiest TIDs:";
-        output += tidTable.format(*this, uid, name);
+        name = ((uid == AID_ROOT) && !pid)
+            ? "Chattiest PIDs:"
+            : "Logging for this PID:";
+        output += pidTable.format(*this, uid, pid, name);
+        name = "Chattiest TIDs";
+        if (pid) {
+            name += android::base::StringPrintf(" for PID %d", pid);
+        }
+        name += ":";
+        output += tidTable.format(*this, uid, pid, name);
     }
 
     if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
-        name = "Chattiest events log buffer TAGs:";
-        output += tagTable.format(*this, uid, name, LOG_ID_EVENTS);
+        name = "Chattiest events log buffer TAGs";
+        if (pid) {
+            name += android::base::StringPrintf(" for PID %d", pid);
+        }
+        name += ":";
+        output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
     }
 
     if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
-        name = "Chattiest security log buffer TAGs:";
-        output += securityTagTable.format(*this, uid, name, LOG_ID_SECURITY);
+        name = "Chattiest security log buffer TAGs";
+        if (pid) {
+            name += android::base::StringPrintf(" for PID %d", pid);
+        }
+        name += ":";
+        output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
     }
 
     return output;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 8558b06..6d999d2 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -47,7 +47,8 @@
     typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
     typedef typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
 
-    std::unique_ptr<const TEntry *[]> sort(size_t len) const {
+    std::unique_ptr<const TEntry *[]> sort(uid_t uid, pid_t pid,
+                                           size_t len) const {
         if (!len) {
             std::unique_ptr<const TEntry *[]> sorted(NULL);
             return sorted;
@@ -58,6 +59,14 @@
 
         for(const_iterator it = map.begin(); it != map.end(); ++it) {
             const TEntry &entry = it->second;
+
+            if ((uid != AID_ROOT) && (uid != entry.getUid())) {
+                continue;
+            }
+            if (pid && entry.getPid() && (pid != entry.getPid())) {
+                continue;
+            }
+
             size_t sizes = entry.getSizes();
             ssize_t index = len - 1;
             while ((!retval[index] || (sizes > retval[index]->getSizes()))
@@ -118,12 +127,13 @@
     std::string format(
             const LogStatistics &stat,
             uid_t uid,
+            pid_t pid,
             const std::string &name = std::string(""),
             log_id_t id = LOG_ID_MAX) const {
         static const size_t maximum_sorted_entries = 32;
         std::string output;
-        std::unique_ptr<const TEntry *[]> sorted = sort(maximum_sorted_entries);
-
+        std::unique_ptr<const TEntry *[]> sorted = sort(uid, pid,
+                                                        maximum_sorted_entries);
         if (!sorted.get()) {
             return output;
         }
@@ -136,9 +146,6 @@
             if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
                 break;
             }
-            if ((uid != AID_ROOT) && (uid != entry->getUid())) {
-                continue;
-            }
             if (!headerPrinted) {
                 output += "\n\n";
                 output += entry->formatHeader(name, id);
@@ -217,14 +224,24 @@
 
 struct UidEntry : public EntryBaseDropped {
     const uid_t uid;
+    pid_t pid;
 
     UidEntry(LogBufferElement *element):
             EntryBaseDropped(element),
-            uid(element->getUid()) {
+            uid(element->getUid()),
+            pid(element->getPid()) {
     }
 
     inline const uid_t&getKey() const { return uid; }
-    inline const uid_t&getUid() const { return uid; }
+    inline const uid_t&getUid() const { return getKey(); }
+    inline const pid_t&getPid() const { return pid; }
+
+    inline void add(LogBufferElement *element) {
+        if (pid != element->getPid()) {
+            pid = -1;
+        }
+        EntryBase::add(element);
+    }
 
     std::string formatHeader(const std::string &name, log_id_t id) const;
     std::string format(const LogStatistics &stat, log_id_t id) const;
@@ -260,6 +277,7 @@
     ~PidEntry() { free(name); }
 
     const pid_t&getKey() const { return pid; }
+    const pid_t&getPid() const { return getKey(); }
     const uid_t&getUid() const { return uid; }
     const char*getName() const { return name; }
 
@@ -291,30 +309,36 @@
 
 struct TidEntry : public EntryBaseDropped {
     const pid_t tid;
+    pid_t pid;
     uid_t uid;
     char *name;
 
-    TidEntry(pid_t tid):
+    TidEntry(pid_t tid, pid_t pid):
             EntryBaseDropped(),
             tid(tid),
+            pid(pid),
             uid(android::pidToUid(tid)),
             name(android::tidToName(tid)) {
     }
     TidEntry(LogBufferElement *element):
             EntryBaseDropped(element),
             tid(element->getTid()),
+            pid(element->getPid()),
             uid(element->getUid()),
             name(android::tidToName(tid)) {
     }
     TidEntry(const TidEntry &element):
             EntryBaseDropped(element),
             tid(element.tid),
+            pid(element.pid),
             uid(element.uid),
             name(element.name ? strdup(element.name) : NULL) {
     }
     ~TidEntry() { free(name); }
 
     const pid_t&getKey() const { return tid; }
+    const pid_t&getTid() const { return getKey(); }
+    const pid_t&getPid() const { return pid; }
     const uid_t&getUid() const { return uid; }
     const char*getName() const { return name; }
 
@@ -330,8 +354,10 @@
 
     inline void add(LogBufferElement *element) {
         uid_t incomingUid = element->getUid();
-        if (getUid() != incomingUid) {
+        pid_t incomingPid = element->getPid();
+        if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
             uid = incomingUid;
+            pid = incomingPid;
             free(name);
             name = android::tidToName(element->getTid());
         } else {
@@ -346,23 +372,28 @@
 
 struct TagEntry : public EntryBase {
     const uint32_t tag;
+    pid_t pid;
     uid_t uid;
 
     TagEntry(LogBufferElement *element):
             EntryBase(element),
             tag(element->getTag()),
+            pid(element->getPid()),
             uid(element->getUid()) {
     }
 
     const uint32_t&getKey() const { return tag; }
+    const pid_t&getPid() const { return pid; }
     const uid_t&getUid() const { return uid; }
     const char*getName() const { return android::tagToName(tag); }
 
     inline void add(LogBufferElement *element) {
-        uid_t incomingUid = element->getUid();
-        if (uid != incomingUid) {
+        if (uid != element->getUid()) {
             uid = -1;
         }
+        if (pid != element->getPid()) {
+            pid = -1;
+        }
         EntryBase::add(element);
     }
 
@@ -416,8 +447,9 @@
         --mDroppedElements[log_id];
     }
 
-    std::unique_ptr<const UidEntry *[]> sort(size_t len, log_id id) {
-        return uidTable[id].sort(len);
+    std::unique_ptr<const UidEntry *[]> sort(uid_t uid, pid_t pid,
+                                             size_t len, log_id id) {
+        return uidTable[id].sort(uid, pid, len);
     }
 
     // fast track current value by id only
@@ -429,7 +461,7 @@
     size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
     size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
 
-    std::string format(uid_t uid, unsigned int logMask) const;
+    std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
 
     // helper (must be locked directly or implicitly by mLogElementsLock)
     const char *pidToName(pid_t pid) const;
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index b591f28..fccba61 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -43,6 +43,9 @@
 bool clientHasLogCredentials(uid_t uid, gid_t gid, pid_t pid);
 bool clientHasLogCredentials(SocketClient *cli);
 
+// Furnished in main.cpp
+bool property_get_bool(const char *key, bool def);
+
 static inline bool worstUidEnabledForLogid(log_id_t id) {
     return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) || (id == LOG_ID_RADIO);
 }
diff --git a/logd/main.cpp b/logd/main.cpp
index 0f55d60..2fcabdc 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -143,7 +143,7 @@
 }
 
 // Property helper
-static bool property_get_bool(const char *key, bool def) {
+bool property_get_bool(const char *key, bool def) {
     char property[PROPERTY_VALUE_MAX];
     property_get(key, property, "");
 
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 4472c1d..7d0dd44 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -26,8 +26,6 @@
 #include "log/log.h"
 #include "log/logger.h"
 
-#define __unused __attribute__((__unused__))
-
 /*
  * returns statistics
  */
@@ -196,7 +194,7 @@
     delete [] buf;
 }
 
-static void caught_signal(int signum __unused) { }
+static void caught_signal(int /* signum */) { }
 
 static void dump_log_msg(const char *prefix,
                          log_msg *msg, unsigned int version, int lid) {