Merge "system/audio.h: Make function inline"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 2c959a4..9c1ead5 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -721,56 +721,50 @@
         return 1;
     }
 
-    if (!strncmp(service, "forward:",8) ||
-        !strncmp(service, "killforward:",12)) {
-        char *local, *remote;
-        atransport *transport;
-
-        int createForward = strncmp(service, "kill", 4);
-        int no_rebind = 0;
-
-        local = strchr(service, ':') + 1;
-
-        // Handle forward:norebind:<local>... here
-        if (createForward && !strncmp(local, "norebind:", 9)) {
-            no_rebind = 1;
-            local = strchr(local, ':') + 1;
+    if (!strncmp(service, "forward:", 8) || !strncmp(service, "killforward:", 12)) {
+        // killforward:local
+        // forward:(norebind:)?local;remote
+        bool kill_forward = false;
+        bool no_rebind = false;
+        if (android::base::StartsWith(service, "killforward:")) {
+            kill_forward = true;
+            service += 12;
+            if (android::base::StartsWith(service, "norebind:")) {
+                no_rebind = true;
+                service += 9;
+            }
+        } else {
+            service += 8;
         }
 
-        remote = strchr(local,';');
+        std::vector<std::string> pieces = android::base::Split(service, ";");
 
-        if (createForward) {
-            // Check forward: parameter format: '<local>;<remote>'
-            if(remote == 0) {
-                SendFail(reply_fd, "malformed forward spec");
-                return 1;
-            }
-
-            *remote++ = 0;
-            if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
-                SendFail(reply_fd, "malformed forward spec");
+        if (kill_forward) {
+            // Check killforward: parameter format: '<local>'
+            if (pieces.size() != 1 || pieces[0].empty()) {
+                SendFail(reply_fd, android::base::StringPrintf("bad killforward: %s", service));
                 return 1;
             }
         } else {
-            // Check killforward: parameter format: '<local>'
-            if (local[0] == 0) {
-                SendFail(reply_fd, "malformed forward spec");
+            // Check forward: parameter format: '<local>;<remote>'
+            if (pieces.size() != 2 || pieces[0].empty() || pieces[1].empty() || pieces[1][0] == '*') {
+                SendFail(reply_fd, android::base::StringPrintf("bad forward: %s", service));
                 return 1;
             }
         }
 
         std::string error_msg;
-        transport = acquire_one_transport(kCsAny, type, serial, &error_msg);
+        atransport* transport = acquire_one_transport(kCsAny, type, serial, &error_msg);
         if (!transport) {
             SendFail(reply_fd, error_msg);
             return 1;
         }
 
         InstallStatus r;
-        if (createForward) {
-            r = install_listener(local, remote, transport, no_rebind);
+        if (kill_forward) {
+            r = remove_listener(pieces[0].c_str(), transport);
         } else {
-            r = remove_listener(local, transport);
+            r = install_listener(pieces[0], pieces[1].c_str(), transport, no_rebind);
         }
         if (r == INSTALL_STATUS_OK) {
 #if ADB_HOST
@@ -783,7 +777,7 @@
 
         std::string message;
         switch (r) {
-          case INSTALL_STATUS_OK: message = " "; break;
+          case INSTALL_STATUS_OK: message = "success (!)"; break;
           case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
           case INSTALL_STATUS_CANNOT_BIND:
             message = android::base::StringPrintf("cannot bind to socket: %s", strerror(errno));
@@ -791,7 +785,9 @@
           case INSTALL_STATUS_CANNOT_REBIND:
             message = android::base::StringPrintf("cannot rebind existing socket: %s", strerror(errno));
             break;
-          case INSTALL_STATUS_LISTENER_NOT_FOUND: message = "listener not found"; break;
+          case INSTALL_STATUS_LISTENER_NOT_FOUND:
+            message = android::base::StringPrintf("listener '%s' not found", service);
+            break;
         }
         SendFail(reply_fd, message);
         return 1;
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index c73d737..ef9a586 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -256,19 +256,21 @@
 }
 
 
-int adb_command(const std::string& service, std::string* error) {
-    int fd = adb_connect(service, error);
+bool adb_command(const std::string& service) {
+    std::string error;
+    int fd = adb_connect(service, &error);
     if (fd < 0) {
-        fprintf(stderr, "error: %s\n", error->c_str());
-        return -1;
+        fprintf(stderr, "error: %s\n", error.c_str());
+        return false;
     }
 
-    if (!adb_status(fd, error)) {
+    if (!adb_status(fd, &error)) {
+        fprintf(stderr, "error: %s\n", error.c_str());
         adb_close(fd);
-        return -1;
+        return false;
     }
 
-    return 0;
+    return true;
 }
 
 bool adb_query(const std::string& service, std::string* result, std::string* error) {
diff --git a/adb/adb_client.h b/adb/adb_client.h
index 9895c49..5de0638 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -26,9 +26,9 @@
 int adb_connect(const std::string& service, std::string* error);
 int _adb_connect(const std::string& service, std::string* error);
 
-// Connect to adb, connect to the named service, return 0 if the connection
-// succeeded AND the service returned OKAY.
-int adb_command(const std::string& service, std::string* error);
+// Connect to adb, connect to the named service, returns true if the connection
+// succeeded AND the service returned OKAY. Outputs any returned error otherwise.
+bool adb_command(const std::string& service);
 
 // Connects to the named adb service and fills 'result' with the response.
 // Returns true on success; returns false and fills 'error' on failure.
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index cf193ab..a335eec 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -26,13 +26,12 @@
 
 int gListenAll = 0; /* Not static because it is used in commandline.c. */
 
-alistener listener_list = {
+static alistener listener_list = {
     .next = &listener_list,
     .prev = &listener_list,
 };
 
-void ss_listener_event_func(int _fd, unsigned ev, void *_l)
-{
+static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
     asocket *s;
 
     if(ev & FDE_READ) {
@@ -56,7 +55,7 @@
     }
 }
 
-void listener_event_func(int _fd, unsigned ev, void* _l)
+static void listener_event_func(int _fd, unsigned ev, void* _l)
 {
     alistener* listener = reinterpret_cast<alistener*>(_l);
     asocket *s;
@@ -106,38 +105,27 @@
     free(l);
 }
 
-void listener_disconnect(void* listener, atransport*  t)
-{
+static void listener_disconnect(void* listener, atransport* t) {
     free_listener(reinterpret_cast<alistener*>(listener));
 }
 
-int local_name_to_fd(const char *name)
-{
-    int port;
-
-    if(!strncmp("tcp:", name, 4)){
-        int  ret;
-        port = atoi(name + 4);
-
+static int local_name_to_fd(const char* name) {
+    if (!strncmp("tcp:", name, 4)) {
+        int port = atoi(name + 4);
         if (gListenAll > 0) {
-            ret = socket_inaddr_any_server(port, SOCK_STREAM);
+            return socket_inaddr_any_server(port, SOCK_STREAM);
         } else {
-            ret = socket_loopback_server(port, SOCK_STREAM);
+            return socket_loopback_server(port, SOCK_STREAM);
         }
-
-        return ret;
     }
 #ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
-    // It's non-sensical to support the "reserved" space on the adb host side
-    if(!strncmp(name, "local:", 6)) {
-        return socket_local_server(name + 6,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-    } else if(!strncmp(name, "localabstract:", 14)) {
-        return socket_local_server(name + 14,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-    } else if(!strncmp(name, "localfilesystem:", 16)) {
-        return socket_local_server(name + 16,
-                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+    // It's nonsensical to support the "reserved" space on the adb host side
+    if (!strncmp(name, "local:", 6)) {
+        return socket_local_server(name + 6, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    } else if (!strncmp(name, "localabstract:", 14)) {
+        return socket_local_server(name + 14, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+    } else if (!strncmp(name, "localfilesystem:", 16)) {
+        return socket_local_server(name + 16, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
     }
 
 #endif
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 9a7ded1..67deb21 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -30,12 +30,6 @@
   INSTALL_STATUS_LISTENER_NOT_FOUND = -4,
 };
 
-extern alistener listener_list;
-
-void listener_disconnect(void*  _l, atransport*  t);
-void listener_event_func(int _fd, unsigned ev, void *_l);
-void ss_listener_event_func(int _fd, unsigned ev, void *_l);
-
 InstallStatus install_listener(const std::string& local_name,
                                const char* connect_to,
                                atransport* transport,
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index d7bee91..7fbca31 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -680,14 +680,7 @@
     }
 
     std::string cmd = format_host_command(service, t, serial);
-    std::string error;
-    if (adb_command(cmd, &error)) {
-        D("failure: %s *\n", error.c_str());
-        fprintf(stderr,"error: %s\n", error.c_str());
-        return false;
-    }
-
-    return true;
+    return adb_command(cmd);
 }
 
 static int send_shell_command(TransportType transport_type, const char* serial,
@@ -1249,90 +1242,50 @@
         if (argc != 1) return usage();
         return send_shell_command(transport_type, serial, "shell:bugreport");
     }
-    /* adb_command() wrapper commands */
     else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
-        std::string cmd;
-        char host_prefix[64];
-        char reverse = (char) !strcmp(argv[0], "reverse");
-        char remove = 0;
-        char remove_all = 0;
-        char list = 0;
-        char no_rebind = 0;
-
-        // Parse options here.
-        while (argc > 1 && argv[1][0] == '-') {
-            if (!strcmp(argv[1], "--list"))
-                list = 1;
-            else if (!strcmp(argv[1], "--remove"))
-                remove = 1;
-            else if (!strcmp(argv[1], "--remove-all"))
-                remove_all = 1;
-            else if (!strcmp(argv[1], "--no-rebind"))
-                no_rebind = 1;
-            else {
-                return usage();
-            }
-            argc--;
-            argv++;
-        }
-
-        // Ensure we can only use one option at a time.
-        if (list + remove + remove_all + no_rebind > 1) {
-            return usage();
-        }
+        bool reverse = !strcmp(argv[0], "reverse");
+        ++argv;
+        --argc;
+        if (argc < 1) return usage();
 
         // Determine the <host-prefix> for this command.
+        std::string host_prefix;
         if (reverse) {
-            snprintf(host_prefix, sizeof host_prefix, "reverse");
+            host_prefix = "reverse";
         } else {
             if (serial) {
-                snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
-                        serial);
+                host_prefix = android::base::StringPrintf("host-serial:%s", serial);
             } else if (transport_type == kTransportUsb) {
-                snprintf(host_prefix, sizeof host_prefix, "host-usb");
+                host_prefix = "host-usb";
             } else if (transport_type == kTransportLocal) {
-                snprintf(host_prefix, sizeof host_prefix, "host-local");
+                host_prefix = "host-local";
             } else {
-                snprintf(host_prefix, sizeof host_prefix, "host");
+                host_prefix = "host";
             }
         }
 
-        // Implement forward --list
-        if (list) {
-            if (argc != 1) {
-                return usage();
-            }
-
-            std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
-            return adb_query_command(query);
-        }
-
-        // Implement forward --remove-all
-        else if (remove_all) {
+        std::string cmd;
+        if (strcmp(argv[0], "--list") == 0) {
             if (argc != 1) return usage();
-            cmd = android::base::StringPrintf("%s:killforward-all", host_prefix);
-        }
-
-        // Implement forward --remove <local>
-        else if (remove) {
+            return adb_query_command(host_prefix + ":list-forward");
+        } else if (strcmp(argv[0], "--remove-all") == 0) {
+            if (argc != 1) return usage();
+            cmd = host_prefix + ":killforward-all";
+        } else if (strcmp(argv[0], "--remove") == 0) {
+            // forward --remove <local>
             if (argc != 2) return usage();
-            cmd = android::base::StringPrintf("%s:killforward:%s", host_prefix, argv[1]);
-        }
-        // Or implement one of:
-        //    forward <local> <remote>
-        //    forward --no-rebind <local> <remote>
-        else {
+            cmd = host_prefix + ":killforward:" + argv[1];
+        } else if (strcmp(argv[0], "--no-rebind") == 0) {
+            // forward --no-rebind <local> <remote>
             if (argc != 3) return usage();
-            const char* command = no_rebind ? "forward:norebind" : "forward";
-            cmd = android::base::StringPrintf("%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
+            cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
+        } else {
+            // forward <local> <remote>
+            if (argc != 2) return usage();
+            cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
         }
 
-        std::string error;
-        if (adb_command(cmd, &error)) {
-            fprintf(stderr, "error: %s\n", error.c_str());
-            return 1;
-        }
-        return 0;
+        return adb_command(cmd) ? 0 : 1;
     }
     /* do_sync_*() commands */
     else if (!strcmp(argv[0], "ls")) {
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 95cd4d1..2714d93 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -96,7 +96,7 @@
 static void SignalHandler(int, siginfo_t*, void* sigcontext) {
   ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false);
   if (!entry) {
-    BACK_LOGW("Unable to find pid %d tid %d information", getpid(), gettid());
+    BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid());
     return;
   }
 
@@ -109,9 +109,14 @@
   // the thread run ahead causing problems.
   // The number indicates that we are waiting for the second Wake() call
   // overall which is made by the thread requesting an unwind.
-  entry->Wait(2);
-
-  ThreadEntry::Remove(entry);
+  if (entry->Wait(2)) {
+    // Do not remove the entry here because that can result in a deadlock
+    // if the code cannot properly send a signal to the thread under test.
+    entry->Wake();
+  } else {
+    // At this point, it is possible that entry has been freed, so just exit.
+    BACK_LOGE("Timed out waiting for unwind thread to indicate it completed.");
+  }
 }
 
 bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
@@ -128,17 +133,15 @@
   act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
   sigemptyset(&act.sa_mask);
   if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) {
-    BACK_LOGW("sigaction failed %s", strerror(errno));
-    entry->Unlock();
+    BACK_LOGE("sigaction failed: %s", strerror(errno));
     ThreadEntry::Remove(entry);
     pthread_mutex_unlock(&g_sigaction_mutex);
     return false;
   }
 
   if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
-    BACK_LOGW("tgkill %d failed: %s", Tid(), strerror(errno));
+    BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno));
     sigaction(THREAD_SIGNAL, &oldact, nullptr);
-    entry->Unlock();
     ThreadEntry::Remove(entry);
     pthread_mutex_unlock(&g_sigaction_mutex);
     return false;
@@ -146,17 +149,30 @@
 
   // Wait for the thread to get the ucontext. The number indicates
   // that we are waiting for the first Wake() call made by the thread.
-  entry->Wait(1);
+  bool wait_completed = entry->Wait(1);
 
   // After the thread has received the signal, allow other unwinders to
   // continue.
   sigaction(THREAD_SIGNAL, &oldact, nullptr);
   pthread_mutex_unlock(&g_sigaction_mutex);
 
-  bool unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext());
+  bool unwind_done = false;
+  if (wait_completed) {
+    unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext());
 
-  // Tell the signal handler to exit and release the entry.
-  entry->Wake();
+    // Tell the signal handler to exit and release the entry.
+    entry->Wake();
+
+    // Wait for the thread to indicate it is done with the ThreadEntry.
+    if (!entry->Wait(3)) {
+      // Send a warning, but do not mark as a failure to unwind.
+      BACK_LOGW("Timed out waiting for signal handler to indicate it finished.");
+    }
+  } else {
+    BACK_LOGE("Timed out waiting for signal handler to get ucontext data.");
+  }
+
+  ThreadEntry::Remove(entry);
 
   return unwind_done;
 }
diff --git a/libbacktrace/BacktraceLog.h b/libbacktrace/BacktraceLog.h
index 1632ec2..5c39f1c 100644
--- a/libbacktrace/BacktraceLog.h
+++ b/libbacktrace/BacktraceLog.h
@@ -25,4 +25,7 @@
 #define BACK_LOGW(format, ...) \
   ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
 
+#define BACK_LOGE(format, ...) \
+  ALOGE("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
+
 #endif // _LIBBACKTRACE_BACKTRACE_LOG_H
diff --git a/libbacktrace/ThreadEntry.cpp b/libbacktrace/ThreadEntry.cpp
index e8b60c8..084c1aa 100644
--- a/libbacktrace/ThreadEntry.cpp
+++ b/libbacktrace/ThreadEntry.cpp
@@ -69,7 +69,7 @@
 }
 
 void ThreadEntry::Remove(ThreadEntry* entry) {
-  pthread_mutex_unlock(&entry->mutex_);
+  entry->Unlock();
 
   pthread_mutex_lock(&ThreadEntry::list_mutex_);
   if (--entry->ref_count_ == 0) {
@@ -96,20 +96,24 @@
   pthread_cond_destroy(&wait_cond_);
 }
 
-void ThreadEntry::Wait(int value) {
+bool ThreadEntry::Wait(int value) {
   timespec ts;
   clock_gettime(CLOCK_MONOTONIC, &ts);
-  ts.tv_sec += 10;
+  ts.tv_sec += 5;
 
+  bool wait_completed = true;
   pthread_mutex_lock(&wait_mutex_);
   while (wait_value_ != value) {
     int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts);
     if (ret != 0) {
-      BACK_LOGW("pthread_cond_timedwait failed: %s", strerror(ret));
+      BACK_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret));
+      wait_completed = false;
       break;
     }
   }
   pthread_mutex_unlock(&wait_mutex_);
+
+  return wait_completed;
 }
 
 void ThreadEntry::Wake() {
diff --git a/libbacktrace/ThreadEntry.h b/libbacktrace/ThreadEntry.h
index 94becf2..11924a3 100644
--- a/libbacktrace/ThreadEntry.h
+++ b/libbacktrace/ThreadEntry.h
@@ -29,7 +29,7 @@
 
   void Wake();
 
-  void Wait(int);
+  bool Wait(int);
 
   void CopyUcontextFromSigcontext(void*);
 
diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk
index 559c48b..a3087ee 100644
--- a/libziparchive/Android.mk
+++ b/libziparchive/Android.mk
@@ -42,8 +42,8 @@
 include $(CLEAR_VARS)
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_SRC_FILES := ${source_files}
-LOCAL_STATIC_LIBRARIES := libutils
-LOCAL_SHARED_LIBRARIES := libz-host liblog libbase
+LOCAL_STATIC_LIBRARIES := libz libutils
+LOCAL_SHARED_LIBRARIES := liblog libbase
 LOCAL_MODULE:= libziparchive-host
 LOCAL_CFLAGS := -Werror
 LOCAL_MULTILIB := both
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 8c0a0be..1da52d8 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -388,7 +388,6 @@
         bool kick = false;
         bool leading = true;
         LogBufferElementLast last;
-        log_time start(log_time::EPOCH);
         for(it = mLogElements.begin(); it != mLogElements.end();) {
             LogBufferElement *e = *it;
 
@@ -417,8 +416,6 @@
                 continue;
             }
 
-            leading = false;
-
             if (hasBlacklist && mPrune.naughty(e)) {
                 last.clear(e);
                 it = erase(it);
@@ -448,29 +445,24 @@
             }
 
             if (e->getUid() != worst) {
-                if (start != log_time::EPOCH) {
+                if (leading) {
                     static const timespec too_old = {
                         EXPIRE_HOUR_THRESHOLD * 60 * 60, 0
                     };
-                    start = e->getRealTime() + too_old;
+                    LogBufferElementCollection::iterator last;
+                    last = mLogElements.end();
+                    --last;
+                    if ((e->getRealTime() < ((*last)->getRealTime() - too_old))
+                            || (e->getRealTime() > (*last)->getRealTime())) {
+                        break;
+                    }
                 }
+                leading = false;
                 last.clear(e);
                 ++it;
                 continue;
             }
 
-            if ((start != log_time::EPOCH) && (e->getRealTime() > start)) {
-                // KISS. Really a heuristic rather than algorithmically strong,
-                // a crude mechanism, the following loops will move the oldest
-                // watermark possibly wiping out the extra EXPIRE_HOUR_THRESHOLD
-                // we just thought we were preserving. We count on the typical
-                // pruneRows of 10% of total not being a sledgehammer.
-                // A stronger algorithm would have us loop back to the top if
-                // we have worst-UID enabled and we start expiring messages
-                // below less than EXPIRE_HOUR_THRESHOLD old.
-                break;
-            }
-
             pruneRows--;
             if (pruneRows == 0) {
                 break;
@@ -479,15 +471,21 @@
             kick = true;
 
             unsigned short len = e->getMsgLen();
-            stats.drop(e);
-            e->setDropped(1);
-            if (last.merge(e, 1)) {
-                it = mLogElements.erase(it);
-                stats.erase(e);
-                delete e;
+
+            // do not create any leading drops
+            if (leading) {
+                it = erase(it);
             } else {
-                last.add(e);
-                ++it;
+                stats.drop(e);
+                e->setDropped(1);
+                if (last.merge(e, 1)) {
+                    it = mLogElements.erase(it);
+                    stats.erase(e);
+                    delete e;
+                } else {
+                    last.add(e);
+                    ++it;
+                }
             }
             if (worst_sizes < second_worst_sizes) {
                 break;
@@ -526,7 +524,7 @@
             break;
         }
 
-        if (hasWhitelist && mPrune.nice(e)) { // WhiteListed
+        if (hasWhitelist && !e->getDropped() && mPrune.nice(e)) { // WhiteListed
             whitelist = true;
             it++;
             continue;
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 46bd9c0..3266360 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -93,53 +93,42 @@
 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:
+    // a noisiest UID statistics is:
     //
-    // main: UID/PID Total size/num   Now          UID/PID[?]  Total
-    // 0           7500306/304207     71608/3183   0/4225?     7454388/303656
-    //    <wrap>                                                     93432/1012
-    // -or-
-    // 0/gone      7454388/303656     93432/1012
+    // Chattiest UIDs in main log buffer:                           Size Pruned
+    // UID   PACKAGE                                                BYTES LINES
+    // 0     root                                                  54164 147569
     //
-    // basically if we see a *large* number of 0/????? entries
-    unsigned long value;
+    char *benchmark = NULL;
     do {
-        char *benchmark = strstr(cp, " 0/");
-        char *benchmark_newline = strstr(cp, "\n0/");
+        static const char signature[] = "\n0     root ";
+
+        benchmark = strstr(cp, signature);
         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 = benchmark + sizeof(signature);
+        while (isspace(*cp)) {
             ++cp;
         }
-        value = 0;
-        // ###? or gone
-        if ((*cp == '?') || (*cp == 'e')) {
-            while (*++cp == ' ');
-            while (isdigit(*cp)) {
-                value = value * 10ULL + *cp - '0';
-                ++cp;
-            }
-            if (*cp != '/') {
-                value = 0;
-                continue;
-            }
-            while (isdigit(*++cp));
-            while (*cp == ' ') ++cp;
-            if (!isdigit(*cp)) {
-                value = 0;
-            }
+        benchmark = cp;
+        while (isdigit(*cp)) {
+            ++cp;
         }
-    } while ((value < 900000ULL) && *cp);
-    return cp;
+        while (isspace(*cp)) {
+            ++cp;
+        }
+        unsigned long value = 0;
+        while (isdigit(*cp)) {
+            value = value * 10ULL + *cp - '0';
+            ++cp;
+        }
+        if (value > 100000UL) {
+            break;
+        }
+        benchmark = NULL;
+    } while (*cp);
+    return benchmark;
 }
 
 TEST(logd, statistics) {
@@ -179,16 +168,16 @@
     EXPECT_EQ(0, truncated);
 
 #ifdef TARGET_USES_LOGD
-    char *main_logs = strstr(cp, "\nmain:");
+    char *main_logs = strstr(cp, "\nChattiest UIDs in main ");
     EXPECT_TRUE(NULL != main_logs);
 
-    char *radio_logs = strstr(cp, "\nradio:");
+    char *radio_logs = strstr(cp, "\nChattiest UIDs in radio ");
     EXPECT_TRUE(NULL != radio_logs);
 
-    char *system_logs = strstr(cp, "\nsystem:");
+    char *system_logs = strstr(cp, "\nChattiest UIDs in system ");
     EXPECT_TRUE(NULL != system_logs);
 
-    char *events_logs = strstr(cp, "\nevents:");
+    char *events_logs = strstr(cp, "\nChattiest UIDs in events ");
     EXPECT_TRUE(NULL != events_logs);
 #endif
 
@@ -431,13 +420,13 @@
     }
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(100000UL, ns[log_maximum_retry]); // 42777 user
+    EXPECT_GE(200000UL, ns[log_maximum_retry]); // 104734 user
 #else
     EXPECT_GE(10000UL, ns[log_maximum_retry]); // 5636 kernel
 #endif
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(30000UL, ns[log_maximum]); // 27305 user
+    EXPECT_GE(90000UL, ns[log_maximum]); // 46913 user
 #else
     EXPECT_GE(10000UL, ns[log_maximum]); // 5637 kernel
 #endif
@@ -445,13 +434,13 @@
     EXPECT_GE(4096UL, ns[clock_overhead]); // 4095
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(250000UL, ns[log_overhead]); // 121876 user
+    EXPECT_GE(250000UL, ns[log_overhead]); // 126886 user
 #else
     EXPECT_GE(100000UL, ns[log_overhead]); // 50945 kernel
 #endif
 
 #ifdef TARGET_USES_LOGD
-    EXPECT_GE(7500UL, ns[log_latency]); // 3718 user space
+    EXPECT_GE(10000UL, ns[log_latency]); // 5669 user space
 #else
     EXPECT_GE(500000UL, ns[log_latency]); // 254200 kernel
 #endif
@@ -483,8 +472,7 @@
     ASSERT_TRUE(benchmark_statistics_found != NULL);
 
     // Check how effective the SPAM filter is, parse out Now size.
-    //             Total               Now
-    // 0/4225?     7454388/303656      31488/755
+    // 0     root                      54164 147569
     //                                 ^-- benchmark_statistics_found
 
     unsigned long nowSpamSize = atol(benchmark_statistics_found);