Merge "Move libz to vndk-sp"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 23f6580..a7706a0 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1140,6 +1140,7 @@
         if (should_use_libusb()) {
             features.insert(kFeatureLibusb);
         }
+        features.insert(kFeaturePushSync);
         SendOkay(reply_fd, FeatureSetToString(features));
         return 0;
     }
@@ -1241,10 +1242,7 @@
         return true;
     });
 
-    D("update_transport_status: transports_ready = %s", result ? "true" : "false");
-
     bool ready;
-
     {
         std::lock_guard<std::mutex> lock(init_mutex);
         transports_ready = result;
@@ -1252,14 +1250,11 @@
     }
 
     if (ready) {
-        D("update_transport_status: notifying");
         init_cv.notify_all();
     }
 }
 
 void adb_notify_device_scan_complete() {
-    D("device scan complete");
-
     {
         std::lock_guard<std::mutex> lock(init_mutex);
         device_scan_complete = true;
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index bd9ad01..62798cd 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -125,6 +125,11 @@
     });
 #endif
 
+    if (is_daemon) {
+        close_stdin();
+        setup_daemon_logging();
+    }
+
     android::base::at_quick_exit(adb_server_cleanup);
 
     init_transport_registration();
@@ -148,11 +153,6 @@
         std::this_thread::sleep_for(100ms);
     }
 
-    if (is_daemon) {
-        close_stdin();
-        setup_daemon_logging();
-    }
-
     adb_auth_init();
 
     if (is_daemon) {
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 18a8ff2..fc32469 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -151,10 +151,7 @@
 static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>();
 static auto& usb_handles_mutex = *new std::mutex();
 
-static std::thread* device_poll_thread = nullptr;
-static bool terminate_device_poll_thread = false;
-static auto& device_poll_mutex = *new std::mutex();
-static auto& device_poll_cv = *new std::condition_variable();
+static libusb_hotplug_callback_handle hotplug_handle;
 
 static std::string get_device_address(libusb_device* device) {
     return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
@@ -175,6 +172,17 @@
     path += "/serial";
     return path;
 }
+
+static std::string get_device_dev_path(libusb_device* device) {
+    uint8_t ports[7];
+    int port_count = libusb_get_port_numbers(device, ports, 7);
+    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) {
@@ -229,7 +237,7 @@
             // TODO: Is this assumption valid?
             LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address
                          << " (interface " << interface_num << ")";
-            return;
+            continue;
         }
 
         const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
@@ -237,7 +245,7 @@
                               interface_desc.bInterfaceProtocol)) {
             LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface "
                          << interface_num << ")";
-            return;
+            continue;
         }
 
         LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface "
@@ -253,7 +261,7 @@
             const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;
 
             if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
-                return;
+                continue;
             }
 
             if (endpoint_is_output(endpoint_addr) && !found_out) {
@@ -371,33 +379,62 @@
     }
 
     register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable);
-
     LOG(INFO) << "registered new usb device '" << device_serial << "'";
 }
 
-static void poll_for_devices() {
-    libusb_device** list;
-    adb_thread_setname("device poll");
-    while (true) {
-        const ssize_t device_count = libusb_get_device_list(nullptr, &list);
+static std::atomic<int> connecting_devices(0);
 
-        LOG(VERBOSE) << "found " << device_count << " attached devices";
-
-        for (ssize_t i = 0; i < device_count; ++i) {
-            process_device(list[i]);
+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.
+    ++connecting_devices;
+    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);
         }
 
-        libusb_free_device_list(list, 1);
+        process_device(device);
+        --connecting_devices;
+    });
+    thread.detach();
+#else
+    process_device(device);
+#endif
+}
 
-        adb_notify_device_scan_complete();
+static void device_disconnected(libusb_device* device) {
+    std::string device_address = get_device_address(device);
 
-        std::unique_lock<std::mutex> lock(device_poll_mutex);
-        if (device_poll_cv.wait_for(lock, 500ms, []() { return terminate_device_poll_thread; })) {
-            return;
+    LOG(INFO) << "device disconnected: " << device_address;
+    std::unique_lock<std::mutex> lock(usb_handles_mutex);
+    auto it = usb_handles.find(device_address);
+    if (it != usb_handles.end()) {
+        if (!it->second->device_handle) {
+            // If the handle is null, we were never able to open the device.
+            unregister_usb_transport(it->second.get());
         }
+        usb_handles.erase(it);
     }
 }
 
+static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event,
+                            void*) {
+    if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
+        device_connected(device);
+    } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
+        device_disconnected(device);
+    }
+    return 0;
+}
+
 void usb_init() {
     LOG(DEBUG) << "initializing libusb...";
     int rc = libusb_init(nullptr);
@@ -405,6 +442,24 @@
         LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc);
     }
 
+    // Register the hotplug callback.
+    rc = libusb_hotplug_register_callback(
+        nullptr, static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
+                                                   LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
+        LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
+        LIBUSB_CLASS_PER_INTERFACE, hotplug_callback, nullptr, &hotplug_handle);
+
+    if (rc != LIBUSB_SUCCESS) {
+        LOG(FATAL) << "failed to register libusb hotplug callback";
+    }
+
+    // Wait for all of the connecting devices to finish.
+    while (connecting_devices != 0) {
+        std::this_thread::sleep_for(10ms);
+    }
+
+    adb_notify_device_scan_complete();
+
     // Spawn a thread for libusb_handle_events.
     std::thread([]() {
         adb_thread_setname("libusb");
@@ -412,24 +467,10 @@
             libusb_handle_events(nullptr);
         }
     }).detach();
-
-    // Spawn a thread to do device enumeration.
-    // TODO: Use libusb_hotplug_* instead?
-    std::unique_lock<std::mutex> lock(device_poll_mutex);
-    device_poll_thread = new std::thread(poll_for_devices);
 }
 
 void usb_cleanup() {
-    {
-        std::unique_lock<std::mutex> lock(device_poll_mutex);
-        terminate_device_poll_thread = true;
-
-        if (!device_poll_thread) {
-            return;
-        }
-    }
-    device_poll_cv.notify_all();
-    device_poll_thread->join();
+    libusb_hotplug_deregister_callback(nullptr, hotplug_handle);
 }
 
 // Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index f49c69d..68ae4af 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -126,8 +126,9 @@
         " reverse --remove-all     remove all reverse socket connections from device\n"
         "\n"
         "file transfer:\n"
-        " push LOCAL... REMOTE\n"
+        " push [--sync] LOCAL... REMOTE\n"
         "     copy local files/directories to device\n"
+        "     --sync: only push files that are newer on the host than the device\n"
         " pull [-a] REMOTE... LOCAL\n"
         "     copy files/dirs from device\n"
         "     -a: preserve file timestamp and mode\n"
@@ -1233,9 +1234,8 @@
     return 0;
 }
 
-static void parse_push_pull_args(const char** arg, int narg,
-                                 std::vector<const char*>* srcs,
-                                 const char** dst, bool* copy_attrs) {
+static void parse_push_pull_args(const char** arg, int narg, std::vector<const char*>* srcs,
+                                 const char** dst, bool* copy_attrs, bool* sync) {
     *copy_attrs = false;
 
     srcs->clear();
@@ -1248,6 +1248,10 @@
                 // Silently ignore for backwards compatibility.
             } else if (!strcmp(*arg, "-a")) {
                 *copy_attrs = true;
+            } else if (!strcmp(*arg, "--sync")) {
+                if (sync != nullptr) {
+                    *sync = true;
+                }
             } else if (!strcmp(*arg, "--")) {
                 ignore_flags = true;
             } else {
@@ -1654,19 +1658,20 @@
     }
     else if (!strcmp(argv[0], "push")) {
         bool copy_attrs = false;
+        bool sync = false;
         std::vector<const char*> srcs;
         const char* dst = nullptr;
 
-        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
+        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, &sync);
         if (srcs.empty() || !dst) return syntax_error("push requires an argument");
-        return do_sync_push(srcs, dst) ? 0 : 1;
+        return do_sync_push(srcs, dst, sync) ? 0 : 1;
     }
     else if (!strcmp(argv[0], "pull")) {
         bool copy_attrs = false;
         std::vector<const char*> srcs;
         const char* dst = ".";
 
-        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
+        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, nullptr);
         if (srcs.empty()) return syntax_error("pull requires an argument");
         return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
     }
@@ -2086,7 +2091,7 @@
     std::vector<const char*> apk_file = {argv[last_apk]};
     std::string apk_dest = android::base::StringPrintf(
         where, android::base::Basename(argv[last_apk]).c_str());
-    if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
+    if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
     argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
     result = pm_command(transport, serial, argc, argv);
 
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 22bd2f2..2576fb1 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -674,11 +674,22 @@
     return true;
 }
 
-static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
-                      unsigned mtime, mode_t mode)
-{
+static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath, unsigned mtime,
+                      mode_t mode, bool sync) {
     std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
 
+    if (sync) {
+        struct stat st;
+        if (sync_lstat(sc, rpath, &st)) {
+            // For links, we cannot update the atime/mtime.
+            if ((S_ISREG(mode & st.st_mode) && st.st_mtime == static_cast<time_t>(mtime)) ||
+                (S_ISLNK(mode & st.st_mode) && st.st_mtime >= static_cast<time_t>(mtime))) {
+                sc.RecordFilesSkipped(1);
+                return true;
+            }
+        }
+    }
+
     if (S_ISLNK(mode)) {
 #if !defined(_WIN32)
         char buf[PATH_MAX];
@@ -902,7 +913,7 @@
             if (list_only) {
                 sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
             } else {
-                if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
+                if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode, false)) {
                     return false;
                 }
             }
@@ -916,7 +927,7 @@
     return true;
 }
 
-bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
+bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync) {
     SyncConnection sc;
     if (!sc.IsValid()) return false;
 
@@ -981,7 +992,7 @@
                 dst_dir.append(android::base::Basename(src_path));
             }
 
-            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), false, false);
+            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), sync, false);
             continue;
         } else if (!should_push_file(st.st_mode)) {
             sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
@@ -1002,7 +1013,7 @@
 
         sc.NewTransfer();
         sc.SetExpectedTotalBytes(st.st_size);
-        success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
+        success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync);
         sc.ReportTransferRate(src_path, TransferDirection::push);
     }
 
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 90f1965..6606efd 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -81,7 +81,7 @@
 
 void file_sync_service(int fd, void* cookie);
 bool do_sync_ls(const char* path);
-bool do_sync_push(const std::vector<const char*>& srcs, const char* dst);
+bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync);
 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
                   bool copy_attrs, const char* name=nullptr);
 
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index b2b1c18..253d14a 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -139,25 +139,36 @@
     bool any_changed = false;
 
     bool enable = (cookie != NULL);
-    if (!kAllowDisableVerity) {
-        WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
-                   enable ? "enable" : "disable");
+
+    // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
+    // contract, androidboot.vbmeta.digest is set by the bootloader
+    // when using AVB).
+    bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
+
+    // If using AVB, dm-verity is used on any build so we want it to
+    // be possible to disable/enable on any build (except USER). For
+    // VB1.0 dm-verity is only enabled on certain builds.
+    if (!using_avb) {
+        if (!kAllowDisableVerity) {
+            WriteFdFmt(fd, "%s-verity only works for userdebug builds\n",
+                       enable ? "enable" : "disable");
+        }
+
+        if (!android::base::GetBoolProperty("ro.secure", false)) {
+            WriteFdFmt(fd, "verity not enabled - ENG build\n");
+            return;
+        }
     }
 
-    if (!android::base::GetBoolProperty("ro.secure", false)) {
-        WriteFdFmt(fd, "verity not enabled - ENG build\n");
-        return;
-    }
+    // Should never be possible to disable dm-verity on a USER build
+    // regardless of using AVB or VB1.0.
     if (!__android_log_is_debuggable()) {
         WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n");
         return;
     }
 
-    // Figure out if we're using VB1.0 or VB2.0 (aka AVB).
-    std::string vbmeta_hash = android::base::GetProperty("ro.boot.vbmeta.digest", "");
-    if (vbmeta_hash != "") {
-        // Yep, the system is using AVB (by contract, androidboot.vbmeta.hash is
-        // set by the bootloader when using AVB).
+    if (using_avb) {
+        // Yep, the system is using AVB.
         AvbOps* ops = avb_ops_user_new();
         if (ops == nullptr) {
             WriteFdFmt(fd, "Error getting AVB ops\n");
diff --git a/adb/test_device.py b/adb/test_device.py
index e44cc83..737d0c2 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -1130,8 +1130,18 @@
             if host_dir is not None:
                 shutil.rmtree(host_dir)
 
+    def verify_sync(self, device, temp_files, device_dir):
+        """Verifies that a list of temp files was synced to the device."""
+        # Confirm that every file on the device mirrors that on the host.
+        for temp_file in temp_files:
+            device_full_path = posixpath.join(
+                device_dir, temp_file.base_name)
+            dev_md5, _ = device.shell(
+                [get_md5_prog(self.device), device_full_path])[0].split()
+            self.assertEqual(temp_file.checksum, dev_md5)
+
     def test_sync(self):
-        """Sync a randomly generated directory of files to specified device."""
+        """Sync a host directory to the data partition."""
 
         try:
             base_dir = tempfile.mkdtemp()
@@ -1141,27 +1151,50 @@
             os.makedirs(full_dir_path)
 
             # Create 32 random files within the host mirror.
-            temp_files = make_random_host_files(in_dir=full_dir_path, num_files=32)
+            temp_files = make_random_host_files(
+                in_dir=full_dir_path, num_files=32)
 
-            # Clean up any trash on the device.
-            device = adb.get_device(product=base_dir)
+            # Clean up any stale files on the device.
+            device = adb.get_device()  # pylint: disable=no-member
             device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
 
+            old_product_out = os.environ.get('ANDROID_PRODUCT_OUT')
+            os.environ['ANDROID_PRODUCT_OUT'] = base_dir
             device.sync('data')
+            if old_product_out is None:
+                del os.environ['ANDROID_PRODUCT_OUT']
+            else:
+                os.environ['ANDROID_PRODUCT_OUT'] = old_product_out
 
-            # Confirm that every file on the device mirrors that on the host.
-            for temp_file in temp_files:
-                device_full_path = posixpath.join(self.DEVICE_TEMP_DIR,
-                                                  temp_file.base_name)
-                dev_md5, _ = device.shell(
-                    [get_md5_prog(self.device), device_full_path])[0].split()
-                self.assertEqual(temp_file.checksum, dev_md5)
+            self.verify_sync(device, temp_files, self.DEVICE_TEMP_DIR)
 
-            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+            #self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
         finally:
             if base_dir is not None:
                 shutil.rmtree(base_dir)
 
+    def test_push_sync(self):
+        """Sync a host directory to a specific path."""
+
+        try:
+            temp_dir = tempfile.mkdtemp()
+            temp_files = make_random_host_files(in_dir=temp_dir, num_files=32)
+
+            device_dir = posixpath.join(self.DEVICE_TEMP_DIR, 'sync_src_dst')
+
+            # Clean up any stale files on the device.
+            device = adb.get_device()  # pylint: disable=no-member
+            device.shell(['rm', '-rf', device_dir])
+
+            device.push(temp_dir, device_dir, sync=True)
+
+            self.verify_sync(device, temp_files, device_dir)
+
+            self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
+        finally:
+            if temp_dir is not None:
+                shutil.rmtree(temp_dir)
+
     def test_unicode_paths(self):
         """Ensure that we can support non-ASCII paths, even on Windows."""
         name = u'로보카 폴리'
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 13cfaa1..308ee8d 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -55,6 +55,7 @@
 const char* const kFeatureCmd = "cmd";
 const char* const kFeatureStat2 = "stat_v2";
 const char* const kFeatureLibusb = "libusb";
+const char* const kFeaturePushSync = "push_sync";
 
 static std::string dump_packet(const char* name, const char* func, apacket* p) {
     unsigned command = p->msg.command;
@@ -1050,27 +1051,24 @@
         [usb](atransport* t) { return t->usb == usb && t->GetConnectionState() == kCsNoPerm; });
 }
 
-int check_header(apacket* p, atransport* t) {
+bool check_header(apacket* p, atransport* t) {
     if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
         VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
                   << ", magic = " << p->msg.magic;
-        return -1;
+        return false;
     }
 
     if (p->msg.data_length > t->get_max_payload()) {
         VLOG(RWX) << "check_header(): " << p->msg.data_length
                   << " atransport::max_payload = " << t->get_max_payload();
-        return -1;
+        return false;
     }
 
-    return 0;
+    return true;
 }
 
-int check_data(apacket* p) {
-    if (calculate_apacket_checksum(p) != p->msg.data_check) {
-        return -1;
-    }
-    return 0;
+bool check_data(apacket* p) {
+    return calculate_apacket_checksum(p) == p->msg.data_check;
 }
 
 #if ADB_HOST
diff --git a/adb/transport.h b/adb/transport.h
index 006aaf4..57fc988 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -51,6 +51,8 @@
 extern const char* const kFeatureStat2;
 // The server is running with libusb enabled.
 extern const char* const kFeatureLibusb;
+// The server supports `push --sync`.
+extern const char* const kFeaturePushSync;
 
 class atransport {
 public:
@@ -221,8 +223,8 @@
 // This should only be used for transports with connection_state == kCsNoPerm.
 void unregister_usb_transport(usb_handle* usb);
 
-int check_header(apacket* p, atransport* t);
-int check_data(apacket* p);
+bool check_header(apacket* p, atransport* t);
+bool check_data(apacket* p);
 
 void close_usb_devices();
 void close_usb_devices(std::function<bool(const atransport*)> predicate);
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index e5992b1..809ed89 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -62,22 +62,22 @@
 
 static int remote_read(apacket *p, atransport *t)
 {
-    if(!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))){
+    if (!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))) {
         D("remote local: read terminated (message)");
         return -1;
     }
 
-    if(check_header(p, t)) {
+    if (!check_header(p, t)) {
         D("bad header: terminated (data)");
         return -1;
     }
 
-    if(!ReadFdExactly(t->sfd, p->data, p->msg.data_length)){
+    if (!ReadFdExactly(t->sfd, p->data, p->msg.data_length)) {
         D("remote local: terminated (data)");
         return -1;
     }
 
-    if(check_data(p)) {
+    if (!check_data(p)) {
         D("bad data: terminated (data)");
         return -1;
     }
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 885d723..47094b8 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -72,7 +72,7 @@
         D("remote usb: read terminated (message)");
         return -1;
     }
-    if (static_cast<size_t>(n) != sizeof(p->msg) || check_header(p, t)) {
+    if (static_cast<size_t>(n) != sizeof(p->msg) || !check_header(p, t)) {
         D("remote usb: check_header failed, skip it");
         goto err_msg;
     }
@@ -95,7 +95,7 @@
             goto err_msg;
         }
     }
-    if (check_data(p)) {
+    if (!check_data(p)) {
         D("remote usb: check_data failed, skip it");
         goto err_msg;
     }
@@ -124,19 +124,19 @@
         return -1;
     }
 
-    if(check_header(p, t)) {
+    if (!check_header(p, t)) {
         D("remote usb: check_header failed");
         return -1;
     }
 
-    if(p->msg.data_length) {
+    if (p->msg.data_length) {
         if (usb_read(t->usb, p->data, p->msg.data_length)) {
             D("remote usb: terminated (data)");
             return -1;
         }
     }
 
-    if(check_data(p)) {
+    if (!check_data(p)) {
         D("remote usb: check_data failed");
         return -1;
     }
diff --git a/base/Android.bp b/base/Android.bp
index 81b96db..b636dc3 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -53,7 +53,6 @@
 
     header_libs: [
         "libbase_headers",
-        "libutils_headers",
     ],
     export_header_lib_headers: ["libbase_headers"],
 
diff --git a/base/file.cpp b/base/file.cpp
index 7fbebc5..a2f2887 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -32,13 +32,14 @@
 #include "android-base/macros.h"  // For TEMP_FAILURE_RETRY on Darwin.
 #include "android-base/unique_fd.h"
 #include "android-base/utf8.h"
-#include "utils/Compat.h"
 
 #if defined(__APPLE__)
 #include <mach-o/dyld.h>
 #endif
 #if defined(_WIN32)
 #include <windows.h>
+#define O_CLOEXEC O_NOINHERIT
+#define O_NOFOLLOW 0
 #endif
 
 namespace android {
@@ -133,7 +134,7 @@
                        bool follow_symlinks) {
   int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY |
               (follow_symlinks ? 0 : O_NOFOLLOW);
-  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE)));
+  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, 0666)));
   if (fd == -1) {
     return false;
   }
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 6f25d96..d4e215e 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -221,19 +221,24 @@
   }
 }
 
-// Parses and records the set of bootloader stages and associated boot times
-// from the ro.boot.boottime system property.
-void RecordBootloaderTimings(BootEventRecordStore* boot_event_store) {
-  // |ro.boot.boottime| is of the form 'stage1:time1,...,stageN:timeN'.
+// A map from bootloader timing stage to the time that stage took during boot.
+typedef std::map<std::string, int32_t> BootloaderTimingMap;
+
+// Returns a mapping from bootloader stage names to the time those stages
+// took to boot.
+const BootloaderTimingMap GetBootLoaderTimings() {
+  BootloaderTimingMap timings;
+
+  // |ro.boot.boottime| is of the form 'stage1:time1,...,stageN:timeN',
+  // where timeN is in milliseconds.
   std::string value = GetProperty("ro.boot.boottime");
   if (value.empty()) {
     // ro.boot.boottime is not reported on all devices.
-    return;
+    return BootloaderTimingMap();
   }
 
-  int32_t total_time = 0;
   auto stages = android::base::Split(value, ",");
-  for (auto const &stageTiming : stages) {
+  for (const auto& stageTiming : stages) {
     // |stageTiming| is of the form 'stage:time'.
     auto stageTimingValues = android::base::Split(stageTiming, ":");
     DCHECK_EQ(2, stageTimingValues.size());
@@ -241,23 +246,53 @@
     std::string stageName = stageTimingValues[0];
     int32_t time_ms;
     if (android::base::ParseInt(stageTimingValues[1], &time_ms)) {
-      total_time += time_ms;
-      boot_event_store->AddBootEventWithValue(
-          "boottime.bootloader." + stageName, time_ms);
+      timings[stageName] = time_ms;
     }
   }
 
+  return timings;
+}
+
+// Parses and records the set of bootloader stages and associated boot times
+// from the ro.boot.boottime system property.
+void RecordBootloaderTimings(BootEventRecordStore* boot_event_store,
+                             const BootloaderTimingMap& bootloader_timings) {
+  int32_t total_time = 0;
+  for (const auto& timing : bootloader_timings) {
+    total_time += timing.second;
+    boot_event_store->AddBootEventWithValue("boottime.bootloader." + timing.first, timing.second);
+  }
+
   boot_event_store->AddBootEventWithValue("boottime.bootloader.total", total_time);
 }
 
+// Records the closest estimation to the absolute device boot time, i.e.,
+// from power on to boot_complete, including bootloader times.
+void RecordAbsoluteBootTime(BootEventRecordStore* boot_event_store,
+                            const BootloaderTimingMap& bootloader_timings,
+                            std::chrono::milliseconds uptime) {
+  int32_t bootloader_time_ms = 0;
+
+  for (const auto& timing : bootloader_timings) {
+    if (timing.first.compare("SW") != 0) {
+      bootloader_time_ms += timing.second;
+    }
+  }
+
+  auto bootloader_duration = std::chrono::milliseconds(bootloader_time_ms);
+  auto absolute_total =
+      std::chrono::duration_cast<std::chrono::seconds>(bootloader_duration + uptime);
+  boot_event_store->AddBootEventWithValue("absolute_boot_time", absolute_total.count());
+}
+
 // Records several metrics related to the time it takes to boot the device,
 // including disambiguating boot time on encrypted or non-encrypted devices.
 void RecordBootComplete() {
   BootEventRecordStore boot_event_store;
   BootEventRecordStore::BootEventRecord record;
 
-  auto uptime = std::chrono::duration_cast<std::chrono::seconds>(
-      android::base::boot_clock::now().time_since_epoch());
+  auto time_since_epoch = android::base::boot_clock::now().time_since_epoch();
+  auto uptime = std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch);
   time_t current_time_utc = time(nullptr);
 
   if (boot_event_store.GetBootEvent("last_boot_time_utc", &record)) {
@@ -290,7 +325,6 @@
     std::chrono::seconds boot_complete = std::chrono::seconds(uptime.count() - record.second);
     boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt",
                                            boot_complete.count());
-
   } else {
       boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
                                              uptime.count());
@@ -304,7 +338,11 @@
   RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.selinux");
   RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.cold_boot_wait");
 
-  RecordBootloaderTimings(&boot_event_store);
+  const BootloaderTimingMap bootloader_timings = GetBootLoaderTimings();
+  RecordBootloaderTimings(&boot_event_store, bootloader_timings);
+
+  auto uptime_ms = std::chrono::duration_cast<std::chrono::milliseconds>(time_since_epoch);
+  RecordAbsoluteBootTime(&boot_event_store, bootloader_timings, uptime_ms);
 }
 
 // Records the boot_reason metric by querying the ro.boot.bootreason system
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 37d54d7..3a80b50 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -11,12 +11,32 @@
     local_include_dirs: ["include"],
 }
 
-// Utility library to tombstoned and get an output fd.
-cc_library_static {
+cc_library_shared {
     name: "libtombstoned_client",
     defaults: ["debuggerd_defaults"],
     srcs: [
-        "tombstoned_client.cpp",
+        "tombstoned/tombstoned_client.cpp",
+        "util.cpp",
+    ],
+
+    static_libs: [
+        "libasync_safe"
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "libbase",
+    ],
+
+    export_include_dirs: ["tombstoned/include"]
+}
+
+// Utility library to tombstoned and get an output fd.
+cc_library_static {
+    name: "libtombstoned_client_static",
+    defaults: ["debuggerd_defaults"],
+    srcs: [
+        "tombstoned/tombstoned_client.cpp",
         "util.cpp",
     ],
 
@@ -25,6 +45,8 @@
         "libcutils",
         "libbase",
     ],
+
+    export_include_dirs: ["tombstoned/include"]
 }
 
 // Core implementation, linked into libdebuggerd_handler and the dynamic linker.
@@ -64,7 +86,7 @@
 
     whole_static_libs: [
         "libdebuggerd_handler_core",
-        "libtombstoned_client",
+        "libtombstoned_client_static",
         "libasync_safe",
         "libbase",
         "libdebuggerd",
@@ -159,10 +181,8 @@
             srcs: [
                 "client/debuggerd_client_test.cpp",
                 "debuggerd_test.cpp",
-                "tombstoned_client.cpp",
-                "util.cpp"
             ],
-            static_libs: ["libasync_safe"],
+            static_libs: ["libasync_safe", "libtombstoned_client_static"],
         },
     },
 
@@ -171,6 +191,7 @@
         "libbase",
         "libcutils",
         "libdebuggerd_client",
+        "liblog"
     ],
 
     static_libs: [
@@ -211,7 +232,7 @@
     },
 
     static_libs: [
-        "libtombstoned_client",
+        "libtombstoned_client_static",
         "libdebuggerd",
         "libcutils",
     ],
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 2be13c6..4ce038c 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -31,9 +31,10 @@
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
-#include <debuggerd/handler.h>
-#include <debuggerd/protocol.h>
-#include <debuggerd/util.h>
+
+#include "debuggerd/handler.h"
+#include "protocol.h"
+#include "util.h"
 
 using namespace std::chrono_literals;
 
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index aff03e5..8f97db1 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -31,7 +31,7 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 
-#include <debuggerd/util.h>
+#include "util.h"
 
 using namespace std::chrono_literals;
 using android::base::unique_fd;
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index d2a4239..be28079 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -48,9 +48,9 @@
 #include "utility.h"
 
 #include "debuggerd/handler.h"
-#include "debuggerd/protocol.h"
-#include "debuggerd/tombstoned.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "tombstoned/tombstoned.h"
+#include "util.h"
 
 using android::base::unique_fd;
 using android::base::ReadFileToString;
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 492e9f0..4997dd6 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -27,8 +27,8 @@
 #include <android-base/parseint.h>
 #include <android-base/unique_fd.h>
 #include <debuggerd/client.h>
-#include <debuggerd/util.h>
 #include <selinux/selinux.h>
+#include "util.h"
 
 using android::base::unique_fd;
 
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 0b4bbfb..f17724a 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -35,12 +35,13 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
-#include <debuggerd/handler.h>
-#include <debuggerd/protocol.h>
-#include <debuggerd/tombstoned.h>
-#include <debuggerd/util.h>
 #include <gtest/gtest.h>
 
+#include "debuggerd/handler.h"
+#include "protocol.h"
+#include "tombstoned/tombstoned.h"
+#include "util.h"
+
 using namespace std::chrono_literals;
 using android::base::unique_fd;
 
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 47c98d1..a9c9862 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -42,8 +42,8 @@
 #include <async_safe/log.h>
 
 #include "debuggerd/handler.h"
-#include "debuggerd/tombstoned.h"
-#include "debuggerd/util.h"
+#include "tombstoned/tombstoned.h"
+#include "util.h"
 
 #include "backtrace.h"
 #include "tombstone.h"
diff --git a/debuggerd/include/debuggerd/protocol.h b/debuggerd/protocol.h
similarity index 96%
rename from debuggerd/include/debuggerd/protocol.h
rename to debuggerd/protocol.h
index 0756876..144efc8 100644
--- a/debuggerd/include/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -21,6 +21,7 @@
 // Sockets in the ANDROID_SOCKET_NAMESPACE_RESERVED namespace.
 // Both sockets are SOCK_SEQPACKET sockets, so no explicit length field is needed.
 constexpr char kTombstonedCrashSocketName[] = "tombstoned_crash";
+constexpr char kTombstonedJavaTraceSocketName[] = "tombstoned_java_trace";
 constexpr char kTombstonedInterceptSocketName[] = "tombstoned_intercept";
 
 enum class CrashPacketType : uint8_t {
diff --git a/debuggerd/include/debuggerd/tombstoned.h b/debuggerd/tombstoned/include/tombstoned/tombstoned.h
similarity index 89%
rename from debuggerd/include/debuggerd/tombstoned.h
rename to debuggerd/tombstoned/include/tombstoned/tombstoned.h
index d158d50..908517d 100644
--- a/debuggerd/include/debuggerd/tombstoned.h
+++ b/debuggerd/tombstoned/include/tombstoned/tombstoned.h
@@ -21,6 +21,6 @@
 #include <android-base/unique_fd.h>
 
 bool tombstoned_connect(pid_t pid, android::base::unique_fd* tombstoned_socket,
-                        android::base::unique_fd* output_fd);
+                        android::base::unique_fd* output_fd, bool is_native_crash = true);
 
 bool tombstoned_notify_completion(int tombstoned_socket);
diff --git a/debuggerd/tombstoned/intercept_manager.cpp b/debuggerd/tombstoned/intercept_manager.cpp
index dff942c..4d4eb9e 100644
--- a/debuggerd/tombstoned/intercept_manager.cpp
+++ b/debuggerd/tombstoned/intercept_manager.cpp
@@ -28,8 +28,8 @@
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
 
-#include "debuggerd/protocol.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "util.h"
 
 using android::base::unique_fd;
 
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 2248a21..05df9f2 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -35,8 +35,8 @@
 #include <cutils/sockets.h>
 
 #include "debuggerd/handler.h"
-#include "debuggerd/protocol.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "util.h"
 
 #include "intercept_manager.h"
 
@@ -50,86 +50,154 @@
   kCrashStatusQueued,
 };
 
+struct Crash;
+
+class CrashType {
+ public:
+  CrashType(const std::string& dir_path, const std::string& file_name_prefix, size_t max_artifacts,
+            size_t max_concurrent_dumps)
+      : file_name_prefix_(file_name_prefix),
+        dir_path_(dir_path),
+        dir_fd_(open(dir_path.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC)),
+        max_artifacts_(max_artifacts),
+        next_artifact_(0),
+        max_concurrent_dumps_(max_concurrent_dumps),
+        num_concurrent_dumps_(0) {
+    if (dir_fd_ == -1) {
+      PLOG(FATAL) << "failed to open directory: " << dir_path;
+    }
+
+    // NOTE: If max_artifacts_ <= max_concurrent_dumps_, then theoretically the
+    // same filename could be handed out to multiple processes.
+    CHECK(max_artifacts_ > max_concurrent_dumps_);
+
+    find_oldest_artifact();
+  }
+
+  unique_fd get_output_fd() {
+    unique_fd result;
+    char buf[PATH_MAX];
+    snprintf(buf, sizeof(buf), "%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;
+    }
+
+    result.reset(openat(dir_fd_, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
+    if (result == -1) {
+      PLOG(FATAL) << "failed to create tombstone at " << dir_path_ << buf;
+    }
+
+    next_artifact_ = (next_artifact_ + 1) % max_artifacts_;
+    return result;
+  }
+
+  bool maybe_enqueue_crash(Crash* crash) {
+    if (num_concurrent_dumps_ == max_concurrent_dumps_) {
+      queued_requests_.push_back(crash);
+      return true;
+    }
+
+    return false;
+  }
+
+  void maybe_dequeue_crashes(void (*handler)(Crash* crash)) {
+    while (!queued_requests_.empty() && num_concurrent_dumps_ < max_concurrent_dumps_) {
+      Crash* next_crash = queued_requests_.front();
+      queued_requests_.pop_front();
+      handler(next_crash);
+    }
+  }
+
+  void on_crash_started() { ++num_concurrent_dumps_; }
+
+  void on_crash_completed() { --num_concurrent_dumps_; }
+
+  static CrashType* const tombstone;
+  static CrashType* const java_trace;
+
+ private:
+  void find_oldest_artifact() {
+    size_t oldest_tombstone = 0;
+    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);
+      struct stat st;
+      if (stat(path.c_str(), &st) != 0) {
+        if (errno == ENOENT) {
+          oldest_tombstone = i;
+          break;
+        } else {
+          PLOG(ERROR) << "failed to stat " << path;
+          continue;
+        }
+      }
+
+      if (st.st_mtime < oldest_time) {
+        oldest_tombstone = i;
+        oldest_time = st.st_mtime;
+      }
+    }
+
+    next_artifact_ = oldest_tombstone;
+  }
+
+  const std::string file_name_prefix_;
+
+  const std::string dir_path_;
+  const int dir_fd_;
+
+  const size_t max_artifacts_;
+  int next_artifact_;
+
+  const size_t max_concurrent_dumps_;
+  size_t num_concurrent_dumps_;
+
+  std::deque<Crash*> queued_requests_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrashType);
+};
+
+// Whether java trace dumps are produced via tombstoned.
+static constexpr bool kJavaTraceDumpsEnabled = false;
+
+/* static */ CrashType* const CrashType::tombstone =
+    new CrashType("/data/tombstones", "tombstone_" /* file_name_prefix */, 10 /* max_artifacts */,
+                  1 /* max_concurrent_dumps */);
+
+/* static */ CrashType* const CrashType::java_trace =
+    (kJavaTraceDumpsEnabled ? new CrashType("/data/anr", "anr_" /* file_name_prefix */,
+                                            64 /* max_artifacts */, 4 /* max_concurrent_dumps */)
+                            : nullptr);
+
 // Ownership of Crash is a bit messy.
 // It's either owned by an active event that must have a timeout, or owned by
 // queued_requests, in the case that multiple crashes come in at the same time.
 struct Crash {
-  ~Crash() {
-    event_free(crash_event);
-  }
+  ~Crash() { event_free(crash_event); }
 
   unique_fd crash_fd;
   pid_t crash_pid;
   event* crash_event = nullptr;
+
+  // Not owned by |Crash|.
+  CrashType* crash_type = nullptr;
 };
 
-static constexpr char kTombstoneDirectory[] = "/data/tombstones/";
-static constexpr size_t kTombstoneCount = 10;
-static int tombstone_directory_fd = -1;
-static int next_tombstone = 0;
-
-static constexpr size_t kMaxConcurrentDumps = 1;
-static size_t num_concurrent_dumps = 0;
-
-static std::deque<Crash*> queued_requests;
-
 // Forward declare the callbacks so they can be placed in a sensible order.
 static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*);
 static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg);
 static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg);
 
-static void find_oldest_tombstone() {
-  size_t oldest_tombstone = 0;
-  time_t oldest_time = std::numeric_limits<time_t>::max();
-
-  for (size_t i = 0; i < kTombstoneCount; ++i) {
-    std::string path = android::base::StringPrintf("%stombstone_%02zu", kTombstoneDirectory, i);
-    struct stat st;
-    if (stat(path.c_str(), &st) != 0) {
-      if (errno == ENOENT) {
-        oldest_tombstone = i;
-        break;
-      } else {
-        PLOG(ERROR) << "failed to stat " << path;
-        continue;
-      }
-    }
-
-    if (st.st_mtime < oldest_time) {
-      oldest_tombstone = i;
-      oldest_time = st.st_mtime;
-    }
-  }
-
-  next_tombstone = oldest_tombstone;
-}
-
-static unique_fd get_tombstone_fd() {
-  // If kMaxConcurrentDumps is greater than 1, then theoretically the same
-  // filename could be handed out to multiple processes. Unlink and create the
-  // file, instead of using O_TRUNC, to avoid two processes interleaving their
-  // output.
-  unique_fd result;
-  char buf[PATH_MAX];
-  snprintf(buf, sizeof(buf), "tombstone_%02d", next_tombstone);
-  if (unlinkat(tombstone_directory_fd, buf, 0) != 0 && errno != ENOENT) {
-    PLOG(FATAL) << "failed to unlink tombstone at " << kTombstoneDirectory << buf;
-  }
-
-  result.reset(
-    openat(tombstone_directory_fd, buf, O_CREAT | O_EXCL | O_WRONLY | O_APPEND | O_CLOEXEC, 0640));
-  if (result == -1) {
-    PLOG(FATAL) << "failed to create tombstone at " << kTombstoneDirectory << buf;
-  }
-
-  next_tombstone = (next_tombstone + 1) % kTombstoneCount;
-  return result;
-}
-
 static void perform_request(Crash* crash) {
   unique_fd output_fd;
-  if (!intercept_manager->GetIntercept(crash->crash_pid, &output_fd)) {
-    output_fd = get_tombstone_fd();
+  // Note that java traces are not interceptible.
+  if ((crash->crash_type == CrashType::java_trace) ||
+      !intercept_manager->GetIntercept(crash->crash_pid, &output_fd)) {
+    output_fd = crash->crash_type->get_output_fd();
   }
 
   TombstonedCrashPacket response = {
@@ -152,23 +220,15 @@
     event_add(crash->crash_event, &timeout);
   }
 
-  ++num_concurrent_dumps;
+  crash->crash_type->on_crash_started();
   return;
 
 fail:
   delete crash;
 }
 
-static void dequeue_requests() {
-  while (!queued_requests.empty() && num_concurrent_dumps < kMaxConcurrentDumps) {
-    Crash* next_crash = queued_requests.front();
-    queued_requests.pop_front();
-    perform_request(next_crash);
-  }
-}
-
 static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int,
-                            void*) {
+                            void* crash_type) {
   event_base* base = evconnlistener_get_base(listener);
   Crash* crash = new Crash();
 
@@ -176,12 +236,15 @@
   event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
   crash->crash_fd.reset(sockfd);
   crash->crash_event = crash_event;
+  crash->crash_type = static_cast<CrashType*>(crash_type);
   event_add(crash_event, &timeout);
 }
 
 static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
   ssize_t rc;
   Crash* crash = static_cast<Crash*>(arg);
+  CrashType* type = crash->crash_type;
+
   TombstonedCrashPacket request = {};
 
   if ((ev & EV_TIMEOUT) != 0) {
@@ -208,12 +271,27 @@
     goto fail;
   }
 
-  crash->crash_pid = request.packet.dump_request.pid;
+  if (type == CrashType::tombstone) {
+    crash->crash_pid = request.packet.dump_request.pid;
+  } else {
+    // Requests for java traces are sent from untrusted processes, so we
+    // must not trust the PID sent down with the request. Instead, we ask the
+    // kernel.
+    ucred cr = {};
+    socklen_t len = sizeof(cr);
+    int ret = getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
+    if (ret != 0) {
+      PLOG(ERROR) << "Failed to getsockopt(..SO_PEERCRED)";
+      goto fail;
+    }
+
+    crash->crash_pid = cr.pid;
+  }
+
   LOG(INFO) << "received crash request for pid " << crash->crash_pid;
 
-  if (num_concurrent_dumps == kMaxConcurrentDumps) {
+  if (type->maybe_enqueue_crash(crash)) {
     LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
-    queued_requests.push_back(crash);
   } else {
     perform_request(crash);
   }
@@ -229,7 +307,7 @@
   Crash* crash = static_cast<Crash*>(arg);
   TombstonedCrashPacket request = {};
 
-  --num_concurrent_dumps;
+  crash->crash_type->on_crash_completed();
 
   if ((ev & EV_READ) == 0) {
     goto fail;
@@ -252,10 +330,11 @@
   }
 
 fail:
+  CrashType* type = crash->crash_type;
   delete crash;
 
   // If there's something queued up, let them proceed.
-  dequeue_requests();
+  type->maybe_dequeue_crashes(perform_request);
 }
 
 int main(int, char* []) {
@@ -269,13 +348,6 @@
   };
   debuggerd_register_handlers(&action);
 
-  tombstone_directory_fd = open(kTombstoneDirectory, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
-  if (tombstone_directory_fd == -1) {
-    PLOG(FATAL) << "failed to open tombstone directory";
-  }
-
-  find_oldest_tombstone();
-
   int intercept_socket = android_get_control_socket(kTombstonedInterceptSocketName);
   int crash_socket = android_get_control_socket(kTombstonedCrashSocketName);
 
@@ -293,10 +365,24 @@
 
   intercept_manager = new InterceptManager(base, intercept_socket);
 
-  evconnlistener* listener =
-    evconnlistener_new(base, crash_accept_cb, nullptr, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
-  if (!listener) {
-    LOG(FATAL) << "failed to create evconnlistener";
+  evconnlistener* tombstone_listener = evconnlistener_new(
+      base, crash_accept_cb, CrashType::tombstone, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
+  if (!tombstone_listener) {
+    LOG(FATAL) << "failed to create evconnlistener for tombstones.";
+  }
+
+  if (kJavaTraceDumpsEnabled) {
+    const int java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName);
+    if (java_trace_socket == -1) {
+      PLOG(FATAL) << "failed to get socket from init";
+    }
+
+    evutil_make_socket_nonblocking(java_trace_socket);
+    evconnlistener* java_trace_listener = evconnlistener_new(
+        base, crash_accept_cb, CrashType::java_trace, -1, LEV_OPT_CLOSE_ON_FREE, java_trace_socket);
+    if (!java_trace_listener) {
+      LOG(FATAL) << "failed to create evconnlistener for java traces.";
+    }
   }
 
   LOG(INFO) << "tombstoned successfully initialized";
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc
index b8345ca..53ef01c 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -7,4 +7,5 @@
 
     socket tombstoned_crash seqpacket 0666 system system
     socket tombstoned_intercept seqpacket 0666 system system
+    socket tombstoned_java_trace seqpacket 0666 system system
     writepid /dev/cpuset/system-background/tasks
diff --git a/debuggerd/tombstoned_client.cpp b/debuggerd/tombstoned/tombstoned_client.cpp
similarity index 89%
rename from debuggerd/tombstoned_client.cpp
rename to debuggerd/tombstoned/tombstoned_client.cpp
index 4741fa6..39dc6eb 100644
--- a/debuggerd/tombstoned_client.cpp
+++ b/debuggerd/tombstoned/tombstoned_client.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "debuggerd/tombstoned.h"
+#include "tombstoned/tombstoned.h"
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -25,14 +25,16 @@
 #include <async_safe/log.h>
 #include <cutils/sockets.h>
 
-#include "debuggerd/protocol.h"
-#include "debuggerd/util.h"
+#include "protocol.h"
+#include "util.h"
 
 using android::base::unique_fd;
 
-bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd) {
-  unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName,
-                                       ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
+bool tombstoned_connect(pid_t pid, unique_fd* tombstoned_socket, unique_fd* output_fd,
+                        bool is_native_crash) {
+  unique_fd sockfd(socket_local_client(
+      (is_native_crash ? kTombstonedCrashSocketName : kTombstonedJavaTraceSocketName),
+      ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
   if (sockfd == -1) {
     async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to connect to tombstoned: %s",
                           strerror(errno));
diff --git a/debuggerd/util.cpp b/debuggerd/util.cpp
index 32d2f18..c6a997b 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "debuggerd/util.h"
+#include "util.h"
 
 #include <sys/socket.h>
 
@@ -22,7 +22,7 @@
 
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
-#include <debuggerd/protocol.h>
+#include "protocol.h"
 
 using android::base::unique_fd;
 
diff --git a/debuggerd/include/debuggerd/util.h b/debuggerd/util.h
similarity index 100%
rename from debuggerd/include/debuggerd/util.h
rename to debuggerd/util.h
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 8a6877a..3e890c7 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -118,6 +118,7 @@
     { "boot",     "boot.img",         "boot.sig",     "boot",     false, false },
     { nullptr,    "boot_other.img",   "boot.sig",     "boot",     true,  true  },
     { "dtbo",     "dtbo.img",         "dtbo.sig",     "dtbo",     true,  false },
+    { "dts",      "dt.img",           "dt.sig",       "dts",      true,  false },
     { "recovery", "recovery.img",     "recovery.sig", "recovery", true,  false },
     { "system",   "system.img",       "system.sig",   "system",   false, false },
     { nullptr,    "system_other.img", "system.sig",   "system",   true,  true  },
@@ -1259,10 +1260,10 @@
     fb_queue_command("flashing unlock_bootloader", "unlocking bootloader");
 }
 
-static void do_oem_command(std::vector<std::string>* args) {
+static void do_oem_command(const std::string& cmd, std::vector<std::string>* args) {
     if (args->empty()) syntax_error("empty oem command");
 
-    std::string command("oem");
+    std::string command(cmd);
     while (!args->empty()) {
         command += " " + next_arg(args);
     }
@@ -1765,7 +1766,7 @@
             std::string filename = next_arg(&args);
             fb_queue_upload(filename.c_str());
         } else if (command == "oem") {
-            do_oem_command(&args);
+            do_oem_command("oem", &args);
         } else if (command == "flashing") {
             if (args.empty()) {
                 syntax_error("missing 'flashing' command");
@@ -1775,7 +1776,7 @@
                                             args[0] == "get_unlock_ability" ||
                                             args[0] == "get_unlock_bootloader_nonce" ||
                                             args[0] == "lock_bootloader")) {
-                do_oem_command(&args);
+                do_oem_command("flashing", &args);
             } else if (args.size() == 2 && args[0] == "unlock_bootloader") {
                 do_bypass_unlock_command(&args);
             } else {
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
new file mode 100644
index 0000000..0af6159
--- /dev/null
+++ b/fs_mgr/Android.bp
@@ -0,0 +1,62 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_defaults {
+    name: "fs_mgr_defaults",
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    local_include_dirs: ["include/"],
+    cppflags: ["-Werror"],
+    static_libs: [
+        "liblogwrap",
+        "libfec",
+        "libfec_rs",
+        "libbase",
+        "libcrypto_utils",
+        "libcrypto",
+        "libext4_utils",
+        "libsquashfs_utils",
+        "libselinux",
+        "libavb",
+    ],
+}
+
+cc_library_static {
+    name: "libfs_mgr",
+    defaults: ["fs_mgr_defaults"],
+    export_include_dirs: ["include"],
+    include_dirs: ["system/vold"],
+    srcs: [
+        "fs_mgr.cpp",
+        "fs_mgr_dm_ioctl.cpp",
+        "fs_mgr_format.cpp",
+        "fs_mgr_fstab.cpp",
+        "fs_mgr_slotselect.cpp",
+        "fs_mgr_verity.cpp",
+        "fs_mgr_avb.cpp",
+        "fs_mgr_avb_ops.cpp",
+        "fs_mgr_boot_config.cpp",
+    ],
+    product_variables: {
+        debuggable: {
+            cppflags: ["-DALLOW_ADBD_DISABLE_VERITY=1"],
+        },
+        eng: {
+            cppflags: ["-DALLOW_SKIP_SECURE_CHECK=1"],
+        },
+    },
+}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 2863a26..f3ca724 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -17,35 +17,6 @@
 include $(CLEAR_VARS)
 LOCAL_CLANG := true
 LOCAL_SANITIZE := integer
-LOCAL_SRC_FILES:= \
-    fs_mgr.cpp \
-    fs_mgr_dm_ioctl.cpp \
-    fs_mgr_format.cpp \
-    fs_mgr_fstab.cpp \
-    fs_mgr_slotselect.cpp \
-    fs_mgr_verity.cpp \
-    fs_mgr_avb.cpp \
-    fs_mgr_avb_ops.cpp \
-    fs_mgr_boot_config.cpp
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/include \
-    system/vold \
-    system/extras/ext4_utils
-LOCAL_MODULE:= libfs_mgr
-LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Werror
-ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
-LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
-endif
-ifneq (,$(filter eng,$(TARGET_BUILD_VARIANT)))
-LOCAL_CFLAGS += -DALLOW_SKIP_SECURE_CHECK=1
-endif
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
 LOCAL_SRC_FILES:= fs_mgr_main.cpp
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_MODULE:= fs_mgr
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index c21139e..6618003 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -16,15 +16,14 @@
 
 #include "fs_mgr_avb.h"
 
-#include <errno.h>
 #include <fcntl.h>
-#include <inttypes.h>
 #include <libgen.h>
-#include <stdio.h>
 #include <string.h>
-#include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
-#include <unistd.h>
+
+#include <sstream>
+#include <string>
 #include <vector>
 
 #include <android-base/file.h>
@@ -33,11 +32,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
-#include <cutils/properties.h>
 #include <libavb/libavb.h>
-#include <openssl/sha.h>
-#include <sys/ioctl.h>
-#include <utils/Compat.h>
 
 #include "fs_mgr.h"
 #include "fs_mgr_priv.h"
@@ -45,48 +40,6 @@
 #include "fs_mgr_priv_dm_ioctl.h"
 #include "fs_mgr_priv_sha.h"
 
-/* The format of dm-verity construction parameters:
- *     <version> <dev> <hash_dev> <data_block_size> <hash_block_size>
- *     <num_data_blocks> <hash_start_block> <algorithm> <digest> <salt>
- */
-#define VERITY_TABLE_FORMAT \
-    "%u %s %s %u %u "       \
-    "%" PRIu64 " %" PRIu64 " %s %s %s "
-
-#define VERITY_TABLE_PARAMS(hashtree_desc, blk_device, digest, salt)                        \
-    hashtree_desc.dm_verity_version, blk_device, blk_device, hashtree_desc.data_block_size, \
-        hashtree_desc.hash_block_size,                                                      \
-        hashtree_desc.image_size / hashtree_desc.data_block_size,  /* num_data_blocks. */   \
-        hashtree_desc.tree_offset / hashtree_desc.hash_block_size, /* hash_start_block. */  \
-        (char*)hashtree_desc.hash_algorithm, digest, salt
-
-#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
-#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
-
-/* The default format of dm-verity optional parameters:
- *     <#opt_params> ignore_zero_blocks restart_on_corruption
- */
-#define VERITY_TABLE_OPT_DEFAULT_FORMAT "2 %s %s"
-#define VERITY_TABLE_OPT_DEFAULT_PARAMS VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
-
-/* The FEC (forward error correction) format of dm-verity optional parameters:
- *     <#opt_params> use_fec_from_device <fec_dev>
- *     fec_roots <num> fec_blocks <num> fec_start <offset>
- *     ignore_zero_blocks restart_on_corruption
- */
-#define VERITY_TABLE_OPT_FEC_FORMAT \
-    "10 use_fec_from_device %s fec_roots %u fec_blocks %" PRIu64 " fec_start %" PRIu64 " %s %s"
-
-/* Note that fec_blocks is the size that FEC covers, *not* the
- * size of the FEC data. Since we use FEC for everything up until
- * the FEC data, it's the same as the offset (fec_start).
- */
-#define VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device)                     \
-    blk_device, hashtree_desc.fec_num_roots,                                       \
-        hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_blocks */ \
-        hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_start */  \
-        VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
-
 static inline bool nibble_value(const char& c, uint8_t* value) {
     FS_MGR_CHECK(value != nullptr);
 
@@ -280,10 +233,81 @@
     return true;
 }
 
-static bool hashtree_load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name,
-                                       int fd, const std::string& blk_device,
-                                       const AvbHashtreeDescriptor& hashtree_desc,
-                                       const std::string& salt, const std::string& root_digest) {
+// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
+// See the following link for more details:
+// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
+static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc,
+                                          const std::string& salt, const std::string& root_digest,
+                                          const std::string& blk_device) {
+    // Loads androidboot.veritymode from kernel cmdline.
+    std::string verity_mode;
+    if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
+        verity_mode = "enforcing";  // Defaults to enforcing when it's absent.
+    }
+
+    // Converts veritymode to the format used in kernel.
+    std::string dm_verity_mode;
+    if (verity_mode == "enforcing") {
+        dm_verity_mode = "restart_on_corruption";
+    } else if (verity_mode == "logging") {
+        dm_verity_mode = "ignore_corruption";
+    } else if (verity_mode != "eio") {  // Default dm_verity_mode is eio.
+        LERROR << "Unknown androidboot.veritymode: " << verity_mode;
+        return "";
+    }
+
+    // dm-verity construction parameters:
+    //   <version> <dev> <hash_dev>
+    //   <data_block_size> <hash_block_size>
+    //   <num_data_blocks> <hash_start_block>
+    //   <algorithm> <digest> <salt>
+    //   [<#opt_params> <opt_params>]
+    std::ostringstream verity_table;
+    verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " "
+                 << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " "
+                 << hashtree_desc.image_size / hashtree_desc.data_block_size << " "
+                 << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " "
+                 << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt;
+
+    // Continued from the above optional parameters:
+    //   [<#opt_params> <opt_params>]
+    int optional_argc = 0;
+    std::ostringstream optional_args;
+
+    // dm-verity optional parameters for FEC (forward error correction):
+    //   use_fec_from_device <fec_dev>
+    //   fec_roots <num>
+    //   fec_blocks <num>
+    //   fec_start <offset>
+    if (hashtree_desc.fec_size > 0) {
+        // Note that fec_blocks is the size that FEC covers, *NOT* the
+        // size of the FEC data. Since we use FEC for everything up until
+        // the FEC data, it's the same as the offset (fec_start).
+        optional_argc += 8;
+        // clang-format off
+        optional_args << "use_fec_from_device " << blk_device
+                      << " fec_roots " << hashtree_desc.fec_num_roots
+                      << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
+                      << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
+                      << " ";
+        // clang-format on
+    }
+
+    if (!dm_verity_mode.empty()) {
+        optional_argc += 1;
+        optional_args << dm_verity_mode << " ";
+    }
+
+    // Always use ignore_zero_blocks.
+    optional_argc += 1;
+    optional_args << "ignore_zero_blocks";
+
+    verity_table << " " << optional_argc << " " << optional_args.str();
+    return verity_table.str();
+}
+
+static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd,
+                              uint64_t image_size, const std::string& verity_table) {
     fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG);
 
     // The buffer consists of [dm_ioctl][dm_target_spec][verity_params].
@@ -294,35 +318,25 @@
     io->target_count = 1;
     dm_target->status = 0;
     dm_target->sector_start = 0;
-    dm_target->length = hashtree_desc.image_size / 512;
+    dm_target->length = image_size / 512;
     strcpy(dm_target->target_type, "verity");
 
     // Builds the verity params.
     char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
     size_t bufsize = DM_BUF_SIZE - (verity_params - buffer);
 
-    int res = 0;
-    if (hashtree_desc.fec_size > 0) {
-        res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_FEC_FORMAT,
-                       VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(),
-                                           salt.c_str()),
-                       VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device.c_str()));
-    } else {
-        res = snprintf(verity_params, bufsize, VERITY_TABLE_FORMAT VERITY_TABLE_OPT_DEFAULT_FORMAT,
-                       VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(), root_digest.c_str(),
-                                           salt.c_str()),
-                       VERITY_TABLE_OPT_DEFAULT_PARAMS);
-    }
+    LINFO << "Loading verity table: '" << verity_table << "'";
 
-    if (res < 0 || (size_t)res >= bufsize) {
-        LERROR << "Error building verity table; insufficient buffer size?";
+    // Copies verity_table to verity_params (including the terminating null byte).
+    if (verity_table.size() > bufsize - 1) {
+        LERROR << "Verity table size too large: " << verity_table.size()
+               << " (max allowable size: " << bufsize - 1 << ")";
         return false;
     }
-
-    LINFO << "Loading verity table: '" << verity_params << "'";
+    memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1);
 
     // Sets ext target boundary.
-    verity_params += strlen(verity_params) + 1;
+    verity_params += verity_table.size() + 1;
     verity_params = (char*)(((unsigned long)verity_params + 7) & ~7);
     dm_target->next = verity_params - buffer;
 
@@ -362,9 +376,15 @@
         return false;
     }
 
+    std::string verity_table =
+        construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device);
+    if (verity_table.empty()) {
+        LERROR << "Failed to construct verity table.";
+        return false;
+    }
+
     // Loads the verity mapping table.
-    if (!hashtree_load_verity_table(io, mount_point, fd, std::string(fstab_entry->blk_device),
-                                    hashtree_desc, salt, root_digest)) {
+    if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) {
         LERROR << "Couldn't load verity table!";
         return false;
     }
@@ -486,8 +506,11 @@
         return nullptr;
     }
 
-    AvbSlotVerifyResult verify_result = avb_ops->AvbSlotVerify(
-        fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_);
+    AvbSlotVerifyFlags flags = avb_verifier->IsDeviceUnlocked()
+                                   ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+                                   : AVB_SLOT_VERIFY_FLAGS_NONE;
+    AvbSlotVerifyResult verify_result =
+        avb_ops->AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->avb_slot_data_);
 
     // Only allow two verify results:
     //   - AVB_SLOT_VERIFY_RESULT_OK.
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
index 8feeb53..512839b 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -177,13 +177,15 @@
 }
 
 AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix,
-                                                   bool allow_verification_error,
+                                                   AvbSlotVerifyFlags flags,
                                                    AvbSlotVerifyData** out_data) {
     // Invokes avb_slot_verify() to load and verify all vbmeta images.
     // Sets requested_partitions to nullptr as it's to copy the contents
     // of HASH partitions into handle>avb_slot_data_, which is not required as
     // fs_mgr only deals with HASHTREE partitions.
     const char* requested_partitions[] = {nullptr};
-    return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(),
-                           allow_verification_error, out_data);
+    // The |hashtree_error_mode| field doesn't matter as it only
+    // influences the generated kernel cmdline parameters.
+    return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), flags,
+                           AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, out_data);
 }
diff --git a/fs_mgr/fs_mgr_priv_avb_ops.h b/fs_mgr/fs_mgr_priv_avb_ops.h
index a6b52e4..d1ef2e9 100644
--- a/fs_mgr/fs_mgr_priv_avb_ops.h
+++ b/fs_mgr/fs_mgr_priv_avb_ops.h
@@ -56,7 +56,7 @@
     AvbIOResult ReadFromPartition(const char* partition, int64_t offset, size_t num_bytes,
                                   void* buffer, size_t* out_num_read);
 
-    AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, bool allow_verification_error,
+    AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, AvbSlotVerifyFlags flags,
                                       AvbSlotVerifyData** out_data);
 
   private:
diff --git a/init/Android.bp b/init/Android.bp
new file mode 100644
index 0000000..80d5c42
--- /dev/null
+++ b/init/Android.bp
@@ -0,0 +1,164 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_defaults {
+    name: "init_defaults",
+    cpp_std: "experimental",
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    tidy_checks: ["-misc-forwarding-reference-overload"],
+    cppflags: [
+        "-DLOG_UEVENTS=0",
+        "-Wall",
+        "-Wextra",
+        "-Wno-unused-parameter",
+        "-Werror",
+        "-DALLOW_LOCAL_PROP_OVERRIDE=0",
+        "-DALLOW_PERMISSIVE_SELINUX=0",
+        "-DREBOOT_BOOTLOADER_ON_PANIC=0",
+        "-DWORLD_WRITABLE_KMSG=0",
+        "-DDUMP_ON_UMOUNT_FAILURE=0",
+        "-DSHUTDOWN_ZERO_TIMEOUT=0",
+    ],
+    product_variables: {
+        debuggable: {
+            cppflags: [
+                "-UALLOW_LOCAL_PROP_OVERRIDE",
+                "-DALLOW_LOCAL_PROP_OVERRIDE=1",
+                "-UALLOW_PERMISSIVE_SELINUX",
+                "-DALLOW_PERMISSIVE_SELINUX=1",
+                "-UREBOOT_BOOTLOADER_ON_PANIC",
+                "-DREBOOT_BOOTLOADER_ON_PANIC=1",
+                "-UWORLD_WRITABLE_KMSG",
+                "-DWORLD_WRITABLE_KMSG=1",
+                "-UDUMP_ON_UMOUNT_FAILURE",
+                "-DDUMP_ON_UMOUNT_FAILURE=1",
+            ],
+        },
+        eng: {
+            cppflags: [
+                "-USHUTDOWN_ZERO_TIMEOUT",
+                "-DSHUTDOWN_ZERO_TIMEOUT=1",
+            ],
+        },
+    },
+}
+
+cc_library_static {
+    name: "libinit",
+    defaults: ["init_defaults"],
+    srcs: [
+        "action.cpp",
+        "capabilities.cpp",
+        "descriptors.cpp",
+        "devices.cpp",
+        "import_parser.cpp",
+        "init_parser.cpp",
+        "log.cpp",
+        "parser.cpp",
+        "service.cpp",
+        "util.cpp",
+    ],
+    whole_static_libs: ["libcap"],
+    static_libs: [
+        "libbase",
+        "libselinux",
+        "liblog",
+        "libprocessgroup",
+    ],
+}
+
+/*
+This is not yet ready, see the below TODOs for what is missing
+
+cc_binary {
+    // TODO: Missing,
+    //LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+    //LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
+
+    name: "init",
+    defaults: ["init_defaults"],
+    static_executable: true,
+    srcs: [
+        "bootchart.cpp",
+        "builtins.cpp",
+        "init.cpp",
+        "init_first_stage.cpp",
+        "keychords.cpp",
+        "property_service.cpp",
+        "reboot.cpp",
+        "signal_handler.cpp",
+        "ueventd.cpp",
+        "watchdogd.cpp",
+    ],
+    include_dirs: [
+        "system/core/mkbootimg"
+    ],
+    static_libs: [
+        "libinit",
+        "libbootloader_message",
+        "libfs_mgr",
+        "libfec",
+        "libfec_rs",
+        "libsquashfs_utils",
+        "liblogwrap",
+        "libext4_utils",
+        "libcutils",
+        "libbase",
+        "libc",
+        "libselinux",
+        "liblog",
+        "libcrypto_utils",
+        "libcrypto",
+        "libc++_static",
+        "libdl",
+        "libsparse",
+        "libz",
+        "libprocessgroup",
+        "libavb",
+        "libkeyutils",
+    ],
+    symlinks: [
+        "sbin/ueventd",
+        "sbin/watchdogd",
+    ],
+}
+*/
+
+// Tests
+// ------------------------------------------------------------------------------
+
+cc_test {
+    name: "init_tests",
+    defaults: ["init_defaults"],
+    srcs: [
+        "devices_test.cpp",
+        "init_parser_test.cpp",
+        "init_test.cpp",
+        "property_service_test.cpp",
+        "service_test.cpp",
+        "util_test.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libselinux",
+    ],
+    static_libs: ["libinit"],
+}
+
+subdirs = ["*"]
diff --git a/init/Android.mk b/init/Android.mk
index 617a809..489d076 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -39,50 +39,6 @@
 
 # --
 
-# If building on Linux, then build unit test for the host.
-ifeq ($(HOST_OS),linux)
-include $(CLEAR_VARS)
-LOCAL_CPPFLAGS := $(init_cflags)
-LOCAL_SRC_FILES:= \
-    parser/tokenizer.cpp \
-
-LOCAL_MODULE := libinit_parser
-LOCAL_CLANG := true
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := init_parser_tests
-LOCAL_SRC_FILES := \
-    parser/tokenizer_test.cpp \
-
-LOCAL_STATIC_LIBRARIES := libinit_parser
-LOCAL_CLANG := true
-include $(BUILD_HOST_NATIVE_TEST)
-endif
-
-include $(CLEAR_VARS)
-# b/38002385, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
-LOCAL_CPPFLAGS := $(init_cflags)
-LOCAL_SRC_FILES:= \
-    action.cpp \
-    capabilities.cpp \
-    descriptors.cpp \
-    devices.cpp \
-    import_parser.cpp \
-    init_parser.cpp \
-    log.cpp \
-    parser.cpp \
-    service.cpp \
-    util.cpp \
-
-LOCAL_STATIC_LIBRARIES := libbase libselinux liblog libprocessgroup
-LOCAL_WHOLE_STATIC_LIBRARIES := libcap
-LOCAL_MODULE := libinit
-LOCAL_SANITIZE := integer
-LOCAL_CLANG := true
-include $(BUILD_STATIC_LIBRARY)
-
 include $(CLEAR_VARS)
 # b/38002385, work around clang-tidy segmentation fault.
 LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
@@ -139,35 +95,3 @@
 LOCAL_SANITIZE := integer
 LOCAL_CLANG := true
 include $(BUILD_EXECUTABLE)
-
-
-# Unit tests.
-# =========================================================
-include $(CLEAR_VARS)
-# b/38002385, work around clang-tidy segmentation fault.
-LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
-LOCAL_MODULE := init_tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_SRC_FILES := \
-    devices_test.cpp \
-    init_parser_test.cpp \
-    init_test.cpp \
-    property_service_test.cpp \
-    service_test.cpp \
-    util_test.cpp \
-
-LOCAL_SHARED_LIBRARIES += \
-    libbase \
-    libcutils \
-    libselinux \
-
-LOCAL_STATIC_LIBRARIES := libinit
-LOCAL_SANITIZE := integer
-LOCAL_CLANG := true
-LOCAL_CPPFLAGS := -Wall -Wextra -Werror -std=gnu++1z
-include $(BUILD_NATIVE_TEST)
-
-
-# Include targets in subdirs.
-# =========================================================
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/init/AndroidTest.xml b/init/AndroidTest.xml
deleted file mode 100644
index 3de69ed..0000000
--- a/init/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-<configuration description="Config for init_tests">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="init_tests->/data/local/tmp/init_tests" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="init_tests" />
-    </test>
-</configuration>
diff --git a/init/devices.cpp b/init/devices.cpp
index d8258cf..e0351a3 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -30,6 +30,7 @@
 #include <string.h>
 #include <sys/sendfile.h>
 #include <sys/socket.h>
+#include <sys/sysmacros.h>
 #include <sys/time.h>
 #include <sys/un.h>
 #include <sys/wait.h>
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 838406d..cdfc698 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -331,7 +331,7 @@
     // keep debugging tools until non critical ones are all gone.
     const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
     // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
-    const std::set<std::string> to_starts{"watchdogd", "vold"};
+    const std::set<std::string> to_starts{"watchdogd", "vold", "ueventd"};
     ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {
         if (kill_after_apps.count(s->name())) {
             s->SetShutdownCritical();
diff --git a/init/test_service/Android.bp b/init/test_service/Android.bp
new file mode 100644
index 0000000..9bd6f27
--- /dev/null
+++ b/init/test_service/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2017 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.
+//
+
+cc_binary {
+    name: "test_service",
+    srcs: ["test_service.cpp"],
+    shared_libs: ["libbase"],
+    init_rc: ["test_service.rc"],
+}
diff --git a/init/test_service/Android.mk b/init/test_service/Android.mk
deleted file mode 100644
index 30c9e9d..0000000
--- a/init/test_service/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2016 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)
-
-# Sample service for testing.
-# =========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := test_service
-LOCAL_SRC_FILES := test_service.cpp
-
-LOCAL_SHARED_LIBRARIES += libbase
-
-LOCAL_INIT_RC := test_service.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index b42a049..653e96b 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -119,7 +119,12 @@
                     return ResultOrAgain::kFailure;
             }
         }
-        CHECK(static_cast<uint32_t>(result) == header.len);
+
+        if (static_cast<unsigned int>(result) != header.len) {
+            LOG(ERROR) << "Written bytes " << result << " is different from length in header "
+                       << header.len;
+            return ResultOrAgain::kFailure;
+        }
         return ResultOrAgain::kSuccess;
     }
 }
@@ -141,8 +146,8 @@
     }
 
     constexpr int kMaxMessageSize = sizeof(FuseBuffer);
-    if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0 ||
-        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0) {
+    if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0 ||
+        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0) {
         PLOG(ERROR) << "Failed to update buffer size for socket";
         return false;
     }
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index f2560e6..4a5f2a7 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -16,6 +16,7 @@
 
 cc_library {
     name: "libcrypto_utils",
+    vendor_available: true,
     host_supported: true,
     srcs: [
         "android_pubkey.c",
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index 92717c0..b4abb79 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <sys/types.h>
 #include <unistd.h>
 
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index ea99595..221dea2 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -139,14 +139,8 @@
     { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" },
     { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_file + 1 },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/odm/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/odm/default.prop" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/odm/etc/fs_config_dirs" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/odm/etc/fs_config_files" },
     { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_file + 1 },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/oem/etc/fs_config_dirs" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/oem/etc/fs_config_files" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump32" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump64" },
@@ -163,10 +157,6 @@
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
     { 00440, AID_ROOT,      AID_ROOT,      0, "system/etc/recovery.img" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/vendor/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "system/vendor/default.prop" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/vendor/etc/fs_config_dirs" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, "system/vendor/etc/fs_config_files" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/build.prop" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/default.prop" },
     { 00444, AID_ROOT,      AID_ROOT,      0, ven_conf_dir + 1 },
@@ -196,18 +186,12 @@
     // Support hostapd administering a network interface.
     { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_NET_RAW),
-                                              "system/vendor/bin/hostapd" },
-    { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
-                                           CAP_MASK_LONG(CAP_NET_RAW),
                                               "vendor/bin/hostapd" },
 
     // Support Bluetooth legacy hal accessing /sys/class/rfkill
     // Support RT scheduling in Bluetooth
     { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_SYS_NICE),
-                                              "system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
-    { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
-                                           CAP_MASK_LONG(CAP_SYS_NICE),
                                               "vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
 
     // Support wifi_hal_legacy administering a network interface.
@@ -233,8 +217,6 @@
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
     { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/valgrind/*" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
-    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/xbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
@@ -273,6 +255,36 @@
     return fd;
 }
 
+// if path is "vendor/<stuff>", "oem/<stuff>" or "odm/<stuff>"
+static bool is_partition(const char* path, size_t len) {
+    static const char* partitions[] = {"vendor/", "oem/", "odm/"};
+    for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
+        size_t plen = strlen(partitions[i]);
+        if (len <= plen) continue;
+        if (!strncmp(path, partitions[i], plen)) return true;
+    }
+    return false;
+}
+
+// alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or
+// "system/<partition>/<stuff>" to "<partition>/<stuff>"
+static bool prefix_cmp(const char* prefix, const char* path, size_t len) {
+    if (!strncmp(prefix, path, len)) return true;
+
+    static const char system[] = "system/";
+    if (!strncmp(path, system, strlen(system))) {
+        path += strlen(system);
+    } else if (len <= strlen(system)) {
+        return false;
+    } else if (strncmp(prefix, system, strlen(system))) {
+        return false;
+    } else {
+        prefix += strlen(system);
+        len -= strlen(system);
+    }
+    return is_partition(prefix, len) && !strncmp(prefix, path, len);
+}
+
 static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) {
     if (dir) {
         if (plen < len) {
@@ -281,13 +293,13 @@
     } else {
         // If name ends in * then allow partial matches.
         if (prefix[len - 1] == '*') {
-            return !strncmp(prefix, path, len - 1);
+            return prefix_cmp(prefix, path, len - 1);
         }
         if (plen != len) {
             return false;
         }
     }
-    return !strncmp(prefix, path, len);
+    return prefix_cmp(prefix, path, len);
 }
 
 void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 48b50a5..02141d6 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -130,6 +130,7 @@
 #define AID_MEDIA_OBB 1059       /* GID for OBB files on internal media storage */
 #define AID_ESE 1060             /* embedded secure element (eSE) subsystem */
 #define AID_OTA_UPDATE 1061      /* resource tracking UID for OTA updates */
+#define AID_AUTOMOTIVE_EVS 1062  /* Automotive rear and surround view system */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/libcutils/tests/fs_config.cpp b/libcutils/tests/fs_config.cpp
index 3917a0b..a62cd51 100644
--- a/libcutils/tests/fs_config.cpp
+++ b/libcutils/tests/fs_config.cpp
@@ -14,63 +14,188 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+
 #include <string>
 
 #include <gtest/gtest.h>
 
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
 #include <private/android_filesystem_config.h>
+#include <private/fs_config.h>
 
-extern const struct fs_path_config* __for_testing_only__android_dirs;
-extern const struct fs_path_config* __for_testing_only__android_files;
+extern const fs_path_config* __for_testing_only__android_dirs;
+extern const fs_path_config* __for_testing_only__android_files;
 
-static void check_one(const struct fs_path_config* paths, const std::string& prefix,
-                      const std::string& alternate) {
-    for (size_t idx = 0; paths[idx].prefix; ++idx) {
-        std::string path(paths[idx].prefix);
-        if (android::base::StartsWith(path, prefix.c_str())) {
-            path = alternate + path.substr(prefix.length());
-            size_t second;
-            for (second = 0; paths[second].prefix; ++second) {
-                if (path == paths[second].prefix) break;
+// Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we
+// hit a nullptr termination, before we declare the list is just too big or
+// could be missing the nullptr.
+static constexpr size_t max_idx = 4096;
+
+static bool check_unique(std::vector<const char*>& paths, const std::string& config_name,
+                         const std::string& prefix) {
+    bool retval = false;
+
+    std::string alternate = "system/" + prefix;
+
+    for (size_t idx = 0; idx < paths.size(); ++idx) {
+        size_t second;
+        std::string path(paths[idx]);
+        // check if there are multiple identical paths
+        for (second = idx + 1; second < paths.size(); ++second) {
+            if (path == paths[second]) {
+                GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx];
+                retval = true;
+                break;
             }
-            if (!paths[second].prefix) {
-                // guaranteed to fail expectations, trigger test failure with
-                // a message that reports the violation as an inequality.
-                EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str());
+        }
+
+        // check if path is <partition>/
+        if (android::base::StartsWith(path, prefix.c_str())) {
+            // rebuild path to be system/<partition>/... to check for alias
+            path = alternate + path.substr(prefix.size());
+            for (second = 0; second < paths.size(); ++second) {
+                if (path == paths[second]) {
+                    GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": "
+                                      << paths[idx] << " and " << paths[second]
+                                      << " (remove latter)";
+                    retval = true;
+                    break;
+                }
+            }
+            continue;
+        }
+
+        // check if path is system/<partition>/
+        if (android::base::StartsWith(path, alternate.c_str())) {
+            // rebuild path to be <partition>/... to check for alias
+            path = prefix + path.substr(alternate.size());
+            for (second = 0; second < paths.size(); ++second) {
+                if (path == paths[second]) break;
+            }
+            if (second >= paths.size()) {
+                GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx]
+                                  << " with " << path;
+                retval = true;
             }
         }
     }
+    return retval;
 }
 
-static void check_two(const struct fs_path_config* paths, const std::string& prefix) {
+static bool check_unique(const fs_path_config* paths, const char* type_name,
+                         const std::string& prefix) {
+    std::string config("system/core/libcutils/fs_config.cpp:android_");
+    config += type_name;
+    config += "[]";
+
+    bool retval = false;
+    std::vector<const char*> paths_tmp;
+    for (size_t idx = 0; paths[idx].prefix; ++idx) {
+        if (idx > max_idx) {
+            GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)";
+            retval = true;
+            break;
+        }
+        paths_tmp.push_back(paths[idx].prefix);
+    }
+
+    return check_unique(paths_tmp, config, prefix) || retval;
+}
+
+#define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field))
+
+static bool check_unique(const std::string& config, const std::string& prefix) {
+    int retval = false;
+
+    std::string data;
+    if (!android::base::ReadFileToString(config, &data)) return retval;
+
+    const fs_path_config_from_file* pc =
+        reinterpret_cast<const fs_path_config_from_file*>(data.c_str());
+    size_t len = data.size();
+
+    std::vector<const char*> paths_tmp;
+    size_t entry_number = 0;
+    while (len > 0) {
+        uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX;
+        if (host_len > len) {
+            GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " ("
+                                << host_len << " > " << len << ")";
+            const std::string unknown("?");
+            GTEST_LOG_(WARNING)
+                << config << ": entry[" << entry_number << "]={ "
+                << "len=" << ((len >= endof(pc, len))
+                                  ? android::base::StringPrintf("%" PRIu16, pc->len)
+                                  : unknown)
+                << ", mode=" << ((len >= endof(pc, mode))
+                                     ? android::base::StringPrintf("0%" PRIo16, pc->mode)
+                                     : unknown)
+                << ", uid=" << ((len >= endof(pc, uid))
+                                    ? android::base::StringPrintf("%" PRIu16, pc->uid)
+                                    : unknown)
+                << ", gid=" << ((len >= endof(pc, gid))
+                                    ? android::base::StringPrintf("%" PRIu16, pc->gid)
+                                    : unknown)
+                << ", capabilities="
+                << ((len >= endof(pc, capabilities))
+                        ? android::base::StringPrintf("0x%" PRIx64, pc->capabilities)
+                        : unknown)
+                << ", prefix="
+                << ((len >= offsetof(fs_path_config_from_file, prefix))
+                        ? android::base::StringPrintf(
+                              "\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)),
+                              pc->prefix)
+                        : unknown)
+                << " }";
+            retval = true;
+            break;
+        }
+        paths_tmp.push_back(pc->prefix);
+
+        pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) +
+                                                               host_len);
+        len -= host_len;
+        ++entry_number;
+    }
+
+    return check_unique(paths_tmp, config, prefix) || retval;
+}
+
+void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) {
     ASSERT_FALSE(paths == nullptr);
-    std::string alternate = "system/" + prefix;
-    check_one(paths, prefix, alternate);
-    check_one(paths, alternate, prefix);
+    ASSERT_FALSE(type_name == nullptr);
+    ASSERT_FALSE(prefix == nullptr);
+    bool check_internal = check_unique(paths, type_name, prefix);
+    EXPECT_FALSE(check_internal);
+    bool check_overrides =
+        check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix);
+    EXPECT_FALSE(check_overrides);
 }
 
 TEST(fs_config, vendor_dirs_alias) {
-    check_two(__for_testing_only__android_dirs, "vendor/");
+    check_two(__for_testing_only__android_dirs, "dirs", "vendor/");
 }
 
 TEST(fs_config, vendor_files_alias) {
-    check_two(__for_testing_only__android_files, "vendor/");
+    check_two(__for_testing_only__android_files, "files", "vendor/");
 }
 
 TEST(fs_config, oem_dirs_alias) {
-    check_two(__for_testing_only__android_dirs, "oem/");
+    check_two(__for_testing_only__android_dirs, "dirs", "oem/");
 }
 
 TEST(fs_config, oem_files_alias) {
-    check_two(__for_testing_only__android_files, "oem/");
+    check_two(__for_testing_only__android_files, "files", "oem/");
 }
 
 TEST(fs_config, odm_dirs_alias) {
-    check_two(__for_testing_only__android_dirs, "odm/");
+    check_two(__for_testing_only__android_dirs, "dirs", "odm/");
 }
 
 TEST(fs_config, odm_files_alias) {
-    check_two(__for_testing_only__android_files, "odm/");
+    check_two(__for_testing_only__android_files, "files", "odm/");
 }
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index da8afe1..26a041a 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -23,6 +23,7 @@
         // 524291 corresponds to sysui_histogram, from
         // frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
         "-DHISTOGRAM_LOG_TAG=524292",
+        "-DCOUNT_LOG_TAG=524290",
     ],
 }
 
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index 26aa189..36e124d 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -24,13 +24,18 @@
 // buffer.
 void LogHistogram(const std::string& event, int32_t data);
 
+// Logs a Tron counter metric named |name| containing |val| count to the Tron
+// log buffer.
+void LogCounter(const std::string& name, int32_t val);
+
 // TODO: replace these with the metric_logger.proto definitions
 enum {
-  LOGBUILDER_CATEGORY = 757,
-  LOGBUILDER_NAME = 799,
-  LOGBUILDER_BUCKET = 801,
-  LOGBUILDER_VALUE = 802,
-  LOGBUILDER_HISTOGRAM = 804,
+    LOGBUILDER_CATEGORY = 757,
+    LOGBUILDER_NAME = 799,
+    LOGBUILDER_BUCKET = 801,
+    LOGBUILDER_VALUE = 802,
+    LOGBUILDER_COUNTER = 803,
+    LOGBUILDER_HISTOGRAM = 804,
 };
 
 }  // namespace metricslogger
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index 0d08f5c..6f65e10 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -25,12 +25,16 @@
 
 // Mirror com.android.internal.logging.MetricsLogger#histogram().
 void LogHistogram(const std::string& event, int32_t data) {
-  android_log_event_list log(HISTOGRAM_LOG_TAG);
-  log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM
-      << LOGBUILDER_NAME << event
-      << LOGBUILDER_BUCKET << data
-      << LOGBUILDER_VALUE << 1
-      << LOG_ID_EVENTS;
+    android_log_event_list log(HISTOGRAM_LOG_TAG);
+    log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM << LOGBUILDER_NAME << event
+        << LOGBUILDER_BUCKET << data << LOGBUILDER_VALUE << 1 << LOG_ID_EVENTS;
+}
+
+// Mirror com.android.internal.logging.MetricsLogger#count().
+void LogCounter(const std::string& name, int32_t val) {
+    android_log_event_list log(COUNT_LOG_TAG);
+    log << LOGBUILDER_CATEGORY << LOGBUILDER_COUNTER << LOGBUILDER_NAME << name << LOGBUILDER_VALUE
+        << val << LOG_ID_EVENTS;
 }
 
 }  // namespace metricslogger
diff --git a/libmetricslogger/metrics_logger_test.cpp b/libmetricslogger/metrics_logger_test.cpp
index 5a30ad7..440645c 100644
--- a/libmetricslogger/metrics_logger_test.cpp
+++ b/libmetricslogger/metrics_logger_test.cpp
@@ -19,6 +19,10 @@
 #include <gtest/gtest.h>
 
 TEST(MetricsLoggerTest, AddSingleBootEvent) {
-  android::metricslogger::LogHistogram("test_event", 42);
-  // TODO(jhawkins): Verify the EventLog is updated.
+    android::metricslogger::LogHistogram("test_event", 42);
+    // TODO(jhawkins): Verify the EventLog is updated.
+}
+
+TEST(MetricsLoggerTest, AddCounterVal) {
+    android::metricslogger::LogCounter("test_count", 10);
 }
diff --git a/libnetutils/Android.bp b/libnetutils/Android.bp
index f710ba2..0caf145 100644
--- a/libnetutils/Android.bp
+++ b/libnetutils/Android.bp
@@ -17,3 +17,17 @@
 
     export_include_dirs: ["include"],
 }
+
+cc_binary {
+    name: "dhcpdbg",
+
+    srcs: [
+        "dhcptool.c",
+    ],
+
+    shared_libs: [
+        "libnetutils",
+    ],
+
+    cflags: ["-Werror"],
+}
diff --git a/libnetutils/dhcptool.c b/libnetutils/dhcptool.c
new file mode 100644
index 0000000..280b977
--- /dev/null
+++ b/libnetutils/dhcptool.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 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.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <error.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <netutils/ifc.h>
+
+extern int do_dhcp(char*);
+
+int main(int argc, char* argv[]) {
+    if (argc != 2) {
+        error(EXIT_FAILURE, 0, "usage: %s INTERFACE", argv[0]);
+    }
+
+    char* interface = argv[1];
+    if (ifc_init()) {
+        err(errno, "dhcptool %s: ifc_init failed", interface);
+        ifc_close();
+        return EXIT_FAILURE;
+    }
+
+    int rc = do_dhcp(interface);
+    if (rc) {
+        err(errno, "dhcptool %s: do_dhcp failed", interface);
+    }
+    warn("IP assignment is for debug purposes ONLY");
+    ifc_close();
+
+    return rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 64d1d2f..e9ef9cc 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -530,6 +530,7 @@
         "  process    — Display PID only.\n"
         "  raw        — Display the raw log message, with no other metadata fields.\n"
         "  tag        — Display the priority/tag only.\n"
+        "  thread     — Display priority, PID and TID of process issuing the message.\n"
         "  threadtime — Display the date, invocation time, priority, tag, and the PID\n"
         "               and TID of the thread issuing the message. (the default format).\n"
         "  time       — Display the date, invocation time, priority/tag, and PID of the\n"
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 8b609cb..7498325 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -79,10 +79,16 @@
             if (monotonic) {
                 if (!android::isMonotonic(e->mRealTime)) {
                     LogKlog::convertRealToMonotonic(e->mRealTime);
+                    if ((e->mRealTime.tv_nsec % 1000) == 0) {
+                        e->mRealTime.tv_nsec++;
+                    }
                 }
             } else {
                 if (android::isMonotonic(e->mRealTime)) {
                     LogKlog::convertMonotonicToReal(e->mRealTime);
+                    if ((e->mRealTime.tv_nsec % 1000) == 0) {
+                        e->mRealTime.tv_nsec++;
+                    }
                 }
             }
             ++it;
@@ -196,6 +202,11 @@
         return -EINVAL;
     }
 
+    // Slip the time by 1 nsec if the incoming lands on xxxxxx000 ns.
+    // This prevents any chance that an outside source can request an
+    // exact entry with time specified in ms or us precision.
+    if ((realtime.tv_nsec % 1000) == 0) ++realtime.tv_nsec;
+
     LogBufferElement* elem =
         new LogBufferElement(log_id, realtime, uid, pid, tid, msg, len);
     if (log_id != LOG_ID_SECURITY) {
@@ -607,6 +618,33 @@
     }
 };
 
+// Determine if watermark is within pruneMargin + 1s from the end of the list,
+// the caller will use this result to set an internal busy flag indicating
+// the prune operation could not be completed because a reader is blocking
+// the request.
+bool LogBuffer::isBusy(log_time watermark) {
+    LogBufferElementCollection::iterator ei = mLogElements.end();
+    --ei;
+    return watermark < ((*ei)->getRealTime() - pruneMargin - log_time(1, 0));
+}
+
+// If the selected reader is blocking our pruning progress, decide on
+// what kind of mitigation is necessary to unblock the situation.
+void LogBuffer::kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows) {
+    if (stats.sizes(id) > (2 * log_buffer_size(id))) {  // +100%
+        // A misbehaving or slow reader has its connection
+        // dropped if we hit too much memory pressure.
+        me->release_Locked();
+    } else if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
+        // Allow a blocked WRAP timeout reader to
+        // trigger and start reporting the log data.
+        me->triggerReader_Locked();
+    } else {
+        // tell slow reader to skip entries to catch up
+        me->triggerSkip_Locked(id, pruneRows);
+    }
+}
+
 // prune "pruneRows" of type "id" from the buffer.
 //
 // This garbage collection task is used to expire log entries. It is called to
@@ -697,12 +735,8 @@
             }
 
             if (oldest && (watermark <= element->getRealTime())) {
-                busy = true;
-                if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
-                    oldest->triggerReader_Locked();
-                } else {
-                    oldest->triggerSkip_Locked(id, pruneRows);
-                }
+                busy = isBusy(watermark);
+                if (busy) kickMe(oldest, id, pruneRows);
                 break;
             }
 
@@ -789,10 +823,8 @@
             LogBufferElement* element = *it;
 
             if (oldest && (watermark <= element->getRealTime())) {
-                busy = true;
-                if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
-                    oldest->triggerReader_Locked();
-                }
+                busy = isBusy(watermark);
+                // Do not let chatty eliding trigger any reader mitigation
                 break;
             }
 
@@ -943,19 +975,8 @@
         }
 
         if (oldest && (watermark <= element->getRealTime())) {
-            busy = true;
-            if (whitelist) {
-                break;
-            }
-
-            if (stats.sizes(id) > (2 * log_buffer_size(id))) {
-                // kick a misbehaving log reader client off the island
-                oldest->release_Locked();
-            } else if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
-                oldest->triggerReader_Locked();
-            } else {
-                oldest->triggerSkip_Locked(id, pruneRows);
-            }
+            busy = isBusy(watermark);
+            if (!whitelist && busy) kickMe(oldest, id, pruneRows);
             break;
         }
 
@@ -987,15 +1008,8 @@
             }
 
             if (oldest && (watermark <= element->getRealTime())) {
-                busy = true;
-                if (stats.sizes(id) > (2 * log_buffer_size(id))) {
-                    // kick a misbehaving log reader client off the island
-                    oldest->release_Locked();
-                } else if (oldest->mTimeout.tv_sec || oldest->mTimeout.tv_nsec) {
-                    oldest->triggerReader_Locked();
-                } else {
-                    oldest->triggerSkip_Locked(id, pruneRows);
-                }
+                busy = isBusy(watermark);
+                if (busy) kickMe(oldest, id, pruneRows);
                 break;
             }
 
@@ -1108,6 +1122,9 @@
             LogBufferElement* element = *it;
             if (element->getRealTime() > start) {
                 last = it;
+            } else if (element->getRealTime() == start) {
+                last = ++it;
+                break;
             } else if (!--count || (element->getRealTime() < min)) {
                 break;
             }
@@ -1115,7 +1132,7 @@
         it = last;
     }
 
-    log_time max = start;
+    log_time curr = start;
 
     LogBufferElement* lastElement = nullptr;  // iterator corruption paranoia
     static const size_t maxSkip = 4194304;    // maximum entries to skip
@@ -1141,10 +1158,6 @@
             continue;
         }
 
-        if (element->getRealTime() <= start) {
-            continue;
-        }
-
         // NB: calling out to another object with wrlock() held (safe)
         if (filter) {
             int ret = (*filter)(element, arg);
@@ -1171,10 +1184,10 @@
         unlock();
 
         // range locking in LastLogTimes looks after us
-        max = element->flushTo(reader, this, privileged, sameTid);
+        curr = element->flushTo(reader, this, privileged, sameTid);
 
-        if (max == element->FLUSH_ERROR) {
-            return max;
+        if (curr == element->FLUSH_ERROR) {
+            return curr;
         }
 
         skip = maxSkip;
@@ -1182,7 +1195,7 @@
     }
     unlock();
 
-    return max;
+    return curr;
 }
 
 std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index f0d6fcb..0942987 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -184,6 +184,9 @@
     static const log_time pruneMargin;
 
     void maybePrune(log_id_t id);
+    bool isBusy(log_time watermark);
+    void kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows);
+
     bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
     LogBufferElementCollection::iterator erase(
         LogBufferElementCollection::iterator it, bool coalesce = false);
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index a1b69e3..773ca06 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -77,9 +77,12 @@
 # to load the compiled *.so file and libmediandk.so can be used here.
 ###############################################################################
 namespace.rs.isolated = true
-namespace.rs.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.rs.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
 namespace.rs.permitted.paths = /vendor/${LIB}:/data
 
+namespace.rs.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+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.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:libutils.so:libc++.so:libz.so
@@ -90,10 +93,10 @@
 # This namespace is exclusively for vndk-sp libs.
 ###############################################################################
 namespace.vndk.isolated = true
-namespace.vndk.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
 namespace.vndk.permitted.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl
 
-namespace.vndk.asan.search.paths = /data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.vndk.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
 namespace.vndk.asan.permitted.paths = /data/asan/vendor/${LIB}/hw:/vendor/${LIB}/hw:/data/asan/vendor/${LIB}/egl:/vendor/${LIB}/egl
 
 # When these NDK libs are required inside this namespace, then it is redirected
@@ -105,6 +108,6 @@
 
 [vendor]
 namespace.default.isolated = false
-namespace.default.search.paths = /vendor/${LIB}:/system/${LIB}/vndk-sp:/system/${LIB}
+namespace.default.search.paths = /vendor/${LIB}:/vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/system/${LIB}
 
-namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
+namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a224d5e..c006d80 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -7,6 +7,7 @@
 import /init.environ.rc
 import /init.usb.rc
 import /init.${ro.hardware}.rc
+import /vendor/etc/init/hw/init.${ro.hardware}.rc
 import /init.usb.configfs.rc
 import /init.${ro.zygote}.rc
 
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 81cf315..4f4fc5d 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -5,9 +5,12 @@
         "grep",
         "gzip",
         "mkshrc",
+        "mkshrc_vendor",
         "reboot",
         "sh",
+        "sh_vendor",
         "toolbox",
         "toybox",
+        "toybox_vendor",
     ],
 }
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
new file mode 100644
index 0000000..1c9fb20
--- /dev/null
+++ b/toolbox/Android.bp
@@ -0,0 +1,44 @@
+common_cflags = [
+    "-Werror",
+    "-Wno-unused-parameter",
+    "-Wno-unused-const-variable",
+    "-include bsd-compatibility.h"
+]
+
+cc_library_static {
+    srcs: [
+        "upstream-netbsd/bin/dd/args.c",
+        "upstream-netbsd/bin/dd/conv.c",
+        "upstream-netbsd/bin/dd/dd.c",
+        "upstream-netbsd/bin/dd/dd_hostops.c",
+        "upstream-netbsd/bin/dd/misc.c",
+        "upstream-netbsd/bin/dd/position.c",
+        "upstream-netbsd/lib/libc/gen/getbsize.c",
+        "upstream-netbsd/lib/libc/gen/humanize_number.c",
+        "upstream-netbsd/lib/libc/stdlib/strsuftoll.c",
+        "upstream-netbsd/lib/libc/string/swab.c",
+        "upstream-netbsd/lib/libutil/raise_default_signal.c",
+    ],
+    cflags: common_cflags + [
+        "-Dmain=dd_main",
+        "-DNO_CONV",
+    ],
+    local_include_dirs: ["upstream-netbsd/include/"],
+    name: "libtoolbox_dd",
+}
+
+// We build BSD grep separately, so it can provide egrep and fgrep too.
+cc_binary {
+    name: "grep",
+    srcs: [
+        "upstream-netbsd/usr.bin/grep/fastgrep.c",
+        "upstream-netbsd/usr.bin/grep/file.c",
+        "upstream-netbsd/usr.bin/grep/grep.c",
+        "upstream-netbsd/usr.bin/grep/queue.c",
+        "upstream-netbsd/usr.bin/grep/util.c",
+    ],
+    cflags: common_cflags,
+    local_include_dirs: ["upstream-netbsd/include/"],
+    symlinks: ["egrep", "fgrep"],
+
+}
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index d6ead1a..94029d8 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -1,30 +1,9 @@
 LOCAL_PATH:= $(call my-dir)
 
-
 common_cflags := \
     -Werror -Wno-unused-parameter -Wno-unused-const-variable \
     -include bsd-compatibility.h \
 
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
-    upstream-netbsd/bin/dd/args.c \
-    upstream-netbsd/bin/dd/conv.c \
-    upstream-netbsd/bin/dd/dd.c \
-    upstream-netbsd/bin/dd/dd_hostops.c \
-    upstream-netbsd/bin/dd/misc.c \
-    upstream-netbsd/bin/dd/position.c \
-    upstream-netbsd/lib/libc/gen/getbsize.c \
-    upstream-netbsd/lib/libc/gen/humanize_number.c \
-    upstream-netbsd/lib/libc/stdlib/strsuftoll.c \
-    upstream-netbsd/lib/libc/string/swab.c \
-    upstream-netbsd/lib/libutil/raise_default_signal.c
-LOCAL_CFLAGS += $(common_cflags) -Dmain=dd_main -DNO_CONV
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_MODULE := libtoolbox_dd
-include $(BUILD_STATIC_LIBRARY)
-
-
 include $(CLEAR_VARS)
 
 BSD_TOOLS := \
@@ -80,18 +59,3 @@
 $(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py $(UAPI_INPUT_EVENT_CODES_H)
 $(INPUT_H_LABELS_H):
 	$(transform-generated-source)
-
-
-# We build BSD grep separately, so it can provide egrep and fgrep too.
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
-    upstream-netbsd/usr.bin/grep/fastgrep.c \
-    upstream-netbsd/usr.bin/grep/file.c \
-    upstream-netbsd/usr.bin/grep/grep.c \
-    upstream-netbsd/usr.bin/grep/queue.c \
-    upstream-netbsd/usr.bin/grep/util.c
-LOCAL_CFLAGS += $(common_cflags)
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_MODULE := grep
-LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,egrep fgrep,ln -sf grep $(TARGET_OUT)/bin/$(t);)
-include $(BUILD_EXECUTABLE)