Merge "liblp: Remove alignment_offset handling."
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index c8dbf77..dcf92be 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -3,3 +3,6 @@
 
 [Builtin Hooks Options]
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
+
+[Hook Scripts]
+aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
diff --git a/adb/Android.bp b/adb/Android.bp
index 19e921f..432770c 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -165,17 +165,26 @@
     "adb_unique_fd.cpp",
     "adb_utils.cpp",
     "fdevent/fdevent.cpp",
-    "fdevent/fdevent_poll.cpp",
     "services.cpp",
     "sockets.cpp",
     "socket_spec.cpp",
     "sysdeps/errno.cpp",
     "transport.cpp",
     "transport_fd.cpp",
-    "transport_local.cpp",
     "types.cpp",
 ]
 
+libadb_darwin_srcs = [
+    "fdevent/fdevent_poll.cpp",
+]
+
+libadb_windows_srcs = [
+    "fdevent/fdevent_poll.cpp",
+    "sysdeps_win32.cpp",
+    "sysdeps/win32/errno.cpp",
+    "sysdeps/win32/stat.cpp",
+]
+
 libadb_posix_srcs = [
     "sysdeps_unix.cpp",
     "sysdeps/posix/network.cpp",
@@ -207,6 +216,7 @@
         "client/adb_wifi.cpp",
         "client/usb_libusb.cpp",
         "client/usb_dispatch.cpp",
+        "client/transport_local.cpp",
         "client/transport_mdns.cpp",
         "client/transport_usb.cpp",
         "client/pairing/pairing_client.cpp",
@@ -219,7 +229,7 @@
             srcs: ["client/usb_linux.cpp"] + libadb_linux_srcs,
         },
         darwin: {
-            srcs: ["client/usb_osx.cpp"],
+            srcs: ["client/usb_osx.cpp"] + libadb_darwin_srcs,
         },
         not_windows: {
             srcs: libadb_posix_srcs,
@@ -228,10 +238,7 @@
             enabled: true,
             srcs: [
                 "client/usb_windows.cpp",
-                "sysdeps_win32.cpp",
-                "sysdeps/win32/errno.cpp",
-                "sysdeps/win32/stat.cpp",
-            ],
+            ] + libadb_windows_srcs,
             shared_libs: ["AdbWinApi"],
         },
     },
@@ -383,10 +390,11 @@
     compile_multilib: "both",
 
     srcs: libadb_srcs + libadb_linux_srcs + libadb_posix_srcs + [
+        "daemon/adb_wifi.cpp",
         "daemon/auth.cpp",
         "daemon/jdwp_service.cpp",
         "daemon/logging.cpp",
-        "daemon/adb_wifi.cpp",
+        "daemon/transport_local.cpp",
     ],
 
     generated_headers: ["platform_tools_version"],
@@ -585,7 +593,6 @@
 cc_binary {
     name: "adbd",
     defaults: ["adbd_defaults", "host_adbd_supported", "libadbd_binary_dependencies"],
-    stl: "libc++_static",
     recovery_available: true,
     apex_available: ["com.android.adbd"],
 
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 06fdb69..dcec0ba 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1076,6 +1076,25 @@
     g_reject_kill_server = value;
 }
 
+static bool handle_mdns_request(std::string_view service, int reply_fd) {
+    if (!android::base::ConsumePrefix(&service, "mdns:")) {
+        return false;
+    }
+
+    if (service == "check") {
+        std::string check = mdns_check();
+        SendOkay(reply_fd, check);
+        return true;
+    }
+    if (service == "services") {
+        std::string services_list = mdns_list_discovered_services();
+        SendOkay(reply_fd, services_list);
+        return true;
+    }
+
+    return false;
+}
+
 HostRequestResult handle_host_request(std::string_view service, TransportType type,
                                       const char* serial, TransportId transport_id, int reply_fd,
                                       asocket* s) {
@@ -1320,6 +1339,10 @@
         return HostRequestResult::Handled;
     }
 
+    if (handle_mdns_request(service, reply_fd)) {
+        return HostRequestResult::Handled;
+    }
+
     return HostRequestResult::Unhandled;
 }
 
diff --git a/adb/adb_trace.cpp b/adb/adb_trace.cpp
index cea24fe..c579dde 100644
--- a/adb/adb_trace.cpp
+++ b/adb/adb_trace.cpp
@@ -89,18 +89,13 @@
 
 int adb_trace_mask;
 
-std::string get_trace_setting_from_env() {
+std::string get_trace_setting() {
+#if ADB_HOST
     const char* setting = getenv("ADB_TRACE");
     if (setting == nullptr) {
         setting = "";
     }
-
-    return std::string(setting);
-}
-
-std::string get_trace_setting() {
-#if ADB_HOST
-    return get_trace_setting_from_env();
+    return setting;
 #else
     return android::base::GetProperty("persist.adb.trace_mask", "");
 #endif
diff --git a/adb/adb_wifi.h b/adb/adb_wifi.h
index 585748c..3a6b0b1 100644
--- a/adb/adb_wifi.h
+++ b/adb/adb_wifi.h
@@ -27,6 +27,9 @@
                           std::string& response);
 bool adb_wifi_is_known_host(const std::string& host);
 
+std::string mdns_check();
+std::string mdns_list_discovered_services();
+
 #else  // !ADB_HOST
 
 struct AdbdAuthContext;
diff --git a/adb/apex/Android.bp b/adb/apex/Android.bp
index 4346f67..ddb17da 100644
--- a/adb/apex/Android.bp
+++ b/adb/apex/Android.bp
@@ -1,6 +1,7 @@
 apex_defaults {
     name: "com.android.adbd-defaults",
     updatable: true,
+    min_sdk_version: "R",
 
     binaries: ["adbd"],
     compile_multilib: "both",
diff --git a/adb/client/adb_client.h b/adb/client/adb_client.h
index 27be28f..caf4e86 100644
--- a/adb/client/adb_client.h
+++ b/adb/client/adb_client.h
@@ -90,8 +90,9 @@
 
 // ADB Secure DNS service interface. Used to query what ADB Secure DNS services have been
 // resolved, and to run some kind of callback for each one.
-using adb_secure_foreach_service_callback = std::function<void(
-        const char* _Nonnull service_name, const char* _Nonnull ip_address, uint16_t port)>;
+using adb_secure_foreach_service_callback =
+        std::function<void(const char* _Nonnull service_name, const char* _Nonnull reg_type,
+                           const char* _Nonnull ip_address, uint16_t port)>;
 
 // Queries pairing/connect services that have been discovered and resolved.
 // If |host_name| is not null, run |cb| only for services
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 59c8563..e562f8b 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -154,6 +154,14 @@
     *buf = '\0';
 }
 
+static unique_fd send_command(const std::vector<std::string>& cmd_args, std::string* error) {
+    if (is_abb_exec_supported()) {
+        return send_abb_exec_command(cmd_args, error);
+    } else {
+        return unique_fd(adb_connect(android::base::Join(cmd_args, " "), error));
+    }
+}
+
 static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy) {
     printf("Performing Streamed Install\n");
 
@@ -226,12 +234,7 @@
         cmd_args.push_back("--apex");
     }
 
-    unique_fd remote_fd;
-    if (use_abb_exec) {
-        remote_fd = send_abb_exec_command(cmd_args, &error);
-    } else {
-        remote_fd.reset(adb_connect(android::base::Join(cmd_args, " "), &error));
-    }
+    unique_fd remote_fd = send_command(cmd_args, &error);
     if (remote_fd < 0) {
         fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
         return 1;
@@ -547,24 +550,28 @@
 
     if (first_apk == -1) error_exit("need APK file on command line");
 
-    std::string install_cmd;
-    if (best_install_mode() == INSTALL_PUSH) {
-        install_cmd = "exec:pm";
-    } else {
-        install_cmd = "exec:cmd package";
-    }
+    const bool use_abb_exec = is_abb_exec_supported();
 
-    std::string cmd = android::base::StringPrintf("%s install-create -S %" PRIu64,
-                                                  install_cmd.c_str(), total_size);
+    const std::string install_cmd =
+            use_abb_exec ? "package"
+                         : best_install_mode() == INSTALL_PUSH ? "exec:pm" : "exec:cmd package";
+
+    std::vector<std::string> cmd_args = {install_cmd, "install-create", "-S",
+                                         std::to_string(total_size)};
+    cmd_args.reserve(first_apk + 4);
     for (int i = 1; i < first_apk; i++) {
-        cmd += " " + escape_arg(argv[i]);
+        if (use_abb_exec) {
+            cmd_args.push_back(argv[i]);
+        } else {
+            cmd_args.push_back(escape_arg(argv[i]));
+        }
     }
 
     // Create install session
     std::string error;
     char buf[BUFSIZ];
     {
-        unique_fd fd(adb_connect(cmd, &error));
+        unique_fd fd = send_command(cmd_args, &error);
         if (fd < 0) {
             fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
             return EXIT_FAILURE;
@@ -586,6 +593,7 @@
         fputs(buf, stderr);
         return EXIT_FAILURE;
     }
+    const auto session_id_str = std::to_string(session_id);
 
     // Valid session, now stream the APKs
     bool success = true;
@@ -598,10 +606,15 @@
             goto finalize_session;
         }
 
-        std::string cmd =
-                android::base::StringPrintf("%s install-write -S %" PRIu64 " %d %s -",
-                                            install_cmd.c_str(), static_cast<uint64_t>(sb.st_size),
-                                            session_id, android::base::Basename(file).c_str());
+        std::vector<std::string> cmd_args = {
+                install_cmd,
+                "install-write",
+                "-S",
+                std::to_string(sb.st_size),
+                session_id_str,
+                android::base::Basename(file),
+                "-",
+        };
 
         unique_fd local_fd(adb_open(file, O_RDONLY | O_CLOEXEC));
         if (local_fd < 0) {
@@ -611,7 +624,7 @@
         }
 
         std::string error;
-        unique_fd remote_fd(adb_connect(cmd, &error));
+        unique_fd remote_fd = send_command(cmd_args, &error);
         if (remote_fd < 0) {
             fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
             success = false;
@@ -636,10 +649,13 @@
 
 finalize_session:
     // Commit session if we streamed everything okay; otherwise abandon.
-    std::string service = android::base::StringPrintf("%s install-%s %d", install_cmd.c_str(),
-                                                      success ? "commit" : "abandon", session_id);
+    std::vector<std::string> service_args = {
+            install_cmd,
+            success ? "install-commit" : "install-abandon",
+            session_id_str,
+    };
     {
-        unique_fd fd(adb_connect(service, &error));
+        unique_fd fd = send_command(service_args, &error);
         if (fd < 0) {
             fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
             return EXIT_FAILURE;
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 29f9dc1..f0a287d 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -127,6 +127,8 @@
         "       localfilesystem:<unix domain socket name>\n"
         " reverse --remove REMOTE  remove specific reverse socket connection\n"
         " reverse --remove-all     remove all reverse socket connections from device\n"
+        " mdns check               check if mdns discovery is available\n"
+        " mdns services            list all discovered services\n"
         "\n"
         "file transfer:\n"
         " push [--sync] [-z ALGORITHM] [-Z] LOCAL... REMOTE\n"
@@ -238,6 +240,7 @@
         " $ANDROID_SERIAL          serial number to connect to (see -s)\n"
         " $ANDROID_LOG_TAGS        tags to be used by logcat (see logcat --help)\n"
         " $ADB_LOCAL_TRANSPORT_MAX_PORT max emulator scan port (default 5585, 16 emus)\n"
+        " $ADB_MDNS_AUTO_CONNECT   comma-separated list of mdns services to allow auto-connect (default adb-tls-connect)\n"
     );
     // clang-format on
 }
@@ -1910,6 +1913,29 @@
 
         ReadOrderlyShutdown(fd);
         return 0;
+    } else if (!strcmp(argv[0], "mdns")) {
+        --argc;
+        if (argc < 1) error_exit("mdns requires an argument");
+        ++argv;
+
+        std::string error;
+        if (!adb_check_server_version(&error)) {
+            error_exit("failed to check server version: %s", error.c_str());
+        }
+
+        std::string query = "host:mdns:";
+        if (!strcmp(argv[0], "check")) {
+            if (argc != 1) error_exit("mdns %s doesn't take any arguments", argv[0]);
+            query += "check";
+        } else if (!strcmp(argv[0], "services")) {
+            if (argc != 1) error_exit("mdns %s doesn't take any arguments", argv[0]);
+            query += "services";
+            printf("List of discovered mdns services\n");
+        } else {
+            error_exit("unknown mdns command [%s]", argv[0]);
+        }
+
+        return adb_query_command(query);
     }
     /* do_sync_*() commands */
     else if (!strcmp(argv[0], "ls")) {
diff --git a/adb/transport_local.cpp b/adb/client/transport_local.cpp
similarity index 78%
rename from adb/transport_local.cpp
rename to adb/client/transport_local.cpp
index 5ec8e16..15a0724 100644
--- a/adb/transport_local.cpp
+++ b/adb/client/transport_local.cpp
@@ -38,10 +38,6 @@
 #include <android-base/thread_annotations.h>
 #include <cutils/sockets.h>
 
-#if !ADB_HOST
-#include <android-base/properties.h>
-#endif
-
 #include "adb.h"
 #include "adb_io.h"
 #include "adb_unique_fd.h"
@@ -49,8 +45,6 @@
 #include "socket_spec.h"
 #include "sysdeps/chrono.h"
 
-#if ADB_HOST
-
 // Android Wear has been using port 5601 in all of its documentation/tooling,
 // but we search for emulators on ports [5554, 5555 + ADB_LOCAL_TRANSPORT_MAX].
 // Avoid stomping on their port by restricting the active scanning range.
@@ -76,9 +70,8 @@
 
 // We keep a map from emulator port to transport.
 // TODO: weak_ptr?
-static auto& local_transports GUARDED_BY(local_transports_lock) =
-    *new std::unordered_map<int, atransport*>();
-#endif /* ADB_HOST */
+static std::unordered_map<int, atransport*> local_transports
+        [[clang::no_destroy]] GUARDED_BY(local_transports_lock);
 
 bool local_connect(int port) {
     std::string dummy;
@@ -140,21 +133,19 @@
     }
 }
 
-
 int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error) {
     unique_fd fd;
 
-#if ADB_HOST
     if (find_emulator_transport_by_adb_port(adb_port) != nullptr ||
         find_emulator_transport_by_console_port(console_port) != nullptr) {
         return -1;
     }
 
-    const char *host = getenv("ADBHOST");
+    const char* host = getenv("ADBHOST");
     if (host) {
         fd.reset(network_connect(host, adb_port, SOCK_STREAM, 0, error));
     }
-#endif
+
     if (fd < 0) {
         fd.reset(network_loopback_client(adb_port, SOCK_STREAM, error));
     }
@@ -173,8 +164,6 @@
     return -1;
 }
 
-#if ADB_HOST
-
 static void PollAllLocalPortsForEmulator() {
     // Try to connect to any number of running emulator instances.
     for (int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; port <= adb_local_transport_max_port;
@@ -194,8 +183,8 @@
 
 // Retry emulators just kicked.
 static std::vector<RetryPort>& retry_ports = *new std::vector<RetryPort>;
-std::mutex &retry_ports_lock = *new std::mutex;
-std::condition_variable &retry_ports_cond = *new std::condition_variable;
+std::mutex& retry_ports_lock = *new std::mutex;
+std::condition_variable& retry_ports_cond = *new std::condition_variable;
 
 static void client_socket_thread(std::string_view) {
     adb_thread_setname("client_socket_thread");
@@ -220,7 +209,7 @@
         std::vector<RetryPort> next_ports;
         for (auto& port : ports) {
             VLOG(TRANSPORT) << "retry port " << port.port << ", last retry_count "
-                << port.retry_count;
+                            << port.retry_count;
             if (local_connect(port.port)) {
                 VLOG(TRANSPORT) << "retry port " << port.port << " successfully";
                 continue;
@@ -240,77 +229,12 @@
     }
 }
 
-#else  // !ADB_HOST
-
-void server_socket_thread(std::function<unique_fd(std::string_view, std::string*)> listen_func,
-                          std::string_view addr) {
-    adb_thread_setname("server socket");
-
-    unique_fd serverfd;
-    std::string error;
-
-    while (serverfd == -1) {
-        errno = 0;
-        serverfd = listen_func(addr, &error);
-        if (errno == EAFNOSUPPORT || errno == EINVAL || errno == EPROTONOSUPPORT) {
-            D("unrecoverable error: '%s'", error.c_str());
-            return;
-        } else if (serverfd < 0) {
-            D("server: cannot bind socket yet: %s", error.c_str());
-            std::this_thread::sleep_for(1s);
-            continue;
-        }
-        close_on_exec(serverfd.get());
-    }
-
-    while (true) {
-        D("server: trying to get new connection from fd %d", serverfd.get());
-        unique_fd fd(adb_socket_accept(serverfd, nullptr, nullptr));
-        if (fd >= 0) {
-            D("server: new connection on fd %d", fd.get());
-            close_on_exec(fd.get());
-            disable_tcp_nagle(fd.get());
-            std::string serial = android::base::StringPrintf("host-%d", fd.get());
-            // We don't care about port value in "register_socket_transport" as it is used
-            // only from ADB_HOST. "server_socket_thread" is never called from ADB_HOST.
-            register_socket_transport(
-                    std::move(fd), std::move(serial), 0, 1,
-                    [](atransport*) { return ReconnectResult::Abort; }, false);
-        }
-    }
-    D("transport: server_socket_thread() exiting");
-}
-
-#endif
-
-#if !ADB_HOST
-unique_fd adb_listen(std::string_view addr, std::string* error) {
-    return unique_fd{socket_spec_listen(addr, error, nullptr)};
-}
-#endif
-
 void local_init(const std::string& addr) {
-#if ADB_HOST
     D("transport: local client init");
     std::thread(client_socket_thread, addr).detach();
     adb_local_transport_max_port_env_override();
-#elif !defined(__ANDROID__)
-    // Host adbd.
-    D("transport: local server init");
-    std::thread(server_socket_thread, adb_listen, addr).detach();
-#else
-    D("transport: local server init");
-    // For the adbd daemon in the system image we need to distinguish
-    // between the device, and the emulator.
-    if (addr.starts_with("tcp:") && use_qemu_goldfish()) {
-        std::thread(qemu_socket_thread, addr).detach();
-    } else {
-        std::thread(server_socket_thread, adb_listen, addr).detach();
-    }
-#endif // !ADB_HOST
 }
 
-#if ADB_HOST
 struct EmulatorConnection : public FdConnection {
     EmulatorConnection(unique_fd fd, int local_port)
         : FdConnection(std::move(fd)), local_port_(local_port) {}
@@ -336,7 +260,7 @@
 
 /* Only call this function if you already hold local_transports_lock. */
 static atransport* find_emulator_transport_by_adb_port_locked(int adb_port)
-    REQUIRES(local_transports_lock) {
+        REQUIRES(local_transports_lock) {
     auto it = local_transports.find(adb_port);
     if (it == local_transports.end()) {
         return nullptr;
@@ -352,7 +276,6 @@
 atransport* find_emulator_transport_by_console_port(int console_port) {
     return find_transport(getEmulatorSerialString(console_port).c_str());
 }
-#endif
 
 std::string getEmulatorSerialString(int console_port) {
     return android::base::StringPrintf("emulator-%d", console_port);
@@ -363,7 +286,6 @@
 
     t->type = kTransportLocal;
 
-#if ADB_HOST
     // Emulator connection.
     if (local) {
         auto emulator_connection = std::make_unique<EmulatorConnection>(std::move(fd), adb_port);
@@ -380,7 +302,6 @@
 
         return fail;
     }
-#endif
 
     // Regular tcp connection.
     auto fd_connection = std::make_unique<FdConnection>(std::move(fd));
diff --git a/adb/client/transport_mdns.cpp b/adb/client/transport_mdns.cpp
index 22b9b18..2b6aa7c 100644
--- a/adb/client/transport_mdns.cpp
+++ b/adb/client/transport_mdns.cpp
@@ -26,6 +26,7 @@
 
 #include <memory>
 #include <thread>
+#include <unordered_set>
 #include <vector>
 
 #include <android-base/stringprintf.h>
@@ -42,27 +43,75 @@
 
 static DNSServiceRef service_refs[kNumADBDNSServices];
 static fdevent* service_ref_fdes[kNumADBDNSServices];
+static auto& g_autoconn_whitelist = *new std::unordered_set<int>();
 
-static int adb_DNSServiceIndexByName(const char* regType) {
+static int adb_DNSServiceIndexByName(std::string_view regType) {
     for (int i = 0; i < kNumADBDNSServices; ++i) {
-        if (!strncmp(regType, kADBDNSServices[i], strlen(kADBDNSServices[i]))) {
+        if (!strncmp(regType.data(), kADBDNSServices[i], strlen(kADBDNSServices[i]))) {
             return i;
         }
     }
     return -1;
 }
 
-static bool adb_DNSServiceShouldConnect(const char* regType, const char* serviceName) {
-    int index = adb_DNSServiceIndexByName(regType);
-    if (index == kADBTransportServiceRefIndex) {
-        // Ignore adb-EMULATOR* service names, as it interferes with the
-        // emulator ports that are already connected.
-        if (android::base::StartsWith(serviceName, "adb-EMULATOR")) {
-            LOG(INFO) << "Ignoring emulator transport service [" << serviceName << "]";
-            return false;
+static void config_auto_connect_services() {
+    // ADB_MDNS_AUTO_CONNECT is a comma-delimited list of mdns services
+    // that are allowed to auto-connect. By default, only allow "adb-tls-connect"
+    // to auto-connect, since this is filtered down to auto-connect only to paired
+    // devices.
+    g_autoconn_whitelist.insert(kADBSecureConnectServiceRefIndex);
+    const char* srvs = getenv("ADB_MDNS_AUTO_CONNECT");
+    if (!srvs) {
+        return;
+    }
+
+    if (strcmp(srvs, "0") == 0) {
+        D("Disabling all auto-connecting");
+        g_autoconn_whitelist.clear();
+        return;
+    }
+
+    if (strcmp(srvs, "1") == 0) {
+        D("Allow all auto-connecting");
+        g_autoconn_whitelist.insert(kADBTransportServiceRefIndex);
+        return;
+    }
+
+    // Selectively choose which services to allow auto-connect.
+    // E.g. ADB_MDNS_AUTO_CONNECT=adb,adb-tls-connect would allow
+    // _adb._tcp and _adb-tls-connnect._tcp services to auto-connect.
+    auto srvs_list = android::base::Split(srvs, ",");
+    std::unordered_set<int> new_whitelist;
+    for (const auto& item : srvs_list) {
+        auto full_srv = android::base::StringPrintf("_%s._tcp", item.data());
+        int idx = adb_DNSServiceIndexByName(full_srv);
+        if (idx >= 0) {
+            new_whitelist.insert(idx);
         }
     }
-    return (index == kADBTransportServiceRefIndex || index == kADBSecureConnectServiceRefIndex);
+
+    if (!new_whitelist.empty()) {
+        g_autoconn_whitelist = std::move(new_whitelist);
+    }
+}
+
+static bool adb_DNSServiceShouldAutoConnect(const char* regType, const char* serviceName) {
+    // Try to auto-connect to any "_adb" or "_adb-tls-connect" services excluding emulator services.
+    int index = adb_DNSServiceIndexByName(regType);
+    if (index != kADBTransportServiceRefIndex && index != kADBSecureConnectServiceRefIndex) {
+        return false;
+    }
+    if (g_autoconn_whitelist.find(index) == g_autoconn_whitelist.end()) {
+        D("Auto-connect for regType '%s' disabled", regType);
+        return false;
+    }
+    // Ignore adb-EMULATOR* service names, as it interferes with the
+    // emulator ports that are already connected.
+    if (android::base::StartsWith(serviceName, "adb-EMULATOR")) {
+        LOG(INFO) << "Ignoring emulator transport service [" << serviceName << "]";
+        return false;
+    }
+    return true;
 }
 
 // Use adb_DNSServiceRefSockFD() instead of calling DNSServiceRefSockFD()
@@ -196,7 +245,7 @@
 
         // adb secure service needs to do something different from just
         // connecting here.
-        if (adb_DNSServiceShouldConnect(regType_.c_str(), serviceName_.c_str())) {
+        if (adb_DNSServiceShouldAutoConnect(regType_.c_str(), serviceName_.c_str())) {
             std::string response;
             D("Attempting to serviceName=[%s], regtype=[%s] ipaddr=(%s:%hu)", serviceName_.c_str(),
               regType_.c_str(), ip_addr_, port_);
@@ -216,6 +265,9 @@
 
         int adbSecureServiceType = serviceIndex();
         switch (adbSecureServiceType) {
+            case kADBTransportServiceRefIndex:
+                sAdbTransportServices->push_back(this);
+                break;
             case kADBSecurePairingServiceRefIndex:
                 sAdbSecurePairingServices->push_back(this);
                 break;
@@ -233,16 +285,21 @@
 
     std::string serviceName() const { return serviceName_; }
 
+    std::string regType() const { return regType_; }
+
     std::string ipAddress() const { return ip_addr_; }
 
     uint16_t port() const { return port_; }
 
     using ServiceRegistry = std::vector<ResolvedService*>;
 
+    // unencrypted tcp connections
+    static ServiceRegistry* sAdbTransportServices;
+
     static ServiceRegistry* sAdbSecurePairingServices;
     static ServiceRegistry* sAdbSecureConnectServices;
 
-    static void initAdbSecure();
+    static void initAdbServiceRegistries();
 
     static void forEachService(const ServiceRegistry& services, const std::string& hostname,
                                adb_secure_foreach_service_callback cb);
@@ -264,13 +321,19 @@
 };
 
 // static
+std::vector<ResolvedService*>* ResolvedService::sAdbTransportServices = NULL;
+
+// static
 std::vector<ResolvedService*>* ResolvedService::sAdbSecurePairingServices = NULL;
 
 // static
 std::vector<ResolvedService*>* ResolvedService::sAdbSecureConnectServices = NULL;
 
 // static
-void ResolvedService::initAdbSecure() {
+void ResolvedService::initAdbServiceRegistries() {
+    if (!sAdbTransportServices) {
+        sAdbTransportServices = new ServiceRegistry;
+    }
     if (!sAdbSecurePairingServices) {
         sAdbSecurePairingServices = new ServiceRegistry;
     }
@@ -283,17 +346,18 @@
 void ResolvedService::forEachService(const ServiceRegistry& services,
                                      const std::string& wanted_service_name,
                                      adb_secure_foreach_service_callback cb) {
-    initAdbSecure();
+    initAdbServiceRegistries();
 
     for (auto service : services) {
         auto service_name = service->serviceName();
+        auto reg_type = service->regType();
         auto ip = service->ipAddress();
         auto port = service->port();
 
         if (wanted_service_name == "") {
-            cb(service_name.c_str(), ip.c_str(), port);
+            cb(service_name.c_str(), reg_type.c_str(), ip.c_str(), port);
         } else if (service_name == wanted_service_name) {
-            cb(service_name.c_str(), ip.c_str(), port);
+            cb(service_name.c_str(), reg_type.c_str(), ip.c_str(), port);
         }
     }
 }
@@ -301,7 +365,7 @@
 // static
 bool ResolvedService::connectByServiceName(const ServiceRegistry& services,
                                            const std::string& service_name) {
-    initAdbSecure();
+    initAdbServiceRegistries();
     for (auto service : services) {
         if (service_name == service->serviceName()) {
             D("Got service_name match [%s]", service->serviceName().c_str());
@@ -398,6 +462,9 @@
     int index = adb_DNSServiceIndexByName(regType);
     ResolvedService::ServiceRegistry* services;
     switch (index) {
+        case kADBTransportServiceRefIndex:
+            services = ResolvedService::sAdbTransportServices;
+            break;
         case kADBSecurePairingServiceRefIndex:
             services = ResolvedService::sAdbSecurePairingServices;
             break;
@@ -521,8 +588,15 @@
 }
 
 void init_mdns_transport_discovery_thread(void) {
-    int errorCodes[kNumADBDNSServices];
+    config_auto_connect_services();
+    std::string res;
+    std::for_each(g_autoconn_whitelist.begin(), g_autoconn_whitelist.end(), [&](const int& i) {
+        res += kADBDNSServices[i];
+        res += ",";
+    });
+    D("mdns auto-connect whitelist: [%s]", res.data());
 
+    int errorCodes[kNumADBDNSServices];
     for (int i = 0; i < kNumADBDNSServices; ++i) {
         errorCodes[i] = DNSServiceBrowse(&service_refs[i], 0, 0, kADBDNSServices[i], nullptr,
                                          on_service_browsed, nullptr);
@@ -542,6 +616,34 @@
 }
 
 void init_mdns_transport_discovery(void) {
-    ResolvedService::initAdbSecure();
+    ResolvedService::initAdbServiceRegistries();
     std::thread(init_mdns_transport_discovery_thread).detach();
 }
+
+std::string mdns_check() {
+    uint32_t daemon_version;
+    uint32_t sz = sizeof(daemon_version);
+
+    auto dnserr = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &daemon_version, &sz);
+    std::string result = "ERROR: mdns daemon unavailable";
+    if (dnserr != kDNSServiceErr_NoError) {
+        return result;
+    }
+
+    result = android::base::StringPrintf("mdns daemon version [%u]", daemon_version);
+    return result;
+}
+
+std::string mdns_list_discovered_services() {
+    std::string result;
+    auto cb = [&](const char* service_name, const char* reg_type, const char* ip_addr,
+                  uint16_t port) {
+        result += android::base::StringPrintf("%s\t%s\t%s:%u\n", service_name, reg_type, ip_addr,
+                                              port);
+    };
+
+    ResolvedService::forEachService(*ResolvedService::sAdbTransportServices, "", cb);
+    ResolvedService::forEachService(*ResolvedService::sAdbSecureConnectServices, "", cb);
+    ResolvedService::forEachService(*ResolvedService::sAdbSecurePairingServices, "", cb);
+    return result;
+}
diff --git a/adb/coverage.sh b/adb/coverage.sh
deleted file mode 100755
index 50ccdf5..0000000
--- a/adb/coverage.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2020 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.
-
-set -euxo pipefail
-
-adb root
-adb shell logcat -c -G128M
-adb shell setprop persist.adb.trace_mask 1
-adb shell killall adbd
-
-# TODO: Add `adb transport-id` and wait-for-offline on it.
-sleep 5
-
-adb wait-for-device shell rm "/data/misc/trace/*"
-
-./test_device.py
-
-# Dump traces from the currently running adbd.
-adb shell killall -37 adbd
-
-echo Waiting for adbd to finish dumping traces
-sleep 5
-
-TRACEDIR=`mktemp -d`
-adb pull /data/misc/trace "$TRACEDIR"/
-echo Pulled traces to $TRACEDIR
-
-
-# Identify which of the trace files are actually adbd, in case something else exited simultaneously.
-ADBD_PIDS=$(adb shell "logcat -d -s adbd --format=process | grep 'adbd started' | cut -c 3-7 | tr -d ' ' | sort | uniq")
-mkdir "$TRACEDIR"/adbd_traces
-
-adb shell 'setprop persist.adb.trace_mask 0; killall adbd'
-
-IFS=$'\n'
-for PID in $ADBD_PIDS; do
-  cp "$TRACEDIR"/trace/clang-$PID-*.profraw "$TRACEDIR"/adbd_traces 2>/dev/null || true
-done
-
-llvm-profdata merge --output="$TRACEDIR"/adbd.profdata "$TRACEDIR"/adbd_traces/*
-
-cd $ANDROID_BUILD_TOP
-llvm-cov report --instr-profile="$TRACEDIR"/adbd.profdata \
-  $ANDROID_PRODUCT_OUT/apex/com.android.adbd/bin/adbd \
-  --show-region-summary=false \
-  /proc/self/cwd/system/core/adb
-
-llvm-cov show --instr-profile="$TRACEDIR"/adbd.profdata \
-  $ANDROID_PRODUCT_OUT/apex/com.android.adbd/bin/adbd \
-  --format=html \
-  /proc/self/cwd/system/core/adb > $TRACEDIR/report.html
diff --git a/adb/coverage/.gitignore b/adb/coverage/.gitignore
new file mode 100644
index 0000000..b6a2582
--- /dev/null
+++ b/adb/coverage/.gitignore
@@ -0,0 +1,2 @@
+/adbd.profdata
+/report
diff --git a/adb/coverage/gen_coverage.sh b/adb/coverage/gen_coverage.sh
new file mode 100755
index 0000000..cced62a
--- /dev/null
+++ b/adb/coverage/gen_coverage.sh
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+OUTPUT_DIR=$(dirname "$0")
+. "$OUTPUT_DIR"/include.sh
+
+TRACEDIR=`mktemp -d`
+
+### Make sure we can connect to the device.
+
+# Get the device's wlan0 address.
+IP_ADDR=$(adb shell ip route get 0.0.0.0 oif wlan0 | sed -En -e 's/.*src (\S+)\s.*/\1/p')
+REMOTE_PORT=5555
+REMOTE=$IP_ADDR:$REMOTE_PORT
+LOCAL_SERIAL=$(adb shell getprop ro.serialno)
+
+# Check that we can connect to it.
+adb disconnect
+adb tcpip $REMOTE_PORT
+
+# TODO: Add `adb transport-id` and wait-for-offline on it.
+sleep 5
+
+adb connect $REMOTE
+
+REMOTE_FETCHED_SERIAL=$(adb -s $REMOTE shell getprop ro.serialno)
+
+if [[ "$LOCAL_SERIAL" != "$REMOTE_FETCHED_SERIAL" ]]; then
+  echo "Mismatch: local serial = $LOCAL_SERIAL, remote serial = $REMOTE_FETCHED_SERIAL"
+  exit 1
+fi
+
+# Back to USB, and make sure adbd is root.
+adb disconnect $REMOTE
+
+adb root
+adb wait-for-device usb
+
+# TODO: Add `adb transport-id` and wait-for-offline on it.
+sleep 5
+
+adb wait-for-device
+
+### Run the adb unit tests and fetch traces from them.
+mkdir "$TRACEDIR"/test_traces
+adb shell rm -rf /data/local/tmp/adb_coverage
+adb shell mkdir /data/local/tmp/adb_coverage
+
+for TEST in $ADB_TESTS; do
+  adb shell LLVM_PROFILE_FILE=/data/local/tmp/adb_coverage/$TEST.profraw /data/nativetest64/$TEST/$TEST
+  adb pull /data/local/tmp/adb_coverage/$TEST.profraw "$TRACEDIR"/test_traces/
+done
+
+adb pull /data/local/tmp/adb_coverage "$TRACEDIR"/test_traces
+
+# Clear logcat and increase the buffer to something ridiculous so we can fetch the pids of adbd later.
+adb shell logcat -c -G128M
+
+# Turn on extremely verbose logging so as to not count debug logging against us.
+adb shell setprop persist.adb.trace_mask 1
+
+### Run test_device.py over USB.
+adb shell killall adbd
+
+# TODO: Add `adb transport-id` and wait-for-offline on it.
+sleep 5
+
+adb wait-for-device shell rm -rf "/data/misc/trace/*" /data/local/tmp/adb_coverage/
+"$OUTPUT_DIR"/../test_device.py
+
+# Do a usb reset to exercise the disconnect code.
+adb_usbreset
+adb wait-for-device
+
+# Dump traces from the currently running adbd.
+adb shell killall -37 adbd
+
+echo Waiting for adbd to finish dumping traces
+sleep 5
+
+# Restart adbd in tcp mode.
+adb tcpip $REMOTE_PORT
+sleep 5
+adb connect $REMOTE
+adb -s $REMOTE wait-for-device
+
+# Run test_device.py again.
+ANDROID_SERIAL=$REMOTE "$OUTPUT_DIR"/../test_device.py
+
+# Dump traces again.
+adb disconnect $REMOTE
+adb shell killall -37 adbd
+
+echo Waiting for adbd to finish dumping traces
+sleep 5
+
+adb pull /data/misc/trace "$TRACEDIR"/
+echo Pulled traces to $TRACEDIR
+
+# Identify which of the trace files are actually adbd, in case something else exited simultaneously.
+ADBD_PIDS=$(adb shell "logcat -d -s adbd --format=process | grep 'adbd started' | cut -c 3-7 | tr -d ' ' | sort | uniq")
+mkdir "$TRACEDIR"/adbd_traces
+
+adb shell 'setprop persist.adb.trace_mask 0; killall adbd'
+
+IFS=$'\n'
+for PID in $ADBD_PIDS; do
+  cp "$TRACEDIR"/trace/clang-$PID-*.profraw "$TRACEDIR"/adbd_traces 2>/dev/null || true
+done
+unset IFS
+
+### Merge the traces.
+llvm-profdata merge --output="$OUTPUT_DIR"/adbd.profdata "$TRACEDIR"/adbd_traces/* "$TRACEDIR"/test_traces/*
diff --git a/adb/coverage/include.sh b/adb/coverage/include.sh
new file mode 100644
index 0000000..45ebc34
--- /dev/null
+++ b/adb/coverage/include.sh
@@ -0,0 +1,5 @@
+ADB_TESTS="adbd_test adb_crypto_test adb_pairing_auth_test adb_pairing_connection_test adb_tls_connection_test"
+ADB_TEST_BINARIES=""
+for TEST in $ADB_TESTS; do
+  ADB_TEST_BINARIES="--object=$ANDROID_PRODUCT_OUT/data/nativetest64/$TEST/$TEST $ADB_TEST_BINARIES"
+done
diff --git a/adb/coverage/report.sh b/adb/coverage/report.sh
new file mode 100755
index 0000000..257310c
--- /dev/null
+++ b/adb/coverage/report.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+OUTPUT_DIR=$(realpath $(dirname "$0"))
+. "$OUTPUT_DIR"/include.sh
+
+rm -rf "$OUTPUT_DIR"/report
+
+cd $ANDROID_BUILD_TOP
+llvm-cov show --instr-profile="$OUTPUT_DIR"/adbd.profdata \
+  $ANDROID_PRODUCT_OUT/apex/com.android.adbd/bin/adbd \
+  /proc/self/cwd/system/core/adb \
+  $ADB_TEST_BINARIES \
+  --show-region-summary=false \
+  --format=html -o "$OUTPUT_DIR"/report
+
+llvm-cov report --instr-profile="$OUTPUT_DIR"/adbd.profdata \
+  $ANDROID_PRODUCT_OUT/apex/com.android.adbd/bin/adbd \
+  /proc/self/cwd/system/core/adb \
+  $ADB_TEST_BINARIES \
+  --show-region-summary=false
diff --git a/adb/coverage/show.sh b/adb/coverage/show.sh
new file mode 100755
index 0000000..3b2faa3
--- /dev/null
+++ b/adb/coverage/show.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+OUTPUT_DIR=$(realpath $(dirname "$0"))
+. "$OUTPUT_DIR"/include.sh
+
+BASE_PATH=/proc/self/cwd/system/core/adb
+PATHS=""
+if [[ $# == 0 ]]; then
+  PATHS=$BASE_PATH
+else
+  for arg in "$@"; do
+    PATHS="$PATHS $BASE_PATH/$arg"
+  done
+fi
+
+cd $ANDROID_BUILD_TOP
+llvm-cov show --instr-profile="$OUTPUT_DIR"/adbd.profdata \
+  $ANDROID_PRODUCT_OUT/apex/com.android.adbd/bin/adbd \
+  $PATHS \
+  $ADB_TEST_BINARIES
diff --git a/adb/daemon/transport_local.cpp b/adb/daemon/transport_local.cpp
new file mode 100644
index 0000000..9e0b887
--- /dev/null
+++ b/adb/daemon/transport_local.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#define TRACE_TAG TRANSPORT
+
+#include "sysdeps.h"
+#include "transport.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <condition_variable>
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+#include <android-base/parsenetaddress.h>
+#include <android-base/stringprintf.h>
+#include <android-base/thread_annotations.h>
+#include <cutils/sockets.h>
+
+#if !ADB_HOST
+#include <android-base/properties.h>
+#endif
+
+#include "adb.h"
+#include "adb_io.h"
+#include "adb_unique_fd.h"
+#include "adb_utils.h"
+#include "socket_spec.h"
+#include "sysdeps/chrono.h"
+
+void server_socket_thread(std::function<unique_fd(std::string_view, std::string*)> listen_func,
+                          std::string_view addr) {
+    adb_thread_setname("server socket");
+
+    unique_fd serverfd;
+    std::string error;
+
+    while (serverfd == -1) {
+        errno = 0;
+        serverfd = listen_func(addr, &error);
+        if (errno == EAFNOSUPPORT || errno == EINVAL || errno == EPROTONOSUPPORT) {
+            D("unrecoverable error: '%s'", error.c_str());
+            return;
+        } else if (serverfd < 0) {
+            D("server: cannot bind socket yet: %s", error.c_str());
+            std::this_thread::sleep_for(1s);
+            continue;
+        }
+        close_on_exec(serverfd.get());
+    }
+
+    while (true) {
+        D("server: trying to get new connection from fd %d", serverfd.get());
+        unique_fd fd(adb_socket_accept(serverfd, nullptr, nullptr));
+        if (fd >= 0) {
+            D("server: new connection on fd %d", fd.get());
+            close_on_exec(fd.get());
+            disable_tcp_nagle(fd.get());
+            std::string serial = android::base::StringPrintf("host-%d", fd.get());
+            // We don't care about port value in "register_socket_transport" as it is used
+            // only from ADB_HOST. "server_socket_thread" is never called from ADB_HOST.
+            register_socket_transport(
+                    std::move(fd), std::move(serial), 0, 1,
+                    [](atransport*) { return ReconnectResult::Abort; }, false);
+        }
+    }
+    D("transport: server_socket_thread() exiting");
+}
+
+unique_fd adb_listen(std::string_view addr, std::string* error) {
+    return unique_fd{socket_spec_listen(addr, error, nullptr)};
+}
+
+void local_init(const std::string& addr) {
+#if !defined(__ANDROID__)
+    // Host adbd.
+    D("transport: local server init");
+    std::thread(server_socket_thread, adb_listen, addr).detach();
+#else
+    D("transport: local server init");
+    // For the adbd daemon in the system image we need to distinguish
+    // between the device, and the emulator.
+    if (addr.starts_with("tcp:") && use_qemu_goldfish()) {
+        std::thread(qemu_socket_thread, addr).detach();
+    } else {
+        std::thread(server_socket_thread, adb_listen, addr).detach();
+    }
+#endif  // !ADB_HOST
+}
+
+int init_socket_transport(atransport* t, unique_fd fd, int adb_port, int local) {
+    t->type = kTransportLocal;
+    auto fd_connection = std::make_unique<FdConnection>(std::move(fd));
+    t->SetConnection(std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection)));
+    return 0;
+}
diff --git a/adb/fdevent/fdevent.cpp b/adb/fdevent/fdevent.cpp
index fd55020..70cb9b3 100644
--- a/adb/fdevent/fdevent.cpp
+++ b/adb/fdevent/fdevent.cpp
@@ -27,7 +27,10 @@
 #include "adb_utils.h"
 #include "fdevent.h"
 #include "fdevent_epoll.h"
+
+#if !defined(__linux__)
 #include "fdevent_poll.h"
+#endif
 
 using namespace std::chrono_literals;
 using std::chrono::duration_cast;
diff --git a/adb/services.cpp b/adb/services.cpp
index d87948c..19a9030 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -202,11 +202,22 @@
                                       transport_id, &is_ambiguous, &error);
 
         for (const auto& state : states) {
-            // wait-for-disconnect uses kCsOffline, we don't actually want to wait for 'offline'.
-            if ((t == nullptr && state == kCsOffline) || (t != nullptr && state == kCsAny) ||
-                (t != nullptr && state == t->GetConnectionState())) {
-                SendOkay(fd);
-                return;
+            if (state == kCsOffline) {
+                // Special case for wait-for-disconnect:
+                // We want to wait for USB devices to completely disappear, but TCP devices can
+                // go into the offline state, since we automatically reconnect.
+                if (!t) {
+                    SendOkay(fd);
+                    return;
+                } else if (!t->GetUsbHandle()) {
+                    SendOkay(fd);
+                    return;
+                }
+            } else {
+                if (t && (state == kCsAny || state == t->GetConnectionState())) {
+                    SendOkay(fd);
+                    return;
+                }
             }
         }
 
diff --git a/adb/test_adb.py b/adb/test_adb.py
index c872fb0..03bdcbd 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -32,6 +32,8 @@
 import time
 import unittest
 import warnings
+from importlib import util
+from parameterized import parameterized_class
 
 def find_open_port():
     # Find an open port.
@@ -576,6 +578,98 @@
         # If the power event was detected, the adb shell command should be broken very quickly.
         self.assertLess(end - start, 2)
 
+"""Use 'adb mdns check' to see if mdns discovery is available."""
+def is_adb_mdns_available():
+    with adb_server() as server_port:
+        output = subprocess.check_output(["adb", "-P", str(server_port),
+                                          "mdns", "check"]).strip()
+        return output.startswith(b"mdns daemon version")
+
+"""Check if we have zeroconf python library installed"""
+def is_zeroconf_installed():
+    zeroconf_spec = util.find_spec("zeroconf")
+    return zeroconf_spec is not None
+
+@contextlib.contextmanager
+def zeroconf_context(ipversion):
+    from zeroconf import Zeroconf
+    """Context manager for a zeroconf instance
+
+    This creates a zeroconf instance and returns it.
+    """
+
+    try:
+        zeroconf = Zeroconf(ip_version=ipversion)
+        yield zeroconf
+    finally:
+        zeroconf.close()
+
+@contextlib.contextmanager
+def zeroconf_register_service(zeroconf_ctx, info):
+    """Context manager for a zeroconf service
+
+    Registers a service and unregisters it on cleanup. Returns the ServiceInfo
+    supplied.
+    """
+
+    try:
+        zeroconf_ctx.register_service(info)
+        yield info
+    finally:
+        zeroconf_ctx.unregister_service(info)
+
+"""Should match the service names listed in adb_mdns.h"""
+@parameterized_class(('service_name',), [
+    ("adb",),
+    ("adb-tls-connect",),
+    ("adb-tls-pairing",),
+])
+@unittest.skipIf(not is_adb_mdns_available(), "mdns feature not available")
+class MdnsTest(unittest.TestCase):
+    """Tests for adb mdns."""
+
+    @unittest.skipIf(not is_zeroconf_installed(), "zeroconf library not installed")
+    def test_mdns_services_register_unregister(self):
+        """Ensure that `adb mdns services` correctly adds and removes a service
+        """
+        from zeroconf import IPVersion, ServiceInfo
+ 
+        def _mdns_services(port):
+            output = subprocess.check_output(["adb", "-P", str(port), "mdns", "services"])
+            return [x.split("\t") for x in output.decode("utf8").strip().splitlines()[1:]]
+
+        with adb_server() as server_port:
+            output = subprocess.check_output(["adb", "-P", str(server_port),
+                                              "mdns", "services"]).strip()
+            self.assertTrue(output.startswith(b"List of discovered mdns services"))
+            print(f"services={_mdns_services(server_port)}")
+
+            """TODO(joshuaduong): Add ipv6 tests once we have it working in adb"""
+            """Register/Unregister a service"""
+            with zeroconf_context(IPVersion.V4Only) as zc:
+                serv_instance = "my_fake_test_service"
+                serv_type = "_" + self.service_name + "._tcp."
+                serv_ipaddr = socket.inet_aton("1.2.3.4")
+                serv_port = 12345
+                service_info = ServiceInfo(
+                        serv_type + "local.",
+                        name=serv_instance + "." + serv_type + "local.",
+                        addresses=[serv_ipaddr],
+                        port=serv_port)
+                print(f"Registering {serv_instance}.{serv_type} ...")
+                with zeroconf_register_service(zc, service_info) as info:
+                    """Give adb some time to register the service"""
+                    time.sleep(0.25)
+                    print(f"services={_mdns_services(server_port)}")
+                    self.assertTrue(any((serv_instance in line and serv_type in line)
+                        for line in _mdns_services(server_port)))
+
+                """Give adb some time to unregister the service"""
+                print("Unregistering mdns service...")
+                time.sleep(0.25)
+                print(f"services={_mdns_services(server_port)}")
+                self.assertFalse(any((serv_instance in line and serv_type in line)
+                    for line in _mdns_services(server_port)))
 
 def main():
     """Main entrypoint."""
diff --git a/adb/tools/Android.bp b/adb/tools/Android.bp
index 71e32b7..a7af53c 100644
--- a/adb/tools/Android.bp
+++ b/adb/tools/Android.bp
@@ -34,3 +34,26 @@
         ],
     },
 }
+
+cc_binary_host {
+    name: "adb_usbreset",
+
+    defaults: ["adb_defaults"],
+
+    srcs: [
+        "adb_usbreset.cpp",
+    ],
+
+    static_libs: [
+        "libbase",
+        "libusb",
+    ],
+
+    stl: "libc++_static",
+
+    dist: {
+        targets: [
+            "sdk",
+        ],
+    },
+}
diff --git a/adb/tools/adb_usbreset.cpp b/adb/tools/adb_usbreset.cpp
new file mode 100644
index 0000000..6f141bd
--- /dev/null
+++ b/adb/tools/adb_usbreset.cpp
@@ -0,0 +1,188 @@
+// Copyright (C) 2020 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 <getopt.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <string>
+#include <string_view>
+#include <variant>
+#include <vector>
+
+#include <libusb/libusb.h>
+
+struct AllDevices {};
+struct SingleDevice {};
+struct Serial {
+    std::string_view serial;
+};
+
+using DeviceSelection = std::variant<std::monostate, AllDevices, SingleDevice, Serial>;
+
+[[noreturn]] static void Usage(int rc) {
+    fprintf(stderr, "usage: [ANDROID_SERIAL=SERIAL] usbreset [-d] [-s SERIAL]\n");
+    fprintf(stderr, "\t-a --all\t\tReset all connected devices\n");
+    fprintf(stderr, "\t-d --device\t\tReset the single connected device\n");
+    fprintf(stderr, "\t-s --serial\t\tReset device with specified serial\n");
+    exit(rc);
+}
+
+static void SetOption(DeviceSelection* out, DeviceSelection in) {
+    if (!std::get_if<std::monostate>(out)) {
+        printf("error: multiple device selection options provided\n");
+        Usage(1);
+    }
+
+    *out = in;
+}
+
+static __attribute__((format(printf, 2, 3))) void PrintLibusbError(int err, const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    vprintf(fmt, args);
+    vprintf(fmt, args);
+    va_end(args);
+
+    printf(": %s", libusb_strerror(static_cast<libusb_error>(err)));
+}
+
+static bool IsAdbInterface(const libusb_interface_descriptor* desc) {
+    return desc->bInterfaceClass == 0xFF && desc->bInterfaceSubClass == 0x42 &&
+           desc->bInterfaceProtocol == 0x1;
+}
+
+int main(int argc, char** argv) {
+    std::variant<std::monostate, AllDevices, SingleDevice, Serial> selection;
+
+    static constexpr struct option long_opts[] = {
+            {"all", 0, 0, 'a'},    {"help", 0, 0, 'h'}, {"serial", required_argument, 0, 's'},
+            {"device", 0, 0, 'd'}, {0, 0, 0, 0},
+    };
+
+    int opt;
+    while ((opt = getopt_long(argc, argv, "adhs:", long_opts, nullptr)) != -1) {
+        if (opt == 'h') {
+            Usage(0);
+        } else if (opt == 'a') {
+            SetOption(&selection, AllDevices{});
+        } else if (opt == 's') {
+            SetOption(&selection, Serial{optarg});
+        } else if (opt == 'd') {
+            SetOption(&selection, Serial{optarg});
+        } else {
+            errx(1, "unknown option: '%c'", opt);
+        }
+    }
+
+    if (std::get_if<std::monostate>(&selection)) {
+        const char* env = getenv("ANDROID_SERIAL");
+        if (env) {
+            SetOption(&selection, Serial{env});
+        } else {
+            fprintf(stderr, "adb_usbreset: no device specified\n");
+            Usage(1);
+        }
+    }
+
+    libusb_context* ctx;
+    int rc = libusb_init(&ctx);
+    if (rc != LIBUSB_SUCCESS) {
+        PrintLibusbError(rc, "error: failed to initialize libusb");
+        exit(1);
+    }
+
+    libusb_device** device_list;
+    ssize_t device_count = libusb_get_device_list(ctx, &device_list);
+    if (device_count < 0) {
+        PrintLibusbError(device_count, "error: failed to list devices");
+        exit(1);
+    }
+
+    std::vector<std::pair<std::string, libusb_device_handle*>> selected_devices;
+    for (int i = 0; i < device_count; ++i) {
+        libusb_device* device = device_list[i];
+        libusb_device_descriptor device_desc;
+
+        // Always succeeds for LIBUSB_API_VERSION >= 0x01000102.
+        libusb_get_device_descriptor(device, &device_desc);
+        static_assert(LIBUSB_API_VERSION >= 0x01000102);
+
+        libusb_config_descriptor* config_desc;
+        rc = libusb_get_active_config_descriptor(device, &config_desc);
+        if (rc != 0) {
+            PrintLibusbError(rc, "warning: failed to get config descriptor");
+            continue;
+        }
+
+        bool found_adb_interface = false;
+        for (int i = 0; i < config_desc->bNumInterfaces; ++i) {
+            if (IsAdbInterface(&config_desc->interface[i].altsetting[0])) {
+                found_adb_interface = true;
+                break;
+            }
+        }
+
+        if (found_adb_interface) {
+            libusb_device_handle* device_handle;
+            rc = libusb_open(device, &device_handle);
+            if (rc != 0) {
+                PrintLibusbError(rc, "warning: failed to open device");
+                continue;
+            }
+
+            char buf[128];
+            rc = libusb_get_string_descriptor_ascii(device_handle, device_desc.iSerialNumber,
+                                                    reinterpret_cast<unsigned char*>(buf),
+                                                    sizeof(buf));
+
+            if (rc < 0) {
+                PrintLibusbError(rc, "warning: failed to get device serial");
+                continue;
+            }
+
+            std::string serial(buf, buf + rc);
+            if (auto s = std::get_if<Serial>(&selection)) {
+                if (s->serial == serial) {
+                    selected_devices.push_back(std::make_pair(std::move(serial), device_handle));
+                }
+            } else {
+                selected_devices.push_back(std::make_pair(std::move(serial), device_handle));
+            }
+        }
+    }
+
+    if (selected_devices.empty()) {
+        errx(1, "no devices match criteria");
+    } else if (std::get_if<SingleDevice>(&selection) && selected_devices.size() != 1) {
+        errx(1, "more than 1 device connected");
+    }
+
+    bool success = true;
+    for (auto& [serial, device_handle] : selected_devices) {
+        rc = libusb_reset_device(device_handle);
+        // libusb_reset_device will try to restore the previous state, and will return
+        // LIBUSB_ERROR_NOT_FOUND if it can't.
+        if (rc == 0 || rc == LIBUSB_ERROR_NOT_FOUND) {
+            printf("%s: successfully reset\n", serial.c_str());
+        } else {
+            PrintLibusbError(rc, "%s: failed to reset", serial.c_str());
+            success = false;
+        }
+    }
+
+    return !success;
+}
diff --git a/base/Android.bp b/base/Android.bp
index 894ad6c..61fbc3d 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -51,6 +51,7 @@
         "//apex_available:anyapex",
         "//apex_available:platform",
     ],
+    min_sdk_version: "29",
 }
 
 cc_defaults {
@@ -132,6 +133,7 @@
         "//apex_available:anyapex",
         "//apex_available:platform",
     ],
+    min_sdk_version: "29",
 }
 
 cc_library_static {
@@ -157,6 +159,7 @@
         "errors_test.cpp",
         "expected_test.cpp",
         "file_test.cpp",
+        "logging_splitters_test.cpp",
         "logging_test.cpp",
         "macros_test.cpp",
         "mapped_file_test.cpp",
diff --git a/base/include/android-base/expected.h b/base/include/android-base/expected.h
index 9603bb1..9470344 100644
--- a/base/include/android-base/expected.h
+++ b/base/include/android-base/expected.h
@@ -182,7 +182,7 @@
                 !std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
                 std::is_convertible_v<U&&, T> /* non-explicit */
                 )>
-  // NOLINTNEXTLINE(google-explicit-constructor)
+  // NOLINTNEXTLINE(google-explicit-constructor,bugprone-forwarding-reference-overload)
   constexpr expected(U&& v) : var_(std::in_place_index<0>, std::forward<U>(v)) {}
 
   template <class U = T _ENABLE_IF(
@@ -192,6 +192,7 @@
                 !std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
                 !std::is_convertible_v<U&&, T> /* explicit */
                 )>
+  // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
   constexpr explicit expected(U&& v) : var_(std::in_place_index<0>, T(std::forward<U>(v))) {}
 
   template<class G = E _ENABLE_IF(
@@ -387,13 +388,9 @@
 
 template<class T1, class E1, class T2, class E2>
 constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y) {
-  if (x.has_value() != y.has_value()) {
-    return false;
-  } else if (!x.has_value()) {
-    return x.error() == y.error();
-  } else {
-    return *x == *y;
-  }
+  if (x.has_value() != y.has_value()) return false;
+  if (!x.has_value()) return x.error() == y.error();
+  return *x == *y;
 }
 
 template<class T1, class E1, class T2, class E2>
@@ -581,35 +578,23 @@
 
 template<class E1, class E2>
 constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y) {
-  if (x.has_value() != y.has_value()) {
-    return false;
-  } else if (!x.has_value()) {
-    return x.error() == y.error();
-  } else {
-    return true;
-  }
+  if (x.has_value() != y.has_value()) return false;
+  if (!x.has_value()) return x.error() == y.error();
+  return true;
 }
 
 template<class T1, class E1, class E2>
 constexpr bool operator==(const expected<T1, E1>& x, const expected<void, E2>& y) {
-  if (x.has_value() != y.has_value()) {
-    return false;
-  } else if (!x.has_value()) {
-    return x.error() == y.error();
-  } else {
-    return false;
-  }
+  if (x.has_value() != y.has_value()) return false;
+  if (!x.has_value()) return x.error() == y.error();
+  return false;
 }
 
 template<class E1, class T2, class E2>
 constexpr bool operator==(const expected<void, E1>& x, const expected<T2, E2>& y) {
-  if (x.has_value() != y.has_value()) {
-    return false;
-  } else if (!x.has_value()) {
-    return x.error() == y.error();
-  } else {
-    return false;
-  }
+  if (x.has_value() != y.has_value()) return false;
+  if (!x.has_value()) return x.error() == y.error();
+  return false;
 }
 
 template<class E>
@@ -623,7 +608,7 @@
                 std::is_constructible_v<E, Err> &&
                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, std::in_place_t> &&
                 !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, unexpected>)>
-  // NOLINTNEXTLINE(google-explicit-constructor)
+  // NOLINTNEXTLINE(google-explicit-constructor,bugprone-forwarding-reference-overload)
   constexpr unexpected(Err&& e) : val_(std::forward<Err>(e)) {}
 
   template<class U, class... Args _ENABLE_IF(
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index accc225..26827fb 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -118,8 +118,10 @@
 
 void SetDefaultTag(const std::string& tag);
 
-// We expose this even though it is the default because a user that wants to
-// override the default log buffer will have to construct this themselves.
+// The LogdLogger sends chunks of up to ~4000 bytes at a time to logd.  It does not prevent other
+// threads from writing to logd between sending each chunk, so other threads may interleave their
+// messages.  If preventing interleaving is required, then a custom logger that takes a lock before
+// calling this logger should be provided.
 class LogdLogger {
  public:
   explicit LogdLogger(LogId default_log_id = android::base::MAIN);
diff --git a/base/include/android-base/result.h b/base/include/android-base/result.h
index 5e65876..56a4f3e 100644
--- a/base/include/android-base/result.h
+++ b/base/include/android-base/result.h
@@ -130,6 +130,7 @@
 
   template <typename T>
   Error& operator<<(T&& t) {
+    // NOLINTNEXTLINE(bugprone-suspicious-semicolon)
     if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError>) {
       errno_ = t.code();
       return (*this) << t.message();
diff --git a/base/logging.cpp b/base/logging.cpp
index cd460eb..6e9c67f 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -61,6 +61,7 @@
 #include <android-base/threads.h>
 
 #include "liblog_symbols.h"
+#include "logging_splitters.h"
 
 namespace android {
 namespace base {
@@ -190,12 +191,6 @@
   }
 }
 
-static std::mutex& LoggingLock() {
-  static auto& logging_lock = *new std::mutex();
-  return logging_lock;
-}
-
-// Only used for Q fallback.
 static LogFunction& Logger() {
 #ifdef __ANDROID__
   static auto& logger = *new LogFunction(LogdLogger());
@@ -205,7 +200,6 @@
   return logger;
 }
 
-// Only used for Q fallback.
 static AbortFunction& Aborter() {
   static auto& aborter = *new AbortFunction(DefaultAborter);
   return aborter;
@@ -241,8 +235,8 @@
 static LogSeverity gMinimumLogSeverity = INFO;
 
 #if defined(__linux__)
-void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
-                  const char* tag, const char*, unsigned int, const char* msg) {
+static void KernelLogLine(const char* msg, int length, android::base::LogSeverity severity,
+                          const char* tag) {
   // clang-format off
   static constexpr int kLogSeverityToKernelLogLevel[] = {
       [android::base::VERBOSE] = 7,              // KERN_DEBUG (there is no verbose kernel log
@@ -267,7 +261,7 @@
   // TODO: should we automatically break up long lines into multiple lines?
   // Or we could log but with something like "..." at the end?
   char buf[1024];
-  size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %s\n", level, tag, msg);
+  size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %.*s\n", level, tag, length, msg);
   if (size > sizeof(buf)) {
     size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
                     level, tag, size);
@@ -278,6 +272,11 @@
   iov[0].iov_len = size;
   TEMP_FAILURE_RETRY(writev(klog_fd, iov, 1));
 }
+
+void KernelLogger(android::base::LogId, android::base::LogSeverity severity, const char* tag,
+                  const char*, unsigned int, const char* full_message) {
+  SplitByLines(full_message, KernelLogLine, severity, tag);
+}
 #endif
 
 void StderrLogger(LogId, LogSeverity severity, const char* tag, const char* file, unsigned int line,
@@ -290,21 +289,10 @@
 #else
   localtime_r(&t, &now);
 #endif
+  auto output_string =
+      StderrOutputGenerator(now, getpid(), GetThreadId(), severity, tag, file, line, message);
 
-  char timestamp[32];
-  strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
-
-  static const char log_characters[] = "VDIWEFF";
-  static_assert(arraysize(log_characters) - 1 == FATAL + 1,
-                "Mismatch in size of log_characters and values in LogSeverity");
-  char severity_char = log_characters[severity];
-  if (file != nullptr) {
-    fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n", tag ? tag : "nullptr", severity_char,
-            timestamp, getpid(), GetThreadId(), file, line, message);
-  } else {
-    fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s\n", tag ? tag : "nullptr", severity_char,
-            timestamp, getpid(), GetThreadId(), message);
-  }
+  fputs(output_string.c_str(), stderr);
 }
 
 void StdioLogger(LogId, LogSeverity severity, const char* /*tag*/, const char* /*file*/,
@@ -326,26 +314,9 @@
   abort();
 }
 
-
-LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
-}
-
-void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
-                            const char* file, unsigned int line,
-                            const char* message) {
-  int32_t priority = LogSeverityToPriority(severity);
-  if (id == DEFAULT) {
-    id = default_log_id_;
-  }
-
+static void LogdLogChunk(LogId id, LogSeverity severity, const char* tag, const char* message) {
   int32_t lg_id = LogIdTolog_id_t(id);
-
-  char log_message_with_file[4068];  // LOGGER_ENTRY_MAX_PAYLOAD, not available in the NDK.
-  if (priority == ANDROID_LOG_FATAL && file != nullptr) {
-    snprintf(log_message_with_file, sizeof(log_message_with_file), "%s:%u] %s", file, line,
-             message);
-    message = log_message_with_file;
-  }
+  int32_t priority = LogSeverityToPriority(severity);
 
   static auto& liblog_functions = GetLibLogFunctions();
   if (liblog_functions) {
@@ -357,6 +328,17 @@
   }
 }
 
+LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {}
+
+void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag, const char* file,
+                            unsigned int line, const char* message) {
+  if (id == DEFAULT) {
+    id = default_log_id_;
+  }
+
+  SplitByLogdChunks(id, severity, tag, file, line, message, LogdLogChunk);
+}
+
 void InitLogging(char* argv[], LogFunction&& logger, AbortFunction&& aborter) {
   SetLogger(std::forward<LogFunction>(logger));
   SetAborter(std::forward<AbortFunction>(aborter));
@@ -416,45 +398,27 @@
 }
 
 void SetLogger(LogFunction&& logger) {
+  Logger() = std::move(logger);
+
   static auto& liblog_functions = GetLibLogFunctions();
   if (liblog_functions) {
-    // We need to atomically swap the old and new pointers since other threads may be logging.
-    // We know all threads will be using the new logger after __android_log_set_logger() returns,
-    // so we can delete it then.
-    // This leaks one std::function<> per instance of libbase if multiple copies of libbase within a
-    // single process call SetLogger().  That is the same cost as having a static
-    // std::function<>, which is the not-thread-safe alternative.
-    static std::atomic<LogFunction*> logger_function(nullptr);
-    auto* old_logger_function = logger_function.exchange(new LogFunction(logger));
     liblog_functions->__android_log_set_logger([](const struct __android_log_message* log_message) {
       auto log_id = log_id_tToLogId(log_message->buffer_id);
       auto severity = PriorityToLogSeverity(log_message->priority);
 
-      auto& function = *logger_function.load(std::memory_order_acquire);
-      function(log_id, severity, log_message->tag, log_message->file, log_message->line,
+      Logger()(log_id, severity, log_message->tag, log_message->file, log_message->line,
                log_message->message);
     });
-    delete old_logger_function;
-  } else {
-    std::lock_guard<std::mutex> lock(LoggingLock());
-    Logger() = std::move(logger);
   }
 }
 
 void SetAborter(AbortFunction&& aborter) {
+  Aborter() = std::move(aborter);
+
   static auto& liblog_functions = GetLibLogFunctions();
   if (liblog_functions) {
-    // See the comment in SetLogger().
-    static std::atomic<AbortFunction*> abort_function(nullptr);
-    auto* old_abort_function = abort_function.exchange(new AbortFunction(aborter));
-    liblog_functions->__android_log_set_aborter([](const char* abort_message) {
-      auto& function = *abort_function.load(std::memory_order_acquire);
-      function(abort_message);
-    });
-    delete old_abort_function;
-  } else {
-    std::lock_guard<std::mutex> lock(LoggingLock());
-    Aborter() = std::move(aborter);
+    liblog_functions->__android_log_set_aborter(
+        [](const char* abort_message) { Aborter()(abort_message); });
   }
 }
 
@@ -535,26 +499,8 @@
 #endif
   }
 
-  {
-    // Do the actual logging with the lock held.
-    std::lock_guard<std::mutex> lock(LoggingLock());
-    if (msg.find('\n') == std::string::npos) {
-      LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), data_->GetTag(),
-              msg.c_str());
-    } else {
-      msg += '\n';
-      size_t i = 0;
-      while (i < msg.size()) {
-        size_t nl = msg.find('\n', i);
-        msg[nl] = '\0';
-        LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), data_->GetTag(),
-                &msg[i]);
-        // Undo the zero-termination so we can give the complete message to the aborter.
-        msg[nl] = '\n';
-        i = nl + 1;
-      }
-    }
-  }
+  LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), data_->GetTag(),
+          msg.c_str());
 
   // Abort if necessary.
   if (data_->GetSeverity() == FATAL) {
diff --git a/base/logging_splitters.h b/base/logging_splitters.h
new file mode 100644
index 0000000..2ec2b20
--- /dev/null
+++ b/base/logging_splitters.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <inttypes.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+#define LOGGER_ENTRY_MAX_PAYLOAD 4068  // This constant is not in the NDK.
+
+namespace android {
+namespace base {
+
+// This splits the message up line by line, by calling log_function with a pointer to the start of
+// each line and the size up to the newline character.  It sends size = -1 for the final line.
+template <typename F, typename... Args>
+static void SplitByLines(const char* msg, const F& log_function, Args&&... args) {
+  const char* newline = strchr(msg, '\n');
+  while (newline != nullptr) {
+    log_function(msg, newline - msg, args...);
+    msg = newline + 1;
+    newline = strchr(msg, '\n');
+  }
+
+  log_function(msg, -1, args...);
+}
+
+// This splits the message up into chunks that logs can process delimited by new lines.  It calls
+// log_function with the exact null terminated message that should be sent to logd.
+// Note, despite the loops and snprintf's, if severity is not fatal and there are no new lines,
+// this function simply calls log_function with msg without any extra overhead.
+template <typename F>
+static void SplitByLogdChunks(LogId log_id, LogSeverity severity, const char* tag, const char* file,
+                              unsigned int line, const char* msg, const F& log_function) {
+  // The maximum size of a payload, after the log header that logd will accept is
+  // LOGGER_ENTRY_MAX_PAYLOAD, so subtract the other elements in the payload to find the size of
+  // the string that we can log in each pass.
+  // The protocol is documented in liblog/README.protocol.md.
+  // Specifically we subtract a byte for the priority, the length of the tag + its null terminator,
+  // and an additional byte for the null terminator on the payload.  We subtract an additional 32
+  // bytes for slack, similar to java/android/util/Log.java.
+  ptrdiff_t max_size = LOGGER_ENTRY_MAX_PAYLOAD - strlen(tag) - 35;
+  if (max_size <= 0) {
+    abort();
+  }
+  // If we're logging a fatal message, we'll append the file and line numbers.
+  bool add_file = file != nullptr && (severity == FATAL || severity == FATAL_WITHOUT_ABORT);
+
+  std::string file_header;
+  if (add_file) {
+    file_header = StringPrintf("%s:%u] ", file, line);
+  }
+  int file_header_size = file_header.size();
+
+  __attribute__((uninitialized)) char logd_chunk[max_size + 1];
+  ptrdiff_t chunk_position = 0;
+
+  auto call_log_function = [&]() {
+    log_function(log_id, severity, tag, logd_chunk);
+    chunk_position = 0;
+  };
+
+  auto write_to_logd_chunk = [&](const char* message, int length) {
+    int size_written = 0;
+    const char* new_line = chunk_position > 0 ? "\n" : "";
+    if (add_file) {
+      size_written = snprintf(logd_chunk + chunk_position, sizeof(logd_chunk) - chunk_position,
+                              "%s%s%.*s", new_line, file_header.c_str(), length, message);
+    } else {
+      size_written = snprintf(logd_chunk + chunk_position, sizeof(logd_chunk) - chunk_position,
+                              "%s%.*s", new_line, length, message);
+    }
+
+    // This should never fail, if it does and we set size_written to 0, which will skip this line
+    // and move to the next one.
+    if (size_written < 0) {
+      size_written = 0;
+    }
+    chunk_position += size_written;
+  };
+
+  const char* newline = strchr(msg, '\n');
+  while (newline != nullptr) {
+    // If we have data in the buffer and this next line doesn't fit, write the buffer.
+    if (chunk_position != 0 && chunk_position + (newline - msg) + 1 + file_header_size > max_size) {
+      call_log_function();
+    }
+
+    // Otherwise, either the next line fits or we have any empty buffer and too large of a line to
+    // ever fit, in both cases, we add it to the buffer and continue.
+    write_to_logd_chunk(msg, newline - msg);
+
+    msg = newline + 1;
+    newline = strchr(msg, '\n');
+  }
+
+  // If we have left over data in the buffer and we can fit the rest of msg, add it to the buffer
+  // then write the buffer.
+  if (chunk_position != 0 &&
+      chunk_position + static_cast<int>(strlen(msg)) + 1 + file_header_size <= max_size) {
+    write_to_logd_chunk(msg, -1);
+    call_log_function();
+  } else {
+    // If the buffer is not empty and we can't fit the rest of msg into it, write its contents.
+    if (chunk_position != 0) {
+      call_log_function();
+    }
+    // Then write the rest of the msg.
+    if (add_file) {
+      snprintf(logd_chunk, sizeof(logd_chunk), "%s%s", file_header.c_str(), msg);
+      log_function(log_id, severity, tag, logd_chunk);
+    } else {
+      log_function(log_id, severity, tag, msg);
+    }
+  }
+}
+
+static std::pair<int, int> CountSizeAndNewLines(const char* message) {
+  int size = 0;
+  int new_lines = 0;
+  while (*message != '\0') {
+    size++;
+    if (*message == '\n') {
+      ++new_lines;
+    }
+    ++message;
+  }
+  return {size, new_lines};
+}
+
+// This adds the log header to each line of message and returns it as a string intended to be
+// written to stderr.
+static std::string StderrOutputGenerator(const struct tm& now, int pid, uint64_t tid,
+                                         LogSeverity severity, const char* tag, const char* file,
+                                         unsigned int line, const char* message) {
+  char timestamp[32];
+  strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
+
+  static const char log_characters[] = "VDIWEFF";
+  static_assert(arraysize(log_characters) - 1 == FATAL + 1,
+                "Mismatch in size of log_characters and values in LogSeverity");
+  char severity_char = log_characters[severity];
+  std::string line_prefix;
+  if (file != nullptr) {
+    line_prefix = StringPrintf("%s %c %s %5d %5" PRIu64 " %s:%u] ", tag ? tag : "nullptr",
+                               severity_char, timestamp, pid, tid, file, line);
+  } else {
+    line_prefix = StringPrintf("%s %c %s %5d %5" PRIu64 " ", tag ? tag : "nullptr", severity_char,
+                               timestamp, pid, tid);
+  }
+
+  auto [size, new_lines] = CountSizeAndNewLines(message);
+  std::string output_string;
+  output_string.reserve(size + new_lines * line_prefix.size() + 1);
+
+  auto concat_lines = [&](const char* message, int size) {
+    output_string.append(line_prefix);
+    if (size == -1) {
+      output_string.append(message);
+    } else {
+      output_string.append(message, size);
+    }
+    output_string.append("\n");
+  };
+  SplitByLines(message, concat_lines);
+  return output_string;
+}
+
+}  // namespace base
+}  // namespace android
diff --git a/base/logging_splitters_test.cpp b/base/logging_splitters_test.cpp
new file mode 100644
index 0000000..679d19e
--- /dev/null
+++ b/base/logging_splitters_test.cpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2020 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 "logging_splitters.h"
+
+#include <string>
+#include <vector>
+
+#include <android-base/strings.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace base {
+
+void TestNewlineSplitter(const std::string& input,
+                         const std::vector<std::string>& expected_output) {
+  std::vector<std::string> output;
+  auto logger_function = [&](const char* msg, int length) {
+    if (length == -1) {
+      output.push_back(msg);
+    } else {
+      output.push_back(std::string(msg, length));
+    }
+  };
+  SplitByLines(input.c_str(), logger_function);
+
+  EXPECT_EQ(expected_output, output);
+}
+
+TEST(logging_splitters, NewlineSplitter_EmptyString) {
+  TestNewlineSplitter("", std::vector<std::string>{""});
+}
+
+TEST(logging_splitters, NewlineSplitter_BasicString) {
+  TestNewlineSplitter("normal string", std::vector<std::string>{"normal string"});
+}
+
+TEST(logging_splitters, NewlineSplitter_ormalBasicStringTrailingNewline) {
+  TestNewlineSplitter("normal string\n", std::vector<std::string>{"normal string", ""});
+}
+
+TEST(logging_splitters, NewlineSplitter_MultilineTrailing) {
+  TestNewlineSplitter("normal string\nsecond string\nthirdstring",
+                      std::vector<std::string>{"normal string", "second string", "thirdstring"});
+}
+
+TEST(logging_splitters, NewlineSplitter_MultilineTrailingNewline) {
+  TestNewlineSplitter(
+      "normal string\nsecond string\nthirdstring\n",
+      std::vector<std::string>{"normal string", "second string", "thirdstring", ""});
+}
+
+TEST(logging_splitters, NewlineSplitter_MultilineEmbeddedNewlines) {
+  TestNewlineSplitter(
+      "normal string\n\n\nsecond string\n\nthirdstring\n",
+      std::vector<std::string>{"normal string", "", "", "second string", "", "thirdstring", ""});
+}
+
+void TestLogdChunkSplitter(const std::string& tag, const std::string& file,
+                           const std::string& input,
+                           const std::vector<std::string>& expected_output) {
+  std::vector<std::string> output;
+  auto logger_function = [&](LogId, LogSeverity, const char*, const char* msg) {
+    output.push_back(msg);
+  };
+
+  SplitByLogdChunks(MAIN, FATAL, tag.c_str(), file.empty() ? nullptr : file.c_str(), 1000,
+                    input.c_str(), logger_function);
+
+  auto return_lengths = [&] {
+    std::string sizes;
+    sizes += "expected_output sizes:";
+    for (const auto& string : expected_output) {
+      sizes += " " + std::to_string(string.size());
+    }
+    sizes += "\noutput sizes:";
+    for (const auto& string : output) {
+      sizes += " " + std::to_string(string.size());
+    }
+    return sizes;
+  };
+
+  EXPECT_EQ(expected_output, output) << return_lengths();
+}
+
+TEST(logging_splitters, LogdChunkSplitter_EmptyString) {
+  TestLogdChunkSplitter("tag", "", "", std::vector<std::string>{""});
+}
+
+TEST(logging_splitters, LogdChunkSplitter_BasicString) {
+  TestLogdChunkSplitter("tag", "", "normal string", std::vector<std::string>{"normal string"});
+}
+
+TEST(logging_splitters, LogdChunkSplitter_NormalBasicStringTrailingNewline) {
+  TestLogdChunkSplitter("tag", "", "normal string\n", std::vector<std::string>{"normal string\n"});
+}
+
+TEST(logging_splitters, LogdChunkSplitter_MultilineTrailing) {
+  TestLogdChunkSplitter("tag", "", "normal string\nsecond string\nthirdstring",
+                        std::vector<std::string>{"normal string\nsecond string\nthirdstring"});
+}
+
+TEST(logging_splitters, LogdChunkSplitter_MultilineTrailingNewline) {
+  TestLogdChunkSplitter("tag", "", "normal string\nsecond string\nthirdstring\n",
+                        std::vector<std::string>{"normal string\nsecond string\nthirdstring\n"});
+}
+
+TEST(logging_splitters, LogdChunkSplitter_MultilineEmbeddedNewlines) {
+  TestLogdChunkSplitter(
+      "tag", "", "normal string\n\n\nsecond string\n\nthirdstring\n",
+      std::vector<std::string>{"normal string\n\n\nsecond string\n\nthirdstring\n"});
+}
+
+// This test should return the same string, the logd logger itself will truncate down to size.
+// This has historically been the behavior both in libbase and liblog.
+TEST(logging_splitters, LogdChunkSplitter_HugeLineNoNewline) {
+  auto long_string = std::string(LOGGER_ENTRY_MAX_PAYLOAD, 'x');
+  ASSERT_EQ(LOGGER_ENTRY_MAX_PAYLOAD, static_cast<int>(long_string.size()));
+
+  TestLogdChunkSplitter("tag", "", long_string, std::vector{long_string});
+}
+
+std::string ReduceToMaxSize(const std::string& tag, const std::string& string) {
+  return string.substr(0, LOGGER_ENTRY_MAX_PAYLOAD - tag.size() - 35);
+}
+
+TEST(logging_splitters, LogdChunkSplitter_MultipleHugeLineNoNewline) {
+  auto long_string_x = std::string(LOGGER_ENTRY_MAX_PAYLOAD, 'x');
+  auto long_string_y = std::string(LOGGER_ENTRY_MAX_PAYLOAD, 'y');
+  auto long_string_z = std::string(LOGGER_ENTRY_MAX_PAYLOAD, 'z');
+
+  auto long_strings = long_string_x + '\n' + long_string_y + '\n' + long_string_z;
+
+  std::string tag = "tag";
+  std::vector expected = {ReduceToMaxSize(tag, long_string_x), ReduceToMaxSize(tag, long_string_y),
+                          long_string_z};
+
+  TestLogdChunkSplitter(tag, "", long_strings, expected);
+}
+
+// With a ~4k buffer, we should print 2 long strings per logger call.
+TEST(logging_splitters, LogdChunkSplitter_Multiple2kLines) {
+  std::vector expected = {
+      std::string(2000, 'a') + '\n' + std::string(2000, 'b'),
+      std::string(2000, 'c') + '\n' + std::string(2000, 'd'),
+      std::string(2000, 'e') + '\n' + std::string(2000, 'f'),
+  };
+
+  auto long_strings = Join(expected, '\n');
+
+  TestLogdChunkSplitter("tag", "", long_strings, expected);
+}
+
+TEST(logging_splitters, LogdChunkSplitter_ExactSizedLines) {
+  const char* tag = "tag";
+  ptrdiff_t max_size = LOGGER_ENTRY_MAX_PAYLOAD - strlen(tag) - 35;
+  auto long_string_a = std::string(max_size, 'a');
+  auto long_string_b = std::string(max_size, 'b');
+  auto long_string_c = std::string(max_size, 'c');
+
+  auto long_strings = long_string_a + '\n' + long_string_b + '\n' + long_string_c;
+
+  TestLogdChunkSplitter(tag, "", long_strings,
+                        std::vector{long_string_a, long_string_b, long_string_c});
+}
+
+TEST(logging_splitters, LogdChunkSplitter_UnderEqualOver) {
+  std::string tag = "tag";
+  ptrdiff_t max_size = LOGGER_ENTRY_MAX_PAYLOAD - tag.size() - 35;
+
+  auto first_string_size = 1000;
+  auto first_string = std::string(first_string_size, 'a');
+  auto second_string_size = max_size - first_string_size - 1;
+  auto second_string = std::string(second_string_size, 'b');
+
+  auto exact_string = std::string(max_size, 'c');
+
+  auto large_string = std::string(max_size + 50, 'd');
+
+  auto final_string = std::string("final string!\n\nfinal \n \n final \n");
+
+  std::vector expected = {first_string + '\n' + second_string, exact_string,
+                          ReduceToMaxSize(tag, large_string), final_string};
+
+  std::vector input_strings = {first_string + '\n' + second_string, exact_string, large_string,
+                               final_string};
+  auto long_strings = Join(input_strings, '\n');
+
+  TestLogdChunkSplitter(tag, "", long_strings, expected);
+}
+
+TEST(logging_splitters, LogdChunkSplitter_WithFile) {
+  std::string tag = "tag";
+  std::string file = "/path/to/myfile.cpp";
+  int line = 1000;
+  auto file_header = StringPrintf("%s:%d] ", file.c_str(), line);
+  ptrdiff_t max_size = LOGGER_ENTRY_MAX_PAYLOAD - tag.size() - 35;
+
+  auto first_string_size = 1000;
+  auto first_string = std::string(first_string_size, 'a');
+  auto second_string_size = max_size - first_string_size - 1 - 2 * file_header.size();
+  auto second_string = std::string(second_string_size, 'b');
+
+  auto exact_string = std::string(max_size - file_header.size(), 'c');
+
+  auto large_string = std::string(max_size + 50, 'd');
+
+  auto final_string = std::string("final string!");
+
+  std::vector expected = {
+      file_header + first_string + '\n' + file_header + second_string, file_header + exact_string,
+      file_header + ReduceToMaxSize(file_header + tag, large_string), file_header + final_string};
+
+  std::vector input_strings = {first_string + '\n' + second_string, exact_string, large_string,
+                               final_string};
+  auto long_strings = Join(input_strings, '\n');
+
+  TestLogdChunkSplitter(tag, file, long_strings, expected);
+}
+
+// We set max_size based off of tag, so if it's too large, the buffer will be sized wrong.
+// We could recover from this, but it's certainly an error for someone to attempt to use a tag this
+// large, so we abort instead.
+TEST(logging_splitters, LogdChunkSplitter_TooLongTag) {
+  auto long_tag = std::string(5000, 'x');
+  auto logger_function = [](LogId, LogSeverity, const char*, const char*) {};
+  ASSERT_DEATH(
+      SplitByLogdChunks(MAIN, ERROR, long_tag.c_str(), nullptr, 0, "message", logger_function), "");
+}
+
+// We do handle excessively large file names correctly however.
+TEST(logging_splitters, LogdChunkSplitter_TooLongFile) {
+  auto long_file = std::string(5000, 'x');
+  std::string tag = "tag";
+
+  std::vector expected = {ReduceToMaxSize(tag, long_file), ReduceToMaxSize(tag, long_file)};
+
+  TestLogdChunkSplitter(tag, long_file, "can't see me\nor me", expected);
+}
+
+void TestStderrOutputGenerator(const char* tag, const char* file, int line, const char* message,
+                               const std::string& expected) {
+  // All log messages will show "01-01 00:00:00"
+  struct tm now = {
+      .tm_sec = 0,
+      .tm_min = 0,
+      .tm_hour = 0,
+      .tm_mday = 1,
+      .tm_mon = 0,
+      .tm_year = 1970,
+  };
+
+  int pid = 1234;       // All log messages will have 1234 for their PID.
+  uint64_t tid = 4321;  // All log messages will have 4321 for their TID.
+
+  auto result = StderrOutputGenerator(now, pid, tid, ERROR, tag, file, line, message);
+  EXPECT_EQ(expected, result);
+}
+
+TEST(logging_splitters, StderrOutputGenerator_Basic) {
+  TestStderrOutputGenerator(nullptr, nullptr, 0, "simple message",
+                            "nullptr E 01-01 00:00:00  1234  4321 simple message\n");
+  TestStderrOutputGenerator("tag", nullptr, 0, "simple message",
+                            "tag E 01-01 00:00:00  1234  4321 simple message\n");
+  TestStderrOutputGenerator(
+      "tag", "/path/to/some/file", 0, "simple message",
+      "tag E 01-01 00:00:00  1234  4321 /path/to/some/file:0] simple message\n");
+}
+
+TEST(logging_splitters, StderrOutputGenerator_NewlineTagAndFile) {
+  TestStderrOutputGenerator("tag\n\n", nullptr, 0, "simple message",
+                            "tag\n\n E 01-01 00:00:00  1234  4321 simple message\n");
+  TestStderrOutputGenerator(
+      "tag", "/path/to/some/file\n\n", 0, "simple message",
+      "tag E 01-01 00:00:00  1234  4321 /path/to/some/file\n\n:0] simple message\n");
+}
+
+TEST(logging_splitters, StderrOutputGenerator_TrailingNewLine) {
+  TestStderrOutputGenerator(
+      "tag", nullptr, 0, "simple message\n",
+      "tag E 01-01 00:00:00  1234  4321 simple message\ntag E 01-01 00:00:00  1234  4321 \n");
+}
+
+TEST(logging_splitters, StderrOutputGenerator_MultiLine) {
+  const char* expected_result =
+      "tag E 01-01 00:00:00  1234  4321 simple message\n"
+      "tag E 01-01 00:00:00  1234  4321 \n"
+      "tag E 01-01 00:00:00  1234  4321 \n"
+      "tag E 01-01 00:00:00  1234  4321 another message \n"
+      "tag E 01-01 00:00:00  1234  4321 \n"
+      "tag E 01-01 00:00:00  1234  4321  final message \n"
+      "tag E 01-01 00:00:00  1234  4321 \n"
+      "tag E 01-01 00:00:00  1234  4321 \n"
+      "tag E 01-01 00:00:00  1234  4321 \n";
+
+  TestStderrOutputGenerator("tag", nullptr, 0,
+                            "simple message\n\n\nanother message \n\n final message \n\n\n",
+                            expected_result);
+}
+
+TEST(logging_splitters, StderrOutputGenerator_MultiLineLong) {
+  auto long_string_a = std::string(4000, 'a');
+  auto long_string_b = std::string(4000, 'b');
+
+  auto message = long_string_a + '\n' + long_string_b;
+  auto expected_result = "tag E 01-01 00:00:00  1234  4321 " + long_string_a + '\n' +
+                         "tag E 01-01 00:00:00  1234  4321 " + long_string_b + '\n';
+  TestStderrOutputGenerator("tag", nullptr, 0, message.c_str(), expected_result);
+}
+
+}  // namespace base
+}  // namespace android
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 3a453e6..593e2c1 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -24,8 +24,10 @@
 
 #include <regex>
 #include <string>
+#include <thread>
 
 #include "android-base/file.h"
+#include "android-base/scopeguard.h"
 #include "android-base/stringprintf.h"
 #include "android-base/test_utils.h"
 
@@ -596,7 +598,7 @@
   CapturedStderr cap;
   LOG(FATAL) << "foo\nbar";
 
-  EXPECT_EQ(CountLineAborter::newline_count, 1U + 1U);  // +1 for final '\n'.
+  EXPECT_EQ(CountLineAborter::newline_count, 1U);
 }
 
 __attribute__((constructor)) void TestLoggingInConstructor() {
@@ -617,3 +619,55 @@
   // Whereas ERROR logging includes the program name.
   ASSERT_EQ(android::base::Basename(android::base::GetExecutablePath()) + ": err\n", cap_err.str());
 }
+
+TEST(logging, ForkSafe) {
+#if !defined(_WIN32)
+  using namespace android::base;
+  SetLogger(
+      [&](LogId, LogSeverity, const char*, const char*, unsigned int, const char*) { sleep(3); });
+
+  auto guard = make_scope_guard([&] {
+#ifdef __ANDROID__
+    SetLogger(LogdLogger());
+#else
+    SetLogger(StderrLogger);
+#endif
+  });
+
+  auto thread = std::thread([] {
+    LOG(ERROR) << "This should sleep for 3 seconds, long enough to fork another process, if there "
+                  "is no intervention";
+  });
+  thread.detach();
+
+  auto pid = fork();
+  ASSERT_NE(-1, pid);
+
+  if (pid == 0) {
+    // Reset the logger, so the next message doesn't sleep().
+    SetLogger([](LogId, LogSeverity, const char*, const char*, unsigned int, const char*) {});
+    LOG(ERROR) << "This should succeed in the child, only if libbase is forksafe.";
+    _exit(EXIT_SUCCESS);
+  }
+
+  // Wait for up to 3 seconds for the child to exit.
+  int tries = 3;
+  bool found_child = false;
+  while (tries-- > 0) {
+    auto result = waitpid(pid, nullptr, WNOHANG);
+    EXPECT_NE(-1, result);
+    if (result == pid) {
+      found_child = true;
+      break;
+    }
+    sleep(1);
+  }
+
+  EXPECT_TRUE(found_child);
+
+  // Kill the child if it did not exit.
+  if (!found_child) {
+    kill(pid, SIGKILL);
+  }
+#endif
+}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index e0168d5..d6b2e25 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -43,6 +43,7 @@
 #include <android-base/unique_fd.h>
 #include <android/log.h>
 #include <log/log.h>
+#include <log/log_read.h>
 #include <log/logprint.h>
 #include <private/android_filesystem_config.h>
 #include <unwindstack/DexFiles.h>
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index f579078..ca782b9 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -42,7 +42,7 @@
     $ adb push <source> <destination>
     $ adb reboot
 
-Note that you can replace these two lines:
+Note that you can replace these two lines in the above sequence:
 
     $ adb disable-verity
     $ adb reboot
@@ -51,7 +51,7 @@
 
     $ adb remount -R
 
-**Note:** _adb reboot -R_ won’t reboot if the device is already in the adb remount state.
+**Note:** _adb remount -R_ won’t reboot if the device is already in the adb remount state.
 
 None of this changes if OverlayFS needs to be engaged.
 The decisions whether to use traditional direct file-system remount,
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 0b98e1a..6051ac7 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -42,6 +42,7 @@
         "//apex_available:platform",
         "//apex_available:anyapex",
     ],
+    min_sdk_version: "29",
     native_bridge_supported: true,
     export_include_dirs: ["include"],
     system_shared_libs: [],
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 512c7cd..8a0ebf2 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -185,14 +185,26 @@
  * and sending log messages to user defined loggers specified in __android_log_set_logger().
  */
 struct __android_log_message {
-  size_t
-      struct_size;   /** Must be set to sizeof(__android_log_message) and is used for versioning. */
-  int32_t buffer_id; /** {@link log_id_t} values. */
-  int32_t priority;  /** {@link android_LogPriority} values. */
-  const char* tag;   /** The tag for the log message. */
-  const char* file;  /** Optional file name, may be set to nullptr. */
-  uint32_t line;     /** Optional line number, ignore if file is nullptr. */
-  const char* message; /** The log message itself. */
+  /** Must be set to sizeof(__android_log_message) and is used for versioning. */
+  size_t struct_size;
+
+  /** {@link log_id_t} values. */
+  int32_t buffer_id;
+
+  /** {@link android_LogPriority} values. */
+  int32_t priority;
+
+  /** The tag for the log message. */
+  const char* tag;
+
+  /** Optional file name, may be set to nullptr. */
+  const char* file;
+
+  /** Optional line number, ignore if file is nullptr. */
+  uint32_t line;
+
+  /** The log message itself. */
+  const char* message;
 };
 
 /**
@@ -215,7 +227,7 @@
  * buffers, then pass the message to liblog via this function, and therefore we do not want to
  * duplicate the loggability check here.
  *
- * @param log_message the log message itself, see {@link __android_log_message}.
+ * @param log_message the log message itself, see __android_log_message.
  *
  * Available since API level 30.
  */
@@ -237,7 +249,7 @@
  * Writes the log message to logd.  This is an __android_logger_function and can be provided to
  * __android_log_set_logger().  It is the default logger when running liblog on a device.
  *
- * @param log_message the log message to write, see {@link __android_log_message}.
+ * @param log_message the log message to write, see __android_log_message.
  *
  * Available since API level 30.
  */
@@ -247,7 +259,7 @@
  * Writes the log message to stderr.  This is an __android_logger_function and can be provided to
  * __android_log_set_logger().  It is the default logger when running liblog on host.
  *
- * @param log_message the log message to write, see {@link __android_log_message}.
+ * @param log_message the log message to write, see __android_log_message.
  *
  * Available since API level 30.
  */
@@ -259,7 +271,7 @@
  * user defined aborter function is highly recommended to abort and be noreturn, but is not strictly
  * required to.
  *
- * @param aborter the new aborter function, see {@link __android_aborter_function}.
+ * @param aborter the new aborter function, see __android_aborter_function.
  *
  * Available since API level 30.
  */
@@ -297,7 +309,26 @@
  * minimum priority needed to log.  If only one is set, then that value is used to determine the
  * minimum priority needed.  If none are set, then default_priority is used.
  *
- * @param prio         the priority to test, takes {@link android_LogPriority} values.
+ * @param prio         the priority to test, takes android_LogPriority values.
+ * @param tag          the tag to test.
+ * @param default_prio the default priority to use if no properties or minimum priority are set.
+ * @return an integer where 1 indicates that the message is loggable and 0 indicates that it is not.
+ *
+ * Available since API level 30.
+ */
+int __android_log_is_loggable(int prio, const char* tag, int default_prio) __INTRODUCED_IN(30);
+
+/**
+ * Use the per-tag properties "log.tag.<tagname>" along with the minimum priority from
+ * __android_log_set_minimum_priority() to determine if a log message with a given prio and tag will
+ * be printed.  A non-zero result indicates yes, zero indicates false.
+ *
+ * If both a priority for a tag and a minimum priority are set by
+ * __android_log_set_minimum_priority(), then the lowest of the two values are to determine the
+ * minimum priority needed to log.  If only one is set, then that value is used to determine the
+ * minimum priority needed.  If none are set, then default_priority is used.
+ *
+ * @param prio         the priority to test, takes android_LogPriority values.
  * @param tag          the tag to test.
  * @param len          the length of the tag.
  * @param default_prio the default priority to use if no properties or minimum priority are set.
@@ -305,15 +336,14 @@
  *
  * Available since API level 30.
  */
-int __android_log_is_loggable(int prio, const char* tag, int default_prio) __INTRODUCED_IN(30);
 int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio)
     __INTRODUCED_IN(30);
 
 /**
  * Sets the minimum priority that will be logged for this process.
  *
- * @param priority the new minimum priority to set, takes @{link android_LogPriority} values.
- * @return the previous set minimum priority as @{link android_LogPriority} values, or
+ * @param priority the new minimum priority to set, takes android_LogPriority values.
+ * @return the previous set minimum priority as android_LogPriority values, or
  *         ANDROID_LOG_DEFAULT if none was set.
  *
  * Available since API level 30.
@@ -324,7 +354,7 @@
  * Gets the minimum priority that will be logged for this process.  If none has been set by a
  * previous __android_log_set_minimum_priority() call, this returns ANDROID_LOG_DEFAULT.
  *
- * @return the current minimum priority as @{link android_LogPriority} values, or
+ * @return the current minimum priority as android_LogPriority values, or
  *         ANDROID_LOG_DEFAULT if none is set.
  *
  * Available since API level 30.
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 19edb83..f27b8e6 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -29,7 +29,6 @@
 #include <log/log_id.h>
 #include <log/log_main.h>
 #include <log/log_radio.h>
-#include <log/log_read.h>
 #include <log/log_safetynet.h>
 #include <log/log_system.h>
 #include <log/log_time.h>
@@ -65,6 +64,13 @@
 #endif
 
 /*
+ * The maximum size of the log entry payload that can be
+ * written to the logger. An attempt to write more than
+ * this amount will result in a truncated log entry.
+ */
+#define LOGGER_ENTRY_MAX_PAYLOAD 4068
+
+/*
  * Event logging.
  */
 
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index e2bc297..ffd3b52 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -48,13 +48,6 @@
 };
 
 /*
- * The maximum size of the log entry payload that can be
- * written to the logger. An attempt to write more than
- * this amount will result in a truncated log entry.
- */
-#define LOGGER_ENTRY_MAX_PAYLOAD 4068
-
-/*
  * The maximum size of a log entry which can be read.
  * An attempt to read less than this amount may result
  * in read() returning EINVAL.
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index d15b367..3a75fa3 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -28,7 +28,6 @@
 #endif
 
 #include <atomic>
-#include <shared_mutex>
 
 #include <android-base/errno_restorer.h>
 #include <android-base/macros.h>
@@ -38,7 +37,6 @@
 #include "android/log.h"
 #include "log/log_read.h"
 #include "logger.h"
-#include "rwlock.h"
 #include "uio.h"
 
 #ifdef __ANDROID__
@@ -142,10 +140,8 @@
   static std::string default_tag = getprogname();
   return default_tag;
 }
-RwLock default_tag_lock;
 
 void __android_log_set_default_tag(const char* tag) {
-  auto lock = std::unique_lock{default_tag_lock};
   GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
 }
 
@@ -163,10 +159,8 @@
 #else
 static __android_logger_function logger_function = __android_log_stderr_logger;
 #endif
-static RwLock logger_function_lock;
 
 void __android_log_set_logger(__android_logger_function logger) {
-  auto lock = std::unique_lock{logger_function_lock};
   logger_function = logger;
 }
 
@@ -180,15 +174,12 @@
 }
 
 static __android_aborter_function aborter_function = __android_log_default_aborter;
-static RwLock aborter_function_lock;
 
 void __android_log_set_aborter(__android_aborter_function aborter) {
-  auto lock = std::unique_lock{aborter_function_lock};
   aborter_function = aborter;
 }
 
 void __android_log_call_aborter(const char* abort_message) {
-  auto lock = std::shared_lock{aborter_function_lock};
   aborter_function(abort_message);
 }
 
@@ -310,9 +301,7 @@
     return;
   }
 
-  auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
   if (log_message->tag == nullptr) {
-    tag_lock.lock();
     log_message->tag = GetDefaultTag().c_str();
   }
 
@@ -322,7 +311,6 @@
   }
 #endif
 
-  auto lock = std::shared_lock{logger_function_lock};
   logger_function(log_message);
 }
 
diff --git a/liblog/logger_write.h b/liblog/logger_write.h
index 065fd55..eee2778 100644
--- a/liblog/logger_write.h
+++ b/liblog/logger_write.h
@@ -18,7 +18,4 @@
 
 #include <string>
 
-#include "rwlock.h"
-
-std::string& GetDefaultTag();  // Must read lock default_tag_lock
-extern RwLock default_tag_lock;
\ No newline at end of file
+std::string& GetDefaultTag();
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index 5c69bf8..9e8d277 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -19,6 +19,8 @@
 #define HAVE_STRSEP
 #endif
 
+#include <log/logprint.h>
+
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
@@ -37,7 +39,7 @@
 #include <cutils/list.h>
 
 #include <log/log.h>
-#include <log/logprint.h>
+#include <log/log_read.h>
 #include <private/android_logger.h>
 
 #define MS_PER_NSEC 1000000
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index abd48fc..37670ec 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -23,7 +23,6 @@
 #include <unistd.h>
 
 #include <algorithm>
-#include <shared_mutex>
 
 #include <private/android_logger.h>
 
@@ -99,9 +98,7 @@
   static const char log_namespace[] = "persist.log.tag.";
   static const size_t base_offset = 8; /* skip "persist." */
 
-  auto tag_lock = std::shared_lock{default_tag_lock, std::defer_lock};
   if (tag == nullptr || len == 0) {
-    tag_lock.lock();
     auto& tag_string = GetDefaultTag();
     tag = tag_string.c_str();
     len = tag_string.size();
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 3a6ed90..f4734b9 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -31,6 +31,7 @@
 #include <benchmark/benchmark.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
+#include <log/log_read.h>
 #include <private/android_logger.h>
 
 BENCHMARK_MAIN();
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 048bf61..d3d8e91 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -40,6 +40,7 @@
 #include <gtest/gtest.h>
 #include <log/log_event_list.h>
 #include <log/log_properties.h>
+#include <log/log_read.h>
 #include <log/logprint.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
diff --git a/libutils/include/utils/Looper.h b/libutils/include/utils/Looper.h
index c439c5c..466fbb7 100644
--- a/libutils/include/utils/Looper.h
+++ b/libutils/include/utils/Looper.h
@@ -26,6 +26,8 @@
 
 #include <android-base/unique_fd.h>
 
+#include <utility>
+
 namespace android {
 
 /*
@@ -438,9 +440,8 @@
     struct MessageEnvelope {
         MessageEnvelope() : uptime(0) { }
 
-        MessageEnvelope(nsecs_t u, const sp<MessageHandler> h,
-                const Message& m) : uptime(u), handler(h), message(m) {
-        }
+        MessageEnvelope(nsecs_t u, sp<MessageHandler> h, const Message& m)
+            : uptime(u), handler(std::move(h)), message(m) {}
 
         nsecs_t uptime;
         sp<MessageHandler> handler;
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 1c3acb8..8ad9900 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -41,6 +41,7 @@
 #include <string>
 #include <unordered_map>
 #include <unordered_set>
+#include <vector>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -1204,9 +1205,19 @@
                 }
             }
             // We are here because we have confirmed kernel live-lock
+            std::vector<std::string> threads;
+            auto taskdir = procdir + std::to_string(tid) + "/task/";
+            dir taskDirectory(taskdir);
+            for (auto tp = taskDirectory.read(); tp != nullptr; tp = taskDirectory.read()) {
+                std::string piddir;
+                if (getValidTidDir(tp, &piddir))
+                    threads.push_back(android::base::Basename(piddir));
+            }
             const auto message = state + " "s + llkFormat(procp->count) + " " +
                                  std::to_string(ppid) + "->" + std::to_string(pid) + "->" +
-                                 std::to_string(tid) + " " + process_comm + " [panic]";
+                                 std::to_string(tid) + " " + process_comm + " [panic]\n" +
+                                 "  thread group: {" + android::base::Join(threads, ",") +
+                                 "}";
             llkPanicKernel(dump, tid,
                            (state == 'Z') ? "zombie" : (state == 'D') ? "driver" : "sleeping",
                            message);
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index b065855..8185f01 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -50,6 +50,7 @@
 #include <android/log.h>
 #include <log/event_tag_map.h>
 #include <log/log_id.h>
+#include <log/log_read.h>
 #include <log/logprint.h>
 #include <private/android_logger.h>
 #include <processgroup/sched_policy.h>
@@ -122,6 +123,18 @@
     return fd;
 }
 
+static void closeLogFile(const char* pathname) {
+    int fd = open(pathname, O_WRONLY | O_CLOEXEC);
+    if (fd == -1) {
+        return;
+    }
+
+    // no need to check errors
+    __u32 set = 0;
+    ioctl(fd, F2FS_IOC_SET_PIN_FILE, &set);
+    close(fd);
+}
+
 void Logcat::RotateLogs() {
     // Can't rotate logs if we're not outputting to a file
     if (!output_file_name_) return;
@@ -152,6 +165,8 @@
             break;
         }
 
+        closeLogFile(file0.c_str());
+
         int err = rename(file0.c_str(), file1.c_str());
 
         if (err < 0 && errno != ENOENT) {
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 3714800..916ed42 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -22,6 +22,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <log/log_read.h>
 #include <private/android_logger.h>
 
 #include "LogBuffer.h"
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index 8299e66..e45cc8a 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -34,6 +34,7 @@
 #include <android-base/stringprintf.h>
 #include <log/log_event_list.h>
 #include <log/log_properties.h>
+#include <log/log_read.h>
 #include <private/android_filesystem_config.h>
 
 #include "LogTags.h"
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index d57b79e..b092489 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -32,6 +32,7 @@
 #include <android-base/stringprintf.h>
 #include <cutils/sockets.h>
 #include <gtest/gtest.h>
+#include <log/log_read.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 #ifdef __ANDROID__
diff --git a/toolbox/start.cpp b/toolbox/start.cpp
index b87ed15..46314cf 100644
--- a/toolbox/start.cpp
+++ b/toolbox/start.cpp
@@ -36,7 +36,12 @@
 }
 
 static void ControlDefaultServices(bool start) {
-    std::vector<std::string> services = {"netd", "surfaceflinger", "zygote"};
+    std::vector<std::string> services = {
+        "netd",
+        "surfaceflinger",
+        "audioserver",
+        "zygote",
+    };
 
     // Only start zygote_secondary if not single arch.
     std::string zygote_configuration = GetProperty("ro.zygote", "");
@@ -86,4 +91,4 @@
 
 extern "C" int stop_main(int argc, char** argv) {
     return StartStop(argc, argv, false);
-}
\ No newline at end of file
+}