Merge "Mark libdemangle as vendor_available." into oc-dr1-dev
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index b2fdc07..e7f44c6 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -180,10 +180,6 @@
     if (port_count < 0) return "";
     return StringPrintf("/dev/bus/usb/%03u/%03u", libusb_get_bus_number(device), ports[0]);
 }
-
-static bool is_device_accessible(libusb_device* device) {
-    return access(get_device_dev_path(device).c_str(), R_OK | W_OK) == 0;
-}
 #endif
 
 static bool endpoint_is_output(uint8_t endpoint) {
@@ -377,9 +373,10 @@
     {
         std::unique_lock<std::mutex> lock(usb_handles_mutex);
         usb_handles[device_address] = std::move(result);
-    }
 
-    register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable);
+        register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(),
+                               writable);
+    }
     LOG(INFO) << "registered new usb device '" << device_serial << "'";
 }
 
@@ -388,18 +385,12 @@
 static void device_connected(libusb_device* device) {
 #if defined(__linux__)
     // Android's host linux libusb uses netlink instead of udev for device hotplug notification,
-    // which means we can get hotplug notifications before udev has updated ownership/perms on
-    // the device. Since we're not going to be able to link against the system's libudev any
-    // time soon, hack around this by checking for accessibility in a loop.
+    // which means we can get hotplug notifications before udev has updated ownership/perms on the
+    // device. Since we're not going to be able to link against the system's libudev any time soon,
+    // hack around this by inserting a sleep.
     auto thread = std::thread([device]() {
         std::string device_path = get_device_dev_path(device);
-        auto start = std::chrono::steady_clock::now();
-        while (std::chrono::steady_clock::now() - start < 500ms) {
-            if (is_device_accessible(device)) {
-                break;
-            }
-            std::this_thread::sleep_for(10ms);
-        }
+        std::this_thread::sleep_for(1s);
 
         process_device(device);
         if (--connecting_devices == 0) {
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 308ee8d..2bbbefd 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -603,15 +603,15 @@
 static void transport_unref(atransport* t) {
     CHECK(t != nullptr);
 
-    std::lock_guard<std::mutex> lock(transport_lock);
-    CHECK_GT(t->ref_count, 0u);
-    t->ref_count--;
-    if (t->ref_count == 0) {
+    size_t old_refcount = t->ref_count--;
+    CHECK_GT(old_refcount, 0u);
+
+    if (old_refcount == 1u) {
         D("transport: %s unref (kicking and closing)", t->serial);
         t->close(t);
         remove_transport(t);
     } else {
-        D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
+        D("transport: %s unref (count=%zu)", t->serial, old_refcount - 1);
     }
 }
 
diff --git a/adb/transport.h b/adb/transport.h
index 57fc988..4a89ed9 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -61,7 +61,7 @@
     // class in one go is a very large change. Given how bad our testing is,
     // it's better to do this piece by piece.
 
-    atransport(ConnectionState state = kCsOffline) : connection_state_(state) {
+    atransport(ConnectionState state = kCsOffline) : ref_count(0), connection_state_(state) {
         transport_fde = {};
         protocol_version = A_VERSION;
         max_payload = MAX_PAYLOAD;
@@ -88,7 +88,7 @@
     int fd = -1;
     int transport_socket = -1;
     fdevent transport_fde;
-    size_t ref_count = 0;
+    std::atomic<size_t> ref_count;
     uint32_t sync_token = 0;
     bool online = false;
     TransportType type = kTransportAny;
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 0a9f000..b4a2bde 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -23,7 +23,9 @@
 
 #include <array>
 #include <deque>
+#include <string>
 #include <unordered_map>
+#include <utility>
 
 #include <event2/event.h>
 #include <event2/listener.h>
@@ -75,23 +77,24 @@
     find_oldest_artifact();
   }
 
-  unique_fd get_output_fd() {
+  std::pair<unique_fd, std::string> get_output() {
     unique_fd result;
-    char buf[PATH_MAX];
-    snprintf(buf, sizeof(buf), "%s%02d", file_name_prefix_.c_str(), next_artifact_);
+    std::string file_name = StringPrintf("%s%02d", file_name_prefix_.c_str(), next_artifact_);
+
     // Unlink and create the file, instead of using O_TRUNC, to avoid two processes
     // interleaving their output in case we ever get into that situation.
-    if (unlinkat(dir_fd_, buf, 0) != 0 && errno != ENOENT) {
-      PLOG(FATAL) << "failed to unlink tombstone at " << dir_path_ << buf;
+    if (unlinkat(dir_fd_, file_name.c_str(), 0) != 0 && errno != ENOENT) {
+      PLOG(FATAL) << "failed to unlink tombstone at " << dir_path_ << "/" << file_name;
     }
 
-    result.reset(openat(dir_fd_, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
+    result.reset(openat(dir_fd_, file_name.c_str(),
+                        O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
     if (result == -1) {
-      PLOG(FATAL) << "failed to create tombstone at " << dir_path_ << buf;
+      PLOG(FATAL) << "failed to create tombstone at " << dir_path_ << "/" << file_name;
     }
 
     next_artifact_ = (next_artifact_ + 1) % max_artifacts_;
-    return result;
+    return {std::move(result), dir_path_ + "/" + file_name};
   }
 
   bool maybe_enqueue_crash(Crash* crash) {
@@ -124,8 +127,7 @@
     time_t oldest_time = std::numeric_limits<time_t>::max();
 
     for (size_t i = 0; i < max_artifacts_; ++i) {
-      std::string path = android::base::StringPrintf("%s/%s%02zu", dir_path_.c_str(),
-                                                     file_name_prefix_.c_str(), i);
+      std::string path = StringPrintf("%s/%s%02zu", dir_path_.c_str(), file_name_prefix_.c_str(), i);
       struct stat st;
       if (stat(path.c_str(), &st) != 0) {
         if (errno == ENOENT) {
@@ -183,6 +185,7 @@
   unique_fd crash_fd;
   pid_t crash_pid;
   event* crash_event = nullptr;
+  std::string crash_path;
 
   DebuggerdDumpType crash_type;
 };
@@ -203,7 +206,7 @@
 static void perform_request(Crash* crash) {
   unique_fd output_fd;
   if (!intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd)) {
-    output_fd = get_crash_queue(crash)->get_output_fd();
+    std::tie(output_fd, crash->crash_path) = get_crash_queue(crash)->get_output();
   }
 
   TombstonedCrashPacket response = {
@@ -341,6 +344,10 @@
     goto fail;
   }
 
+  if (!crash->crash_path.empty()) {
+    LOG(ERROR) << "Tombstone written to: " << crash->crash_path;
+  }
+
 fail:
   CrashQueue* queue = get_crash_queue(crash);
   delete crash;
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 23bd664..6c527c5 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -389,16 +389,8 @@
 
     dirent* dp;
     while ((dp = readdir(fstabdir.get())) != NULL) {
-        // skip over name and compatible
-        if (dp->d_type != DT_DIR) {
-            continue;
-        }
-
-        // skip if its not 'vendor', 'odm' or 'system'
-        if (strcmp(dp->d_name, "odm") && strcmp(dp->d_name, "system") &&
-            strcmp(dp->d_name, "vendor")) {
-            continue;
-        }
+        // skip over name, compatible and .
+        if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
 
         // create <dev> <mnt_point>  <type>  <mnt_flags>  <fsmgr_flags>\n
         std::vector<std::string> fstab_entry;
diff --git a/init/devices.cpp b/init/devices.cpp
index c52d8f8..2943fb7 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -147,21 +147,34 @@
     }
 }
 
-// Given a path that may start with a platform device, find the length of the
-// platform device prefix.  If it doesn't start with a platform device, return false
-bool PlatformDeviceList::Find(const std::string& path, std::string* out_path) const {
-    out_path->clear();
-    // platform_devices is searched backwards, since parents are added before their children,
-    // and we want to match as deep of a child as we can.
-    for (auto it = platform_devices_.crbegin(); it != platform_devices_.crend(); ++it) {
-        auto platform_device_path_length = it->length();
-        if (platform_device_path_length < path.length() &&
-            path[platform_device_path_length] == '/' &&
-            android::base::StartsWith(path, it->c_str())) {
-            *out_path = *it;
+// Given a path that may start with a platform device, find the parent platform device by finding a
+// parent directory with a 'subsystem' symlink that points to the platform bus.
+// If it doesn't start with a platform device, return false
+bool DeviceHandler::FindPlatformDevice(std::string path, std::string* platform_device_path) const {
+    platform_device_path->clear();
+
+    // Uevents don't contain the mount point, so we need to add it here.
+    path.insert(0, sysfs_mount_point_);
+
+    std::string directory = android::base::Dirname(path);
+
+    while (directory != "/" && directory != ".") {
+        std::string subsystem_link_path;
+        if (android::base::Realpath(directory + "/subsystem", &subsystem_link_path) &&
+            subsystem_link_path == sysfs_mount_point_ + "/bus/platform") {
+            // We need to remove the mount point that we added above before returning.
+            directory.erase(0, sysfs_mount_point_.size());
+            *platform_device_path = directory;
             return true;
         }
+
+        auto last_slash = path.rfind('/');
+        if (last_slash == std::string::npos) return false;
+
+        path.erase(last_slash);
+        directory = android::base::Dirname(path);
     }
+
     return false;
 }
 
@@ -258,7 +271,7 @@
 
 std::vector<std::string> DeviceHandler::GetCharacterDeviceSymlinks(const Uevent& uevent) const {
     std::string parent_device;
-    if (!platform_devices_.Find(uevent.path, &parent_device)) return {};
+    if (!FindPlatformDevice(uevent.path, &parent_device)) return {};
 
     // skip path to the parent driver
     std::string path = uevent.path.substr(parent_device.length());
@@ -316,7 +329,7 @@
     std::string device;
     std::string type;
 
-    if (platform_devices_.Find(uevent.path, &device)) {
+    if (FindPlatformDevice(uevent.path, &device)) {
         // Skip /devices/platform or /devices/ if present
         static const std::string devices_platform_prefix = "/devices/platform/";
         static const std::string devices_prefix = "/devices/";
@@ -388,14 +401,6 @@
     }
 }
 
-void DeviceHandler::HandlePlatformDeviceEvent(const Uevent& uevent) {
-    if (uevent.action == "add") {
-        platform_devices_.Add(uevent.path);
-    } else if (uevent.action == "remove") {
-        platform_devices_.Remove(uevent.path);
-    }
-}
-
 void DeviceHandler::HandleBlockDeviceEvent(const Uevent& uevent) const {
     // if it's not a /dev device, nothing to do
     if (uevent.major < 0 || uevent.minor < 0) return;
@@ -458,8 +463,6 @@
 
     if (uevent.subsystem == "block") {
         HandleBlockDeviceEvent(uevent);
-    } else if (uevent.subsystem == "platform") {
-        HandlePlatformDeviceEvent(uevent);
     } else {
         HandleGenericDeviceEvent(uevent);
     }
@@ -472,7 +475,8 @@
       sysfs_permissions_(std::move(sysfs_permissions)),
       subsystems_(std::move(subsystems)),
       sehandle_(selinux_android_file_context_handle()),
-      skip_restorecon_(skip_restorecon) {}
+      skip_restorecon_(skip_restorecon),
+      sysfs_mount_point_("/sys") {}
 
 DeviceHandler::DeviceHandler()
     : DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
diff --git a/init/devices.h b/init/devices.h
index 09a0ce3..362c38c 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -93,20 +93,6 @@
     DevnameSource devname_source_;
 };
 
-class PlatformDeviceList {
-  public:
-    void Add(const std::string& path) { platform_devices_.emplace_back(path); }
-    void Remove(const std::string& path) {
-        auto it = std::find(platform_devices_.begin(), platform_devices_.end(), path);
-        if (it != platform_devices_.end()) platform_devices_.erase(it);
-    }
-    bool Find(const std::string& path, std::string* out_path) const;
-    auto size() const { return platform_devices_.size(); }
-
-  private:
-    std::vector<std::string> platform_devices_;
-};
-
 class DeviceHandler {
   public:
     friend class DeviceHandlerTester;
@@ -119,16 +105,11 @@
 
     void HandleDeviceEvent(const Uevent& uevent);
 
-    void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
-
-    void HandlePlatformDeviceEvent(const Uevent& uevent);
-    void HandleBlockDeviceEvent(const Uevent& uevent) const;
-    void HandleGenericDeviceEvent(const Uevent& uevent) const;
-
     std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;
     void set_skip_restorecon(bool value) { skip_restorecon_ = value; }
 
   private:
+    bool FindPlatformDevice(std::string path, std::string* platform_device_path) const;
     std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(
         const std::string& path, const std::vector<std::string>& links) const;
     void MakeDevice(const std::string& path, int block, int major, int minor,
@@ -136,13 +117,17 @@
     std::vector<std::string> GetCharacterDeviceSymlinks(const Uevent& uevent) const;
     void HandleDevice(const std::string& action, const std::string& devpath, int block, int major,
                       int minor, const std::vector<std::string>& links) const;
+    void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
+
+    void HandleBlockDeviceEvent(const Uevent& uevent) const;
+    void HandleGenericDeviceEvent(const Uevent& uevent) const;
 
     std::vector<Permissions> dev_permissions_;
     std::vector<SysfsPermissions> sysfs_permissions_;
     std::vector<Subsystem> subsystems_;
-    PlatformDeviceList platform_devices_;
     selabel_handle* sehandle_;
     bool skip_restorecon_;
+    std::string sysfs_mount_point_;
 };
 
 // Exposed for testing
diff --git a/init/devices_test.cpp b/init/devices_test.cpp
index 41b101b..e1e4e49 100644
--- a/init/devices_test.cpp
+++ b/init/devices_test.cpp
@@ -16,33 +16,29 @@
 
 #include "devices.h"
 
-#include <string>
-#include <vector>
-
 #include <android-base/scopeguard.h>
+#include <android-base/test_utils.h>
 #include <gtest/gtest.h>
 
+#include "util.h"
+
+using namespace std::string_literals;
+
 class DeviceHandlerTester {
   public:
-    void AddPlatformDevice(const std::string& path) {
-        Uevent uevent = {
-            .action = "add", .subsystem = "platform", .path = path,
-        };
-        device_handler_.HandlePlatformDeviceEvent(uevent);
-    }
-
-    void RemovePlatformDevice(const std::string& path) {
-        Uevent uevent = {
-            .action = "remove", .subsystem = "platform", .path = path,
-        };
-        device_handler_.HandlePlatformDeviceEvent(uevent);
-    }
-
-    void TestGetSymlinks(const std::string& platform_device_name, const Uevent& uevent,
+    void TestGetSymlinks(const std::string& platform_device, const Uevent& uevent,
                          const std::vector<std::string> expected_links, bool block) {
-        AddPlatformDevice(platform_device_name);
-        auto platform_device_remover = android::base::make_scope_guard(
-            [this, &platform_device_name]() { RemovePlatformDevice(platform_device_name); });
+        TemporaryDir fake_sys_root;
+        device_handler_.sysfs_mount_point_ = fake_sys_root.path;
+
+        std::string platform_device_dir = fake_sys_root.path + platform_device;
+        mkdir_recursive(platform_device_dir, 0777, nullptr);
+
+        std::string platform_bus = fake_sys_root.path + "/bus/platform"s;
+        mkdir_recursive(platform_bus, 0777, nullptr);
+        symlink(platform_bus.c_str(), (platform_device_dir + "/subsystem").c_str());
+
+        mkdir_recursive(android::base::Dirname(fake_sys_root.path + uevent.path), 0777, nullptr);
 
         std::vector<std::string> result;
         if (block) {
@@ -65,30 +61,6 @@
     DeviceHandler device_handler_;
 };
 
-TEST(device_handler, PlatformDeviceList) {
-    PlatformDeviceList platform_device_list;
-
-    platform_device_list.Add("/devices/platform/some_device_name");
-    platform_device_list.Add("/devices/platform/some_device_name/longer");
-    platform_device_list.Add("/devices/platform/other_device_name");
-    EXPECT_EQ(3U, platform_device_list.size());
-
-    std::string out_path;
-    EXPECT_FALSE(platform_device_list.Find("/devices/platform/not_found", &out_path));
-    EXPECT_EQ("", out_path);
-
-    EXPECT_FALSE(platform_device_list.Find("/devices/platform/some_device_name_with_same_prefix",
-                                           &out_path));
-
-    EXPECT_TRUE(platform_device_list.Find("/devices/platform/some_device_name/longer/longer_child",
-                                          &out_path));
-    EXPECT_EQ("/devices/platform/some_device_name/longer", out_path);
-
-    EXPECT_TRUE(
-        platform_device_list.Find("/devices/platform/some_device_name/other_child", &out_path));
-    EXPECT_EQ("/devices/platform/some_device_name", out_path);
-}
-
 TEST(device_handler, get_character_device_symlinks_success) {
     const char* platform_device = "/devices/platform/some_device_name";
     Uevent uevent = {
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 8a7d9a2..ebbe1cd 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -60,9 +60,8 @@
     virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
 
     bool need_dm_verity_;
-    // Device tree fstab entries.
+
     std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
-    // Eligible first stage mount candidates, only allow /system, /vendor and/or /odm.
     std::vector<fstab_rec*> mount_fstab_recs_;
     std::set<std::string> required_devices_partition_names_;
     DeviceHandler device_handler_;
@@ -115,12 +114,10 @@
         LOG(ERROR) << "Failed to read fstab from device tree";
         return;
     }
-    for (auto mount_point : {"/system", "/vendor", "/odm"}) {
-        fstab_rec* fstab_rec =
-            fs_mgr_get_entry_for_mount_point(device_tree_fstab_.get(), mount_point);
-        if (fstab_rec != nullptr) {
-            mount_fstab_recs_.push_back(fstab_rec);
-        }
+    // Stores device_tree_fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
+    // for easier manipulation later, e.g., range-base for loop.
+    for (int i = 0; i < device_tree_fstab_->num_entries; i++) {
+        mount_fstab_recs_.push_back(&device_tree_fstab_->recs[i]);
     }
 }
 
@@ -184,12 +181,6 @@
 }
 
 RegenerationAction FirstStageMount::UeventCallback(const Uevent& uevent) {
-    // We need platform devices to create symlinks.
-    if (uevent.subsystem == "platform") {
-        device_handler_.HandleDeviceEvent(uevent);
-        return RegenerationAction::kContinue;
-    }
-
     // Ignores everything that is not a block device.
     if (uevent.subsystem != "block") {
         return RegenerationAction::kContinue;
@@ -420,7 +411,7 @@
 
 // Public functions
 // ----------------
-// Mounts /system, /vendor, and/or /odm if they are present in the fstab provided by device tree.
+// Mounts partitions specified by fstab in device tree.
 bool DoFirstStageMount() {
     // Skips first stage mount if we're in recovery mode.
     if (IsRecoveryMode()) {
diff --git a/init/service.cpp b/init/service.cpp
index 7c931da..1a6474b 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -209,17 +209,6 @@
 }
 
 void Service::KillProcessGroup(int signal) {
-    // We ignore reporting errors of ESRCH as this commonly happens in the below case,
-    // 1) Terminate() is called, which sends SIGTERM to the process
-    // 2) The process successfully exits
-    // 3) ReapOneProcess() is called, which calls waitpid(-1, ...) which removes the pid entry.
-    // 4) Reap() is called, which sends SIGKILL, but the pid no longer exists.
-    // TODO: sigaction for SIGCHLD reports the pid of the exiting process,
-    // we should do this kill with that pid first before calling waitpid().
-    if (kill(-pid_, signal) == -1 && errno != ESRCH) {
-        PLOG(ERROR) << "kill(" << pid_ << ", " << signal << ") failed";
-    }
-
     // If we've already seen a successful result from killProcessGroup*(), then we have removed
     // the cgroup already and calling these functions a second time will simply result in an error.
     // This is true regardless of which signal was sent.
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 31e4106..8cf9326 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -128,15 +128,7 @@
 void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_processes) {
     for (unsigned int i = process_num; i < uevent_queue_.size(); i += total_processes) {
         auto& uevent = uevent_queue_[i];
-        if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") {
-            device_handler_.FixupSysPermissions(uevent.path, uevent.subsystem);
-        }
-
-        if (uevent.subsystem == "block") {
-            device_handler_.HandleBlockDeviceEvent(uevent);
-        } else {
-            device_handler_.HandleGenericDeviceEvent(uevent);
-        }
+        device_handler_.HandleDeviceEvent(uevent);
     }
     _exit(EXIT_SUCCESS);
 }
@@ -145,14 +137,6 @@
     uevent_listener_.RegenerateUevents([this](const Uevent& uevent) {
         HandleFirmwareEvent(uevent);
 
-        // This is the one mutable part of DeviceHandler, in which platform devices are
-        // added to a vector for later reference.  Since there is no communication after
-        // fork()'ing subprocess handlers, all platform devices must be in the vector before
-        // we fork, and therefore they must be handled in this loop.
-        if (uevent.subsystem == "platform") {
-            device_handler_.HandlePlatformDeviceEvent(uevent);
-        }
-
         uevent_queue_.emplace_back(std::move(uevent));
         return RegenerationAction::kContinue;
     });
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index 3f47066..0792307 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -57,6 +57,12 @@
             return;
     }
 }
+
+void LogResponseError(const std::string& message, const FuseResponse& response) {
+    LOG(ERROR) << message << ": header.len=" << response.header.len
+               << " header.error=" << response.header.error
+               << " header.unique=" << response.header.unique;
+}
 }
 
 class FuseBridgeEntry {
@@ -135,6 +141,7 @@
         }
 
         if (!buffer_.response.Write(device_fd_)) {
+            LogResponseError("Failed to write a reply from proxy to device", buffer_.response);
             return FuseBridgeState::kClosing;
         }
 
@@ -200,6 +207,7 @@
         }
 
         if (!buffer_.response.Write(device_fd_)) {
+            LogResponseError("Failed to write a response to device", buffer_.response);
             return FuseBridgeState::kClosing;
         }
 
@@ -215,6 +223,11 @@
             case ResultOrAgain::kSuccess:
                 return FuseBridgeState::kWaitToReadEither;
             case ResultOrAgain::kFailure:
+                LOG(ERROR) << "Failed to write a request to proxy:"
+                           << " header.len=" << buffer_.request.header.len
+                           << " header.opcode=" << buffer_.request.header.opcode
+                           << " header.unique=" << buffer_.request.header.unique
+                           << " header.nodeid=" << buffer_.request.header.nodeid;
                 return FuseBridgeState::kClosing;
             case ResultOrAgain::kAgain:
                 return FuseBridgeState::kWaitToWriteProxy;
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index 653e96b..1b47e0a 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -115,7 +115,10 @@
                 case EAGAIN:
                     return ResultOrAgain::kAgain;
                 default:
-                    PLOG(ERROR) << "Failed to write a FUSE message";
+                    PLOG(ERROR) << "Failed to write a FUSE message: "
+                                << "fd=" << fd << " "
+                                << "sockflag=" << sockflag << " "
+                                << "data=" << data;
                     return ResultOrAgain::kFailure;
             }
         }
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index 4269eaa..cdac76b 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -23,7 +23,6 @@
 
 cc_library_shared {
     name: "libmemunreachable",
-    vendor_available: true,
     defaults: ["libmemunreachable_defaults"],
     srcs: [
         "Allocator.cpp",
diff --git a/libmemunreachable/MemUnreachable.cpp b/libmemunreachable/MemUnreachable.cpp
index e7c0beb..1c84744 100644
--- a/libmemunreachable/MemUnreachable.cpp
+++ b/libmemunreachable/MemUnreachable.cpp
@@ -502,7 +502,10 @@
 std::string GetUnreachableMemoryString(bool log_contents, size_t limit) {
   UnreachableMemoryInfo info;
   if (!GetUnreachableMemory(info, limit)) {
-    return "Failed to get unreachable memory\n";
+    return "Failed to get unreachable memory\n"
+           "If you are trying to get unreachable memory from a system app\n"
+           "(like com.android.systemui), disable selinux first using\n"
+           "setenforce 0\n";
   }
 
   return info.ToString(log_contents);
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 27b4065..f5d4e1c 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -27,10 +27,12 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include <chrono>
 #include <memory>
 #include <mutex>
+#include <set>
 #include <thread>
 
 #include <android-base/logging.h>
@@ -258,6 +260,12 @@
         return -errno;
     }
 
+    // We separate all of the pids in the cgroup into those pids that are also the leaders of
+    // process groups (stored in the pgids set) and those that are not (stored in the pids set).
+    std::set<pid_t> pgids;
+    pgids.emplace(initialPid);
+    std::set<pid_t> pids;
+
     int ret;
     pid_t pid;
     int processes = 0;
@@ -269,8 +277,40 @@
             LOG(WARNING) << "Yikes, we've been told to kill pid 0!  How about we don't do that?";
             continue;
         }
+        pid_t pgid = getpgid(pid);
+        if (pgid == -1) PLOG(ERROR) << "getpgid(" << pid << ") failed";
+        if (pgid == pid) {
+            pgids.emplace(pid);
+        } else {
+            pids.emplace(pid);
+        }
+    }
+
+    // Erase all pids that will be killed when we kill the process groups.
+    for (auto it = pids.begin(); it != pids.end();) {
+        pid_t pgid = getpgid(pid);
+        if (pgids.count(pgid) == 1) {
+            it = pids.erase(it);
+        } else {
+            ++it;
+        }
+    }
+
+    // Kill all process groups.
+    for (const auto pgid : pgids) {
+        LOG(VERBOSE) << "Killing process group " << -pgid << " in uid " << uid
+                     << " as part of process cgroup " << initialPid;
+
+        if (kill(-pgid, signal) == -1) {
+            PLOG(WARNING) << "kill(" << -pgid << ", " << signal << ") failed";
+        }
+    }
+
+    // Kill remaining pids.
+    for (const auto pid : pids) {
         LOG(VERBOSE) << "Killing pid " << pid << " in uid " << uid << " as part of process cgroup "
                      << initialPid;
+
         if (kill(pid, signal) == -1) {
             PLOG(WARNING) << "kill(" << pid << ", " << signal << ") failed";
         }
diff --git a/qemu_pipe/Android.bp b/qemu_pipe/Android.bp
new file mode 100644
index 0000000..93c347b
--- /dev/null
+++ b/qemu_pipe/Android.bp
@@ -0,0 +1,14 @@
+// Copyright 2011 The Android Open Source Project
+
+cc_library_static {
+    name: "libqemu_pipe",
+    vendor_available: true,
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    srcs: ["qemu_pipe.cpp"],
+    local_include_dirs: ["include"],
+    static_libs: ["libbase"],
+    export_include_dirs: ["include"],
+    cflags: ["-Werror"],
+}
diff --git a/qemu_pipe/Android.mk b/qemu_pipe/Android.mk
deleted file mode 100644
index 6e0144c..0000000
--- a/qemu_pipe/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2011 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-
-common_static_libraries := \
-    libbase
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-LOCAL_SRC_FILES:= \
-    qemu_pipe.cpp
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include \
-    system/base/include
-LOCAL_MODULE:= libqemu_pipe
-LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-include $(BUILD_STATIC_LIBRARY)
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 6db9acd..621b632 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -84,7 +84,7 @@
 namespace.rs.asan.permitted.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data
 
 namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = libc.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so:libvndksupport.so
+namespace.rs.link.default.shared_libs = libc.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libvndksupport.so
 namespace.rs.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libion.so:libutils.so:libc++.so:libz.so
 
 ###############################################################################
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 4f4fc5d..6d35fed 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -3,6 +3,7 @@
     required: [
         "bzip2",
         "grep",
+        "grep_vendor",
         "gzip",
         "mkshrc",
         "mkshrc_vendor",
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 1c9fb20..8db8327 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -28,8 +28,8 @@
 }
 
 // We build BSD grep separately, so it can provide egrep and fgrep too.
-cc_binary {
-    name: "grep",
+cc_defaults {
+    name: "grep_common",
     srcs: [
         "upstream-netbsd/usr.bin/grep/fastgrep.c",
         "upstream-netbsd/usr.bin/grep/file.c",
@@ -40,5 +40,19 @@
     cflags: common_cflags,
     local_include_dirs: ["upstream-netbsd/include/"],
     symlinks: ["egrep", "fgrep"],
+}
 
+cc_binary {
+    name: "grep",
+    defaults: ["grep_common"],
+}
+
+// Build vendor grep.
+// TODO: Add vendor_available to "grep" module and remove "grep_vendor" module
+//       when vendor_available is fully supported.
+cc_binary {
+    name: "grep_vendor",
+    stem: "grep",
+    vendor: true,
+    defaults: ["grep_common"],
 }