Merge changes from topic 'init-rc-breakup'

* changes:
  init: Queue Triggers instead of Actions
  bundle init.rc contents with its service
diff --git a/logd/Android.mk b/logd/Android.mk
index 4d08a23..01c51c7 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -27,7 +27,7 @@
     libsysutils \
     liblog \
     libcutils \
-    libutils
+    libbase
 
 # This is what we want to do:
 #  event_logtags = $(shell \
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index 489bea6..031c740 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -25,6 +25,9 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 
+#include <string>
+
+#include <base/stringprintf.h>
 #include <cutils/sockets.h>
 #include <private/android_filesystem_config.h>
 #include <sysutils/SocketClient.h>
@@ -189,22 +192,13 @@
         mBuf(*buf) {
 }
 
-static void package_string(char **strp) {
-    const char *a = *strp;
-    if (!a) {
-        a = "";
-    }
-
+static std::string package_string(const std::string &str) {
     // Calculate total buffer size prefix, count is the string length w/o nul
     char fmt[32];
-    for(size_t l = strlen(a), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) {
+    for(size_t l = str.length(), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) {
         snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
     }
-
-    char *b = *strp;
-    *strp = NULL;
-    asprintf(strp, fmt, a);
-    free(b);
+    return android::base::StringPrintf(fmt, str.c_str());
 }
 
 int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
@@ -228,16 +222,7 @@
         }
     }
 
-    char *buf = NULL;
-
-    mBuf.formatStatistics(&buf, uid, logMask);
-    if (!buf) {
-        cli->sendMsg("Failed");
-    } else {
-        package_string(&buf);
-        cli->sendMsg(buf);
-        free(buf);
-    }
+    cli->sendMsg(package_string(mBuf.formatStatistics(uid, logMask)).c_str());
     return 0;
 }
 
@@ -249,15 +234,7 @@
 int CommandListener::GetPruneListCmd::runCommand(SocketClient *cli,
                                          int /*argc*/, char ** /*argv*/) {
     setname();
-    char *buf = NULL;
-    mBuf.formatPrune(&buf);
-    if (!buf) {
-        cli->sendMsg("Failed");
-    } else {
-        package_string(&buf);
-        cli->sendMsg(buf);
-        free(buf);
-    }
+    cli->sendMsg(package_string(mBuf.formatPrune()).c_str());
     return 0;
 }
 
@@ -274,20 +251,15 @@
         return 0;
     }
 
-    char *cp = NULL;
+    std::string str;
     for (int i = 1; i < argc; ++i) {
-        char *p = cp;
-        if (p) {
-            cp = NULL;
-            asprintf(&cp, "%s %s", p, argv[i]);
-            free(p);
-        } else {
-            asprintf(&cp, "%s", argv[i]);
+        if (str.length()) {
+            str += " ";
         }
+        str += argv[i];
     }
 
-    int ret = mBuf.initPrune(cp);
-    free(cp);
+    int ret = mBuf.initPrune(str.c_str());
 
     if (ret) {
         cli->sendMsg("Invalid");
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index d584925..823a842 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -72,7 +72,7 @@
             return;
         }
         entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart);
-        times.push_back(entry);
+        times.push_front(entry);
     }
 
     client->incRef();
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index b9e8973..6ea4109 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -217,34 +217,35 @@
     return len;
 }
 
-// If we're using more than 256K of memory for log entries, prune
-// at least 10% of the log entries. For sizes above 1M, prune at
-// least 1% of the log entries.
+// Prune at most 10% of the log entries or 256, whichever is less.
 //
 // mLogElementsLock must be held when this function is called.
 void LogBuffer::maybePrune(log_id_t id) {
     size_t sizes = stats.sizes(id);
     unsigned long maxSize = log_buffer_size(id);
     if (sizes > maxSize) {
-        size_t sizeOver, minElements, elements = stats.elements(id);
-        if (maxSize > (4 * LOG_BUFFER_SIZE)) {
-            sizeOver = sizes - ((maxSize * 99) / 100);
-            minElements = elements / 100;
-        } else {
-            sizeOver = sizes - ((maxSize * 9) / 10);
-            minElements = elements / 10;
-        }
+        size_t sizeOver = sizes - ((maxSize * 9) / 10);
+        size_t elements = stats.elements(id);
+        size_t minElements = elements / 10;
         unsigned long pruneRows = elements * sizeOver / sizes;
         if (pruneRows <= minElements) {
             pruneRows = minElements;
         }
+        if (pruneRows > 256) {
+            pruneRows = 256;
+        }
         prune(id, pruneRows);
     }
 }
 
 LogBufferElementCollection::iterator LogBuffer::erase(LogBufferElementCollection::iterator it) {
     LogBufferElement *e = *it;
+    log_id_t id = e->getLogId();
+    LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(e->getUid());
 
+    if ((f != mLastWorstUid[id].end()) && (it == f->second)) {
+        mLastWorstUid[id].erase(f);
+    }
     it = mLogElements.erase(it);
     stats.subtract(e);
     delete e;
@@ -403,8 +404,17 @@
 
         bool kick = false;
         bool leading = true;
+        it = mLogElements.begin();
+        if (worst != (uid_t) -1) {
+            LogBufferIteratorMap::iterator f = mLastWorstUid[id].find(worst);
+            if ((f != mLastWorstUid[id].end())
+                    && (f->second != mLogElements.end())) {
+                leading = false;
+                it = f->second;
+            }
+        }
         LogBufferElementLast last;
-        for(it = mLogElements.begin(); it != mLogElements.end();) {
+        while (it != mLogElements.end()) {
             LogBufferElement *e = *it;
 
             if (oldest && (oldest->mStart <= e->getSequence())) {
@@ -454,8 +464,10 @@
                 continue;
             }
 
+            // unmerged drop message
             if (dropped) {
                 last.add(e);
+                mLastWorstUid[id][e->getUid()] = it;
                 ++it;
                 continue;
             }
@@ -500,6 +512,7 @@
                     delete e;
                 } else {
                     last.add(e);
+                    mLastWorstUid[id][e->getUid()] = it;
                     ++it;
                 }
             }
@@ -677,10 +690,12 @@
     return max;
 }
 
-void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
+std::string LogBuffer::formatStatistics(uid_t uid, unsigned int logMask) {
     pthread_mutex_lock(&mLogElementsLock);
 
-    stats.format(strp, uid, logMask);
+    std::string ret = stats.format(uid, logMask);
 
     pthread_mutex_unlock(&mLogElementsLock);
+
+    return ret;
 }
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index a13fded..fcb05f5 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -19,9 +19,11 @@
 
 #include <sys/types.h>
 
+#include <list>
+#include <string>
+
 #include <log/log.h>
 #include <sysutils/SocketClient.h>
-#include <utils/List.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -30,7 +32,7 @@
 #include "LogStatistics.h"
 #include "LogWhiteBlackList.h"
 
-typedef android::List<LogBufferElement *> LogBufferElementCollection;
+typedef std::list<LogBufferElement *> LogBufferElementCollection;
 
 class LogBuffer {
     LogBufferElementCollection mLogElements;
@@ -39,6 +41,11 @@
     LogStatistics stats;
 
     PruneList mPrune;
+    // watermark of any worst/chatty uid processing
+    typedef std::unordered_map<uid_t,
+                               LogBufferElementCollection::iterator>
+                LogBufferIteratorMap;
+    LogBufferIteratorMap mLastWorstUid[LOG_ID_MAX];
 
     unsigned long mMaxSize[LOG_ID_MAX];
 
@@ -61,15 +68,14 @@
     int setSize(log_id_t id, unsigned long size);
     unsigned long getSizeUsed(log_id_t id);
     // *strp uses malloc, use free to release.
-    void formatStatistics(char **strp, uid_t uid, unsigned int logMask);
+    std::string formatStatistics(uid_t uid, unsigned int logMask);
 
     void enableStatistics() {
         stats.enableStatistics();
     }
 
-    int initPrune(char *cp) { return mPrune.init(cp); }
-    // *strp uses malloc, use free to release.
-    void formatPrune(char **strp) { mPrune.format(strp); }
+    int initPrune(const char *cp) { return mPrune.init(cp); }
+    std::string formatPrune() { return mPrune.format(); }
 
     // helper must be protected directly or implicitly by lock()/unlock()
     char *pidToName(pid_t pid) { return stats.pidToName(pid); }
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 48c2fe6..61fd559 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -20,9 +20,9 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <base/stringprintf.h>
 #include <log/logger.h>
 #include <private/android_filesystem_config.h>
-#include <utils/String8.h>
 
 #include "LogStatistics.h"
 
@@ -183,8 +183,10 @@
     return name;
 }
 
-static void format_line(android::String8 &output,
-        android::String8 &name, android::String8 &size, android::String8 &pruned) {
+static std::string format_line(
+        const std::string &name,
+        const std::string &size,
+        const std::string &pruned) {
     static const size_t pruned_len = 6;
     static const size_t total_len = 70 + pruned_len;
 
@@ -193,26 +195,21 @@
                                 total_len - name.length() - drop_len - 1);
 
     if (pruned.length()) {
-        output.appendFormat("%s%*s%*s\n", name.string(),
-                                          (int)size_len, size.string(),
-                                          (int)drop_len, pruned.string());
+        return android::base::StringPrintf("%s%*s%*s\n", name.c_str(),
+                                           (int)size_len, size.c_str(),
+                                           (int)drop_len, pruned.c_str());
     } else {
-        output.appendFormat("%s%*s\n", name.string(),
-                                       (int)size_len, size.string());
+        return android::base::StringPrintf("%s%*s\n", name.c_str(),
+                                           (int)size_len, size.c_str());
     }
 }
 
-void LogStatistics::format(char **buf, uid_t uid, unsigned int logMask) {
+std::string LogStatistics::format(uid_t uid, unsigned int logMask) {
     static const unsigned short spaces_total = 19;
 
-    if (*buf) {
-        free(*buf);
-        *buf = NULL;
-    }
-
     // Report on total logging, current and for all time
 
-    android::String8 output("size/num");
+    std::string output = "size/num";
     size_t oldLength;
     short spaces = 1;
 
@@ -224,12 +221,13 @@
         if (spaces < 0) {
             spaces = 0;
         }
-        output.appendFormat("%*s%s", spaces, "", android_log_id_to_name(id));
+        output += android::base::StringPrintf("%*s%s", spaces, "",
+                                              android_log_id_to_name(id));
         spaces += spaces_total + oldLength - output.length();
     }
 
     spaces = 4;
-    output.appendFormat("\nTotal");
+    output += android::base::StringPrintf("\nTotal");
 
     log_id_for_each(id) {
         if (!(logMask & (1 << id))) {
@@ -239,13 +237,14 @@
         if (spaces < 0) {
             spaces = 0;
         }
-        output.appendFormat("%*s%zu/%zu", spaces, "",
-                            sizesTotal(id), elementsTotal(id));
+        output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
+                                              sizesTotal(id),
+                                              elementsTotal(id));
         spaces += spaces_total + oldLength - output.length();
     }
 
     spaces = 6;
-    output.appendFormat("\nNow");
+    output += android::base::StringPrintf("\nNow");
 
     log_id_for_each(id) {
         if (!(logMask & (1 << id))) {
@@ -258,7 +257,8 @@
             if (spaces < 0) {
                 spaces = 0;
             }
-            output.appendFormat("%*s%zu/%zu", spaces, "", sizes(id), els);
+            output += android::base::StringPrintf("%*s%zu/%zu", spaces, "",
+                                                  sizes(id), els);
             spaces -= output.length() - oldLength;
         }
         spaces += spaces_total;
@@ -284,53 +284,54 @@
             }
 
             if (!headerPrinted) {
-                output.appendFormat("\n\n");
-                android::String8 name("");
+                output += android::base::StringPrintf("\n\n");
+                std::string name;
                 if (uid == AID_ROOT) {
-                    name.appendFormat(
+                    name = android::base::StringPrintf(
                         "Chattiest UIDs in %s log buffer:",
                         android_log_id_to_name(id));
                 } else {
-                    name.appendFormat(
+                    name = android::base::StringPrintf(
                         "Logging for your UID in %s log buffer:",
                         android_log_id_to_name(id));
                 }
-                android::String8 size("Size");
-                android::String8 pruned("Pruned");
+                std::string size = "Size";
+                std::string pruned = "Pruned";
                 if (!worstUidEnabledForLogid(id)) {
-                    pruned.setTo("");
+                    pruned = "";
                 }
-                format_line(output, name, size, pruned);
+                output += format_line(name, size, pruned);
 
-                name.setTo("UID   PACKAGE");
-                size.setTo("BYTES");
-                pruned.setTo("LINES");
+                name = "UID   PACKAGE";
+                size = "BYTES";
+                pruned = "LINES";
                 if (!worstUidEnabledForLogid(id)) {
-                    pruned.setTo("");
+                    pruned = "";
                 }
-                format_line(output, name, size, pruned);
+                output += format_line(name, size, pruned);
 
                 headerPrinted = true;
             }
 
-            android::String8 name("");
-            name.appendFormat("%u", u);
+            std::string name = android::base::StringPrintf("%u", u);
             char *n = uidToName(u);
             if (n) {
-                name.appendFormat("%*s%s", (int)std::max(6 - name.length(), (size_t)1), "", n);
+                name += android::base::StringPrintf(
+                    "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
+                    "", n);
                 free(n);
             }
 
-            android::String8 size("");
-            size.appendFormat("%zu", entry->getSizes());
+            std::string size = android::base::StringPrintf("%zu",
+                                                           entry->getSizes());
 
-            android::String8 pruned("");
+            std::string pruned = "";
             size_t dropped = entry->getDropped();
             if (dropped) {
-                pruned.appendFormat("%zu", dropped);
+                pruned = android::base::StringPrintf("%zu", dropped);
             }
 
-            format_line(output, name, size, pruned);
+            output += format_line(name, size, pruned);
         }
     }
 
@@ -347,48 +348,52 @@
             }
 
             if (!headerPrinted) {
-                output.appendFormat("\n\n");
-                android::String8 name("");
+                output += android::base::StringPrintf("\n\n");
+                std::string name;
                 if (uid == AID_ROOT) {
-                    name.appendFormat("Chattiest PIDs:");
+                    name = android::base::StringPrintf("Chattiest PIDs:");
                 } else {
-                    name.appendFormat("Logging for this PID:");
+                    name = android::base::StringPrintf("Logging for this PID:");
                 }
-                android::String8 size("Size");
-                android::String8 pruned("Pruned");
-                format_line(output, name, size, pruned);
+                std::string size = "Size";
+                std::string pruned = "Pruned";
+                output += format_line(name, size, pruned);
 
-                name.setTo("  PID/UID   COMMAND LINE");
-                size.setTo("BYTES");
-                pruned.setTo("LINES");
-                format_line(output, name, size, pruned);
+                name = "  PID/UID   COMMAND LINE";
+                size = "BYTES";
+                pruned = "LINES";
+                output += format_line(name, size, pruned);
 
                 headerPrinted = true;
             }
 
-            android::String8 name("");
-            name.appendFormat("%5u/%u", entry->getKey(), u);
+            std::string name = android::base::StringPrintf("%5u/%u",
+                                                           entry->getKey(), u);
             const char *n = entry->getName();
             if (n) {
-                name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n);
+                name += android::base::StringPrintf(
+                    "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+                    "", n);
             } else {
                 char *un = uidToName(u);
                 if (un) {
-                    name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un);
+                    name += android::base::StringPrintf(
+                        "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+                        "", un);
                     free(un);
                 }
             }
 
-            android::String8 size("");
-            size.appendFormat("%zu", entry->getSizes());
+            std::string size = android::base::StringPrintf("%zu",
+                                                           entry->getSizes());
 
-            android::String8 pruned("");
+            std::string pruned = "";
             size_t dropped = entry->getDropped();
             if (dropped) {
-                pruned.appendFormat("%zu", dropped);
+                pruned = android::base::StringPrintf("%zu", dropped);
             }
 
-            format_line(output, name, size, pruned);
+            output += format_line(name, size, pruned);
         }
     }
 
@@ -406,46 +411,50 @@
             }
 
             if (!headerPrinted) { // Only print header if we have table to print
-                output.appendFormat("\n\n");
-                android::String8 name("Chattiest TIDs:");
-                android::String8 size("Size");
-                android::String8 pruned("Pruned");
-                format_line(output, name, size, pruned);
+                output += android::base::StringPrintf("\n\n");
+                std::string name = "Chattiest TIDs:";
+                std::string size = "Size";
+                std::string pruned = "Pruned";
+                output += format_line(name, size, pruned);
 
-                name.setTo("  TID/UID   COMM");
-                size.setTo("BYTES");
-                pruned.setTo("LINES");
-                format_line(output, name, size, pruned);
+                name = "  TID/UID   COMM";
+                size = "BYTES";
+                pruned = "LINES";
+                output += format_line(name, size, pruned);
 
                 headerPrinted = true;
             }
 
-            android::String8 name("");
-            name.appendFormat("%5u/%u", entry->getKey(), u);
+            std::string name = android::base::StringPrintf("%5u/%u",
+                                                           entry->getKey(), u);
             const char *n = entry->getName();
             if (n) {
-                name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", n);
+                name += android::base::StringPrintf(
+                    "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+                    "", n);
             } else {
                 // if we do not have a PID name, lets punt to try UID name?
                 char *un = uidToName(u);
                 if (un) {
-                    name.appendFormat("%*s%s", (int)std::max(12 - name.length(), (size_t)1), "", un);
+                    name += android::base::StringPrintf(
+                        "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
+                        "", un);
                     free(un);
                 }
                 // We tried, better to not have a name at all, we still
                 // have TID/UID by number to report in any case.
             }
 
-            android::String8 size("");
-            size.appendFormat("%zu", entry->getSizes());
+            std::string size = android::base::StringPrintf("%zu",
+                                                           entry->getSizes());
 
-            android::String8 pruned("");
+            std::string pruned = "";
             size_t dropped = entry->getDropped();
             if (dropped) {
-                pruned.appendFormat("%zu", dropped);
+                pruned = android::base::StringPrintf("%zu", dropped);
             }
 
-            format_line(output, name, size, pruned);
+            output += format_line(name, size, pruned);
         }
     }
 
@@ -461,40 +470,44 @@
                 continue;
             }
 
-            android::String8 pruned("");
+            std::string pruned = "";
 
             if (!headerPrinted) {
-                output.appendFormat("\n\n");
-                android::String8 name("Chattiest events log buffer TAGs:");
-                android::String8 size("Size");
-                format_line(output, name, size, pruned);
+                output += android::base::StringPrintf("\n\n");
+                std::string name = "Chattiest events log buffer TAGs:";
+                std::string size = "Size";
+                output += format_line(name, size, pruned);
 
-                name.setTo("    TAG/UID   TAGNAME");
-                size.setTo("BYTES");
-                format_line(output, name, size, pruned);
+                name = "    TAG/UID   TAGNAME";
+                size = "BYTES";
+                output += format_line(name, size, pruned);
 
                 headerPrinted = true;
             }
 
-            android::String8 name("");
+            std::string name;
             if (u == (uid_t)-1) {
-                name.appendFormat("%7u", entry->getKey());
+                name = android::base::StringPrintf("%7u",
+                                                   entry->getKey());
             } else {
-                name.appendFormat("%7u/%u", entry->getKey(), u);
+                name = android::base::StringPrintf("%7u/%u",
+                                                   entry->getKey(), u);
             }
             const char *n = entry->getName();
             if (n) {
-                name.appendFormat("%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", n);
+                name += android::base::StringPrintf(
+                    "%*s%s", (int)std::max(14 - name.length(), (size_t)1),
+                    "", n);
             }
 
-            android::String8 size("");
-            size.appendFormat("%zu", entry->getSizes());
+            std::string size = android::base::StringPrintf("%zu",
+                                                           entry->getSizes());
 
-            format_line(output, name, size, pruned);
+            output += format_line(name, size, pruned);
         }
     }
 
-    *buf = strdup(output.string());
+    return output;
 }
 
 namespace android {
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 760d6b2..61000d2 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -331,8 +331,7 @@
     size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
     size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
 
-    // *strp = malloc, balance with free
-    void format(char **strp, uid_t uid, unsigned int logMask);
+    std::string format(uid_t uid, unsigned int logMask);
 
     // helper (must be locked directly or implicitly by mLogElementsLock)
     char *pidToName(pid_t pid);
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 783bce6..39bcdd4 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -20,8 +20,10 @@
 #include <pthread.h>
 #include <time.h>
 #include <sys/types.h>
+
+#include <list>
+
 #include <sysutils/SocketClient.h>
-#include <utils/List.h>
 #include <log/log.h>
 
 class LogReader;
@@ -107,6 +109,6 @@
     static int FilterSecondPass(const LogBufferElement *element, void *me);
 };
 
-typedef android::List<LogTimeEntry *> LastLogTimes;
+typedef std::list<LogTimeEntry *> LastLogTimes;
 
-#endif
+#endif // _LOGD_LOG_TIMES_H__
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index 277b3ca..ad005ec 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -16,7 +16,7 @@
 
 #include <ctype.h>
 
-#include <utils/String8.h>
+#include <base/stringprintf.h>
 
 #include "LogWhiteBlackList.h"
 
@@ -35,46 +35,40 @@
     return uid - mUid;
 }
 
-void Prune::format(char **strp) {
+std::string Prune::format() {
     if (mUid != uid_all) {
         if (mPid != pid_all) {
-            asprintf(strp, "%u/%u", mUid, mPid);
-        } else {
-            asprintf(strp, "%u", mUid);
+            return android::base::StringPrintf("%u/%u", mUid, mPid);
         }
-    } else if (mPid != pid_all) {
-        asprintf(strp, "/%u", mPid);
-    } else { // NB: mPid == pid_all can not happen if mUid == uid_all
-        asprintf(strp, "/");
+        return android::base::StringPrintf("%u", mUid);
     }
+    if (mPid != pid_all) {
+        return android::base::StringPrintf("/%u", mPid);
+    }
+    // NB: mPid == pid_all can not happen if mUid == uid_all
+    return std::string("/");
 }
 
 PruneList::PruneList() : mWorstUidEnabled(true) {
-    mNaughty.clear();
-    mNice.clear();
 }
 
 PruneList::~PruneList() {
     PruneCollection::iterator it;
     for (it = mNice.begin(); it != mNice.end();) {
-        delete (*it);
         it = mNice.erase(it);
     }
     for (it = mNaughty.begin(); it != mNaughty.end();) {
-        delete (*it);
         it = mNaughty.erase(it);
     }
 }
 
-int PruneList::init(char *str) {
+int PruneList::init(const char *str) {
     mWorstUidEnabled = true;
     PruneCollection::iterator it;
     for (it = mNice.begin(); it != mNice.end();) {
-        delete (*it);
         it = mNice.erase(it);
     }
     for (it = mNaughty.begin(); it != mNaughty.end();) {
-        delete (*it);
         it = mNaughty.erase(it);
     }
 
@@ -142,28 +136,28 @@
         // insert sequentially into list
         PruneCollection::iterator it = list->begin();
         while (it != list->end()) {
-            Prune *p = *it;
-            int m = uid - p->mUid;
+            Prune &p = *it;
+            int m = uid - p.mUid;
             if (m == 0) {
-                if (p->mPid == p->pid_all) {
+                if (p.mPid == p.pid_all) {
                     break;
                 }
-                if ((pid == p->pid_all) && (p->mPid != p->pid_all)) {
+                if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
                     it = list->erase(it);
                     continue;
                 }
-                m = pid - p->mPid;
+                m = pid - p.mPid;
             }
             if (m <= 0) {
                 if (m < 0) {
-                    list->insert(it, new Prune(uid,pid));
+                    list->insert(it, Prune(uid,pid));
                 }
                 break;
             }
             ++it;
         }
         if (it == list->end()) {
-            list->push_back(new Prune(uid,pid));
+            list->push_back(Prune(uid,pid));
         }
         if (!*str) {
             break;
@@ -173,47 +167,32 @@
     return 0;
 }
 
-void PruneList::format(char **strp) {
-    if (*strp) {
-        free(*strp);
-        *strp = NULL;
-    }
-
+std::string PruneList::format() {
     static const char nice_format[] = " %s";
     const char *fmt = nice_format + 1;
 
-    android::String8 string;
+    std::string string;
 
     if (mWorstUidEnabled) {
-        string.setTo("~!");
+        string = "~!";
         fmt = nice_format;
     }
 
     PruneCollection::iterator it;
 
     for (it = mNice.begin(); it != mNice.end(); ++it) {
-        char *a = NULL;
-        (*it)->format(&a);
-
-        string.appendFormat(fmt, a);
+        string += android::base::StringPrintf(fmt, (*it).format().c_str());
         fmt = nice_format;
-
-        free(a);
     }
 
     static const char naughty_format[] = " ~%s";
     fmt = naughty_format + (*fmt != ' ');
     for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
-        char *a = NULL;
-        (*it)->format(&a);
-
-        string.appendFormat(fmt, a);
+        string += android::base::StringPrintf(fmt, (*it).format().c_str());
         fmt = naughty_format;
-
-        free(a);
     }
 
-    *strp = strdup(string.string());
+    return string;
 }
 
 // ToDo: Lists are in sorted order, Prune->cmp() returns + or -
@@ -223,7 +202,7 @@
 bool PruneList::naughty(LogBufferElement *element) {
     PruneCollection::iterator it;
     for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
-        if (!(*it)->cmp(element)) {
+        if (!(*it).cmp(element)) {
             return true;
         }
     }
@@ -233,7 +212,7 @@
 bool PruneList::nice(LogBufferElement *element) {
     PruneCollection::iterator it;
     for (it = mNice.begin(); it != mNice.end(); ++it) {
-        if (!(*it)->cmp(element)) {
+        if (!(*it).cmp(element)) {
             return true;
         }
     }
diff --git a/logd/LogWhiteBlackList.h b/logd/LogWhiteBlackList.h
index 5f60801..00e1cad 100644
--- a/logd/LogWhiteBlackList.h
+++ b/logd/LogWhiteBlackList.h
@@ -19,7 +19,8 @@
 
 #include <sys/types.h>
 
-#include <utils/List.h>
+#include <list>
+#include <string.h>
 
 #include <LogBufferElement.h>
 
@@ -43,11 +44,10 @@
 
     int cmp(LogBufferElement *e) const { return cmp(e->getUid(), e->getPid()); }
 
-    // *strp is malloc'd, use free to release
-    void format(char **strp);
+    std::string format();
 };
 
-typedef android::List<Prune *> PruneCollection;
+typedef std::list<Prune> PruneCollection;
 
 class PruneList {
     PruneCollection mNaughty;
@@ -58,7 +58,7 @@
     PruneList();
     ~PruneList();
 
-    int init(char *str);
+    int init(const char *str);
 
     bool naughty(LogBufferElement *element);
     bool naughty(void) { return !mNaughty.empty(); }
@@ -66,8 +66,7 @@
     bool nice(void) { return !mNice.empty(); }
     bool worstUidEnabled() const { return mWorstUidEnabled; }
 
-    // *strp is malloc'd, use free to release
-    void format(char **strp);
+    std::string format();
 };
 
 #endif // _LOGD_LOG_WHITE_BLACK_LIST_H__