Merge "crash_reporter: Fix path to dbus-send"
diff --git a/adb/Android.mk b/adb/Android.mk
index e2d0bb1..e271a63 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -277,6 +277,8 @@
 
 LOCAL_MODULE := adbd
 
+LOCAL_INIT_RC := adbd.rc
+
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
diff --git a/adb/adbd.rc b/adb/adbd.rc
new file mode 100644
index 0000000..b91d8b5
--- /dev/null
+++ b/adb/adbd.rc
@@ -0,0 +1,14 @@
+on post-fs-data
+    mkdir /data/misc/adb 02750 system shell
+    mkdir /data/adb 0700 root root
+
+# adbd is controlled via property triggers in init.<platform>.usb.rc
+service adbd /sbin/adbd --root_seclabel=u:r:su:s0
+    class core
+    socket adbd stream 660 system system
+    disabled
+    seclabel u:r:adbd:s0
+
+# adbd on at boot in emulator
+on property:ro.kernel.qemu=1
+    start adbd
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
new file mode 100644
index 0000000..6b98af4
--- /dev/null
+++ b/crash_reporter/Android.mk
@@ -0,0 +1,129 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(HOST_OS),linux)
+
+crash_reporter_cpp_extension := .cc
+
+crash_reporter_src := crash_collector.cc \
+    kernel_collector.cc \
+    kernel_warning_collector.cc \
+    udev_collector.cc \
+    unclean_shutdown_collector.cc \
+    user_collector.cc
+
+crash_reporter_includes := external/gtest/include
+
+crash_reporter_test_src := crash_collector_test.cc \
+    crash_reporter_logs_test.cc \
+    kernel_collector_test.cc \
+    testrunner.cc \
+    udev_collector_test.cc \
+    unclean_shutdown_collector_test.cc \
+    user_collector_test.cc
+
+warn_collector_src := warn_collector.l
+
+# Crash reporter static library.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcrash
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_C_INCLUDES := $(crash_reporter_includes)
+LOCAL_RTTI_FLAG := -frtti
+LOCAL_SHARED_LIBRARIES := libchrome \
+    libchromeos \
+    libcutils \
+    libdbus \
+    libmetrics \
+    libpcrecpp
+LOCAL_SRC_FILES := $(crash_reporter_src)
+include $(BUILD_STATIC_LIBRARY)
+
+# Crash reporter client.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_reporter
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_C_INCLUDES := $(crash_reporter_includes)
+LOCAL_REQUIRED_MODULES := core2md \
+    crash_reporter_logs.conf \
+    crash_sender \
+    dbus-send \
+    init.crash_reporter.rc
+LOCAL_RTTI_FLAG := -frtti
+LOCAL_SHARED_LIBRARIES := libchrome \
+    libchromeos \
+    libcutils \
+    libdbus \
+    libmetrics \
+    libpcrecpp
+LOCAL_SRC_FILES := crash_reporter.cc
+LOCAL_STATIC_LIBRARIES := libcrash
+include $(BUILD_EXECUTABLE)
+
+# Crash sender script.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_sender
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
+LOCAL_SRC_FILES := crash_sender
+include $(BUILD_PREBUILT)
+
+# Warn collector client.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := warn_collector
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_SHARED_LIBRARIES := libmetrics
+LOCAL_SRC_FILES := $(warn_collector_src)
+include $(BUILD_EXECUTABLE)
+
+# Crash reporter init script.
+# ========================================================
+ifdef TARGET_COPY_OUT_INITRCD
+include $(CLEAR_VARS)
+LOCAL_MODULE := init.crash_reporter.rc
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_INITRCD)
+LOCAL_SRC_FILES := init.crash_reporter.rc
+include $(BUILD_PREBUILT)
+endif
+
+# Crash reporter logs conf file.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_reporter_logs.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/etc
+LOCAL_SRC_FILES := crash_reporter_logs.conf
+include $(BUILD_PREBUILT)
+
+# Crash reporter tests.
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_reporter_tests
+LOCAL_CPP_EXTENSION := $(crash_reporter_cpp_extension)
+LOCAL_SHARED_LIBRARIES := libchrome \
+    libchromeos \
+    libdbus \
+    libpcrecpp
+LOCAL_SRC_FILES := $(crash_reporter_test_src)
+LOCAL_STATIC_LIBRARIES := libcrash libgmock
+include $(BUILD_NATIVE_TEST)
+
+endif # HOST_OS == linux
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 3fca709..f7a5f82 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -27,6 +27,9 @@
 
 LOCAL_CPPFLAGS := $(common_cppflags)
 
+LOCAL_INIT_RC_32 := debuggerd.rc
+LOCAL_INIT_RC_64 := debuggerd64.rc
+
 ifeq ($(TARGET_IS_64_BIT),true)
 LOCAL_CPPFLAGS += -DTARGET_IS_64_BIT
 endif
diff --git a/debuggerd/debuggerd.rc b/debuggerd/debuggerd.rc
new file mode 100644
index 0000000..4338ae9
--- /dev/null
+++ b/debuggerd/debuggerd.rc
@@ -0,0 +1,2 @@
+service debuggerd /system/bin/debuggerd
+    class main
diff --git a/debuggerd/debuggerd64.rc b/debuggerd/debuggerd64.rc
new file mode 100644
index 0000000..341a329
--- /dev/null
+++ b/debuggerd/debuggerd64.rc
@@ -0,0 +1,2 @@
+service debuggerd64 /system/bin/debuggerd64
+    class main
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 5d7b151..4dbf32f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -191,7 +191,7 @@
 
 int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
     // Require a matching vendor id if the user specified one with -i.
-    if (vendor_id != 0  && info->dev_vendor != vendor_id) {
+    if (vendor_id != 0 && info->dev_vendor != vendor_id) {
         return -1;
     }
 
@@ -246,7 +246,7 @@
         if(usb) return usb;
         if(announce) {
             announce = 0;
-            fprintf(stderr,"< waiting for device >\n");
+            fprintf(stderr, "< waiting for %s >\n", serial ? serial : "any device");
         }
         usleep(1000);
     }
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 7ae2aa5..45ae833 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -293,6 +293,13 @@
 
     // So, we have a device, finally. Grab its vitals.
 
+
+    kr = (*dev)->USBDeviceOpen(dev);
+    if (kr != 0) {
+        WARN("USBDeviceOpen");
+        goto out;
+    }
+
     kr = (*dev)->GetDeviceVendor(dev, &handle->info.dev_vendor);
     if (kr != 0) {
         ERR("GetDeviceVendor");
@@ -365,12 +372,16 @@
         goto error;
     }
 
+    out:
+
+    (*dev)->USBDeviceClose(dev);
     (*dev)->Release(dev);
     return 0;
 
     error:
 
     if (dev != NULL) {
+        (*dev)->USBDeviceClose(dev);
         (*dev)->Release(dev);
     }
 
diff --git a/init/action.cpp b/init/action.cpp
index 2eb809e..dd366d3 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -154,7 +154,7 @@
     const static std::string prop_str("property:");
     for (std::size_t i = 0; i < args.size(); ++i) {
         if (i % 2) {
-            if (args[i].compare("&&")) {
+            if (args[i] != "&&") {
                 *err = "&& is the only symbol allowed to concatenate actions";
                 return false;
             } else {
@@ -189,24 +189,24 @@
 bool Action::CheckPropertyTriggers(const std::string& name,
                                    const std::string& value) const
 {
-    bool found = !name.compare("");
+    bool found = name.empty();
     if (property_triggers_.empty()) {
         return true;
     }
 
     for (const auto& t : property_triggers_) {
-        if (!t.first.compare(name)) {
-            if (t.second.compare("*") &&
-                t.second.compare(value)) {
+        const auto& trigger_name = t.first;
+        const auto& trigger_value = t.second;
+        if (trigger_name == name) {
+            if (trigger_value != "*" && trigger_value != value) {
                 return false;
             } else {
                 found = true;
             }
         } else {
-            std::string prop_val = property_get(t.first.c_str());
-            if (prop_val.empty() ||
-                (t.second.compare("*") &&
-                 t.second.compare(prop_val))) {
+            std::string prop_val = property_get(trigger_name.c_str());
+            if (prop_val.empty() || (trigger_value != "*" &&
+                                     trigger_value != prop_val)) {
                 return false;
             }
         }
@@ -217,7 +217,7 @@
 bool Action::CheckEventTrigger(const std::string& trigger) const
 {
     return !event_trigger_.empty() &&
-        !trigger.compare(event_trigger_) &&
+        trigger == event_trigger_ &&
         CheckPropertyTriggers();
 }
 
@@ -229,10 +229,8 @@
 
 bool Action::TriggersEqual(const class Action& other) const
 {
-    return property_triggers_.size() == other.property_triggers_.size() &&
-        std::equal(property_triggers_.begin(), property_triggers_.end(),
-                   other.property_triggers_.begin()) &&
-        !event_trigger_.compare(other.event_trigger_);
+    return property_triggers_ == other.property_triggers_ &&
+        event_trigger_ == other.event_trigger_;
 }
 
 std::string Action::BuildTriggersString() const
@@ -255,19 +253,53 @@
 
 void Action::DumpState() const
 {
-    INFO("on ");
     std::string trigger_name = BuildTriggersString();
-    INFO("%s", trigger_name.c_str());
-    INFO("\n");
+    INFO("on %s\n", trigger_name.c_str());
 
     for (const auto& c : commands_) {
         std::string cmd_str = c->BuildCommandString();
-        INFO(" %s", cmd_str.c_str());
+        INFO(" %s\n", cmd_str.c_str());
     }
     INFO("\n");
 }
 
-ActionManager::ActionManager() : cur_command_(0)
+
+class EventTrigger : public Trigger {
+public:
+    EventTrigger(const std::string& trigger) : trigger_(trigger) {
+    }
+    bool CheckTriggers(const Action* action) override {
+        return action->CheckEventTrigger(trigger_);
+    }
+private:
+    std::string trigger_;
+};
+
+class PropertyTrigger : public Trigger {
+public:
+    PropertyTrigger(const std::string& name, const std::string& value)
+        : name_(name), value_(value) {
+    }
+    bool CheckTriggers(const Action* action) override {
+        return action->CheckPropertyTrigger(name_, value_);
+    }
+private:
+    std::string name_;
+    std::string value_;
+};
+
+class BuiltinTrigger : public Trigger {
+public:
+    BuiltinTrigger(Action* action) : action_(action) {
+    }
+    bool CheckTriggers(const Action* action) override {
+        return action == action_;
+    }
+private:
+    Action* action_;
+};
+
+ActionManager::ActionManager() : current_command_(0)
 {
 }
 
@@ -278,21 +310,13 @@
 
 void ActionManager::QueueEventTrigger(const std::string& trigger)
 {
-    for (const auto& a : action_list_) {
-        if (a->CheckEventTrigger(trigger)) {
-            action_queue_.push(a);
-        }
-    }
+    trigger_queue_.push(std::make_unique<EventTrigger>(trigger));
 }
 
 void ActionManager::QueuePropertyTrigger(const std::string& name,
                                          const std::string& value)
 {
-    for (const auto& a : action_list_) {
-        if (a->CheckPropertyTrigger(name, value)) {
-            action_queue_.push(a);
-        }
-    }
+    trigger_queue_.push(std::make_unique<PropertyTrigger>(name, value));
 }
 
 void ActionManager::QueueAllPropertyTriggers()
@@ -312,35 +336,45 @@
 
     act->AddCommand(func, name_vector);
 
-    action_queue_.push(act);
+    actions_.push_back(act);
+    trigger_queue_.push(std::make_unique<BuiltinTrigger>(act));
 }
 
 void ActionManager::ExecuteOneCommand() {
-    if (action_queue_.empty()) {
+    while (current_executing_actions_.empty() && !trigger_queue_.empty()) {
+        std::copy_if(actions_.begin(), actions_.end(),
+                     std::back_inserter(current_executing_actions_),
+                     [this] (Action* act) {
+                         return trigger_queue_.front()->CheckTriggers(act);
+                     });
+        trigger_queue_.pop();
+    }
+
+    if (current_executing_actions_.empty()) {
         return;
     }
 
-    Action* action = action_queue_.front();
+    Action* action = current_executing_actions_.back();
     if (!action->NumCommands()) {
-        action_queue_.pop();
+        current_executing_actions_.pop_back();
         return;
     }
 
-    if (cur_command_ == 0) {
+    if (current_command_ == 0) {
         std::string trigger_name = action->BuildTriggersString();
         INFO("processing action %p (%s)\n", action, trigger_name.c_str());
     }
 
-    action->ExecuteOneCommand(cur_command_++);
-    if (cur_command_ == action->NumCommands()) {
-        cur_command_ = 0;
-        action_queue_.pop();
+    action->ExecuteOneCommand(current_command_++);
+    if (current_command_ == action->NumCommands()) {
+        current_command_ = 0;
+        current_executing_actions_.pop_back();
     }
 }
 
 bool ActionManager::HasMoreCommands() const
 {
-    return !action_queue_.empty();
+    return !current_executing_actions_.empty() || !trigger_queue_.empty();
 }
 
 Action* ActionManager::AddNewAction(const std::vector<std::string>& triggers,
@@ -357,21 +391,21 @@
     }
 
     auto old_act_it =
-        std::find_if(action_list_.begin(), action_list_.end(),
+        std::find_if(actions_.begin(), actions_.end(),
                      [&act] (Action* a) { return act->TriggersEqual(*a); });
 
-    if (old_act_it != action_list_.end()) {
+    if (old_act_it != actions_.end()) {
         delete act;
         return *old_act_it;
     }
 
-    action_list_.push_back(act);
+    actions_.push_back(act);
     return act;
 }
 
 void ActionManager::DumpState() const
 {
-    for (const auto& a : action_list_) {
+    for (const auto& a : actions_) {
         a->DumpState();
     }
     INFO("\n");
diff --git a/init/action.h b/init/action.h
index ae28fe1..5088c71 100644
--- a/init/action.h
+++ b/init/action.h
@@ -54,6 +54,12 @@
     std::vector<Command*> commands_;
 };
 
+class Trigger {
+public:
+    virtual ~Trigger() { }
+    virtual bool CheckTriggers(const Action* action) = 0;
+};
+
 class ActionManager {
 public:
     static ActionManager& GetInstance();
@@ -74,9 +80,10 @@
     ActionManager(ActionManager const&) = delete;
     void operator=(ActionManager const&) = delete;
 
-    std::vector<Action*> action_list_;
-    std::queue<Action*> action_queue_;
-    std::size_t cur_command_;
+    std::vector<Action*> actions_;
+    std::queue<std::unique_ptr<Trigger>> trigger_queue_;
+    std::vector<Action*> current_executing_actions_;
+    std::size_t current_command_;
 };
 
 #endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index e663501..97151c0 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -427,6 +427,19 @@
     while (1) { pause(); }  // never reached
 }
 
+void import_late()
+{
+    static const std::vector<std::string> init_directories = {
+        "/system/etc/init",
+        "/vendor/etc/init",
+        "/odm/etc/init"
+    };
+
+    for (const auto& dir : init_directories) {
+        init_parse_config(dir.c_str());
+    }
+}
+
 /*
  * This function might request a reboot, in which case it will
  * not return.
@@ -478,6 +491,8 @@
         return -1;
     }
 
+    import_late();
+
     if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
         property_set("vold.decrypt", "trigger_encryption");
     } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 128bb04..97f0ef4 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -102,6 +102,11 @@
   uintptr_t relative_pc = BacktraceMap::GetRelativePc(frame->map, frame->pc);
 
   std::string line(StringPrintf("#%02zu pc %" PRIPTR "  %s", frame->num, relative_pc, map_name));
+  // Special handling for non-zero offset maps, we need to print that
+  // information.
+  if (frame->map.offset != 0) {
+    line += " (offset " + StringPrintf("0x%" PRIxPTR, frame->map.offset) + ")";
+  }
   if (!frame->func_name.empty()) {
     line += " (" + frame->func_name;
     if (frame->func_offset) {
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 6bd7529..9ebd639 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -825,6 +825,15 @@
   EXPECT_EQ("#01 pc 123456dc  MapFake (ProcFake+645)",
 #endif
             backtrace->FormatFrameData(&frame));
+
+  // Check a non-zero map offset.
+  frame.map.offset = 0x1000;
+#if defined(__LP64__)
+  EXPECT_EQ("#01 pc 00000000123456dc  MapFake (offset 0x1000) (ProcFake+645)",
+#else
+  EXPECT_EQ("#01 pc 123456dc  MapFake (offset 0x1000) (ProcFake+645)",
+#endif
+            backtrace->FormatFrameData(&frame));
 }
 
 struct map_test_t {
diff --git a/libsparse/backed_block.c b/libsparse/backed_block.c
index 3e72b57..794cd6b 100644
--- a/libsparse/backed_block.c
+++ b/libsparse/backed_block.c
@@ -221,7 +221,8 @@
 		}
 		break;
 	case BACKED_BLOCK_FILE:
-		if (a->file.filename != b->file.filename ||
+		/* Already make sure b->type is BACKED_BLOCK_FILE */
+		if (strcmp(a->file.filename, b->file.filename) ||
 				a->file.offset + a->len != b->file.offset) {
 			return -EINVAL;
 		}
@@ -279,7 +280,10 @@
 	}
 
 	merge_bb(bbl, new_bb, new_bb->next);
-	merge_bb(bbl, bb, new_bb);
+	if (!merge_bb(bbl, bb, new_bb)) {
+		/* new_bb destroyed, point to retained as last_used */
+		bbl->last_used = bb;
+	}
 
 	return 0;
 }
diff --git a/lmkd/Android.mk b/lmkd/Android.mk
index 39081d6..8c88661 100644
--- a/lmkd/Android.mk
+++ b/lmkd/Android.mk
@@ -7,4 +7,6 @@
 
 LOCAL_MODULE := lmkd
 
+LOCAL_INIT_RC := lmkd.rc
+
 include $(BUILD_EXECUTABLE)
diff --git a/lmkd/lmkd.rc b/lmkd/lmkd.rc
new file mode 100644
index 0000000..83c5ff0
--- /dev/null
+++ b/lmkd/lmkd.rc
@@ -0,0 +1,4 @@
+service lmkd /system/bin/lmkd
+    class core
+    critical
+    socket lmkd seqpacket 0660 system system
diff --git a/logcat/Android.mk b/logcat/Android.mk
index 7115f9b..844ab8b 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -11,6 +11,8 @@
 
 LOCAL_CFLAGS := -Werror
 
+LOCAL_INIT_RC := logcatd.rc
+
 include $(BUILD_EXECUTABLE)
 
 include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
new file mode 100644
index 0000000..0bc581e
--- /dev/null
+++ b/logcat/logcatd.rc
@@ -0,0 +1,13 @@
+on property:persist.logd.logpersistd=logcatd
+    # all exec/services are called with umask(077), so no gain beyond 0700
+    mkdir /data/misc/logd 0700 logd log
+    # logd for write to /data/misc/logd, log group for read from pstore (-L)
+    exec - logd log -- /system/bin/logcat -L -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
+    start logcatd
+
+service logcatd /system/bin/logcat -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
+    class late_start
+    disabled
+    # logd for write to /data/misc/logd, log group for read from log daemon
+    user logd
+    group log
diff --git a/logd/Android.mk b/logd/Android.mk
index 615d030..01c51c7 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -4,6 +4,8 @@
 
 LOCAL_MODULE:= logd
 
+LOCAL_INIT_RC := logd.rc
+
 LOCAL_SRC_FILES := \
     main.cpp \
     LogCommand.cpp \
@@ -25,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__
diff --git a/logd/logd.rc b/logd/logd.rc
new file mode 100644
index 0000000..498baec
--- /dev/null
+++ b/logd/logd.rc
@@ -0,0 +1,9 @@
+service logd /system/bin/logd
+    class core
+    socket logd stream 0666 logd logd
+    socket logdr seqpacket 0666 logd logd
+    socket logdw dgram 0222 logd logd
+
+service logd-reinit /system/bin/logd --reinit
+    oneshot
+    disabled
diff --git a/metricsd/constants.h b/metricsd/constants.h
index d65e0e0..56dac0d 100644
--- a/metricsd/constants.h
+++ b/metricsd/constants.h
@@ -21,7 +21,7 @@
 static const char kMetricsDirectory[] = "/data/misc/metrics/";
 static const char kMetricsEventsFilePath[] = "/data/misc/metrics/uma-events";
 static const char kMetricsGUIDFilePath[] = "/data/misc/metrics/Sysinfo.GUID";
-static const char kMetricsServer[] = "http://clients4.google.com/uma/v2";
+static const char kMetricsServer[] = "https://clients4.google.com/uma/v2";
 static const char kConsentFilePath[] = "/data/misc/metrics/enabled";
 static const char kDefaultVersion[] = "0.0.0.0";
 }  // namespace metrics
diff --git a/metricsd/init.metrics_daemon.rc b/metricsd/init.metrics_daemon.rc
index ad78ea5..73ce673 100644
--- a/metricsd/init.metrics_daemon.rc
+++ b/metricsd/init.metrics_daemon.rc
@@ -1,5 +1,5 @@
 on boot
-    mkdir /data/misc/metrics 0700 system system
+    mkdir /data/misc/metrics 0770 system system
 
 service metrics_daemon /system/bin/metrics_daemon --uploader -nodaemon
     class late_start
diff --git a/metricsd/uploader/metrics_log.cc b/metricsd/uploader/metrics_log.cc
index 5f4c599..1f16ca1 100644
--- a/metricsd/uploader/metrics_log.cc
+++ b/metricsd/uploader/metrics_log.cc
@@ -48,6 +48,6 @@
   stability->set_unclean_system_shutdown_count(current + 1);
 }
 
-void MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
-  profile_setter->Populate(uma_proto());
+bool MetricsLog::PopulateSystemProfile(SystemProfileSetter* profile_setter) {
+  return profile_setter->Populate(uma_proto());
 }
diff --git a/metricsd/uploader/metrics_log.h b/metricsd/uploader/metrics_log.h
index 50fed89..5e09070 100644
--- a/metricsd/uploader/metrics_log.h
+++ b/metricsd/uploader/metrics_log.h
@@ -39,7 +39,7 @@
   void IncrementUncleanShutdownCount();
 
   // Populate the system profile with system information using setter.
-  void PopulateSystemProfile(SystemProfileSetter* setter);
+  bool PopulateSystemProfile(SystemProfileSetter* setter);
 
  private:
   FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues);
diff --git a/metricsd/uploader/system_profile_cache.cc b/metricsd/uploader/system_profile_cache.cc
index 35910d7..7dd0323 100644
--- a/metricsd/uploader/system_profile_cache.cc
+++ b/metricsd/uploader/system_profile_cache.cc
@@ -75,7 +75,7 @@
 
   if (!base::SysInfo::GetLsbReleaseValue("BRILLO_BUILD_TARGET_ID",
                                          &profile_.build_target_id)) {
-    LOG(ERROR) << "Could not initialize system profile.";
+    LOG(ERROR) << "BRILLO_BUILD_TARGET_ID is not set in /etc/lsb-release.";
     return false;
   }
 
@@ -109,11 +109,12 @@
   return initialized_ || Initialize();
 }
 
-void SystemProfileCache::Populate(
+bool SystemProfileCache::Populate(
     metrics::ChromeUserMetricsExtension* metrics_proto) {
   CHECK(metrics_proto);
-  CHECK(InitializeOrCheck())
-      << "failed to initialize system information.";
+  if (not InitializeOrCheck()) {
+    return false;
+  }
 
   // The client id is hashed before being sent.
   metrics_proto->set_client_id(
@@ -132,6 +133,8 @@
   metrics::SystemProfileProto_BrilloDeviceData* device_data =
       profile_proto->mutable_brillo();
   device_data->set_build_target_id(profile_.build_target_id);
+
+  return true;
 }
 
 std::string SystemProfileCache::GetPersistentGUID(
diff --git a/metricsd/uploader/system_profile_cache.h b/metricsd/uploader/system_profile_cache.h
index c53a18e..ac80b47 100644
--- a/metricsd/uploader/system_profile_cache.h
+++ b/metricsd/uploader/system_profile_cache.h
@@ -52,7 +52,7 @@
   SystemProfileCache(bool testing, const std::string& config_root);
 
   // Populates the ProfileSystem protobuf with system information.
-  void Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
+  bool Populate(metrics::ChromeUserMetricsExtension* metrics_proto) override;
 
   // Converts a string representation of the channel to a
   // SystemProfileProto_Channel
diff --git a/metricsd/uploader/system_profile_setter.h b/metricsd/uploader/system_profile_setter.h
index cd311a4..bd3ff42 100644
--- a/metricsd/uploader/system_profile_setter.h
+++ b/metricsd/uploader/system_profile_setter.h
@@ -27,7 +27,7 @@
  public:
   virtual ~SystemProfileSetter() {}
   // Populates the protobuf with system informations.
-  virtual void Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
+  virtual bool Populate(metrics::ChromeUserMetricsExtension* profile_proto) = 0;
 };
 
 #endif  // METRICS_UPLOADER_SYSTEM_PROFILE_SETTER_H_
diff --git a/metricsd/uploader/upload_service.cc b/metricsd/uploader/upload_service.cc
index 63b5789..2335630 100644
--- a/metricsd/uploader/upload_service.cc
+++ b/metricsd/uploader/upload_service.cc
@@ -73,7 +73,6 @@
   CHECK(!staged_log_) << "the staged log should be discarded before starting "
                          "a new metrics log";
   MetricsLog* log = new MetricsLog();
-  log->PopulateSystemProfile(system_profile_setter_.get());
   current_log_.reset(log);
 }
 
@@ -97,13 +96,12 @@
   // Previous upload successful, reading metrics sample from the file.
   ReadMetrics();
   GatherHistograms();
-
-  // No samples found. Exit to avoid sending an empty log.
-  if (!current_log_)
-    return;
-
   StageCurrentLog();
-  SendStagedLog();
+
+  // If a log is available for upload, upload it.
+  if (staged_log_) {
+    SendStagedLog();
+  }
 }
 
 void UploadService::SendStagedLog() {
@@ -225,6 +223,11 @@
 
   staged_log_.swap(current_log_);
   staged_log_->CloseLog();
+  if (!staged_log_->PopulateSystemProfile(system_profile_setter_.get())) {
+    LOG(WARNING) << "Error while adding metadata to the log. Discarding the "
+                 << "log.";
+    staged_log_.reset();
+  }
   failed_upload_count_ = 0;
 }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 12999bd..cf16f01 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -235,7 +235,6 @@
 
     # create basic filesystem structure
     mkdir /data/misc 01771 system misc
-    mkdir /data/misc/adb 02750 system shell
     mkdir /data/misc/bluedroid 0770 bluetooth net_bt_stack
     mkdir /data/misc/bluetooth 0770 system system
     mkdir /data/misc/keystore 0700 keystore keystore
@@ -292,7 +291,6 @@
     # the following directory.
     mkdir /data/mediadrm 0770 mediadrm mediadrm
 
-    mkdir /data/adb 0700 root root
     mkdir /data/anr 0775 system system
 
     # symlink to bugreport storage location
@@ -477,16 +475,6 @@
     critical
     seclabel u:r:ueventd:s0
 
-service logd /system/bin/logd
-    class core
-    socket logd stream 0666 logd logd
-    socket logdr seqpacket 0666 logd logd
-    socket logdw dgram 0222 logd logd
-
-service logd-reinit /system/bin/logd --reinit
-    oneshot
-    disabled
-
 service healthd /sbin/healthd
     class core
     critical
@@ -503,139 +491,10 @@
 on property:ro.debuggable=1
     start console
 
-# adbd is controlled via property triggers in init.<platform>.usb.rc
-service adbd /sbin/adbd --root_seclabel=u:r:su:s0
-    class core
-    socket adbd stream 660 system system
-    disabled
-    seclabel u:r:adbd:s0
-
-# adbd on at boot in emulator
-on property:ro.kernel.qemu=1
-    start adbd
-
-service lmkd /system/bin/lmkd
-    class core
-    critical
-    socket lmkd seqpacket 0660 system system
-
-service servicemanager /system/bin/servicemanager
-    class core
-    user system
-    group system
-    critical
-    onrestart restart healthd
-    onrestart restart zygote
-    onrestart restart media
-    onrestart restart surfaceflinger
-    onrestart restart drm
-
-service vold /system/bin/vold
-    class core
-    socket vold stream 0660 root mount
-    ioprio be 2
-
-service netd /system/bin/netd
-    class main
-    socket netd stream 0660 root system
-    socket dnsproxyd stream 0660 root inet
-    socket mdns stream 0660 root system
-    socket fwmarkd stream 0660 root inet
-
-service debuggerd /system/bin/debuggerd
-    class main
-
-service debuggerd64 /system/bin/debuggerd64
-    class main
-
-service ril-daemon /system/bin/rild
-    class main
-    socket rild stream 660 root radio
-    socket rild-debug stream 660 radio system
-    user root
-    group radio cache inet misc audio log
-
-service surfaceflinger /system/bin/surfaceflinger
-    class core
-    user system
-    group graphics drmrpc
-    onrestart restart zygote
-
-service drm /system/bin/drmserver
-    class main
-    user drm
-    group drm system inet drmrpc
-
-service media /system/bin/mediaserver
-    class main
-    user media
-    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
-    ioprio rt 4
-
-# One shot invocation to deal with encrypted volume.
-service defaultcrypto /system/bin/vdc --wait cryptfs mountdefaultencrypted
-    disabled
-    oneshot
-    # vold will set vold.decrypt to trigger_restart_framework (default
-    # encryption) or trigger_restart_min_framework (other encryption)
-
-# One shot invocation to encrypt unencrypted volumes
-service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default
-    disabled
-    oneshot
-    # vold will set vold.decrypt to trigger_restart_framework (default
-    # encryption)
-
-service bootanim /system/bin/bootanimation
-    class core
-    user graphics
-    group graphics audio
-    disabled
-    oneshot
-
-service installd /system/bin/installd
-    class main
-    socket installd stream 600 system system
-
 service flash_recovery /system/bin/install-recovery.sh
     class main
     oneshot
 
-service racoon /system/bin/racoon
-    class main
-    socket racoon stream 600 system system
-    # IKE uses UDP port 500. Racoon will setuid to vpn after binding the port.
-    group vpn net_admin inet
-    disabled
-    oneshot
-
-service mtpd /system/bin/mtpd
-    class main
-    socket mtpd stream 600 system system
-    user vpn
-    group vpn net_admin inet net_raw
-    disabled
-    oneshot
-
-service keystore /system/bin/keystore /data/misc/keystore
-    class main
-    user keystore
-    group keystore drmrpc
-
-service dumpstate /system/bin/dumpstate -s
-    class main
-    socket dumpstate stream 0660 shell log
-    disabled
-    oneshot
-
-service mdnsd /system/bin/mdnsd
-    class main
-    user mdnsr
-    group inet net_raw
-    socket mdnsd stream 0660 mdnsr inet
-    disabled
-    oneshot
-
 service uncrypt /system/bin/uncrypt
     class main
     disabled
@@ -645,22 +504,3 @@
     class main
     disabled
     oneshot
-
-service perfprofd /system/xbin/perfprofd
-    class late_start
-    user root
-    oneshot
-
-on property:persist.logd.logpersistd=logcatd
-    # all exec/services are called with umask(077), so no gain beyond 0700
-    mkdir /data/misc/logd 0700 logd log
-    # logd for write to /data/misc/logd, log group for read from pstore (-L)
-    exec - logd log -- /system/bin/logcat -L -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
-    start logcatd
-
-service logcatd /system/bin/logcat -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 64 -n 256
-    class late_start
-    disabled
-    # logd for write to /data/misc/logd, log group for read from log daemon
-    user logd
-    group log