Snap for 8730993 from ec686d808c88c72277ab88cd0a880c60a09e9ddf to mainline-tzdata3-release

Change-Id: I32c565a009283ab4a71009920aa2731191ce4cf1
diff --git a/Android.bp b/Android.bp
index c44423f..64c5bc7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -146,21 +146,22 @@
     static_libs: [
         "libadb_crypto",
         "libadb_pairing_connection",
-        "libadb_protos",
         "libadb_sysdeps",
         "libadb_tls_connection",
-        "libadbconnection_server",
         "libadbd",
         "libadbd_core",
-        "libapp_processes_protos_lite",
+        "libadbconnection_server",
         "libasyncio",
         "libbrotli",
         "libcrypto_utils",
         "libcutils_sockets",
         "libdiagnose_usb",
         "libmdnssd",
-        "libprotobuf-cpp-lite",
         "libzstd",
+
+        "libadb_protos",
+        "libapp_processes_protos_lite",
+        "libprotobuf-cpp-lite",
     ],
 
     shared_libs: [
@@ -189,7 +190,7 @@
         android: {
             shared_libs: ["libcrypto"],
         },
-        host_linux: {
+        linux_glibc: {
             static_libs: ["libcrypto_static"],
         },
         recovery: {
@@ -300,21 +301,21 @@
 
     static_libs: [
         "libadb_crypto",
-        "libadb_pairing_connection",
         "libadb_protos",
+        "libadb_pairing_connection",
         "libadb_tls_connection",
         "libbase",
-        "libcrypto",
         "libcrypto_utils",
-        "libcutils",
+        "libcrypto",
         "libdiagnose_usb",
-        "liblog",
         "libmdnssd",
+        "libusb",
+        "libutils",
+        "liblog",
+        "libcutils",
         "libopenscreen-discovery",
         "libopenscreen-platform-impl",
         "libprotobuf-cpp-lite",
-        "libusb",
-        "libutils",
     ],
 }
 
@@ -373,12 +374,12 @@
         "libadb_sysdeps",
         "libadb_tls_connection_static",
         "libbase",
-        "libcrypto",
-        "libcrypto_utils",
         "libcutils",
-        "libdiagnose_usb",
+        "libcrypto_utils",
+        "libcrypto",
         "liblog",
         "libmdnssd",
+        "libdiagnose_usb",
         "libopenscreen-discovery",
         "libopenscreen-platform-impl",
         "libprotobuf-cpp-lite",
@@ -435,12 +436,11 @@
         "libapp_processes_protos_full",
         "libbase",
         "libbrotli",
-        "libcrypto",
-        "libcrypto_utils",
         "libcutils",
-        "libdiagnose_usb",
+        "libcrypto_utils",
+        "libcrypto",
         "libfastdeploy_host",
-        "liblog",
+        "libdiagnose_usb",
         "liblog",
         "liblz4",
         "libmdnssd",
@@ -450,8 +450,9 @@
         "libssl",
         "libusb",
         "libutils",
-        "libz",
+        "liblog",
         "libziparchive",
+        "libz",
         "libzstd",
     ],
 
@@ -510,11 +511,11 @@
     ],
 
     shared_libs: [
+        "libadbconnection_server",
         "libadb_crypto",
         "libadb_pairing_connection",
         "libadb_protos",
         "libadb_tls_connection",
-        "libadbconnection_server",
         "libadbd_auth",
         "libapp_processes_protos_lite",
         "libasyncio",
@@ -549,7 +550,6 @@
         }
     },
 
-    min_sdk_version: "30",
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
@@ -584,7 +584,6 @@
         "libbrotli",
         "libdiagnose_usb",
         "liblz4",
-        "libprotobuf-cpp-lite",
         "libzstd",
     ],
 
@@ -598,6 +597,7 @@
         "libbase",
         "libcrypto_utils",
         "libcutils_sockets",
+        "libprotobuf-cpp-lite",
 
         // APEX dependencies.
         "libadbd_auth",
@@ -630,7 +630,6 @@
         },
     },
 
-    min_sdk_version: "30",
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
@@ -645,7 +644,6 @@
     name: "libadbd",
     defaults: ["adbd_defaults", "host_adbd_supported"],
     recovery_available: true,
-    min_sdk_version: "30",
     apex_available: ["com.android.adbd"],
 
     // avoid getting duplicate symbol of android::build::getbuildnumber().
@@ -654,21 +652,10 @@
     // libminadbd wants both, as it's used to build native tests.
     compile_multilib: "both",
 
-    static_libs: [
-        "libadbd_core",
-        "libadbd_services",
-        "libbrotli",
-        "libcutils_sockets",
-        "libdiagnose_usb",
-        "liblz4",
-        "libmdnssd",
-        "libprotobuf-cpp-lite",
-        "libzstd",
-    ],
-
     shared_libs: [
         "libadbconnection_server",
         "libapp_processes_protos_lite",
+        "libprotobuf-cpp-lite",
         "libadb_crypto",
         "libadb_pairing_connection",
         "libadb_tls_connection",
@@ -682,6 +669,7 @@
         // APEX dependencies on the system image.
         "libadbd_auth",
         "libadbd_fs",
+        "libadbd_services",
     ],
 
     target: {
@@ -693,6 +681,15 @@
         }
     },
 
+    static_libs: [
+        "libadbd_core",
+        "libbrotli",
+        "libcutils_sockets",
+        "libdiagnose_usb",
+        "liblz4",
+        "libmdnssd",
+        "libzstd",
+    ],
 
     visibility: [
         "//bootable/recovery/minadbd",
@@ -704,7 +701,6 @@
     name: "adbd",
     defaults: ["adbd_defaults", "host_adbd_supported", "libadbd_binary_dependencies"],
     recovery_available: true,
-    min_sdk_version: "30",
     apex_available: ["com.android.adbd"],
 
     srcs: [
@@ -721,7 +717,6 @@
     },
 
     static_libs: [
-        "libadb_protos",
         "libadbd",
         "libadbd_services",
         "libasyncio",
@@ -732,6 +727,7 @@
     ],
 
     shared_libs: [
+        "libadb_protos",
         "libadbd_auth",
     ],
 
@@ -760,8 +756,8 @@
 phony {
     name: "adbd_system_api_recovery",
     required: [
-        "libadbd_auth.recovery",
-        "libadbd_fs.recovery",
+        "libadbd_auth",
+        "libadbd_fs",
         "reboot.recovery",
     ],
 }
@@ -915,16 +911,16 @@
         "libadb_host",
         "libandroidfw",
         "libbase",
-        "libcrypto",
-        "libcrypto_utils",
         "libcutils",
+        "libcrypto_utils",
+        "libcrypto",
         "libdiagnose_usb",
         "liblog",
         "libmdnssd",
         "libusb",
         "libutils",
-        "libz",
         "libziparchive",
+        "libz",
     ],
     proto: {
         type: "lite",
@@ -956,9 +952,9 @@
         "libadb_tls_connection_static",
         "libandroidfw",
         "libbase",
-        "libcrypto",
-        "libcrypto_utils",
         "libcutils",
+        "libcrypto_utils",
+        "libcrypto",
         "libdiagnose_usb",
         "libfastdeploy_host",
         "liblog",
@@ -969,8 +965,8 @@
         "libssl",
         "libusb",
         "libutils",
-        "libz",
         "libziparchive",
+        "libz",
     ],
     target: {
         windows: {
diff --git a/OVERVIEW.TXT b/OVERVIEW.TXT
index 3e20037..f0b184c 100644
--- a/OVERVIEW.TXT
+++ b/OVERVIEW.TXT
@@ -62,8 +62,8 @@
     Host Services:
       These services run within the ADB Server and thus do not need to
       communicate with a device at all. A typical example is "adb devices"
-      that is used to return the list of currently known devices and their
-      states. There are a few other services, though.
+      which is used to return the list of currently known devices and their
+      states. They are a few other services though.
 
     Local Services:
       These services either run within the adbd daemon, or are started by
@@ -77,7 +77,7 @@
 
   1. Client <-> Server protocol:
 
-    This section details the protocol used between ADB clients and the ADB
+    This details the protocol used between ADB clients and the ADB
     server itself. The ADB server listens on TCP:localhost:5037.
 
     A client sends a request using the following format:
diff --git a/OWNERS b/OWNERS
index 6cbf5b3..2108ae5 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,4 @@
-shaju@google.com
+jmgao@google.com
 enh@google.com
 
 include platform/packages/modules/common:/MODULES_OWNERS  # see go/mainline-owners-policy
diff --git a/README.md b/README.md
index 3f2acac..224387c 100644
--- a/README.md
+++ b/README.md
@@ -33,11 +33,11 @@
 
 A smart socket is a simple TCP socket with a smart protocol built on top of it. This is what Clients connect onto from the Host side. The Client must always initiate communication via a human readable request but the response format varies. The smart protocol is documented in [SERVICES.TXT](SERVICES.TXT).
 
-On the other side, the Server communicates with a device via a Transport. adb initially targeted devices connecting over USB, which is restricted to a fixed number of data streams. Therefore, adb multiplexes multiple byte streams over a single pipe via Transport. When devices connecting over other mechanisms (e.g. emulators over TCP) were introduced, the existing transport protocol was maintained.
+On the other side, the Server communicate with a device via a Transport. adb initially targeted devices connecting over USB, which is restricted to a fixed number of data streams. Therefore, adb multiplexes multiple byte streams over a single pipe via Transport. When devices connecting over other mechanisms (e.g. emulators over TCP) were introduced, the existing transport protocol was maintained.
 
 ## THREADING MODEL and FDEVENT system
 
-At the heart of both the Server and Daemon is a main thread running an fdevent loop, which is a platform-independent abstraction over poll/epoll/WSAPoll monitoring file descriptors events. Requests and services are usually served from the main thread but some service requests result in new threads being spawned.
+At the heart of both the Server and Daemon is a main thread running an fdevent loop, which is an platform-independent abstraction over poll/epoll/WSAPoll monitoring file descriptors events. Requests and services are usually server from the main thread but some service requests result in new threads being spawned.
 
 To allow for operations to run on the Main thread, fdevent features a RunQueue combined with an interrupt fd to force polling to return.
 
@@ -61,7 +61,7 @@
 
 The asocket, apacket, and amessage constructs exist only to wrap data while it transits on a Transport. An asocket handles a stream of apackets. An apacket consists in a amessage header featuring a command (`A_SYNC`, `A_OPEN`, `A_CLSE`, `A_WRTE`, `A_OKAY`, ...) followed by a payload (find more documentation in [protocol.txt](protocol.txt). There is no `A_READ` command because an asocket is unidirectional. To model a bi-directional stream, asocket have a peer which go in the opposite direction.
 
-An asocket features a buffer where the elemental unit is an apacket. If traffic is inbound, the buffer stores the apacket until it is consumed. If the traffic is oubound, the buffer stores apackets until they are sent down the wire (with `A_WRTE` commands).
+An asocket features a buffer where the elemental unit is an apacket. Is traffic is inbound, the buffer stores apacket until they are consumed. If the traffic is oubound, the buffer store apackets until they are sent down the wire (with `A_WRTE` commands).
 
 ```
 +---------------------ASocket------------------------+
@@ -89,6 +89,6 @@
 
 ## adbd <-> APPPLICATION communication
 
-This pipeline is detailed in [daemon/jdwp_service.cpp](daemon/jdwp_service.cpp) with ASCII drawings! The JDWP extension implemented by Dalvik/ART are documented in:
+This pipeline is detailed in [services.cpp](services.cpp). The JDWP extension implemented by Dalvik/ART are documented in:
 - platform/dalvik/+/master/docs/debugmon.html
 - platform/dalvik/+/master/docs/debugger.html
diff --git a/SERVICES.TXT b/SERVICES.TXT
index e0c95c4..43e2396 100644
--- a/SERVICES.TXT
+++ b/SERVICES.TXT
@@ -172,6 +172,12 @@
     This request may not succeed on certain builds which do not allow
     that.
 
+dev:<path>
+    Opens a device file and connects the client directly to it for
+    read/write purposes. Useful for debugging, but may require special
+    privileges and thus may not run on all devices. <path> is a full
+    path from the root of the filesystem.
+
 tcp:<port>
     Tries to connect to tcp port <port> on localhost.
 
diff --git a/SYNC.TXT b/SYNC.TXT
index 1bc5d99..4445a76 100644
--- a/SYNC.TXT
+++ b/SYNC.TXT
@@ -11,17 +11,17 @@
 differs from the regular adb protocol. The connection stays in sync mode until
 explicitly terminated (see below).
 
-After the initial "sync:" command is sent, the server must respond with either
-"OKAY" or "FAIL" as per the usual protocol.
+After the initial "sync:" command is sent the server must respond with either
+"OKAY" or "FAIL" as per usual.
 
 In sync mode both the server and the client will frequently use eight-byte
 packets to communicate. In this document these are called sync requests and sync
-responses. The first four bytes constitute an id that specifies the sync request.
-It is represented by four ASCII bytes in order to make them more human-readable
-when debugging. The last four bytes are a Little-Endian integer, with various
-uses. This number shall be called "length" below. In fact, all binary integers
-are Little-Endian in the sync mode. Sync mode is implicitly exited after each
-sync request, and normal adb communication follows as described in SERVICES.TXT.
+responses. The first four bytes are an id that specifies the sync request. It is
+represented by four utf-8 characters. The last four bytes are a Little-Endian
+integer, with various uses. This number will be called "length" below. In fact
+all binary integers are Little-Endian in the sync mode. Sync mode is
+implicitly exited after each sync request, and normal adb communication
+follows as described in SERVICES.TXT.
 
 The following sync requests are accepted:
 LIST - List the files in a folder
diff --git a/TEST_MAPPING b/TEST_MAPPING
index bb00729..28aecfd 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,63 +2,6 @@
   "mainline-presubmit": [
     {
       "name": "adbd_test[com.google.android.adbd.apex]"
-    },
-    {
-      "name": "adb_crypto_test[com.google.android.adbd.apex]"
-    },
-    {
-      "name": "adb_pairing_auth_test[com.google.android.adbd.apex]"
-    },
-    {
-      "name": "adb_pairing_connection_test[com.google.android.adbd.apex]"
-    },
-    {
-      "name": "adb_tls_connection_test[com.google.android.adbd.apex]"
-    }
-  ],
-  "presubmit": [
-    {
-      "name": "adbd_test"
-    },
-    {
-      "name": "adb_crypto_test"
-    },
-    {
-      "name": "adb_pairing_auth_test"
-    },
-    {
-      "name": "adb_pairing_connection_test"
-    },
-    {
-      "name": "adb_tls_connection_test"
-    },
-    {
-      "name": "MicrodroidHostTestCases"
-    }
-  ],
-  "hwasan-postsubmit": [
-    {
-      "name": "adbd_test"
-    },
-    {
-      "name": "adb_crypto_test"
-    },
-    {
-      "name": "adb_pairing_auth_test"
-    },
-    {
-      "name": "adb_pairing_connection_test"
-    },
-    {
-      "name": "adb_tls_connection_test"
-    },
-    {
-      "name": "MicrodroidHostTestCases"
-    }
-  ],
-  "imports": [
-    {
-      "path": "frameworks/base/tests/StagedInstallTest"
     }
   ]
 }
diff --git a/adb.cpp b/adb.cpp
index 6813da0..d692a0b 100644
--- a/adb.cpp
+++ b/adb.cpp
@@ -45,8 +45,6 @@
 #include <android-base/parsenetaddress.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <diagnose_usb.h>
-
 #include <build/version.h>
 #include <platform_tools_version.h>
 
@@ -110,36 +108,8 @@
     return sum;
 }
 
-std::string to_string(ConnectionState state) {
-    switch (state) {
-        case kCsOffline:
-            return "offline";
-        case kCsBootloader:
-            return "bootloader";
-        case kCsDevice:
-            return "device";
-        case kCsHost:
-            return "host";
-        case kCsRecovery:
-            return "recovery";
-        case kCsRescue:
-            return "rescue";
-        case kCsNoPerm:
-            return UsbNoPermissionsShortHelpText();
-        case kCsSideload:
-            return "sideload";
-        case kCsUnauthorized:
-            return "unauthorized";
-        case kCsAuthorizing:
-            return "authorizing";
-        case kCsConnecting:
-            return "connecting";
-        default:
-            return "unknown";
-    }
-}
-
-apacket* get_apacket(void) {
+apacket* get_apacket(void)
+{
     apacket* p = new apacket();
     if (p == nullptr) {
         LOG(FATAL) << "failed to allocate an apacket";
@@ -726,7 +696,7 @@
     while (static_cast<size_t>(i) < lines.size()) fprintf(stderr, "%s\n", lines[i++].c_str());
 }
 
-int launch_server(const std::string& socket_spec, const char* one_device) {
+int launch_server(const std::string& socket_spec) {
 #if defined(_WIN32)
     /* we need to start the server in the background                    */
     /* we create a PIPE that will be used to wait for the server's "OK" */
@@ -828,14 +798,8 @@
     }
 
     WCHAR   args[64];
-    if (one_device) {
-        snwprintf(args, arraysize(args),
-                  L"adb -L %s fork-server server --reply-fd %d --one-device %s",
-                  socket_spec.c_str(), ack_write_as_int, one_device);
-    } else {
-        snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d",
-                  socket_spec.c_str(), ack_write_as_int);
-    }
+    snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d",
+              socket_spec.c_str(), ack_write_as_int);
 
     PROCESS_INFORMATION   pinfo;
     ZeroMemory(&pinfo, sizeof(pinfo));
@@ -984,14 +948,8 @@
         char reply_fd[30];
         snprintf(reply_fd, sizeof(reply_fd), "%d", pipe_write.get());
         // child process
-        std::vector<const char*> child_argv = {
-                "adb", "-L", socket_spec.c_str(), "fork-server", "server", "--reply-fd", reply_fd};
-        if (one_device) {
-            child_argv.push_back("--one-device");
-            child_argv.push_back(one_device);
-        }
-        child_argv.push_back(nullptr);
-        int result = execv(path.c_str(), const_cast<char* const*>(child_argv.data()));
+        int result = execl(path.c_str(), "adb", "-L", socket_spec.c_str(), "fork-server", "server",
+                           "--reply-fd", reply_fd, NULL);
         // this should not return
         fprintf(stderr, "adb: execl returned %d: %s\n", result, strerror(errno));
     } else {
@@ -1368,7 +1326,7 @@
                 s->transport ? s->transport
                              : acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t) {
-            SendOkay(reply_fd, to_string(t->GetConnectionState()));
+            SendOkay(reply_fd, t->connection_state_name());
         } else {
             SendFail(reply_fd, error);
         }
@@ -1395,59 +1353,13 @@
                                                              &response, true);
         if (t != nullptr) {
             kick_transport(t, true);
-            response = "reconnecting " + t->serial_name() + " [" +
-                       to_string(t->GetConnectionState()) + "]\n";
+            response =
+                    "reconnecting " + t->serial_name() + " [" + t->connection_state_name() + "]\n";
         }
         SendOkay(reply_fd, response);
         return HostRequestResult::Handled;
     }
 
-    if (service == "attach") {
-        std::string error;
-        atransport* t = s->transport ? s->transport
-                                     : acquire_one_transport(type, serial, transport_id, nullptr,
-                                                             &error, true);
-        if (!t) {
-            SendFail(reply_fd, error);
-            return HostRequestResult::Handled;
-        }
-
-        if (t->Attach(&error)) {
-            SendOkay(reply_fd,
-                     android::base::StringPrintf("%s attached", t->serial_name().c_str()));
-        } else {
-            SendFail(reply_fd, error);
-        }
-        return HostRequestResult::Handled;
-    }
-
-    if (service == "detach") {
-        std::string error;
-        atransport* t = s->transport ? s->transport
-                                     : acquire_one_transport(type, serial, transport_id, nullptr,
-                                                             &error, true);
-        if (!t) {
-            SendFail(reply_fd, error);
-            return HostRequestResult::Handled;
-        }
-
-        // HACK:
-        // Detaching the transport will lead to all of its sockets being closed,
-        // but we're handling one of those sockets right now!
-        //
-        // Mark the socket as not having a transport, knowing that it'll be cleaned up by the
-        // function that called us.
-        s->transport = nullptr;
-
-        if (t->Detach(&error)) {
-            SendOkay(reply_fd,
-                     android::base::StringPrintf("%s detached", t->serial_name().c_str()));
-        } else {
-            SendFail(reply_fd, error);
-        }
-        return HostRequestResult::Handled;
-    }
-
     // TODO: Switch handle_forward_request to string_view.
     std::string service_str(service);
     auto transport_acquirer = [=](std::string* error) {
diff --git a/adb.h b/adb.h
index 9dfaf3e..476ed9b 100644
--- a/adb.h
+++ b/adb.h
@@ -104,7 +104,6 @@
     kCsAuthorizing,     // Authorizing with keys from ADB_VENDOR_KEYS.
     kCsUnauthorized,    // ADB_VENDOR_KEYS exhausted, fell back to user prompt.
     kCsNoPerm,          // Insufficient permissions to communicate with the device.
-    kCsDetached,        // USB device that's detached from the adb server.
     kCsOffline,
 
     kCsBootloader,
@@ -115,8 +114,6 @@
     kCsRescue,
 };
 
-std::string to_string(ConnectionState state);
-
 inline bool ConnectionStateIsOnline(ConnectionState state) {
     switch (state) {
         case kCsBootloader:
@@ -135,9 +132,8 @@
 
 void handle_packet(apacket* p, atransport* t);
 
-int launch_server(const std::string& socket_spec, const char* one_device);
-int adb_server_main(int is_daemon, const std::string& socket_spec, const char* one_device,
-                    int ack_reply_fd);
+int launch_server(const std::string& socket_spec);
+int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd);
 
 /* initialize a transport object's func pointers and state */
 int init_socket_transport(atransport* t, unique_fd s, int port, int local);
@@ -204,6 +200,8 @@
 bool local_connect(int port);
 int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
 
+ConnectionState connection_state(atransport* t);
+
 extern const char* adb_device_banner;
 
 #define CHUNK_SIZE (64 * 1024)
diff --git a/adb_auth.h b/adb_auth.h
index 1a1ab11..7e858dc 100644
--- a/adb_auth.h
+++ b/adb_auth.h
@@ -49,7 +49,6 @@
 #else // !ADB_HOST
 
 extern bool auth_required;
-extern bool socket_access_allowed;
 
 void adbd_auth_init(void);
 void adbd_auth_verified(atransport *t);
diff --git a/apex/Android.bp b/apex/Android.bp
index 4588d23..e018565 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -9,7 +9,7 @@
 
 apex_defaults {
     name: "com.android.adbd-defaults",
-    defaults: ["r-launched-apex-module"],
+    updatable: true,
 
     binaries: ["adbd"],
     compile_multilib: "both",
@@ -36,6 +36,7 @@
     module_types: ["library_linking_strategy_apex_defaults"],
 }
 
+// TODO(b/178585590): delete after testing linking strategy
 library_linking_strategy_apex_defaults {
     name: "adbd_manifest_defaults",
     soong_config_variables: {
@@ -63,6 +64,7 @@
     name: "test_com.android.adbd",
     defaults: ["com.android.adbd-defaults"],
     manifest: "test_apex_manifest.json",
+    min_sdk_version: "30",
     file_contexts: ":com.android.adbd-file_contexts",
     installable: false,
 }
diff --git a/apex/apex_manifest.json b/apex/apex_manifest.json
index 5339342..7c9dc75 100644
--- a/apex/apex_manifest.json
+++ b/apex/apex_manifest.json
@@ -1,5 +1,4 @@
 {
   "name": "com.android.adbd",
-  "version": 339990000,
-  "versionName": "339990000"
+  "version": 319999999
 }
diff --git a/client/adb_client.cpp b/client/adb_client.cpp
index 2d3e61f..a308732 100644
--- a/client/adb_client.cpp
+++ b/client/adb_client.cpp
@@ -53,7 +53,6 @@
 static TransportId __adb_transport_id = 0;
 
 static const char* __adb_server_socket_spec;
-static const char* __adb_client_one_device;
 
 void adb_set_transport(TransportType type, const char* serial, TransportId transport_id) {
     __adb_transport = type;
@@ -74,10 +73,6 @@
     __adb_server_socket_spec = socket_spec;
 }
 
-void adb_set_one_device(const char* one_device) {
-    __adb_client_one_device = one_device;
-}
-
 static std::optional<TransportId> switch_socket_transport(int fd, std::string* error) {
     TransportId result;
     bool read_transport = true;
@@ -262,7 +257,7 @@
     } else if (fd == -2) {
         fprintf(stderr, "* daemon not running; starting now at %s\n", __adb_server_socket_spec);
     start_server:
-        if (launch_server(__adb_server_socket_spec, __adb_client_one_device)) {
+        if (launch_server(__adb_server_socket_spec)) {
             fprintf(stderr, "* failed to start daemon\n");
             // launch_server() has already printed detailed error info, so just
             // return a generic error string about the overall adb_connect()
@@ -388,10 +383,9 @@
     return true;
 }
 
-bool adb_query(const std::string& service, std::string* result, std::string* error,
-               bool force_switch_device) {
+bool adb_query(const std::string& service, std::string* result, std::string* error) {
     D("adb_query: %s", service.c_str());
-    unique_fd fd(adb_connect(nullptr, service, error, force_switch_device));
+    unique_fd fd(adb_connect(service, error));
     if (fd < 0) {
         return false;
     }
diff --git a/client/adb_client.h b/client/adb_client.h
index 8262d18..d0a4c4e 100644
--- a/client/adb_client.h
+++ b/client/adb_client.h
@@ -51,17 +51,13 @@
 // Connects to the named adb service and fills 'result' with the response.
 // Returns true on success; returns false and fills 'error' on failure.
 bool adb_query(const std::string& service, std::string* _Nonnull result,
-               std::string* _Nonnull error, bool force_switch_device = false);
+               std::string* _Nonnull error);
 
 // Set the preferred transport to connect to.
 void adb_set_transport(TransportType type, const char* _Nullable serial, TransportId transport_id);
 void adb_get_transport(TransportType* _Nullable type, const char* _Nullable* _Nullable serial,
                        TransportId* _Nullable transport_id);
 
-// Set the server's "one device" id. This is either null, or a pointer to a serial number
-// or a pointer to a usb device path, the argument must live to the end of the process.
-void adb_set_one_device(const char* _Nullable one_device);
-
 // Set the socket specification for the adb server.
 // This function can only be called once, and the argument must live to the end of the process.
 void adb_set_socket_spec(const char* _Nonnull socket_spec);
diff --git a/client/adb_install.cpp b/client/adb_install.cpp
index 1619e85..97debae 100644
--- a/client/adb_install.cpp
+++ b/client/adb_install.cpp
@@ -56,22 +56,28 @@
 enum class CmdlineOption { None, Enable, Disable };
 }
 
+static bool can_use_feature(const char* feature) {
+    // We ignore errors here, if the device is missing, we'll notice when we try to push install.
+    auto&& features = adb_get_feature_set(nullptr);
+    if (!features) {
+        return false;
+    }
+    return CanUseFeature(*features, feature);
+}
+
 static InstallMode best_install_mode() {
-    auto&& features = adb_get_feature_set_or_die();
-    if (CanUseFeature(*features, kFeatureCmd)) {
+    if (can_use_feature(kFeatureCmd)) {
         return INSTALL_STREAM;
     }
     return INSTALL_PUSH;
 }
 
 static bool is_apex_supported() {
-    auto&& features = adb_get_feature_set_or_die();
-    return CanUseFeature(*features, kFeatureApex);
+    return can_use_feature(kFeatureApex);
 }
 
 static bool is_abb_exec_supported() {
-    auto&& features = adb_get_feature_set_or_die();
-    return CanUseFeature(*features, kFeatureAbbExec);
+    return can_use_feature(kFeatureAbbExec);
 }
 
 static int pm_command(int argc, const char** argv) {
@@ -562,7 +568,7 @@
     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 = 0; i < first_apk; i++) {
+    for (int i = 1; i < first_apk; i++) {
         if (use_abb_exec) {
             cmd_args.push_back(argv[i]);
         } else {
diff --git a/client/bugreport.cpp b/client/bugreport.cpp
index 626dfbb..1bee2f8 100644
--- a/client/bugreport.cpp
+++ b/client/bugreport.cpp
@@ -53,8 +53,8 @@
         SetLineMessage("generating");
     }
 
-    bool OnStdout(const char* buffer, size_t length) {
-        for (size_t i = 0; i < length; i++) {
+    void OnStdout(const char* buffer, int length) {
+        for (int i = 0; i < length; i++) {
             char c = buffer[i];
             if (c == '\n') {
                 ProcessLine(line_);
@@ -63,11 +63,10 @@
                 line_.append(1, c);
             }
         }
-        return true;
     }
 
-    bool OnStderr(const char* buffer, size_t length) {
-      return OnStream(nullptr, stderr, buffer, length, false);
+    void OnStderr(const char* buffer, int length) {
+        OnStream(nullptr, stderr, buffer, length);
     }
 
     int Done(int unused_) {
diff --git a/client/commandline.cpp b/client/commandline.cpp
index 018bfd7..0caf9e2 100644
--- a/client/commandline.cpp
+++ b/client/commandline.cpp
@@ -44,12 +44,10 @@
 #include <android-base/strings.h>
 
 #if !defined(_WIN32)
+#include <signal.h>
 #include <sys/ioctl.h>
 #include <termios.h>
 #include <unistd.h>
-#else
-#define _POSIX
-#include <signal.h>
 #endif
 
 #include <google/protobuf/text_format.h>
@@ -88,19 +86,14 @@
     // clang-format off
     fprintf(stdout,
         "global options:\n"
-        " -a                       listen on all network interfaces, not just localhost\n"
-        " -d                       use USB device (error if multiple devices connected)\n"
-        " -e                       use TCP/IP device (error if multiple TCP/IP devices available)\n"
-        " -s SERIAL                use device with given serial (overrides $ANDROID_SERIAL)\n"
-        " -t ID                    use device with given transport id\n"
-        " -H                       name of adb server host [default=localhost]\n"
-        " -P                       port of adb server [default=5037]\n"
-        " -L SOCKET                listen on given socket for adb server"
-        " [default=tcp:localhost:5037]\n"
-        " --one-device SERIAL|USB  only allowed with 'start-server' or 'server nodaemon', server"
-        " will only connect to one USB device, specified by a serial number or USB device"
-        " address.\n"
-        " --exit-on-write-error    exit if stdout is closed\n"
+        " -a         listen on all network interfaces, not just localhost\n"
+        " -d         use USB device (error if multiple devices connected)\n"
+        " -e         use TCP/IP device (error if multiple TCP/IP devices available)\n"
+        " -s SERIAL  use device with given serial (overrides $ANDROID_SERIAL)\n"
+        " -t ID      use device with given transport id\n"
+        " -H         name of adb server host [default=localhost]\n"
+        " -P         port of adb server [default=5037]\n"
+        " -L SOCKET  listen on given socket for adb server [default=tcp:localhost:5037]\n"
         "\n"
         "general commands:\n"
         " devices [-l]             list connected devices (-l for long output)\n"
@@ -120,6 +113,7 @@
         "       localabstract:<unix domain socket name>\n"
         "       localreserved:<unix domain socket name>\n"
         "       localfilesystem:<unix domain socket name>\n"
+        "       dev:<character device name>\n"
         "       jdwp:<process pid> (remote only)\n"
         "       vsock:<CID>:<port> (remote only)\n"
         "       acceptfd:<fd> (listen only)\n"
@@ -143,18 +137,18 @@
         "     copy local files/directories to device\n"
         "     --sync: only push files that are newer on the host than the device\n"
         "     -n: dry run: push files to device without storing to the filesystem\n"
-        "     -z: enable compression with a specified algorithm (any/none/brotli/lz4/zstd)\n"
+        "     -z: enable compression with a specified algorithm (any, none, brotli)\n"
         "     -Z: disable compression\n"
         " pull [-a] [-z ALGORITHM] [-Z] REMOTE... LOCAL\n"
         "     copy files/dirs from device\n"
         "     -a: preserve file timestamp and mode\n"
-        "     -z: enable compression with a specified algorithm (any/none/brotli/lz4/zstd)\n"
+        "     -z: enable compression with a specified algorithm (any, none, brotli)\n"
         "     -Z: disable compression\n"
         " sync [-l] [-z ALGORITHM] [-Z] [all|data|odm|oem|product|system|system_ext|vendor]\n"
         "     sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
         "     -n: dry run: push files to device without storing to the filesystem\n"
         "     -l: list files that would be copied, but don't copy them\n"
-        "     -z: enable compression with a specified algorithm (any/none/brotli/lz4/zstd)\n"
+        "     -z: enable compression with a specified algorithm (any, none, brotli)\n"
         "     -Z: disable compression\n"
         "\n"
         "shell:\n"
@@ -240,10 +234,6 @@
         " reconnect device         kick connection from device side to force reconnect\n"
         " reconnect offline        reset offline/unauthorized devices to force reconnect\n"
         "\n"
-        "usb:\n"
-        " attach                   attach a detached USB device\n"
-        " detach                   detach from a USB device to allow use by other processes\n"
-        ""
         "environment variables:\n"
         " $ADB_TRACE\n"
         "     comma-separated list of debug info to log:\n"
@@ -286,55 +276,57 @@
 }
 #endif
 
-int read_and_dump_protocol(borrowed_fd fd, StandardStreamsCallbackInterface* callback) {
-    int exit_code = 0;
-    std::unique_ptr<ShellProtocol> protocol = std::make_unique<ShellProtocol>(fd);
-    if (!protocol) {
-      LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
-      return 1;
-    }
-    while (protocol->Read()) {
-      if (protocol->id() == ShellProtocol::kIdStdout) {
-        if (!callback->OnStdout(protocol->data(), protocol->data_length())) {
-          exit_code = SIGPIPE + 128;
-          break;
-        }
-      } else if (protocol->id() == ShellProtocol::kIdStderr) {
-        if (!callback->OnStderr(protocol->data(), protocol->data_length())) {
-          exit_code = SIGPIPE + 128;
-          break;
-        }
-      } else if (protocol->id() == ShellProtocol::kIdExit) {
-        // data() returns a char* which doesn't have defined signedness.
-        // Cast to uint8_t to prevent 255 from being sign extended to INT_MIN,
-        // which doesn't get truncated on Windows.
-        exit_code = static_cast<uint8_t>(protocol->data()[0]);
-      }
-    }
-    return exit_code;
-}
-
 int read_and_dump(borrowed_fd fd, bool use_shell_protocol,
                   StandardStreamsCallbackInterface* callback) {
     int exit_code = 0;
     if (fd < 0) return exit_code;
 
+    std::unique_ptr<ShellProtocol> protocol;
+    int length = 0;
+
+    char raw_buffer[BUFSIZ];
+    char* buffer_ptr = raw_buffer;
     if (use_shell_protocol) {
-      exit_code = read_and_dump_protocol(fd, callback);
-    } else {
-      char raw_buffer[BUFSIZ];
-      char* buffer_ptr = raw_buffer;
-      while (true) {
-        D("read_and_dump(): pre adb_read(fd=%d)", fd.get());
-        int length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
-        D("read_and_dump(): post adb_read(fd=%d): length=%d", fd.get(), length);
-        if (length <= 0) {
-          break;
+        protocol = std::make_unique<ShellProtocol>(fd);
+        if (!protocol) {
+            LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
+            return 1;
         }
-        if (!callback->OnStdout(buffer_ptr, length)) {
-          break;
+        buffer_ptr = protocol->data();
+    }
+
+    while (true) {
+        if (use_shell_protocol) {
+            if (!protocol->Read()) {
+                break;
+            }
+            length = protocol->data_length();
+            switch (protocol->id()) {
+                case ShellProtocol::kIdStdout:
+                    callback->OnStdout(buffer_ptr, length);
+                    break;
+                case ShellProtocol::kIdStderr:
+                    callback->OnStderr(buffer_ptr, length);
+                    break;
+                case ShellProtocol::kIdExit:
+                    // data() returns a char* which doesn't have defined signedness.
+                    // Cast to uint8_t to prevent 255 from being sign extended to INT_MIN,
+                    // which doesn't get truncated on Windows.
+                    exit_code = static_cast<uint8_t>(protocol->data()[0]);
+                    continue;
+                default:
+                    continue;
+            }
+            length = protocol->data_length();
+        } else {
+            D("read_and_dump(): pre adb_read(fd=%d)", fd.get());
+            length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
+            D("read_and_dump(): post adb_read(fd=%d): length=%d", fd.get(), length);
+            if (length <= 0) {
+                break;
+            }
+            callback->OnStdout(buffer_ptr, length);
         }
-      }
     }
 
     return callback->Done(exit_code);
@@ -685,11 +677,16 @@
 }
 
 static int adb_shell(int argc, const char** argv) {
+    std::string error;
+    auto&& features = adb_get_feature_set(&error);
+    if (!features) {
+        error_exit("%s", error.c_str());
+    }
+
     enum PtyAllocationMode { kPtyAuto, kPtyNo, kPtyYes, kPtyDefinitely };
 
     // Defaults.
     char escape_char = '~';                                                 // -e
-    auto&& features = adb_get_feature_set_or_die();
     bool use_shell_protocol = CanUseFeature(*features, kFeatureShell2);     // -x
     PtyAllocationMode tty = use_shell_protocol ? kPtyAuto : kPtyDefinitely; // -t/-T
 
@@ -786,7 +783,12 @@
 }
 
 static int adb_abb(int argc, const char** argv) {
-    auto&& features = adb_get_feature_set_or_die();
+    std::string error;
+    auto&& features = adb_get_feature_set(&error);
+    if (!features) {
+        error_exit("%s", error.c_str());
+        return 1;
+    }
     if (!CanUseFeature(*features, kFeatureAbb)) {
         error_exit("abb is not supported by the device");
     }
@@ -1009,6 +1011,13 @@
     return 1;
 }
 
+/**
+ * Run ppp in "notty" mode against a resource listed as the first parameter
+ * eg:
+ *
+ * ppp dev:/dev/omap_csmi_tty0 <ppp options>
+ *
+ */
 static int ppp(int argc, const char** argv) {
 #if defined(_WIN32)
     error_exit("adb %s not implemented on Win32", argv[0]);
@@ -1406,8 +1415,8 @@
     TrackAppStreamsCallback() : DefaultStandardStreamsCallback(nullptr, nullptr) {}
 
     // Assume the buffer contains at least 4 bytes of valid data.
-    bool OnStdout(const char* buffer, size_t length) override {
-        if (length < 4) return true;  // Unexpected length received. Do nothing.
+    void OnStdout(const char* buffer, int length) override {
+        if (length < 4) return;  // Unexpected length received. Do nothing.
 
         adb::proto::AppProcesses binary_proto;
         // The first 4 bytes are the length of remaining content in hexadecimal format.
@@ -1415,13 +1424,11 @@
         char summary[24];  // The following string includes digits and 16 fixed characters.
         int written = snprintf(summary, sizeof(summary), "Process count: %d\n",
                                binary_proto.process_size());
-        if (!OnStream(nullptr, stdout, summary, written, false)) {
-          return false;
-        }
+        OnStream(nullptr, stdout, summary, written);
 
         std::string string_proto;
         google::protobuf::TextFormat::PrintToString(binary_proto, &string_proto);
-        return OnStream(nullptr, stdout, string_proto.data(), string_proto.length(), false);
+        OnStream(nullptr, stdout, string_proto.data(), string_proto.length());
     }
 
   private:
@@ -1463,33 +1470,6 @@
     return 0;
 }
 
-const std::optional<FeatureSet>& adb_get_feature_set_or_die(void) {
-    std::string error;
-    const std::optional<FeatureSet>& features = adb_get_feature_set(&error);
-    if (!features) {
-        error_exit("%s", error.c_str());
-    }
-    return features;
-}
-
-// Helper function to handle processing of shell service commands:
-// remount, disable/enable-verity. There's only one "feature",
-// but they were all moved from adbd to external binaries in the
-// same release.
-static int process_remount_or_verity_service(const int argc, const char** argv) {
-    auto&& features = adb_get_feature_set_or_die();
-    if (CanUseFeature(*features, kFeatureRemountShell)) {
-        std::vector<const char*> args = {"shell"};
-        args.insert(args.cend(), argv, argv + argc);
-        return adb_shell_noinput(args.size(), args.data());
-    } else if (argc > 1) {
-        auto command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
-        return adb_connect_command(command);
-    } else {
-        return adb_connect_command(std::string(argv[0]) + ":");
-    }
-}
-
 static int adb_query_command(const std::string& command) {
     std::string result;
     std::string error;
@@ -1549,7 +1529,6 @@
     const char* server_host_str = nullptr;
     const char* server_port_str = nullptr;
     const char* server_socket_str = nullptr;
-    const char* one_device_str = nullptr;
 
     // We need to check for -d and -e before we look at $ANDROID_SERIAL.
     const char* serial = nullptr;
@@ -1566,26 +1545,21 @@
         } else if (!strcmp(argv[0], "--reply-fd")) {
             if (argc < 2) error_exit("--reply-fd requires an argument");
             const char* reply_fd_str = argv[1];
-            --argc;
-            ++argv;
+            argc--;
+            argv++;
             ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
             if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
                 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
                 return 1;
             }
-        } else if (!strcmp(argv[0], "--one-device")) {
-            if (argc < 2) error_exit("--one-device requires an argument");
-            one_device_str = argv[1];
-            --argc;
-            ++argv;
         } else if (!strncmp(argv[0], "-s", 2)) {
             if (isdigit(argv[0][2])) {
                 serial = argv[0] + 2;
             } else {
                 if (argc < 2 || argv[0][2] != '\0') error_exit("-s requires an argument");
                 serial = argv[1];
-                --argc;
-                ++argv;
+                argc--;
+                argv++;
             }
         } else if (!strncmp(argv[0], "-t", 2)) {
             const char* id;
@@ -1593,8 +1567,8 @@
                 id = argv[0] + 2;
             } else {
                 id = argv[1];
-                --argc;
-                ++argv;
+                argc--;
+                argv++;
             }
             transport_id = strtoll(id, const_cast<char**>(&id), 10);
             if (*id != '\0') {
@@ -1610,8 +1584,8 @@
             if (argv[0][2] == '\0') {
                 if (argc < 2) error_exit("-H requires an argument");
                 server_host_str = argv[1];
-                --argc;
-                ++argv;
+                argc--;
+                argv++;
             } else {
                 server_host_str = argv[0] + 2;
             }
@@ -1619,24 +1593,22 @@
             if (argv[0][2] == '\0') {
                 if (argc < 2) error_exit("-P requires an argument");
                 server_port_str = argv[1];
-                --argc;
-                ++argv;
+                argc--;
+                argv++;
             } else {
                 server_port_str = argv[0] + 2;
             }
         } else if (!strcmp(argv[0], "-L")) {
             if (argc < 2) error_exit("-L requires an argument");
             server_socket_str = argv[1];
-            --argc;
-            ++argv;
-        } else if (strcmp(argv[0], "--exit-on-write-error") == 0) {
-            DEFAULT_STANDARD_STREAMS_CALLBACK.ReturnErrors(true);
+            argc--;
+            argv++;
         } else {
             /* out of recognized modifiers and flags */
             break;
         }
-        --argc;
-        ++argv;
+        argc--;
+        argv++;
     }
 
     if ((server_host_str || server_port_str) && server_socket_str) {
@@ -1677,13 +1649,6 @@
         server_socket_str = temp;
     }
 
-    bool server_start =
-            is_daemon || is_server || (argc > 0 && strcmp(argv[0], "start-server") == 0);
-    if (one_device_str && !server_start) {
-        error_exit("--one-device is only allowed when starting a server.");
-    }
-
-    adb_set_one_device(one_device_str);
     adb_set_socket_spec(server_socket_str);
 
     // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
@@ -1699,9 +1664,9 @@
                 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
                 return 1;
             }
-            r = adb_server_main(is_daemon, server_socket_str, one_device_str, ack_reply_fd);
+            r = adb_server_main(is_daemon, server_socket_str, ack_reply_fd);
         } else {
-            r = launch_server(server_socket_str, one_device_str);
+            r = launch_server(server_socket_str);
         }
         if (r) {
             fprintf(stderr,"* could not start server *\n");
@@ -1729,8 +1694,8 @@
         }
 
         /* Fall through */
-        --argc;
-        ++argv;
+        argc--;
+        argv++;
     }
 
     /* adb_connect() commands */
@@ -1865,11 +1830,32 @@
             error_exit("tcpip: invalid port: %s", argv[1]);
         }
         return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
-    } else if (!strcmp(argv[0], "remount") || !strcmp(argv[0], "disable-verity") ||
-               !strcmp(argv[0], "enable-verity")) {
-        return process_remount_or_verity_service(argc, argv);
-    } else if (!strcmp(argv[0], "reboot") || !strcmp(argv[0], "reboot-bootloader") ||
-               !strcmp(argv[0], "reboot-fastboot") || !strcmp(argv[0], "usb")) {
+    } else if (!strcmp(argv[0], "remount")) {
+        std::string error;
+        auto&& features = adb_get_feature_set(&error);
+        if (!features) {
+            error_exit("%s", error.c_str());
+        }
+
+        if (CanUseFeature(*features, kFeatureRemountShell)) {
+            std::vector<const char*> args = {"shell"};
+            args.insert(args.cend(), argv, argv + argc);
+            return adb_shell_noinput(args.size(), args.data());
+        } else if (argc > 1) {
+            auto command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
+            return adb_connect_command(command);
+        } else {
+            return adb_connect_command("remount:");
+        }
+    }
+    // clang-format off
+    else if (!strcmp(argv[0], "reboot") ||
+             !strcmp(argv[0], "reboot-bootloader") ||
+             !strcmp(argv[0], "reboot-fastboot") ||
+             !strcmp(argv[0], "usb") ||
+             !strcmp(argv[0], "disable-verity") ||
+             !strcmp(argv[0], "enable-verity")) {
+        // clang-format on
         std::string command;
         if (!strcmp(argv[0], "reboot-bootloader")) {
             command = "reboot:bootloader";
@@ -2093,7 +2079,11 @@
     } else if (!strcmp(argv[0], "track-jdwp")) {
         return adb_connect_command("track-jdwp");
     } else if (!strcmp(argv[0], "track-app")) {
-        auto&& features = adb_get_feature_set_or_die();
+        std::string error;
+        auto&& features = adb_get_feature_set(&error);
+        if (!features) {
+            error_exit("%s", error.c_str());
+        }
         if (!CanUseFeature(*features, kFeatureTrackApp)) {
             error_exit("track-app is not supported by the device");
         }
@@ -2120,7 +2110,11 @@
         return 0;
     } else if (!strcmp(argv[0], "features")) {
         // Only list the features common to both the adb client and the device.
-        auto&& features = adb_get_feature_set_or_die();
+        std::string error;
+        auto&& features = adb_get_feature_set(&error);
+        if (!features) {
+            error_exit("%s", error.c_str());
+        }
 
         for (const std::string& name : *features) {
             if (CanUseFeature(*features, name)) {
@@ -2168,15 +2162,6 @@
         output_fd = adb_register_socket(output_fd);
         close_on_exec(output_fd);
         return incremental::serve(connection_fd, output_fd, argc - 3, argv + 3);
-    } else if (!strcmp(argv[0], "attach") || !strcmp(argv[0], "detach")) {
-        const char* service = strcmp(argv[0], "attach") == 0 ? "host:attach" : "host:detach";
-        std::string result;
-        std::string error;
-        if (!adb_query(service, &result, &error, true)) {
-            error_exit("failed to %s: %s", argv[0], error.c_str());
-        }
-        printf("%s\n", result.c_str());
-        return 0;
     }
 
     error_exit("unknown command %s", argv[0]);
diff --git a/client/commandline.h b/client/commandline.h
index a0bba06..b9dee56 100644
--- a/client/commandline.h
+++ b/client/commandline.h
@@ -19,28 +19,22 @@
 
 #include <android-base/strings.h>
 
-#include <optional>
-
 #include "adb.h"
 #include "adb_client.h"
 #include "adb_unique_fd.h"
-#include "transport.h"
 
 // Callback used to handle the standard streams (stdout and stderr) sent by the
 // device's upon receiving a command.
-
 //
 class StandardStreamsCallbackInterface {
   public:
     StandardStreamsCallbackInterface() {
     }
     // Handles the stdout output from devices supporting the Shell protocol.
-    // Returns true on success and false on failure.
-    virtual bool OnStdout(const char* buffer, size_t length) = 0;
+    virtual void OnStdout(const char* buffer, int length) = 0;
 
     // Handles the stderr output from devices supporting the Shell protocol.
-    // Returns true on success and false on failure.
-    virtual bool OnStderr(const char* buffer, size_t length) = 0;
+    virtual void OnStderr(const char* buffer, int length) = 0;
 
     // Indicates the communication is finished and returns the appropriate error
     // code.
@@ -50,15 +44,12 @@
     virtual int Done(int status) = 0;
 
   protected:
-    static bool OnStream(std::string* string, FILE* stream, const char* buffer, size_t length,
-                         bool returnErrors) {
+    static void OnStream(std::string* string, FILE* stream, const char* buffer, int length) {
         if (string != nullptr) {
             string->append(buffer, length);
-            return true;
         } else {
-            bool okay = (fwrite(buffer, 1, length, stream) == length);
+            fwrite(buffer, 1, length, stream);
             fflush(stream);
-            return returnErrors ? okay : true;
         }
     }
 
@@ -66,40 +57,32 @@
     DISALLOW_COPY_AND_ASSIGN(StandardStreamsCallbackInterface);
 };
 
-// Default implementation that redirects the streams to the equivalent host
-// stream or to a string passed to the constructor.
+// Default implementation that redirects the streams to the equilavent host
+// stream or to a string
+// passed to the constructor.
 class DefaultStandardStreamsCallback : public StandardStreamsCallbackInterface {
   public:
     // If |stdout_str| is non-null, OnStdout will append to it.
     // If |stderr_str| is non-null, OnStderr will append to it.
     DefaultStandardStreamsCallback(std::string* stdout_str, std::string* stderr_str)
-        : stdout_str_(stdout_str), stderr_str_(stderr_str), returnErrors_(false) {
-    }
-    DefaultStandardStreamsCallback(std::string* stdout_str, std::string* stderr_str,
-                                   bool returnErrors)
-        : stdout_str_(stdout_str), stderr_str_(stderr_str), returnErrors_(returnErrors) {
+        : stdout_str_(stdout_str), stderr_str_(stderr_str) {
     }
 
-    bool OnStdout(const char* buffer, size_t length) {
-        return OnStream(stdout_str_, stdout, buffer, length, returnErrors_);
+    void OnStdout(const char* buffer, int length) {
+        OnStream(stdout_str_, stdout, buffer, length);
     }
 
-    bool OnStderr(const char* buffer, size_t length) {
-        return OnStream(stderr_str_, stderr, buffer, length, returnErrors_);
+    void OnStderr(const char* buffer, int length) {
+        OnStream(stderr_str_, stderr, buffer, length);
     }
 
     int Done(int status) {
         return status;
     }
 
-    void ReturnErrors(bool returnErrors) {
-        returnErrors_ = returnErrors;
-    }
-
   private:
     std::string* stdout_str_;
     std::string* stderr_str_;
-    bool returnErrors_;
 
     DISALLOW_COPY_AND_ASSIGN(DefaultStandardStreamsCallback);
 };
@@ -107,8 +90,8 @@
 class SilentStandardStreamsCallbackInterface : public StandardStreamsCallbackInterface {
   public:
     SilentStandardStreamsCallbackInterface() = default;
-    bool OnStdout(const char*, size_t) override final { return true; }
-    bool OnStderr(const char*, size_t) override final { return true; }
+    void OnStdout(const char*, int) override final {}
+    void OnStderr(const char*, int) override final {}
     int Done(int status) override final { return status; }
 };
 
@@ -117,9 +100,6 @@
 
 int adb_commandline(int argc, const char** argv);
 
-// Helper retrieval function.
-const std::optional<FeatureSet>& adb_get_feature_set_or_die(void);
-
 bool copy_to_file(int inFd, int outFd);
 
 // Connects to the device "shell" service with |command| and prints the
diff --git a/client/fastdeploycallbacks.cpp b/client/fastdeploycallbacks.cpp
index 7cebe0c..86ceaa1 100644
--- a/client/fastdeploycallbacks.cpp
+++ b/client/fastdeploycallbacks.cpp
@@ -37,8 +37,8 @@
   public:
     DeployAgentBufferCallback(std::vector<char>* outBuffer, std::vector<char>* errBuffer);
 
-    virtual bool OnStdout(const char* buffer, size_t length);
-    virtual bool OnStderr(const char* buffer, size_t length);
+    virtual void OnStdout(const char* buffer, int length);
+    virtual void OnStderr(const char* buffer, int length);
     virtual int Done(int status);
 
   private:
@@ -58,14 +58,12 @@
     mpErrBuffer = errBuffer;
 }
 
-bool DeployAgentBufferCallback::OnStdout(const char* buffer, size_t length) {
+void DeployAgentBufferCallback::OnStdout(const char* buffer, int length) {
     appendBuffer(mpOutBuffer, buffer, length);
-    return true;
 }
 
-bool DeployAgentBufferCallback::OnStderr(const char* buffer, size_t length) {
+void DeployAgentBufferCallback::OnStderr(const char* buffer, int length) {
     appendBuffer(mpErrBuffer, buffer, length);
-    return true;
 }
 
 int DeployAgentBufferCallback::Done(int status) {
diff --git a/client/file_sync_client.cpp b/client/file_sync_client.cpp
index 5a587db..8f8601b 100644
--- a/client/file_sync_client.cpp
+++ b/client/file_sync_client.cpp
@@ -1286,12 +1286,14 @@
         return false;
     }
 
+    bool empty_dir = true;
     dirent* de;
     while ((de = readdir(dir.get()))) {
         if (IsDotOrDotDot(de->d_name)) {
             continue;
         }
 
+        empty_dir = false;
         std::string stat_path = lpath + de->d_name;
 
         struct stat st;
diff --git a/client/main.cpp b/client/main.cpp
index cc89734..4fa58fa 100644
--- a/client/main.cpp
+++ b/client/main.cpp
@@ -81,10 +81,7 @@
     LOG(INFO) << "leaking pointer " << p;
 }
 
-// one_device: if null, server owns all devices, else server owns only
-//     device where atransport::MatchesTarget(one_device) is true.
-int adb_server_main(int is_daemon, const std::string& socket_spec, const char* one_device,
-                    int ack_reply_fd) {
+int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
 #if defined(_WIN32)
     // adb start-server starts us up with stdout and stderr hooked up to
     // anonymous pipes. When the C Runtime sees this, it makes stderr and
@@ -111,10 +108,6 @@
         fdevent_run_on_main_thread([]() { exit(0); });
     });
 
-    if (one_device) {
-        transport_set_one_device(one_device);
-    }
-
     const char* reject_kill_server = getenv("ADB_REJECT_KILL_SERVER");
     if (reject_kill_server && strcmp(reject_kill_server, "1") == 0) {
         adb_set_reject_kill_server(true);
diff --git a/client/transport_mdns.cpp b/client/transport_mdns.cpp
index 1b969b5..8fafdb7 100644
--- a/client/transport_mdns.cpp
+++ b/client/transport_mdns.cpp
@@ -137,10 +137,21 @@
 
     discovery::Config config;
     for (const auto interface : interface_infos) {
-        if (interface.GetIpAddressV4() || interface.GetIpAddressV6()) {
-            config.network_info.push_back({interface});
-            LOG(VERBOSE) << "Listening on interface [" << interface << "]";
+        discovery::Config::NetworkInfo::AddressFamilies supported_address_families =
+                discovery::Config::NetworkInfo::kNoAddressFamily;
+        if (interface.GetIpAddressV4()) {
+            supported_address_families |= discovery::Config::NetworkInfo::kUseIpV4;
         }
+        if (interface.GetIpAddressV6()) {
+            supported_address_families |= discovery::Config::NetworkInfo::kUseIpV6;
+        }
+        if (supported_address_families == discovery::Config::NetworkInfo::kNoAddressFamily) {
+            LOG(INFO) << "Interface [" << interface << "] doesn't support ipv4 or ipv6."
+                      << " Ignoring interface.";
+            continue;
+        }
+        config.network_info.push_back({interface, supported_address_families});
+        LOG(VERBOSE) << "Listening on interface [" << interface << "]";
     }
 
     if (config.network_info.empty()) {
diff --git a/client/usb_libusb.cpp b/client/usb_libusb.cpp
index e0b0104..a877610 100644
--- a/client/usb_libusb.cpp
+++ b/client/usb_libusb.cpp
@@ -21,11 +21,6 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-#if defined(__linux__)
-#include <sys/inotify.h>
-#include <unistd.h>
-#endif
-
 #include <atomic>
 #include <chrono>
 #include <condition_variable>
@@ -34,7 +29,6 @@
 #include <string>
 #include <thread>
 #include <unordered_map>
-#include <vector>
 
 #include <libusb/libusb.h>
 
@@ -50,18 +44,9 @@
 #include "transfer_id.h"
 #include "transport.h"
 
-using namespace std::chrono_literals;
-
 using android::base::ScopedLockAssertion;
 using android::base::StringPrintf;
 
-#define LOG_ERR(out, fmt, ...)                                               \
-    do {                                                                     \
-        std::string __err = android::base::StringPrintf(fmt, ##__VA_ARGS__); \
-        LOG(ERROR) << __err;                                                 \
-        *out = std::move(__err);                                             \
-    } while (0)
-
 // RAII wrappers for libusb.
 struct ConfigDescriptorDeleter {
     void operator()(libusb_config_descriptor* desc) { libusb_free_config_descriptor(desc); }
@@ -84,22 +69,22 @@
 static void process_device(libusb_device* device_raw);
 
 static std::string get_device_address(libusb_device* device) {
-    uint8_t ports[7];
-    int port_count = libusb_get_port_numbers(device, ports, 7);
-    if (port_count < 0) return "";
-
-    std::string address = StringPrintf("%d-%d", libusb_get_bus_number(device), ports[0]);
-    for (int port = 1; port < port_count; ++port) {
-        address += StringPrintf(".%d", ports[port]);
-    }
-
-    return address;
+    return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
+                        libusb_get_device_address(device));
 }
 
 #if defined(__linux__)
 static std::string get_device_serial_path(libusb_device* device) {
-    std::string address = get_device_address(device);
-    std::string path = StringPrintf("/sys/bus/usb/devices/%s/serial", address.c_str());
+    uint8_t ports[7];
+    int port_count = libusb_get_port_numbers(device, ports, 7);
+    if (port_count < 0) return "";
+
+    std::string path =
+            StringPrintf("/sys/bus/usb/devices/%d-%d", libusb_get_bus_number(device), ports[0]);
+    for (int port = 1; port < port_count; ++port) {
+        path += StringPrintf(".%d", ports[port]);
+    }
+    path += "/serial";
     return path;
 }
 #endif
@@ -138,26 +123,24 @@
         if (payload) {
             packet->payload = std::move(*payload);
         }
-        transport_->HandleRead(std::move(packet));
+        read_callback_(this, std::move(packet));
     }
 
     void Cleanup(ReadBlock* read_block) REQUIRES(read_mutex_) {
         libusb_free_transfer(read_block->transfer);
         read_block->active = false;
         read_block->transfer = nullptr;
-        if (terminated_) {
+        if (terminating_) {
             destruction_cv_.notify_one();
         }
     }
 
     bool MaybeCleanup(ReadBlock* read_block) REQUIRES(read_mutex_) {
-        CHECK(read_block);
-        CHECK(read_block->transfer);
         if (read_block->transfer->status == LIBUSB_TRANSFER_CANCELLED) {
-            CHECK(terminated_);
+            CHECK(terminating_);
         }
 
-        if (terminated_) {
+        if (terminating_) {
             Cleanup(read_block);
             return true;
         }
@@ -178,9 +161,7 @@
         if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
             std::string msg = StringPrintf("usb read failed: status = %d", transfer->status);
             LOG(ERROR) << msg;
-            if (!self->detached_) {
-                self->OnError(msg);
-            }
+            self->OnError(msg);
             self->Cleanup(read_block);
             return;
         }
@@ -227,9 +208,7 @@
         if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
             std::string msg = StringPrintf("usb read failed: status = %d", transfer->status);
             LOG(ERROR) << msg;
-            if (!self->detached_) {
-                self->OnError(msg);
-            }
+            self->OnError(msg);
             self->Cleanup(&self->payload_read_);
             return;
         }
@@ -263,12 +242,12 @@
             libusb_free_transfer(transfer);
             self->writes_.erase(write_block->id);
 
-            if (self->terminated_ && self->writes_.empty()) {
+            if (self->terminating_ && self->writes_.empty()) {
                 self->destruction_cv_.notify_one();
             }
         }
 
-        if (!succeeded && !self->detached_) {
+        if (!succeeded) {
             self->OnError("libusb write failed");
         }
     }
@@ -314,13 +293,8 @@
         libusb_fill_bulk_transfer(write->transfer, device_handle_.get(), write_endpoint_,
                                   reinterpret_cast<unsigned char*>(write->block.data()),
                                   write->block.size(), &write_cb, write.get(), 0);
-        int rc = libusb_submit_transfer(write->transfer);
-        if (rc == 0) {
-            writes_[write->id] = std::move(write);
-        } else {
-            LOG(ERROR) << "libusb_submit_transfer failed: " << libusb_strerror(rc);
-            libusb_free_transfer(write->transfer);
-        }
+        libusb_submit_transfer(write->transfer);
+        writes_[write->id] = std::move(write);
     }
 
     bool Write(std::unique_ptr<apacket> packet) final {
@@ -330,14 +304,10 @@
         memcpy(header.data(), &packet->msg, sizeof(packet->msg));
 
         std::lock_guard<std::mutex> lock(write_mutex_);
-        if (terminated_) {
+        if (terminating_) {
             return false;
         }
 
-        if (detached_) {
-            return true;
-        }
-
         SubmitWrite(std::move(header));
         if (!packet->payload.empty()) {
             size_t payload_length = packet->payload.size();
@@ -469,8 +439,6 @@
         return true;
     }
 
-    std::string GetUsbDeviceAddress() const { return std::string("usb:") + device_address_; }
-
     std::string GetSerial() {
         std::string serial;
 
@@ -495,15 +463,37 @@
 
     bool OpenDevice(std::string* error) {
         if (device_handle_) {
-            LOG_ERR(error, "device already open");
-            return false;
+            return true;
         }
 
         libusb_device_handle* handle_raw;
         int rc = libusb_open(device_.get(), &handle_raw);
         if (rc != 0) {
-            // TODO: Handle no permissions.
-            LOG_ERR(error, "failed to open device: %s", libusb_strerror(rc));
+            std::string err = StringPrintf("failed to open device: %s", libusb_strerror(rc));
+            LOG(ERROR) << err;
+
+#if defined(__linux__)
+            std::string device_serial;
+            // libusb doesn't think we should be messing around with devices we don't have
+            // write access to, but Linux at least lets us get the serial number anyway.
+            if (!android::base::ReadFileToString(get_device_serial_path(device_.get()),
+                                                 &device_serial)) {
+                // We don't actually want to treat an unknown serial as an error because
+                // devices aren't able to communicate a serial number in early bringup.
+                // http://b/20883914
+                serial_ = "<unknown>";
+            } else {
+                serial_ = android::base::Trim(device_serial);
+            }
+#else
+            // On Mac OS and Windows, we're screwed. But I don't think this situation actually
+            // happens on those OSes.
+#endif
+
+            if (error) {
+                *error = std::move(err);
+            }
+
             return false;
         }
 
@@ -512,142 +502,46 @@
 
         auto device_desc = GetDeviceDescriptor();
         if (!device_desc) {
-            LOG_ERR(error, "failed to get device descriptor");
             device_handle_.reset();
             return false;
         }
 
         if (!FindInterface(&device_desc.value())) {
-            LOG_ERR(error, "failed to find adb interface");
             device_handle_.reset();
             return false;
         }
 
         serial_ = GetSerial();
+        return true;
+    }
+
+    bool StartImpl(std::string* error) {
+        if (!OpenDevice(error)) {
+            return false;
+        }
 
         LOG(DEBUG) << "successfully opened adb device at " << device_address_ << ", "
                    << StringPrintf("bulk_in = %#x, bulk_out = %#x", read_endpoint_,
                                    write_endpoint_);
 
         // WARNING: this isn't released via RAII.
-        rc = libusb_claim_interface(device_handle_.get(), interface_num_);
+        int rc = libusb_claim_interface(device_handle_.get(), interface_num_);
         if (rc != 0) {
-            LOG_ERR(error, "failed to claim adb interface for device '%s': %s", serial_.c_str(),
-                    libusb_error_name(rc));
-            device_handle_.reset();
+            LOG(WARNING) << "failed to claim adb interface for device '" << serial_ << "'"
+                         << libusb_error_name(rc);
             return false;
         }
 
         for (uint8_t endpoint : {read_endpoint_, write_endpoint_}) {
             rc = libusb_clear_halt(device_handle_.get(), endpoint);
             if (rc != 0) {
-                LOG_ERR(error, "failed to clear halt on device '%s' endpoint %#02x: %s",
-                        serial_.c_str(), endpoint, libusb_error_name(rc));
+                LOG(WARNING) << "failed to clear halt on device '" << serial_ << "' endpoint 0x"
+                             << std::hex << endpoint << ": " << libusb_error_name(rc);
                 libusb_release_interface(device_handle_.get(), interface_num_);
-                device_handle_.reset();
                 return false;
             }
         }
 
-        return true;
-    }
-
-    void CancelReadTransfer(ReadBlock* read_block) REQUIRES(read_mutex_) {
-        if (!read_block->transfer) {
-            return;
-        }
-
-        if (!read_block->active) {
-            // There is no read_cb pending. Clean it up right now.
-            Cleanup(read_block);
-            return;
-        }
-
-        int rc = libusb_cancel_transfer(read_block->transfer);
-        if (rc != 0) {
-            LOG(WARNING) << "libusb_cancel_transfer failed: " << libusb_error_name(rc);
-            // There is no read_cb pending. Clean it up right now.
-            Cleanup(read_block);
-            return;
-        }
-    }
-
-    void CloseDevice() {
-        // This is rather messy, because of the lifecyle of libusb_transfers.
-        //
-        // We can't call libusb_free_transfer for a submitted transfer, we have to cancel it
-        // and free it in the callback. Complicating things more, it's possible for us to be in
-        // the callback for a transfer as the destructor is being called, at which point cancelling
-        // the transfer won't do anything (and it's possible that we'll submit the transfer again
-        // in the callback).
-        //
-        // Resolve this by setting an atomic flag before we lock to cancel transfers, and take the
-        // lock in the callbacks before checking the flag.
-
-        if (terminated_) {
-            return;
-        }
-
-        terminated_ = true;
-
-        {
-            std::unique_lock<std::mutex> lock(write_mutex_);
-            ScopedLockAssertion assumed_locked(write_mutex_);
-
-            std::erase_if(writes_, [](const auto& write_item) {
-                auto const& [id, write_block] = write_item;
-                int rc = libusb_cancel_transfer(write_block->transfer);
-                if (rc != 0) {
-                    // libusb_cancel_transfer failed for some reason. We will
-                    // never get a callback for this transfer. So we need to
-                    // remove it from the list or we will hang below.
-                    LOG(INFO) << "libusb_cancel_transfer failed: " << libusb_error_name(rc);
-                    libusb_free_transfer(write_block->transfer);
-                    return true;
-                }
-                // Wait for the write_cb to fire before removing.
-                return false;
-            });
-
-            // Wait here until the write callbacks have all fired and removed
-            // the remaining writes_.
-            destruction_cv_.wait(lock, [this]() {
-                ScopedLockAssertion assumed_locked(write_mutex_);
-                return writes_.empty();
-            });
-        }
-
-        {
-            std::unique_lock<std::mutex> lock(read_mutex_);
-            ScopedLockAssertion assumed_locked(read_mutex_);
-
-            CancelReadTransfer(&header_read_);
-            CancelReadTransfer(&payload_read_);
-
-            destruction_cv_.wait(lock, [this]() {
-                ScopedLockAssertion assumed_locked(read_mutex_);
-                return !header_read_.active && !payload_read_.active;
-            });
-
-            incoming_header_.reset();
-            incoming_payload_.clear();
-        }
-
-        if (device_handle_) {
-            int rc = libusb_release_interface(device_handle_.get(), interface_num_);
-            if (rc != 0) {
-                LOG(WARNING) << "libusb_release_interface failed: " << libusb_error_name(rc);
-            }
-            device_handle_.reset();
-        }
-    }
-
-    bool StartImpl(std::string* error) {
-        if (!device_handle_) {
-            *error = "device not opened";
-            return false;
-        }
-
         LOG(INFO) << "registered new usb device '" << serial_ << "'";
         std::lock_guard lock(read_mutex_);
         CreateRead(&header_read_, true);
@@ -659,60 +553,95 @@
 
     void OnError(const std::string& error) {
         std::call_once(error_flag_, [this, &error]() {
-            if (transport_) {
-                transport_->HandleError(error);
+            if (error_callback_) {
+                error_callback_(this, error);
             }
         });
     }
 
-    virtual bool Attach(std::string* error) override final {
-        terminated_ = false;
-        detached_ = false;
-
-        if (!OpenDevice(error)) {
-            return false;
-        }
-
-        if (!StartImpl(error)) {
-            CloseDevice();
-            return false;
-        }
-
-        return true;
-    }
-
-    virtual bool Detach(std::string* error) override final {
-        detached_ = true;
-        CloseDevice();
-        return true;
-    }
-
     virtual void Reset() override final {
-        LOG(INFO) << "resetting " << transport_->serial_name();
-        int rc = libusb_reset_device(device_handle_.get());
-        if (rc == 0) {
+        Stop();
+
+        if (libusb_reset_device(device_handle_.get()) == 0) {
             libusb_device* device = libusb_ref_device(device_.get());
-
-            Stop();
-
             fdevent_run_on_main_thread([device]() {
                 process_device(device);
                 libusb_unref_device(device);
             });
-        } else {
-            LOG(ERROR) << "libusb_reset_device failed: " << libusb_error_name(rc);
         }
     }
 
     virtual void Start() override final {
         std::string error;
-        if (!Attach(&error)) {
+        if (!StartImpl(&error)) {
             OnError(error);
+            return;
         }
     }
 
     virtual void Stop() override final {
-        CloseDevice();
+        // This is rather messy, because of the lifecyle of libusb_transfers.
+        //
+        // We can't call libusb_free_transfer for a submitted transfer, we have to cancel it
+        // and free it in the callback. Complicating things more, it's possible for us to be in
+        // the callback for a transfer as the destructor is being called, at which point cancelling
+        // the transfer won't do anything (and it's possible that we'll submit the transfer again
+        // in the callback).
+        //
+        // Resolve this by setting an atomic flag before we lock to cancel transfers, and take the
+        // lock in the callbacks before checking the flag.
+
+        if (terminating_) {
+            return;
+        }
+
+        terminating_ = true;
+
+        {
+            std::unique_lock<std::mutex> lock(write_mutex_);
+            ScopedLockAssertion assumed_locked(write_mutex_);
+
+            if (!writes_.empty()) {
+                for (auto& [id, write] : writes_) {
+                    libusb_cancel_transfer(write->transfer);
+                }
+
+                destruction_cv_.wait(lock, [this]() {
+                    ScopedLockAssertion assumed_locked(write_mutex_);
+                    return writes_.empty();
+                });
+            }
+        }
+
+        {
+            std::unique_lock<std::mutex> lock(read_mutex_);
+            ScopedLockAssertion assumed_locked(read_mutex_);
+            if (header_read_.transfer) {
+                if (header_read_.active) {
+                    libusb_cancel_transfer(header_read_.transfer);
+                } else {
+                    libusb_free_transfer(header_read_.transfer);
+                }
+            }
+
+            if (payload_read_.transfer) {
+                if (payload_read_.active) {
+                    libusb_cancel_transfer(payload_read_.transfer);
+                } else {
+                    libusb_free_transfer(payload_read_.transfer);
+                }
+            }
+
+            destruction_cv_.wait(lock, [this]() {
+                ScopedLockAssertion assumed_locked(read_mutex_);
+                return !header_read_.active && !payload_read_.active;
+            });
+        }
+
+        if (device_handle_) {
+            libusb_release_interface(device_handle_.get(), interface_num_);
+        }
+
         OnError("requested stop");
     }
 
@@ -724,42 +653,14 @@
 
         auto device_desc = connection->GetDeviceDescriptor();
         if (!device_desc) {
-            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress()
-                      << ": not an adb interface. (GetDeviceDescriptor)";
             return {};
         }
 
         if (!connection->FindInterface(&device_desc.value())) {
-            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress()
-                      << ": not an adb interface. (FindInterface)";
             return {};
         }
 
-#if defined(__linux__)
-        std::string device_serial;
-        if (android::base::ReadFileToString(get_device_serial_path(connection->device_.get()),
-                                            &device_serial)) {
-            connection->serial_ = android::base::Trim(device_serial);
-        } else {
-            // We don't actually want to treat an unknown serial as an error because
-            // devices aren't able to communicate a serial number in early bringup.
-            // http://b/20883914
-            connection->serial_ = "<unknown>";
-        }
-#else
-        // We need to open the device to get its serial on Windows and OS X.
         if (!connection->OpenDevice(nullptr)) {
-            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress()
-                      << ": not an adb interface. (OpenDevice)";
-            return {};
-        }
-        connection->serial_ = connection->GetSerial();
-        connection->CloseDevice();
-#endif
-        if (!transport_server_owns_device(connection->GetUsbDeviceAddress(), connection->serial_)) {
-            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress() << " serial "
-                      << connection->serial_ << ": this server owns '" << transport_get_one_device()
-                      << "'";
             return {};
         }
 
@@ -786,8 +687,7 @@
     std::atomic<size_t> next_write_id_ = 0;
 
     std::once_flag error_flag_;
-    std::atomic<bool> terminated_ = false;
-    std::atomic<bool> detached_ = false;
+    std::atomic<bool> terminating_ = false;
     std::condition_variable destruction_cv_;
 
     size_t zero_mask_ = 0;
@@ -806,16 +706,11 @@
     unique_device device(libusb_ref_device(device_raw));
     auto connection_opt = LibusbConnection::Create(std::move(device));
     if (!connection_opt) {
+        LOG(INFO) << "ignoring device: not an adb interface";
         return;
     }
 
     auto connection = *connection_opt;
-
-    {
-        std::lock_guard<std::mutex> lock(usb_handles_mutex);
-        usb_handles.emplace(libusb_ref_device(device_raw), connection);
-    }
-
     LOG(INFO) << "constructed LibusbConnection for device " << connection->serial_ << " ("
               << device_address << ")";
 
@@ -827,60 +722,10 @@
     // Android's host linux libusb uses netlink instead of udev for device hotplug notification,
     // which means we can get hotplug notifications before udev has updated ownership/perms on the
     // device. Since we're not going to be able to link against the system's libudev any time soon,
-    // poll for accessibility changes with inotify until a timeout expires.
+    // hack around this by inserting a sleep.
     libusb_ref_device(device);
     auto thread = std::thread([device]() {
-        std::string bus_path = StringPrintf("/dev/bus/usb/%03d/", libusb_get_bus_number(device));
-        std::string device_path =
-                StringPrintf("%s/%03d", bus_path.c_str(), libusb_get_device_address(device));
-        auto deadline = std::chrono::steady_clock::now() + 1s;
-        unique_fd infd(inotify_init1(IN_CLOEXEC | IN_NONBLOCK));
-        if (infd == -1) {
-            PLOG(FATAL) << "failed to create inotify fd";
-        }
-
-        // Register the watch first, and then check for accessibility, to avoid a race.
-        // We can't watch the device file itself, as that requires us to be able to access it.
-        if (inotify_add_watch(infd.get(), bus_path.c_str(), IN_ATTRIB) == -1) {
-            PLOG(ERROR) << "failed to register inotify watch on '" << bus_path
-                        << "', falling back to sleep";
-            std::this_thread::sleep_for(std::chrono::seconds(1));
-        } else {
-            adb_pollfd pfd = {.fd = infd.get(), .events = POLLIN, .revents = 0};
-
-            while (access(device_path.c_str(), R_OK | W_OK) == -1) {
-                auto timeout = deadline - std::chrono::steady_clock::now();
-                if (timeout < 0s) {
-                    break;
-                }
-
-                uint64_t ms = timeout / 1ms;
-                int rc = adb_poll(&pfd, 1, ms);
-                if (rc == -1) {
-                    if (errno == EINTR) {
-                        continue;
-                    } else {
-                        LOG(WARNING) << "timeout expired while waiting for device accessibility";
-                        break;
-                    }
-                }
-
-                union {
-                    struct inotify_event ev;
-                    char bytes[sizeof(struct inotify_event) + NAME_MAX + 1];
-                } buf;
-
-                rc = adb_read(infd.get(), &buf, sizeof(buf));
-                if (rc == -1) {
-                    break;
-                }
-
-                // We don't actually care about the data: we might get spurious events for
-                // other devices on the bus, but we'll double check in the loop condition.
-                continue;
-            }
-        }
-
+        std::this_thread::sleep_for(std::chrono::seconds(1));
         process_device(device);
         if (--connecting_devices == 0) {
             adb_notify_device_scan_complete();
@@ -899,7 +744,6 @@
     if (it != usb_handles.end()) {
         // We need to ensure that we don't destroy the LibusbConnection on this thread,
         // as we're in a context with internal libusb mutexes held.
-        libusb_device* device = it->first;
         std::weak_ptr<LibusbConnection> connection_weak = it->second;
         usb_handles.erase(it);
         fdevent_run_on_main_thread([connection_weak]() {
@@ -911,7 +755,6 @@
                 LOG(INFO) << "libusb_hotplug: device disconnected: (destroyed)";
             }
         });
-        libusb_unref_device(device);
     }
     usb_handles_mutex.unlock();
 }
@@ -925,13 +768,9 @@
             libusb_hotplug_event event = pair.first;
             libusb_device* device = pair.second;
             if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
-                LOG(INFO) << "libusb hotplug: device arrived";
                 device_connected(device);
             } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
-                LOG(INFO) << "libusb hotplug: device left";
                 device_disconnected(device);
-            } else {
-                LOG(WARNING) << "unknown libusb hotplug event: " << event;
             }
         });
     }
diff --git a/client/usb_linux.cpp b/client/usb_linux.cpp
index 7f92626..00f3297 100644
--- a/client/usb_linux.cpp
+++ b/client/usb_linux.cpp
@@ -148,6 +148,7 @@
             struct usb_endpoint_descriptor *ep1, *ep2;
             unsigned zero_mask = 0;
             size_t max_packet_size = 0;
+            unsigned vid, pid;
 
             if (contains_non_digit(de->d_name)) continue;
 
@@ -179,10 +180,11 @@
                 continue;
             }
 
-            DBGX("[ %s is V:%04x P:%04x ]\n", dev_name.c_str(), device->idVendor,
-                 device->idProduct);
+            vid = device->idVendor;
+            pid = device->idProduct;
+            DBGX("[ %s is V:%04x P:%04x ]\n", dev_name.c_str(), vid, pid);
 
-            // should have config descriptor next
+                // should have config descriptor next
             config = (struct usb_config_descriptor *)bufptr;
             bufptr += USB_DT_CONFIG_SIZE;
             if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
@@ -531,24 +533,6 @@
 static void register_device(const char* dev_name, const char* dev_path, unsigned char ep_in,
                             unsigned char ep_out, int interface, int serial_index,
                             unsigned zero_mask, size_t max_packet_size) {
-    // Read the device's serial number.
-    std::string serial_path =
-            android::base::StringPrintf("/sys/bus/usb/devices/%s/serial", dev_path + 4);
-    std::string serial;
-    if (!android::base::ReadFileToString(serial_path, &serial)) {
-        D("[ usb read %s failed: %s ]", serial_path.c_str(), strerror(errno));
-        // We don't actually want to treat an unknown serial as an error because
-        // devices aren't able to communicate a serial number in early bringup.
-        // http://b/20883914
-        serial = "";
-    }
-    serial = android::base::Trim(serial);
-
-    if (!transport_server_owns_device(dev_path, serial)) {
-        // We aren't allowed to communicate with this device. Don't open this device.
-        return;
-    }
-
     // Since Linux will not reassign the device ID (and dev_name) as long as the
     // device is open, we can add to the list here once we open it and remove
     // from the list when we're finally closed and everything will work out
@@ -597,6 +581,19 @@
         }
     }
 
+    // Read the device's serial number.
+    std::string serial_path = android::base::StringPrintf(
+        "/sys/bus/usb/devices/%s/serial", dev_path + 4);
+    std::string serial;
+    if (!android::base::ReadFileToString(serial_path, &serial)) {
+        D("[ usb read %s failed: %s ]", serial_path.c_str(), strerror(errno));
+        // We don't actually want to treat an unknown serial as an error because
+        // devices aren't able to communicate a serial number in early bringup.
+        // http://b/20883914
+        serial = "";
+    }
+    serial = android::base::Trim(serial);
+
     // Add to the end of the active handles.
     usb_handle* done_usb = usb.release();
     {
diff --git a/client/usb_osx.cpp b/client/usb_osx.cpp
index e72d719..42ba812 100644
--- a/client/usb_osx.cpp
+++ b/client/usb_osx.cpp
@@ -296,13 +296,6 @@
             continue;
         }
 
-        if (!transport_server_owns_device(devpath, serial)) {
-            // We aren't allowed to communicate with this device. Don't open this device.
-            D("ignoring device: not owned by this server dev_path: '%s', serial: '%s'",
-              devpath.c_str(), serial);
-            continue;
-        }
-
         std::unique_ptr<usb_handle> handle =
             CheckInterface((IOUSBInterfaceInterface550**)iface, vendor, product);
         if (handle == nullptr) {
diff --git a/client/usb_windows.cpp b/client/usb_windows.cpp
index 6581928..0ffcc09 100644
--- a/client/usb_windows.cpp
+++ b/client/usb_windows.cpp
@@ -574,15 +574,6 @@
                     unsigned long serial_number_len = sizeof(serial_number);
                     if (AdbGetSerialNumber(handle->adb_interface, serial_number, &serial_number_len,
                                            true)) {
-                        if (!transport_server_owns_device(serial_number)) {
-                            // We aren't allowed to communicate with this device. Don't open this
-                            // device.
-                            D("ignoring device: not owned by this server serial: '%s'",
-                              serial_number);
-                            usb_cleanup_handle(handle);
-                            free(handle);
-                            return;
-                        }
                         // Lets make sure that we don't duplicate this device
                         if (register_new_device(handle)) {
                             register_usb_transport(handle, serial_number, nullptr, 1);
diff --git a/coverage/build.sh b/coverage/build.sh
deleted file mode 100755
index e7b8575..0000000
--- a/coverage/build.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-OUTPUT_DIR=$(dirname "$0")
-. "$OUTPUT_DIR"/include.sh
-export CLANG_COVERAGE=true
-export NATIVE_COVERAGE_PATHS=packages/modules/adb
-
-. "$ANDROID_BUILD_TOP"/build/envsetup.sh
-
-# When generating coverage on non-AOSP builds, APEX_NAME should be set to com.google.android.adbd.
-# TODO: Figure this out from the environment instead?
-APEX_NAME="${APEX_NAME:-com.android.adbd}"
-
-m $APEX_NAME $ADB_TESTS
-adb push $ANDROID_PRODUCT_OUT/data/nativetest64 /data
-adb install $ANDROID_PRODUCT_OUT/system/apex/$APEX_NAME.apex
-adb reboot
diff --git a/coverage/gen_coverage.sh b/coverage/gen_coverage.sh
index df49486..43d45f0 100755
--- a/coverage/gen_coverage.sh
+++ b/coverage/gen_coverage.sh
@@ -55,6 +55,8 @@
   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
 
@@ -93,8 +95,6 @@
 
 # Dump traces again.
 adb disconnect $REMOTE
-
-sleep 5
 adb shell killall -37 adbd
 
 echo Waiting for adbd to finish dumping traces
@@ -116,5 +116,4 @@
 unset IFS
 
 ### Merge the traces.
-echo "Traces fetched to $TRACEDIR"
 llvm-profdata merge --output="$OUTPUT_DIR"/adbd.profdata "$TRACEDIR"/adbd_traces/* "$TRACEDIR"/test_traces/*
diff --git a/coverage/include.sh b/coverage/include.sh
index 8fd4cd5..45ebc34 100644
--- a/coverage/include.sh
+++ b/coverage/include.sh
@@ -1,5 +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/symbols/data/nativetest64/$TEST/$TEST $ADB_TEST_BINARIES"
+  ADB_TEST_BINARIES="--object=$ANDROID_PRODUCT_OUT/data/nativetest64/$TEST/$TEST $ADB_TEST_BINARIES"
 done
diff --git a/crypto/Android.bp b/crypto/Android.bp
index 9628348..8fdce89 100644
--- a/crypto/Android.bp
+++ b/crypto/Android.bp
@@ -69,7 +69,6 @@
     name: "libadb_crypto",
     defaults: ["libadb_crypto_defaults"],
 
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
diff --git a/crypto/tests/Android.bp b/crypto/tests/Android.bp
index d45b05d..1ef5f3d 100644
--- a/crypto/tests/Android.bp
+++ b/crypto/tests/Android.bp
@@ -47,5 +47,5 @@
         "libadb_sysdeps",
     ],
 
-    test_suites: ["general-tests", "mts-adbd"],
+    test_suites: ["device-tests"],
 }
diff --git a/daemon/auth.cpp b/daemon/auth.cpp
index 2c3844b..1a1e4ad 100644
--- a/daemon/auth.cpp
+++ b/daemon/auth.cpp
@@ -64,7 +64,6 @@
 static uint32_t transport_auth_id = 0;
 
 bool auth_required = true;
-bool socket_access_allowed = true;
 
 static void* transport_to_callback_arg(atransport* transport) {
     uint32_t id = transport_auth_id++;
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 1efa797..4b3cf6d 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -111,11 +111,10 @@
     // AID_UHID for using 'hid' command to read/write to /dev/uhid
     // AID_EXT_DATA_RW for writing to /sdcard/Android/data (devices without sdcardfs)
     // AID_EXT_OBB_RW for writing to /sdcard/Android/obb (devices without sdcardfs)
-    // AID_READTRACEFS for reading tracefs entries
     gid_t groups[] = {AID_ADB,          AID_LOG,          AID_INPUT,    AID_INET,
                       AID_NET_BT,       AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
                       AID_NET_BW_STATS, AID_READPROC,     AID_UHID,     AID_EXT_DATA_RW,
-                      AID_EXT_OBB_RW,   AID_READTRACEFS};
+                      AID_EXT_OBB_RW};
     minijail_set_supplementary_gids(jail.get(), arraysize(groups), groups);
 
     // Don't listen on a port (default 5037) if running in secure mode.
@@ -208,18 +207,10 @@
     adbd_cloexec_auth_socket();
 
 #if defined(__ANDROID__)
-    bool device_unlocked = android::base::GetProperty("ro.boot.verifiedbootstate", "") == "orange";
-    if (device_unlocked || __android_log_is_debuggable()) {
-#if defined(__ANDROID_RECOVERY__)
-        auth_required = false;  // Bypass authorization when the device transitions to
-        // fastbootd (from recovery). A corrupt userdata image can potentially
-        // result in the device falling into rescue, and a subsequent fastboot
-        // state should not require authorization - otherwise, it will force the
-        // need for manual intervention(b/188703874).
-#else
-        // If we're on userdebug/eng or the device is unlocked, permit no-authentication.
+    // If we're on userdebug/eng or the device is unlocked, permit no-authentication.
+    bool device_unlocked = "orange" == android::base::GetProperty("ro.boot.verifiedbootstate", "");
+    if (__android_log_is_debuggable() || device_unlocked) {
         auth_required = android::base::GetBoolProperty("ro.adb.secure", false);
-#endif
     }
 #endif
 
diff --git a/daemon/services.cpp b/daemon/services.cpp
index d86b54a..a9d1fe8 100644
--- a/daemon/services.cpp
+++ b/daemon/services.cpp
@@ -49,6 +49,7 @@
 #include "adb_utils.h"
 #include "services.h"
 #include "socket_spec.h"
+#include "sysdeps.h"
 #include "transport.h"
 
 #include "daemon/file_sync_service.h"
@@ -308,7 +309,9 @@
     }
 #endif
 
-    if (android::base::ConsumePrefix(&name, "jdwp:")) {
+    if (android::base::ConsumePrefix(&name, "dev:")) {
+        return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
+    } else if (android::base::ConsumePrefix(&name, "jdwp:")) {
         pid_t pid;
         if (!ParseUint(&pid, name)) {
             return unique_fd{};
diff --git a/daemon/usb.cpp b/daemon/usb.cpp
index 6c3f735..4366ea9 100644
--- a/daemon/usb.cpp
+++ b/daemon/usb.cpp
@@ -582,7 +582,7 @@
 
                 // TODO: Make apacket contain an IOVector so we don't have to coalesce.
                 packet->payload = std::move(incoming_payload_).coalesce();
-                transport_->HandleRead(std::move(packet));
+                read_callback_(this, std::move(packet));
 
                 incoming_header_.reset();
                 // reuse the capacity of the incoming payload while we can.
@@ -678,10 +678,7 @@
 
     void HandleError(const std::string& error) {
         std::call_once(error_flag_, [&]() {
-            if (transport_) {
-                transport_->HandleError(error);
-            }
-
+            error_callback_(this, error);
             if (!stopped_) {
                 Stop();
             }
diff --git a/fastdeploy/deploypatchgenerator/patch_utils_test.cpp b/fastdeploy/deploypatchgenerator/patch_utils_test.cpp
index 070c131..3ec5ab3 100644
--- a/fastdeploy/deploypatchgenerator/patch_utils_test.cpp
+++ b/fastdeploy/deploypatchgenerator/patch_utils_test.cpp
@@ -93,7 +93,7 @@
 
     std::string expectedMetadata;
     android::base::ReadFileToString(GetTestFile("rotating_cube-metadata-release.data"),
-                                    &expectedMetadata, true);
+                                    &expectedMetadata);
     APKMetaData expected;
     EXPECT_TRUE(expected.ParseFromString(expectedMetadata));
 
@@ -123,7 +123,7 @@
 
     {
         std::string cd;
-        android::base::ReadFileToString(GetTestFile("sample.cd"), &cd, true);
+        android::base::ReadFileToString(GetTestFile("sample.cd"), &cd);
 
         APKDump dump;
         dump.set_cd(std::move(cd));
diff --git a/libs/adbconnection/Android.bp b/libs/adbconnection/Android.bp
index 0698a98..da0b5b6 100644
--- a/libs/adbconnection/Android.bp
+++ b/libs/adbconnection/Android.bp
@@ -27,7 +27,6 @@
     use_version_lib: false,
 
     recovery_available: true,
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         // TODO(b/151398197) remove the below
@@ -51,7 +50,6 @@
         "//art:__subpackages__",
         "//packages/modules/adb/apex:__subpackages__",
     ],
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
diff --git a/libs/libadbd_fs/Android.bp b/libs/libadbd_fs/Android.bp
index 9d74d5d..ef7bc10 100644
--- a/libs/libadbd_fs/Android.bp
+++ b/libs/libadbd_fs/Android.bp
@@ -36,6 +36,4 @@
             enabled: false,
         }
     },
-    // This doesn't need to depend on libbuildversion.
-    use_version_lib: false,
 }
diff --git a/pairing_auth/Android.bp b/pairing_auth/Android.bp
index 1d6dd98..e2e9fc4 100644
--- a/pairing_auth/Android.bp
+++ b/pairing_auth/Android.bp
@@ -71,7 +71,6 @@
     name: "libadb_pairing_auth",
     defaults: ["libadb_pairing_auth_defaults"],
 
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
     ],
diff --git a/pairing_auth/tests/Android.bp b/pairing_auth/tests/Android.bp
index 9105aa5..b6cff91 100644
--- a/pairing_auth/tests/Android.bp
+++ b/pairing_auth/tests/Android.bp
@@ -43,5 +43,5 @@
         "libadb_pairing_auth_static",
     ],
 
-    test_suites: ["general-tests", "mts-adbd"],
+    test_suites: ["device-tests"],
 }
diff --git a/pairing_connection/Android.bp b/pairing_connection/Android.bp
index 3557810..3c5b0a3 100644
--- a/pairing_connection/Android.bp
+++ b/pairing_connection/Android.bp
@@ -81,7 +81,6 @@
     name: "libadb_pairing_connection",
     defaults: ["libadb_pairing_connection_defaults"],
 
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
     ],
@@ -164,7 +163,6 @@
     name: "libadb_pairing_server",
     defaults: ["libadb_pairing_server_defaults"],
 
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
     ],
diff --git a/pairing_connection/tests/Android.bp b/pairing_connection/tests/Android.bp
index a6eb35f..6070ef9 100644
--- a/pairing_connection/tests/Android.bp
+++ b/pairing_connection/tests/Android.bp
@@ -52,5 +52,5 @@
         "libadb_tls_connection_static",
     ],
 
-    test_suites: ["general-tests", "mts-adbd"],
+    test_suites: ["device-tests"],
 }
diff --git a/proto/Android.bp b/proto/Android.bp
index fae321f..c7271fb 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -65,7 +65,6 @@
     name: "libadb_protos",
     defaults: ["libadb_protos_defaults"],
 
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
@@ -122,7 +121,6 @@
     name: "libapp_processes_protos_lite",
     defaults: ["libapp_processes_protos_defaults"],
 
-    min_sdk_version: "30",
     apex_available: ["//apex_available:platform"],
 
     proto: {
diff --git a/socket_spec.cpp b/socket_spec.cpp
index 5e0678a..c93b023 100644
--- a/socket_spec.cpp
+++ b/socket_spec.cpp
@@ -29,7 +29,6 @@
 #include <cutils/sockets.h>
 
 #include "adb.h"
-#include "adb_auth.h"
 #include "adb_mdns.h"
 #include "adb_utils.h"
 #include "sysdeps.h"
@@ -186,15 +185,6 @@
 
 bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std::string* serial,
                          std::string* error) {
-#if !ADB_HOST
-    if (!socket_access_allowed) {  // Check whether this security suppression is
-        // active (initiated from minadbd), and if so disable socket communications
-        // for the (min)deamon.
-        *error = "Suppressing minadbd socket communications";
-        return false;
-    }
-#endif
-
     if (address.starts_with("tcp:")) {
         std::string hostname;
         int port_value = port ? *port : 0;
@@ -274,7 +264,7 @@
             errno = EINVAL;
             return false;
         }
-        fd->reset(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC, 0));
+        fd->reset(socket(AF_VSOCK, SOCK_STREAM, 0));
         if (fd->get() == -1) {
             *error = "could not open vsock socket";
             return false;
@@ -384,7 +374,7 @@
             errno = EINVAL;
             return -1;
         }
-        unique_fd serverfd(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC, 0));
+        unique_fd serverfd(socket(AF_VSOCK, SOCK_STREAM, 0));
         if (serverfd == -1) {
             int error_num = errno;
             *error = android::base::StringPrintf("could not create vsock server: '%s'",
diff --git a/test_device.py b/test_device.py
index 0d63591..aa06369 100755
--- a/test_device.py
+++ b/test_device.py
@@ -523,9 +523,7 @@
         stdout, _ = self.device.shell(["cat", log_path])
         self.assertEqual(stdout.strip(), "SIGHUP")
 
-    # Temporarily disabled because it seems to cause later instability.
-    # http://b/228114748
-    def disabled_test_exit_stress(self):
+    def test_exit_stress(self):
         """Hammer `adb shell exit 42` with multiple threads."""
         thread_count = 48
         result = dict()
@@ -1575,14 +1573,6 @@
         thread.join()
 
 
-class FramebufferTest(DeviceTest):
-    @requires_root
-    def test_framebuffer(self):
-        """Test that we get something from the framebuffer service."""
-        output = subprocess.check_output(self.device.adb_cmd + ["raw", "framebuffer:"])
-        self.assertFalse(len(output) == 0)
-
-
 if sys.platform == "win32":
     # From https://stackoverflow.com/a/38749458
     import os
diff --git a/tls/Android.bp b/tls/Android.bp
index b45fc8d..9e850ab 100644
--- a/tls/Android.bp
+++ b/tls/Android.bp
@@ -64,7 +64,6 @@
     name: "libadb_tls_connection",
     defaults: ["libadb_tls_connection_defaults"],
 
-    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
diff --git a/tls/tests/Android.bp b/tls/tests/Android.bp
index cbb3a6a..2d3bb2b 100644
--- a/tls/tests/Android.bp
+++ b/tls/tests/Android.bp
@@ -47,5 +47,5 @@
         "libadb_tls_connection_static",
     ],
 
-    test_suites: ["general-tests", "mts-adbd"],
+    test_suites: ["device-tests"],
 }
diff --git a/transport.cpp b/transport.cpp
index 0dfad0e..fbcf79b 100644
--- a/transport.cpp
+++ b/transport.cpp
@@ -44,6 +44,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/thread_annotations.h>
+
 #include <diagnose_usb.h>
 
 #include "adb.h"
@@ -54,10 +55,6 @@
 #include "fdevent/fdevent.h"
 #include "sysdeps/chrono.h"
 
-#if ADB_HOST
-#include "client/usb.h"
-#endif
-
 using namespace adb::crypto;
 using namespace adb::tls;
 using android::base::ScopedLockAssertion;
@@ -96,7 +93,6 @@
 namespace {
 
 #if ADB_HOST
-
 // Tracks and handles atransport*s that are attempting reconnection.
 class ReconnectHandler {
   public:
@@ -209,6 +205,7 @@
 
             // Scan the whole list for kicked transports, so that we immediately handle an explicit
             // disconnect request.
+            bool kicked = false;
             for (auto it = reconnect_queue_.begin(); it != reconnect_queue_.end();) {
                 if (it->transport->kicked()) {
                     D("transport %s was kicked. giving up on it.", it->transport->serial.c_str());
@@ -217,6 +214,7 @@
                 } else {
                     ++it;
                 }
+                kicked = true;
             }
 
             if (reconnect_queue_.empty()) continue;
@@ -280,28 +278,25 @@
     Stop();
 }
 
-std::string Connection::Serial() const {
-    return transport_ ? transport_->serial_name() : "<unknown>";
-}
-
 BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
     : underlying_(std::move(connection)) {}
 
 BlockingConnectionAdapter::~BlockingConnectionAdapter() {
-    LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): destructing";
+    LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): destructing";
     Stop();
 }
 
 void BlockingConnectionAdapter::Start() {
     std::lock_guard<std::mutex> lock(mutex_);
     if (started_) {
-        LOG(FATAL) << "BlockingConnectionAdapter(" << Serial() << "): started multiple times";
+        LOG(FATAL) << "BlockingConnectionAdapter(" << this->transport_name_
+                   << "): started multiple times";
     }
 
     StartReadThread();
 
     write_thread_ = std::thread([this]() {
-        LOG(INFO) << Serial() << ": write thread spawning";
+        LOG(INFO) << this->transport_name_ << ": write thread spawning";
         while (true) {
             std::unique_lock<std::mutex> lock(mutex_);
             ScopedLockAssertion assume_locked(mutex_);
@@ -321,7 +316,7 @@
                 break;
             }
         }
-        std::call_once(this->error_flag_, [this]() { transport_->HandleError("write failed"); });
+        std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "write failed"); });
     });
 
     started_ = true;
@@ -329,11 +324,11 @@
 
 void BlockingConnectionAdapter::StartReadThread() {
     read_thread_ = std::thread([this]() {
-        LOG(INFO) << Serial() << ": read thread spawning";
+        LOG(INFO) << this->transport_name_ << ": read thread spawning";
         while (true) {
             auto packet = std::make_unique<apacket>();
             if (!underlying_->Read(packet.get())) {
-                PLOG(INFO) << Serial() << ": read failed";
+                PLOG(INFO) << this->transport_name_ << ": read failed";
                 break;
             }
 
@@ -342,17 +337,18 @@
                 got_stls_cmd = true;
             }
 
-            transport_->HandleRead(std::move(packet));
+            read_callback_(this, std::move(packet));
 
             // If we received the STLS packet, we are about to perform the TLS
             // handshake. So this read thread must stop and resume after the
             // handshake completes otherwise this will interfere in the process.
             if (got_stls_cmd) {
-                LOG(INFO) << Serial() << ": Received STLS packet. Stopping read thread.";
+                LOG(INFO) << this->transport_name_
+                          << ": Received STLS packet. Stopping read thread.";
                 return;
             }
         }
-        std::call_once(this->error_flag_, [this]() { transport_->HandleError("read failed"); });
+        std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "read failed"); });
     });
 }
 
@@ -370,17 +366,18 @@
     {
         std::lock_guard<std::mutex> lock(mutex_);
         if (!started_) {
-            LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
+            LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): not started";
             return;
         }
 
         if (stopped_) {
-            LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
+            LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_
+                      << "): already stopped";
             return;
         }
     }
 
-    LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): resetting";
+    LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): resetting";
     this->underlying_->Reset();
     Stop();
 }
@@ -389,19 +386,20 @@
     {
         std::lock_guard<std::mutex> lock(mutex_);
         if (!started_) {
-            LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
+            LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): not started";
             return;
         }
 
         if (stopped_) {
-            LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
+            LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_
+                      << "): already stopped";
             return;
         }
 
         stopped_ = true;
     }
 
-    LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopping";
+    LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopping";
 
     this->underlying_->Close();
     this->cv_.notify_one();
@@ -419,8 +417,8 @@
     read_thread.join();
     write_thread.join();
 
-    LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopped";
-    std::call_once(this->error_flag_, [this]() { transport_->HandleError("requested stop"); });
+    LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopped";
+    std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "requested stop"); });
 }
 
 bool BlockingConnectionAdapter::Write(std::unique_ptr<apacket> packet) {
@@ -764,16 +762,6 @@
     return 0;
 }
 
-static bool usb_devices_start_detached() {
-#if ADB_HOST
-    static const char* env = getenv("ADB_LIBUSB_START_DETACHED");
-    static bool result = env && strcmp("1", env) == 0;
-    return should_use_libusb() && result;
-#else
-    return false;
-#endif
-}
-
 static void transport_registration_func(int _fd, unsigned ev, void*) {
     tmsg m;
     atransport* t;
@@ -804,16 +792,34 @@
 
     /* don't create transport threads for inaccessible devices */
     if (t->GetConnectionState() != kCsNoPerm) {
-        t->connection()->SetTransport(t);
+        // The connection gets a reference to the atransport. It will release it
+        // upon a read/write error.
+        t->connection()->SetTransportName(t->serial_name());
+        t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
+            if (!check_header(p.get(), t)) {
+                D("%s: remote read: bad header", t->serial.c_str());
+                return false;
+            }
 
-        if (t->type == kTransportUsb && usb_devices_start_detached()) {
-            t->SetConnectionState(kCsDetached);
-        } else {
-            t->connection()->Start();
+            VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "from remote", p.get());
+            apacket* packet = p.release();
+
+            // TODO: Does this need to run on the main thread?
+            fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
+            return true;
+        });
+        t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
+            LOG(INFO) << t->serial_name() << ": connection terminated: " << error;
+            fdevent_run_on_main_thread([t]() {
+                handle_offline(t);
+                transport_destroy(t);
+            });
+        });
+
+        t->connection()->Start();
 #if ADB_HOST
-            send_connect(t);
+        send_connect(t);
 #endif
-        }
     }
 
     {
@@ -846,7 +852,7 @@
     transport_registration_recv = s[1];
 
     transport_registration_fde =
-            fdevent_create(transport_registration_recv, transport_registration_func, nullptr);
+        fdevent_create(transport_registration_recv, transport_registration_func, nullptr);
     fdevent_set(transport_registration_fde, FDE_READ);
 }
 
@@ -949,42 +955,14 @@
     return !*ptr;
 }
 
-// Contains either a device serial string or a USB device address like "usb:2-6"
-const char* __transport_server_one_device = nullptr;
-
-void transport_set_one_device(const char* adb_one_device) {
-    __transport_server_one_device = adb_one_device;
-}
-
-const char* transport_get_one_device() {
-    return __transport_server_one_device;
-}
-
-bool transport_server_owns_device(std::string_view serial) {
-    if (!__transport_server_one_device) {
-        // If the server doesn't own one device, server owns all devices.
-        return true;
-    }
-    return serial.compare(__transport_server_one_device) == 0;
-}
-
-bool transport_server_owns_device(std::string_view dev_path, std::string_view serial) {
-    if (!__transport_server_one_device) {
-        // If the server doesn't own one device, server owns all devices.
-        return true;
-    }
-    return serial.compare(__transport_server_one_device) == 0 ||
-           dev_path.compare(__transport_server_one_device) == 0;
-}
-
 atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
                                   bool* is_ambiguous, std::string* error_out,
                                   bool accept_any_state) {
     atransport* result = nullptr;
 
     if (transport_id != 0) {
-        *error_out = android::base::StringPrintf("no device with transport id '%" PRIu64 "'",
-                                                 transport_id);
+        *error_out =
+            android::base::StringPrintf("no device with transport id '%" PRIu64 "'", transport_id);
     } else if (serial) {
         *error_out = android::base::StringPrintf("device '%s' not found", serial);
     } else if (type == kTransportLocal) {
@@ -1146,87 +1124,39 @@
     update_transports();
 }
 
-#if ADB_HOST
-bool atransport::Attach(std::string* error) {
-    D("%s: attach", serial.c_str());
-    check_main_thread();
-
-    if (!should_use_libusb()) {
-        *error = "attach/detach only implemented for libusb backend";
-        return false;
-    }
-
-    if (GetConnectionState() != ConnectionState::kCsDetached) {
-        *error = android::base::StringPrintf("transport %s is not detached", serial.c_str());
-        return false;
-    }
-
-    ResetKeys();
-
-    {
-        std::lock_guard<std::mutex> lock(mutex_);
-        if (!connection_->Attach(error)) {
-            return false;
-        }
-    }
-
-    send_connect(this);
-    return true;
-}
-
-bool atransport::Detach(std::string* error) {
-    D("%s: detach", serial.c_str());
-    check_main_thread();
-
-    if (!should_use_libusb()) {
-        *error = "attach/detach only implemented for libusb backend";
-        return false;
-    }
-
-    if (GetConnectionState() == ConnectionState::kCsDetached) {
-        *error = android::base::StringPrintf("transport %s is already detached", serial.c_str());
-        return false;
-    }
-
-    handle_offline(this);
-
-    {
-        std::lock_guard<std::mutex> lock(mutex_);
-        if (!connection_->Detach(error)) {
-            return false;
-        }
-    }
-
-    this->SetConnectionState(kCsDetached);
-    return true;
-}
-#endif
-
 void atransport::SetConnection(std::shared_ptr<Connection> connection) {
     std::lock_guard<std::mutex> lock(mutex_);
     connection_ = std::shared_ptr<Connection>(std::move(connection));
 }
 
-bool atransport::HandleRead(std::unique_ptr<apacket> p) {
-    if (!check_header(p.get(), this)) {
-        D("%s: remote read: bad header", serial.c_str());
-        return false;
+std::string atransport::connection_state_name() const {
+    ConnectionState state = GetConnectionState();
+    switch (state) {
+        case kCsOffline:
+            return "offline";
+        case kCsBootloader:
+            return "bootloader";
+        case kCsDevice:
+            return "device";
+        case kCsHost:
+            return "host";
+        case kCsRecovery:
+            return "recovery";
+        case kCsRescue:
+            return "rescue";
+        case kCsNoPerm:
+            return UsbNoPermissionsShortHelpText();
+        case kCsSideload:
+            return "sideload";
+        case kCsUnauthorized:
+            return "unauthorized";
+        case kCsAuthorizing:
+            return "authorizing";
+        case kCsConnecting:
+            return "connecting";
+        default:
+            return "unknown";
     }
-
-    VLOG(TRANSPORT) << dump_packet(serial.c_str(), "from remote", p.get());
-    apacket* packet = p.release();
-
-    // TODO: Does this need to run on the main thread?
-    fdevent_run_on_main_thread([packet, this]() { handle_packet(packet, this); });
-    return true;
-}
-
-void atransport::HandleError(const std::string& error) {
-    LOG(INFO) << serial_name() << ": connection terminated: " << error;
-    fdevent_run_on_main_thread([this]() {
-        handle_offline(this);
-        transport_destroy(this);
-    });
 }
 
 void atransport::update_version(int version, size_t payload) {
@@ -1338,8 +1268,7 @@
             // Parse our |serial| and the given |target| to check if the hostnames and ports match.
             std::string serial_host, error;
             int serial_port = -1;
-            if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr,
-                                               &error)) {
+            if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) {
                 // |target| may omit the port to default to ours.
                 std::string target_host;
                 int target_port = serial_port;
@@ -1393,10 +1322,10 @@
     if (!long_listing) {
         *result += serial;
         *result += '\t';
-        *result += to_string(t->GetConnectionState());
+        *result += t->connection_state_name();
     } else {
         android::base::StringAppendF(result, "%-22s %s", serial.c_str(),
-                                     to_string(t->GetConnectionState()).c_str());
+                                     t->connection_state_name().c_str());
 
         append_transport_info(result, "", t->devpath, false);
         append_transport_info(result, "product:", t->product, false);
diff --git a/transport.h b/transport.h
index 8618693..d098b7c 100644
--- a/transport.h
+++ b/transport.h
@@ -106,7 +106,22 @@
     Connection() = default;
     virtual ~Connection() = default;
 
-    void SetTransport(atransport* transport) { transport_ = transport; }
+    void SetTransportName(std::string transport_name) {
+        transport_name_ = std::move(transport_name);
+    }
+
+    using ReadCallback = std::function<bool(Connection*, std::unique_ptr<apacket>)>;
+    void SetReadCallback(ReadCallback callback) {
+        CHECK(!read_callback_);
+        read_callback_ = callback;
+    }
+
+    // Called after the Connection has terminated, either by an error or because Stop was called.
+    using ErrorCallback = std::function<void(Connection*, const std::string&)>;
+    void SetErrorCallback(ErrorCallback callback) {
+        CHECK(!error_callback_);
+        error_callback_ = callback;
+    }
 
     virtual bool Write(std::unique_ptr<apacket> packet) = 0;
 
@@ -118,19 +133,9 @@
     // Stop, and reset the device if it's a USB connection.
     virtual void Reset();
 
-    virtual bool Attach(std::string* error) {
-        *error = "transport type doesn't support attach";
-        return false;
-    }
-
-    virtual bool Detach(std::string* error) {
-        *error = "transport type doesn't support detach";
-        return false;
-    }
-
-    std::string Serial() const;
-
-    atransport* transport_ = nullptr;
+    std::string transport_name_;
+    ReadCallback read_callback_;
+    ErrorCallback error_callback_;
 
     static std::unique_ptr<Connection> FromFd(unique_fd fd);
 };
@@ -290,9 +295,6 @@
         return connection_;
     }
 
-    bool HandleRead(std::unique_ptr<apacket> p);
-    void HandleError(const std::string& error);
-
 #if ADB_HOST
     void SetUsbHandle(usb_handle* h) { usb_handle_ = h; }
     usb_handle* GetUsbHandle() { return usb_handle_; }
@@ -335,6 +337,7 @@
     size_t failed_auth_attempts = 0;
 
     std::string serial_name() const { return !serial.empty() ? serial : "<unknown>"; }
+    std::string connection_state_name() const;
 
     void update_version(int version, size_t payload);
     int get_protocol_version() const;
@@ -352,11 +355,6 @@
     void RunDisconnects();
 
 #if ADB_HOST
-    bool Attach(std::string* error);
-    bool Detach(std::string* error);
-#endif
-
-#if ADB_HOST
     // Returns true if |target| matches this transport. A matching |target| can be any of:
     //   * <serial>
     //   * <devpath>
@@ -422,18 +420,6 @@
     DISALLOW_COPY_AND_ASSIGN(atransport);
 };
 
-// --one-device command line parameter is eventually put here.
-void transport_set_one_device(const char* adb_one_device);
-
-// Returns one device owned by this server of nullptr if all devices belong to server.
-const char* transport_get_one_device();
-
-// Returns true if the adb server owns all devices, or `serial`.
-bool transport_server_owns_device(std::string_view serial);
-
-// Returns true if the adb server owns all devices, `serial`, or `dev_path`.
-bool transport_server_owns_device(std::string_view dev_path, std::string_view serial);
-
 /*
  * Obtain a transport from the available transports.
  * If serial is non-null then only the device with that serial will be chosen.
diff --git a/transport_fd.cpp b/transport_fd.cpp
index d88d57d..b9b4f42 100644
--- a/transport_fd.cpp
+++ b/transport_fd.cpp
@@ -121,7 +121,7 @@
                         packet->msg = *read_header_;
                         packet->payload = std::move(payload);
                         read_header_ = nullptr;
-                        transport_->HandleRead(std::move(packet));
+                        read_callback_(this, std::move(packet));
                     }
                 }
             }
@@ -145,7 +145,7 @@
         thread_ = std::thread([this]() {
             std::string error = "connection closed";
             Run(&error);
-            transport_->HandleError(error);
+            this->error_callback_(this, error);
         });
     }
 
diff --git a/transport_test.cpp b/transport_test.cpp
index 1a047aa..8579ff4 100644
--- a/transport_test.cpp
+++ b/transport_test.cpp
@@ -21,19 +21,6 @@
 #include "adb.h"
 #include "fdevent/fdevent_test.h"
 
-TEST(ConnectionStateTest, to_string) {
-    ASSERT_EQ("offline", to_string(ConnectionState::kCsOffline));
-    ASSERT_EQ("bootloader", to_string(ConnectionState::kCsBootloader));
-    ASSERT_EQ("device", to_string(ConnectionState::kCsDevice));
-    ASSERT_EQ("host", to_string(ConnectionState::kCsHost));
-    ASSERT_EQ("recovery", to_string(ConnectionState::kCsRecovery));
-    ASSERT_EQ("rescue", to_string(ConnectionState::kCsRescue));
-    ASSERT_EQ("sideload", to_string(ConnectionState::kCsSideload));
-    ASSERT_EQ("unauthorized", to_string(ConnectionState::kCsUnauthorized));
-    ASSERT_EQ("authorizing", to_string(ConnectionState::kCsAuthorizing));
-    ASSERT_EQ("connecting", to_string(ConnectionState::kCsConnecting));
-}
-
 struct TransportTest : public FdeventTest {};
 
 static void DisconnectFunc(void* arg, atransport*) {
diff --git a/types.h b/types.h
index cd08ed8..620aa8e 100644
--- a/types.h
+++ b/types.h
@@ -306,7 +306,7 @@
         return *this;
     }
 
-    T* get() const {
+    T* get() {
         check_main_thread();
         return ptr_;
     }
@@ -349,7 +349,7 @@
     weak_ptr<T> weak() { return weak_ptr<T>(static_cast<T*>(this)); }
 
     void schedule_deletion() {
-        fdevent_run_on_main_thread([this]() { delete static_cast<T*>(this); });
+        fdevent_run_on_main_thread([this]() { delete this; });
     }
 
   private:
diff --git a/types_test.cpp b/types_test.cpp
index 086a35d..41fa1db 100644
--- a/types_test.cpp
+++ b/types_test.cpp
@@ -14,14 +14,10 @@
  * limitations under the License.
  */
 
-#include "types.h"
-
 #include <gtest/gtest.h>
 
 #include <memory>
-#include <utility>
-
-#include "fdevent/fdevent_test.h"
+#include "types.h"
 
 static IOVector::block_type create_block(const std::string& string) {
     return IOVector::block_type(string.begin(), string.end());
@@ -138,70 +134,3 @@
     ASSERT_EQ(1000U, vec.front_size());
     ASSERT_EQ(1000U, vec.size());
 }
-
-TEST(IOVector, take_front) {
-    IOVector vec;
-    ASSERT_TRUE(vec.take_front(0).empty());
-
-    vec.append(create_block('x', 2));
-    ASSERT_EQ(2ULL, vec.size());
-
-    ASSERT_EQ(1ULL, vec.take_front(1).size());
-    ASSERT_EQ(1ULL, vec.size());
-
-    ASSERT_EQ(1ULL, vec.take_front(1).size());
-    ASSERT_EQ(0ULL, vec.size());
-}
-
-TEST(IOVector, trim_front) {
-    IOVector vec;
-    vec.append(create_block('x', 2));
-
-    ASSERT_EQ(1ULL, vec.take_front(1).size());
-    ASSERT_EQ(1ULL, vec.size());
-    vec.trim_front();
-    ASSERT_EQ(1ULL, vec.size());
-}
-
-class weak_ptr_test : public FdeventTest {};
-
-struct Destructor : public enable_weak_from_this<Destructor> {
-    Destructor(bool* destroyed) : destroyed_(destroyed) {}
-    ~Destructor() { *destroyed_ = true; }
-
-    bool* destroyed_;
-};
-
-TEST_F(weak_ptr_test, smoke) {
-    PrepareThread();
-
-    Destructor* destructor = nullptr;
-    bool destroyed = false;
-    std::optional<weak_ptr<Destructor>> p;
-
-    fdevent_run_on_main_thread([&p, &destructor, &destroyed]() {
-        destructor = new Destructor(&destroyed);
-        p = destructor->weak();
-        ASSERT_TRUE(p->get());
-
-        p->reset();
-        ASSERT_FALSE(p->get());
-
-        p->reset(destructor);
-        ASSERT_TRUE(p->get());
-    });
-    WaitForFdeventLoop();
-    ASSERT_TRUE(destructor);
-    ASSERT_FALSE(destroyed);
-
-    destructor->schedule_deletion();
-    WaitForFdeventLoop();
-
-    ASSERT_TRUE(destroyed);
-    fdevent_run_on_main_thread([&p]() {
-        ASSERT_FALSE(p->get());
-        p.reset();
-    });
-
-    TerminateThread();
-}