Merge "libdm: Link libraries statically for VTS." into rvc-dev
diff --git a/adb/Android.bp b/adb/Android.bp
index 9d47b8b..0af82e1 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -114,6 +114,44 @@
     },
 }
 
+cc_defaults {
+    name: "libadbd_binary_dependencies",
+    static_libs: [
+        "libadb_crypto",
+        "libadb_pairing_connection",
+        "libadb_tls_connection",
+        "libadbd",
+        "libadbd_core",
+        "libadbconnection_server",
+        "libasyncio",
+        "libbrotli",
+        "libcutils_sockets",
+        "libdiagnose_usb",
+        "libmdnssd",
+        "libbase",
+
+        "libadb_protos",
+    ],
+
+    shared_libs: [
+        "libadbd_auth",
+        "libadbd_fs",
+        "libcrypto",
+        "libcrypto_utils",
+        "liblog",
+        "libselinux",
+    ],
+
+    target: {
+        recovery: {
+            exclude_static_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
+        },
+    },
+}
+
 // libadb
 // =========================================================
 // These files are compiled for both the host and the device.
@@ -133,7 +171,6 @@
     "transport.cpp",
     "transport_fd.cpp",
     "transport_local.cpp",
-    "transport_usb.cpp",
     "types.cpp",
 ]
 
@@ -169,6 +206,7 @@
         "client/usb_libusb.cpp",
         "client/usb_dispatch.cpp",
         "client/transport_mdns.cpp",
+        "client/transport_usb.cpp",
         "client/pairing/pairing_client.cpp",
     ],
 
@@ -246,39 +284,6 @@
     },
 }
 
-cc_benchmark {
-    name: "adb_benchmark",
-    defaults: ["adb_defaults"],
-
-    srcs: ["transport_benchmark.cpp"],
-    target: {
-        android: {
-            static_libs: [
-                "libadbd",
-            ],
-        },
-        host: {
-            static_libs: [
-                "libadb_host",
-            ],
-        },
-    },
-
-    static_libs: [
-        "libadb_crypto_static",
-        "libadb_tls_connection_static",
-        "libadbd_auth",
-        "libbase",
-        "libcutils",
-        "libcrypto_utils",
-        "libcrypto_static",
-        "libdiagnose_usb",
-        "liblog",
-        "libssl",
-        "libusb",
-    ],
-}
-
 cc_binary_host {
     name: "adb",
 
@@ -381,10 +386,6 @@
         "daemon/adb_wifi.cpp",
     ],
 
-    local_include_dirs: [
-        "daemon/include",
-    ],
-
     generated_headers: ["platform_tools_version"],
 
     static_libs: [
@@ -402,6 +403,7 @@
         "libbase",
         "libcrypto",
         "libcrypto_utils",
+        "libcutils_sockets",
         "liblog",
     ],
 
@@ -414,12 +416,6 @@
                 "daemon/transport_qemu.cpp",
                 "daemon/usb.cpp",
                 "daemon/usb_ffs.cpp",
-                "daemon/usb_legacy.cpp",
-            ]
-        },
-        linux_glibc: {
-            srcs: [
-                "daemon/usb_dummy.cpp",
             ]
         },
         recovery: {
@@ -461,13 +457,15 @@
         "libadb_pairing_connection",
         "libadb_protos",
         "libadb_tls_connection",
-        "libadbd_auth",
-        "libadbd_fs",
         "libasyncio",
         "libbase",
-        "libcrypto",
         "libcrypto_utils",
         "libcutils_sockets",
+
+        // APEX dependencies.
+        "libadbd_auth",
+        "libadbd_fs",
+        "libcrypto",
         "liblog",
     ],
 
@@ -507,25 +505,21 @@
     // libminadbd wants both, as it's used to build native tests.
     compile_multilib: "both",
 
-    // libadbd doesn't build any additional source, but to expose libadbd_core as a shared library.
-    whole_static_libs: [
-        "libadbconnection_server",
-        "libadbd_core",
-    ],
-
     shared_libs: [
         "libadb_crypto",
         "libadb_pairing_connection",
         "libadb_tls_connection",
-        "libadbd_auth",
-        "libadbd_fs",
-        "libadbd_services",
         "libasyncio",
         "libbase",
         "libcrypto",
         "libcrypto_utils",
         "liblog",
         "libselinux",
+
+        // APEX dependencies on the system image.
+        "libadbd_auth",
+        "libadbd_fs",
+        "libadbd_services",
     ],
 
     target: {
@@ -538,20 +532,22 @@
     },
 
     static_libs: [
+        "libadbd_core",
         "libbrotli",
         "libcutils_sockets",
         "libdiagnose_usb",
         "libmdnssd",
     ],
 
-    export_include_dirs: [
-        "daemon/include",
+    visibility: [
+        "//bootable/recovery/minadbd",
+        "//system/core/adb",
     ],
 }
 
 cc_binary {
     name: "adbd",
-    defaults: ["adbd_defaults", "host_adbd_supported"],
+    defaults: ["adbd_defaults", "host_adbd_supported", "libadbd_binary_dependencies"],
     stl: "libc++_static",
     recovery_available: true,
 
@@ -569,31 +565,17 @@
     },
 
     static_libs: [
-        "libadb_crypto",
-        "libadb_tls_connection",
-        "libadbconnection_server",
         "libadbd",
         "libadbd_services",
         "libasyncio",
-        "libbase",
-        "libbrotli",
         "libcap",
-        "libcrypto_utils",
-        "libcutils_sockets",
-        "libdiagnose_usb",
-        "libmdnssd",
         "libminijail",
         "libssl",
     ],
 
     shared_libs: [
-        "libadb_pairing_connection",
         "libadb_protos",
         "libadbd_auth",
-        "libadbd_fs",
-        "libcrypto",
-        "liblog",
-        "libselinux",
     ],
 
     target: {
@@ -665,8 +647,7 @@
 cc_test {
     name: "adbd_test",
 
-    defaults: ["adbd_defaults"],
-    stl: "libc++_static",
+    defaults: ["adbd_defaults", "libadbd_binary_dependencies"],
 
     recovery_available: false,
     srcs: libadb_test_srcs + [
@@ -677,21 +658,16 @@
         "shell_service_protocol_test.cpp",
     ],
 
+    shared_libs: [
+        "liblog",
+    ],
+
     static_libs: [
         "libadbd",
         "libadbd_auth",
-        "libadb_crypto_static",
-        "libadb_pairing_connection_static",
-        "libadb_tls_connection_static",
         "libbase",
         "libcrypto_utils",
-        "libcrypto_static",
-        "libcutils_sockets",
-        "libdiagnose_usb",
-        "liblog",
         "libusb",
-        "libmdnssd",
-        "libselinux",
     ],
     test_suites: ["device-tests", "mts"],
     require_root: true,
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 98db191..44e5dac 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -66,6 +66,10 @@
 #include "daemon/logging.h"
 #endif
 
+#if ADB_HOST
+#include "client/usb.h"
+#endif
+
 std::string adb_version() {
     // Don't change the format of this --- it's parsed by ddmlib.
     return android::base::StringPrintf(
diff --git a/adb/adb.h b/adb/adb.h
index 86d205c..ce12a55 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -29,7 +29,6 @@
 #include "fdevent/fdevent.h"
 #include "socket.h"
 #include "types.h"
-#include "usb.h"
 
 constexpr size_t MAX_PAYLOAD_V1 = 4 * 1024;
 constexpr size_t MAX_PAYLOAD = 1024 * 1024;
@@ -139,7 +138,6 @@
 
 /* initialize a transport object's func pointers and state */
 int init_socket_transport(atransport* t, unique_fd s, int port, int local);
-void init_usb_transport(atransport* t, usb_handle* usb);
 
 std::string getEmulatorSerialString(int console_port);
 #if ADB_HOST
@@ -252,4 +250,5 @@
 // Wait until device scan has completed and every transport is ready, or a timeout elapses.
 void adb_wait_for_device_initialization();
 
+void usb_init();
 #endif
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index fe9182e..092a866 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -22,11 +22,12 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <algorithm>
-#include <iostream>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/parsebool.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
@@ -39,8 +40,9 @@
 #include "fastdeploy.h"
 #include "incremental.h"
 
+using namespace std::literals;
+
 static constexpr int kFastDeployMinApi = 24;
-static constexpr int kIncrementalMinApi = 29;
 
 namespace {
 
@@ -50,6 +52,8 @@
     INSTALL_STREAM,
     INSTALL_INCREMENTAL,
 };
+
+enum class CmdlineOption { None, Enable, Disable };
 }
 
 static bool can_use_feature(const char* feature) {
@@ -299,45 +303,52 @@
     return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
 }
 
-static int install_app_incremental(int argc, const char** argv) {
-    printf("Performing Incremental Install\n");
+static int install_app_incremental(int argc, const char** argv, bool wait, bool silent) {
     using clock = std::chrono::high_resolution_clock;
     const auto start = clock::now();
     int first_apk = -1;
     int last_apk = -1;
-    std::string cert_path;
-    bool wait = false;
-    std::vector<std::string_view> args = {"package"};
+    std::vector<std::string_view> args = {"package"sv};
     for (int i = 0; i < argc; ++i) {
         const auto arg = std::string_view(argv[i]);
-        if (android::base::EndsWithIgnoreCase(arg, ".apk")) {
+        if (android::base::EndsWithIgnoreCase(arg, ".apk"sv)) {
             last_apk = i;
             if (first_apk == -1) {
                 first_apk = i;
             }
-        } else if (arg == "--wait") {
-            wait = true;
-        } else if (arg.starts_with("install-")) {
+        } else if (arg.starts_with("install-"sv)) {
             // incremental installation command on the device is the same for all its variations in
             // the adb, e.g. install-multiple or install-multi-package
-            args.push_back("install");
+            args.push_back("install"sv);
         } else {
             args.push_back(arg);
         }
     }
 
-    if (first_apk == -1) error_exit("Need at least one APK file on command line");
+    if (first_apk == -1) {
+        if (!silent) {
+            fprintf(stderr, "error: need at least one APK file on command line\n");
+        }
+        return -1;
+    }
 
-    const auto afterApk = clock::now();
+    auto files = incremental::Files{argv + first_apk, argv + last_apk + 1};
+    if (silent) {
+        // For a silent installation we want to do the lightweight check first and bail early and
+        // quietly if it fails.
+        if (!incremental::can_install(files)) {
+            return -1;
+        }
+    }
 
-    auto server_process = incremental::install({argv + first_apk, argv + last_apk + 1});
+    printf("Performing Incremental Install\n");
+    auto server_process = incremental::install(files, silent);
     if (!server_process) {
         return -1;
     }
 
     const auto end = clock::now();
-    printf("Install command complete (ms: %d total, %d apk prep, %d install)\n",
-           msBetween(start, end), msBetween(start, afterApk), msBetween(afterApk, end));
+    printf("Install command complete in %d ms\n", msBetween(start, end));
 
     if (wait) {
         (*server_process).wait();
@@ -346,66 +357,134 @@
     return 0;
 }
 
+static std::pair<InstallMode, std::optional<InstallMode>> calculateInstallMode(
+        InstallMode modeFromArgs, bool fastdeploy, CmdlineOption incrementalRequest) {
+    if (incrementalRequest == CmdlineOption::Enable) {
+        if (fastdeploy) {
+            error_exit(
+                    "--incremental and --fast-deploy options are incompatible. "
+                    "Please choose one");
+        }
+    }
+
+    if (modeFromArgs != INSTALL_DEFAULT) {
+        if (incrementalRequest == CmdlineOption::Enable) {
+            error_exit("--incremental is not compatible with other installation modes");
+        }
+        return {modeFromArgs, std::nullopt};
+    }
+
+    if (incrementalRequest != CmdlineOption::Disable && !is_abb_exec_supported()) {
+        if (incrementalRequest == CmdlineOption::None) {
+            incrementalRequest = CmdlineOption::Disable;
+        } else {
+            error_exit("Device doesn't support incremental installations");
+        }
+    }
+    if (incrementalRequest == CmdlineOption::None) {
+        // check if the host is ok with incremental by default
+        if (const char* incrementalFromEnv = getenv("ADB_INSTALL_DEFAULT_INCREMENTAL")) {
+            using namespace android::base;
+            auto val = ParseBool(incrementalFromEnv);
+            if (val == ParseBoolResult::kFalse) {
+                incrementalRequest = CmdlineOption::Disable;
+            }
+        }
+    }
+    if (incrementalRequest == CmdlineOption::None) {
+        // still ok: let's see if the device allows using incremental by default
+        // it starts feeling like we're looking for an excuse to not to use incremental...
+        std::string error;
+        std::vector<std::string> args = {"settings", "get",
+                                         "enable_adb_incremental_install_default"};
+        auto fd = send_abb_exec_command(args, &error);
+        if (!fd.ok()) {
+            fprintf(stderr, "adb: retrieving the default device installation mode failed: %s",
+                    error.c_str());
+        } else {
+            char buf[BUFSIZ] = {};
+            read_status_line(fd.get(), buf, sizeof(buf));
+            using namespace android::base;
+            auto val = ParseBool(buf);
+            if (val == ParseBoolResult::kFalse) {
+                incrementalRequest = CmdlineOption::Disable;
+            }
+        }
+    }
+
+    if (incrementalRequest == CmdlineOption::Enable) {
+        // explicitly requested - no fallback
+        return {INSTALL_INCREMENTAL, std::nullopt};
+    }
+    const auto bestMode = best_install_mode();
+    if (incrementalRequest == CmdlineOption::None) {
+        // no opinion - use incremental, fallback to regular on a failure.
+        return {INSTALL_INCREMENTAL, bestMode};
+    }
+    // incremental turned off - use the regular best mode without a fallback.
+    return {bestMode, std::nullopt};
+}
+
 int install_app(int argc, const char** argv) {
     std::vector<int> processedArgIndices;
     InstallMode installMode = INSTALL_DEFAULT;
     bool use_fastdeploy = false;
     bool is_reinstall = false;
+    bool wait = false;
+    auto incremental_request = CmdlineOption::None;
     FastDeploy_AgentUpdateStrategy agent_update_strategy = FastDeploy_AgentUpdateDifferentVersion;
 
     for (int i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "--streaming")) {
+        if (argv[i] == "--streaming"sv) {
             processedArgIndices.push_back(i);
             installMode = INSTALL_STREAM;
-        } else if (!strcmp(argv[i], "--no-streaming")) {
+        } else if (argv[i] == "--no-streaming"sv) {
             processedArgIndices.push_back(i);
             installMode = INSTALL_PUSH;
-        } else if (!strcmp(argv[i], "-r")) {
+        } else if (argv[i] == "-r"sv) {
             // Note that this argument is not added to processedArgIndices because it
             // must be passed through to pm
             is_reinstall = true;
-        } else if (!strcmp(argv[i], "--fastdeploy")) {
+        } else if (argv[i] == "--fastdeploy"sv) {
             processedArgIndices.push_back(i);
             use_fastdeploy = true;
-        } else if (!strcmp(argv[i], "--no-fastdeploy")) {
+        } else if (argv[i] == "--no-fastdeploy"sv) {
             processedArgIndices.push_back(i);
             use_fastdeploy = false;
-        } else if (!strcmp(argv[i], "--force-agent")) {
+        } else if (argv[i] == "--force-agent"sv) {
             processedArgIndices.push_back(i);
             agent_update_strategy = FastDeploy_AgentUpdateAlways;
-        } else if (!strcmp(argv[i], "--date-check-agent")) {
+        } else if (argv[i] == "--date-check-agent"sv) {
             processedArgIndices.push_back(i);
             agent_update_strategy = FastDeploy_AgentUpdateNewerTimeStamp;
-        } else if (!strcmp(argv[i], "--version-check-agent")) {
+        } else if (argv[i] == "--version-check-agent"sv) {
             processedArgIndices.push_back(i);
             agent_update_strategy = FastDeploy_AgentUpdateDifferentVersion;
-        } else if (!strcmp(argv[i], "--incremental")) {
+        } else if (strlen(argv[i]) >= "--incr"sv.size() && "--incremental"sv.starts_with(argv[i])) {
             processedArgIndices.push_back(i);
-            installMode = INSTALL_INCREMENTAL;
-        } else if (!strcmp(argv[i], "--no-incremental")) {
+            incremental_request = CmdlineOption::Enable;
+        } else if (strlen(argv[i]) >= "--no-incr"sv.size() &&
+                   "--no-incremental"sv.starts_with(argv[i])) {
             processedArgIndices.push_back(i);
-            installMode = INSTALL_DEFAULT;
+            incremental_request = CmdlineOption::Disable;
+        } else if (argv[i] == "--wait"sv) {
+            processedArgIndices.push_back(i);
+            wait = true;
         }
     }
 
-    if (installMode == INSTALL_INCREMENTAL) {
-        if (get_device_api_level() < kIncrementalMinApi || !is_abb_exec_supported()) {
-            error_exit("Attempting to use incremental install on unsupported device");
-        }
-    }
-
-    if (installMode == INSTALL_DEFAULT) {
-        installMode = best_install_mode();
-    }
-
-    if (installMode == INSTALL_STREAM && best_install_mode() == INSTALL_PUSH) {
+    auto [primaryMode, fallbackMode] =
+            calculateInstallMode(installMode, use_fastdeploy, incremental_request);
+    if ((primaryMode == INSTALL_STREAM || fallbackMode.value_or(INSTALL_PUSH) == INSTALL_STREAM) &&
+        best_install_mode() == INSTALL_PUSH) {
         error_exit("Attempting to use streaming install on unsupported device");
     }
 
     if (use_fastdeploy && get_device_api_level() < kFastDeployMinApi) {
-        printf("Fast Deploy is only compatible with devices of API version %d or higher, "
-               "ignoring.\n",
-               kFastDeployMinApi);
+        fprintf(stderr,
+                "Fast Deploy is only compatible with devices of API version %d or higher, "
+                "ignoring.\n",
+                kFastDeployMinApi);
         use_fastdeploy = false;
     }
     fastdeploy_set_agent_update_strategy(agent_update_strategy);
@@ -421,19 +500,27 @@
         error_exit("install requires an apk argument");
     }
 
-    switch (installMode) {
-        case INSTALL_PUSH:
-            return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
-                                      use_fastdeploy);
-        case INSTALL_STREAM:
-            return install_app_streamed(passthrough_argv.size(), passthrough_argv.data(),
-                                        use_fastdeploy);
-        case INSTALL_INCREMENTAL:
-            return install_app_incremental(passthrough_argv.size(), passthrough_argv.data());
-        case INSTALL_DEFAULT:
-        default:
-            return 1;
+    auto runInstallMode = [&](InstallMode installMode, bool silent) {
+        switch (installMode) {
+            case INSTALL_PUSH:
+                return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
+                                          use_fastdeploy);
+            case INSTALL_STREAM:
+                return install_app_streamed(passthrough_argv.size(), passthrough_argv.data(),
+                                            use_fastdeploy);
+            case INSTALL_INCREMENTAL:
+                return install_app_incremental(passthrough_argv.size(), passthrough_argv.data(),
+                                               wait, silent);
+            case INSTALL_DEFAULT:
+            default:
+                return 1;
+        }
+    };
+    auto res = runInstallMode(primaryMode, fallbackMode.has_value());
+    if (res && fallbackMode.value_or(primaryMode) != primaryMode) {
+        res = runInstallMode(*fallbackMode, false);
     }
+    return res;
 }
 
 int install_multiple_app(int argc, const char** argv) {
diff --git a/adb/client/incremental.cpp b/adb/client/incremental.cpp
index a9e65dc..b56df44 100644
--- a/adb/client/incremental.cpp
+++ b/adb/client/incremental.cpp
@@ -90,38 +90,58 @@
     return total_tree_block_count * INCFS_DATA_FILE_BLOCK_SIZE;
 }
 
-// Base64-encode signature bytes. Keeping fd at the position of start of verity tree.
-static std::pair<unique_fd, std::string> read_and_encode_signature(Size file_size,
-                                                                   std::string signature_file) {
+// Read, verify and return the signature bytes. Keeping fd at the position of start of verity tree.
+static std::pair<unique_fd, std::vector<char>> read_signature(Size file_size,
+                                                              std::string signature_file,
+                                                              bool silent) {
     signature_file += IDSIG;
 
     struct stat st;
     if (stat(signature_file.c_str(), &st)) {
-        fprintf(stderr, "Failed to stat signature file %s. Abort.\n", signature_file.c_str());
+        if (!silent) {
+            fprintf(stderr, "Failed to stat signature file %s. Abort.\n", signature_file.c_str());
+        }
         return {};
     }
 
     unique_fd fd(adb_open(signature_file.c_str(), O_RDONLY | O_CLOEXEC));
     if (fd < 0) {
-        fprintf(stderr, "Failed to open signature file: %s. Abort.\n", signature_file.c_str());
+        if (!silent) {
+            fprintf(stderr, "Failed to open signature file: %s. Abort.\n", signature_file.c_str());
+        }
         return {};
     }
 
     auto [signature, tree_size] = read_id_sig_headers(fd);
     if (auto expected = verity_tree_size_for_file(file_size); tree_size != expected) {
-        fprintf(stderr,
-                "Verity tree size mismatch in signature file: %s [was %lld, expected %lld].\n",
-                signature_file.c_str(), (long long)tree_size, (long long)expected);
+        if (!silent) {
+            fprintf(stderr,
+                    "Verity tree size mismatch in signature file: %s [was %lld, expected %lld].\n",
+                    signature_file.c_str(), (long long)tree_size, (long long)expected);
+        }
+        return {};
+    }
+
+    return {std::move(fd), std::move(signature)};
+}
+
+// Base64-encode signature bytes. Keeping fd at the position of start of verity tree.
+static std::pair<unique_fd, std::string> read_and_encode_signature(Size file_size,
+                                                                   std::string signature_file,
+                                                                   bool silent) {
+    auto [fd, signature] = read_signature(file_size, std::move(signature_file), silent);
+    if (!fd.ok()) {
         return {};
     }
 
     size_t base64_len = 0;
     if (!EVP_EncodedLength(&base64_len, signature.size())) {
-        fprintf(stderr, "Fail to estimate base64 encoded length. Abort.\n");
+        if (!silent) {
+            fprintf(stderr, "Fail to estimate base64 encoded length. Abort.\n");
+        }
         return {};
     }
-    std::string encoded_signature;
-    encoded_signature.resize(base64_len);
+    std::string encoded_signature(base64_len, '\0');
     encoded_signature.resize(EVP_EncodeBlock((uint8_t*)encoded_signature.data(),
                                              (const uint8_t*)signature.data(), signature.size()));
 
@@ -130,7 +150,7 @@
 
 // Send install-incremental to the device along with properly configured file descriptors in
 // streaming format. Once connection established, send all fs-verity tree bytes.
-static unique_fd start_install(const std::vector<std::string>& files) {
+static unique_fd start_install(const Files& files, bool silent) {
     std::vector<std::string> command_args{"package", "install-incremental"};
 
     // fd's with positions at the beginning of fs-verity
@@ -141,11 +161,13 @@
 
         struct stat st;
         if (stat(file.c_str(), &st)) {
-            fprintf(stderr, "Failed to stat input file %s. Abort.\n", file.c_str());
+            if (!silent) {
+                fprintf(stderr, "Failed to stat input file %s. Abort.\n", file.c_str());
+            }
             return {};
         }
 
-        auto [signature_fd, signature] = read_and_encode_signature(st.st_size, file);
+        auto [signature_fd, signature] = read_and_encode_signature(st.st_size, file, silent);
         if (!signature_fd.ok()) {
             return {};
         }
@@ -161,15 +183,19 @@
     std::string error;
     auto connection_fd = unique_fd(send_abb_exec_command(command_args, &error));
     if (connection_fd < 0) {
-        fprintf(stderr, "Failed to run: %s, error: %s\n",
-                android::base::Join(command_args, " ").c_str(), error.c_str());
+        if (!silent) {
+            fprintf(stderr, "Failed to run: %s, error: %s\n",
+                    android::base::Join(command_args, " ").c_str(), error.c_str());
+        }
         return {};
     }
 
     // Pushing verity trees for all installation files.
     for (auto&& local_fd : signature_fds) {
         if (!copy_to_file(local_fd.get(), connection_fd.get())) {
-            fprintf(stderr, "Failed to stream tree bytes: %s. Abort.\n", strerror(errno));
+            if (!silent) {
+                fprintf(stderr, "Failed to stream tree bytes: %s. Abort.\n", strerror(errno));
+            }
             return {};
         }
     }
@@ -179,10 +205,27 @@
 
 }  // namespace
 
-std::optional<Process> install(std::vector<std::string> files) {
-    auto connection_fd = start_install(files);
+bool can_install(const Files& files) {
+    for (const auto& file : files) {
+        struct stat st;
+        if (stat(file.c_str(), &st)) {
+            return false;
+        }
+
+        auto [fd, _] = read_signature(st.st_size, file, true);
+        if (!fd.ok()) {
+            return false;
+        }
+    }
+    return true;
+}
+
+std::optional<Process> install(const Files& files, bool silent) {
+    auto connection_fd = start_install(files, silent);
     if (connection_fd < 0) {
-        fprintf(stderr, "adb: failed to initiate installation on device.\n");
+        if (!silent) {
+            fprintf(stderr, "adb: failed to initiate installation on device.\n");
+        }
         return {};
     }
 
@@ -198,7 +241,9 @@
     // pipe for child process to write output
     int print_fds[2];
     if (adb_socketpair(print_fds) != 0) {
-        fprintf(stderr, "Failed to create socket pair for child to print to parent\n");
+        if (!silent) {
+            fprintf(stderr, "Failed to create socket pair for child to print to parent\n");
+        }
         return {};
     }
     auto [pipe_read_fd, pipe_write_fd] = print_fds;
@@ -210,7 +255,9 @@
     auto child =
             adb_launch_process(adb_path, std::move(args), {connection_fd.get(), pipe_write_fd});
     if (!child) {
-        fprintf(stderr, "adb: failed to fork: %s\n", strerror(errno));
+        if (!silent) {
+            fprintf(stderr, "adb: failed to fork: %s\n", strerror(errno));
+        }
         return {};
     }
 
diff --git a/adb/client/incremental.h b/adb/client/incremental.h
index 731e6fb..1fb1e0b 100644
--- a/adb/client/incremental.h
+++ b/adb/client/incremental.h
@@ -25,7 +25,10 @@
 
 namespace incremental {
 
-std::optional<Process> install(std::vector<std::string> files);
+using Files = std::vector<std::string>;
+
+bool can_install(const Files& files);
+std::optional<Process> install(const Files& files, bool silent);
 
 enum class Result { Success, Failure, None };
 Result wait_for_installation(int read_fd);
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index a85a18c..78f7b8f 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -36,6 +36,7 @@
 #include "adb_listeners.h"
 #include "adb_utils.h"
 #include "adb_wifi.h"
+#include "client/usb.h"
 #include "commandline.h"
 #include "sysdeps/chrono.h"
 #include "transport.h"
diff --git a/adb/transport_usb.cpp b/adb/client/transport_usb.cpp
similarity index 96%
rename from adb/transport_usb.cpp
rename to adb/client/transport_usb.cpp
index fb81b37..777edde 100644
--- a/adb/transport_usb.cpp
+++ b/adb/client/transport_usb.cpp
@@ -16,6 +16,10 @@
 
 #define TRACE_TAG TRANSPORT
 
+#include "sysdeps.h"
+
+#include "client/usb.h"
+
 #include <memory>
 
 #include "sysdeps.h"
@@ -135,8 +139,8 @@
         }
 
         p->payload.resize(p->msg.data_length);
-        if (usb_read(usb, &p->payload[0], p->payload.size())
-                != static_cast<int>(p->payload.size())) {
+        if (usb_read(usb, &p->payload[0], p->payload.size()) !=
+            static_cast<int>(p->payload.size())) {
             PLOG(ERROR) << "remote usb: terminated (data)";
             return -1;
         }
diff --git a/adb/usb.h b/adb/client/usb.h
similarity index 72%
rename from adb/usb.h
rename to adb/client/usb.h
index eb8ca6c..b371788 100644
--- a/adb/usb.h
+++ b/adb/client/usb.h
@@ -18,6 +18,9 @@
 
 #include <sys/types.h>
 
+#include "adb.h"
+#include "transport.h"
+
 // USB host/client interface.
 
 #define ADB_USB_INTERFACE(handle_ref_type)                       \
@@ -30,35 +33,38 @@
     void usb_kick(handle_ref_type h);                            \
     size_t usb_get_max_packet_size(handle_ref_type)
 
-#if !ADB_HOST
-// The daemon has a single implementation.
-
-struct usb_handle;
-ADB_USB_INTERFACE(usb_handle*);
-
-#else // linux host || darwin
 // Linux and Darwin clients have native and libusb implementations.
 
 namespace libusb {
-    struct usb_handle;
-    ADB_USB_INTERFACE(libusb::usb_handle*);
-}
+struct usb_handle;
+ADB_USB_INTERFACE(libusb::usb_handle*);
+}  // namespace libusb
 
 namespace native {
-    struct usb_handle;
-    ADB_USB_INTERFACE(native::usb_handle*);
-}
+struct usb_handle;
+ADB_USB_INTERFACE(native::usb_handle*);
+}  // namespace native
 
 // Empty base that both implementations' opaque handles inherit from.
-struct usb_handle {
-};
+struct usb_handle {};
 
 ADB_USB_INTERFACE(::usb_handle*);
 
-#endif // linux host || darwin
-
-
 // USB device detection.
 int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol);
 
 bool should_use_libusb();
+
+struct UsbConnection : public BlockingConnection {
+    explicit UsbConnection(usb_handle* handle) : handle_(handle) {}
+    ~UsbConnection();
+
+    bool Read(apacket* packet) override final;
+    bool Write(apacket* packet) override final;
+    bool DoTlsHandshake(RSA* key, std::string* auth_key) override final;
+
+    void Close() override final;
+    virtual void Reset() override final;
+
+    usb_handle* handle_;
+};
diff --git a/adb/client/usb_dispatch.cpp b/adb/client/usb_dispatch.cpp
index f55ae90..7b97117 100644
--- a/adb/client/usb_dispatch.cpp
+++ b/adb/client/usb_dispatch.cpp
@@ -15,7 +15,8 @@
  */
 
 #include <android-base/logging.h>
-#include "usb.h"
+
+#include "client/usb.h"
 
 void usb_init() {
     if (should_use_libusb()) {
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 53f01a0..07cbc94 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#include "usb.h"
-
 #include "sysdeps.h"
 
+#include "client/usb.h"
+
 #include <stdint.h>
 #include <stdlib.h>
 
@@ -40,7 +40,6 @@
 #include "adb.h"
 #include "adb_utils.h"
 #include "transport.h"
-#include "usb.h"
 
 using android::base::StringPrintf;
 
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index 343e7b5..95b1817 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -18,6 +18,8 @@
 
 #include "sysdeps.h"
 
+#include "client/usb.h"
+
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
@@ -48,7 +50,6 @@
 
 #include "adb.h"
 #include "transport.h"
-#include "usb.h"
 
 using namespace std::chrono_literals;
 using namespace std::literals;
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index 7207ca7..a93fa3a 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -18,6 +18,8 @@
 
 #include "sysdeps.h"
 
+#include "client/usb.h"
+
 #include <CoreFoundation/CoreFoundation.h>
 
 #include <IOKit/IOKitLib.h>
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index 197c6fa..e209230 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -18,6 +18,8 @@
 
 #include "sysdeps.h"
 
+#include "client/usb.h"
+
 // clang-format off
 #include <winsock2.h>  // winsock.h *must* be included before windows.h.
 #include <windows.h>
diff --git a/adb/crypto/Android.bp b/adb/crypto/Android.bp
index ce1de4a..9d14b03 100644
--- a/adb/crypto/Android.bp
+++ b/adb/crypto/Android.bp
@@ -40,6 +40,7 @@
 
     visibility: [
         "//system/core/adb:__subpackages__",
+        "//bootable/recovery/minadbd:__subpackages__",
     ],
 
     host_supported: true,
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 87937fb..7fff05a 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -45,19 +45,15 @@
 #include <android-base/properties.h>
 #include <android-base/thread_annotations.h>
 
-#include <adbd/usb.h>
-
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
+#include "daemon/usb_ffs.h"
 #include "sysdeps/chrono.h"
 #include "transport.h"
 #include "types.h"
 
 using android::base::StringPrintf;
 
-// We can't find out whether we have support for AIO on ffs endpoints until we submit a read.
-static std::optional<bool> gFfsAioSupported;
-
 // Not all USB controllers support operations larger than 16k, so don't go above that.
 // Also, each submitted operation does an allocation in the kernel of that size, so we want to
 // minimize our queue depth while still maintaining a deep enough queue to keep the USB stack fed.
@@ -612,17 +608,10 @@
         block->pending = true;
         struct iocb* iocb = &block->control;
         if (io_submit(aio_context_.get(), 1, &iocb) != 1) {
-            if (errno == EINVAL && !gFfsAioSupported.has_value()) {
-                HandleError("failed to submit first read, AIO on FFS not supported");
-                gFfsAioSupported = false;
-                return false;
-            }
-
             HandleError(StringPrintf("failed to submit read: %s", strerror(errno)));
             return false;
         }
 
-        gFfsAioSupported = true;
         return true;
     }
 
@@ -741,17 +730,10 @@
     static constexpr int kInterruptionSignal = SIGUSR1;
 };
 
-void usb_init_legacy();
-
 static void usb_ffs_open_thread() {
     adb_thread_setname("usb ffs open");
 
     while (true) {
-        if (gFfsAioSupported.has_value() && !gFfsAioSupported.value()) {
-            LOG(INFO) << "failed to use nonblocking ffs, falling back to legacy";
-            return usb_init_legacy();
-        }
-
         unique_fd control;
         unique_fd bulk_out;
         unique_fd bulk_in;
@@ -773,13 +755,5 @@
 }
 
 void usb_init() {
-    bool use_nonblocking = android::base::GetBoolProperty(
-            "persist.adb.nonblocking_ffs",
-            android::base::GetBoolProperty("ro.adb.nonblocking_ffs", true));
-
-    if (use_nonblocking) {
-        std::thread(usb_ffs_open_thread).detach();
-    } else {
-        usb_init_legacy();
-    }
+    std::thread(usb_ffs_open_thread).detach();
 }
diff --git a/adb/daemon/usb_dummy.cpp b/adb/daemon/usb_dummy.cpp
deleted file mode 100644
index c9bf797..0000000
--- a/adb/daemon/usb_dummy.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <adbd/usb.h>
-
-#include <android-base/logging.h>
-
-int usb_write(usb_handle*, const void*, int) {
-    LOG(FATAL) << "unimplemented";
-    return -1;
-}
-
-int usb_read(usb_handle*, void*, int) {
-    LOG(FATAL) << "unimplemented";
-    return -1;
-}
-
-int usb_close(usb_handle*) {
-    LOG(FATAL) << "unimplemented";
-    return -1;
-}
-
-void usb_reset(usb_handle*) {
-    LOG(FATAL) << "unimplemented";
-}
-
-void usb_kick(usb_handle*) {
-    LOG(FATAL) << "unimplemented";
-}
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index cb7e2fb..7bd611b 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -18,6 +18,8 @@
 
 #include "sysdeps.h"
 
+#include "daemon/usb_ffs.h"
+
 #include <linux/usb/ch9.h>
 #include <linux/usb/functionfs.h>
 
@@ -26,7 +28,6 @@
 #include <android-base/unique_fd.h>
 
 #include "adb.h"
-#include "adbd/usb.h"
 
 #define MAX_PACKET_SIZE_FS 64
 #define MAX_PACKET_SIZE_HS 512
diff --git a/adb/daemon/usb_ffs.h b/adb/daemon/usb_ffs.h
new file mode 100644
index 0000000..a19d7cc
--- /dev/null
+++ b/adb/daemon/usb_ffs.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+
+bool open_functionfs(android::base::unique_fd* control, android::base::unique_fd* bulk_out,
+                     android::base::unique_fd* bulk_in);
diff --git a/adb/pairing_connection/Android.bp b/adb/pairing_connection/Android.bp
index bcde7b1..707161b 100644
--- a/adb/pairing_connection/Android.bp
+++ b/adb/pairing_connection/Android.bp
@@ -41,6 +41,9 @@
         "//art:__subpackages__",
         "//system/core/adb:__subpackages__",
         "//frameworks/base/services:__subpackages__",
+
+        // This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
+        "//bootable/recovery/minadbd:__subpackages__",
     ],
     apex_available: [
         "com.android.adbd",
diff --git a/adb/proto/Android.bp b/adb/proto/Android.bp
index a7e5d9c..f7cba95 100644
--- a/adb/proto/Android.bp
+++ b/adb/proto/Android.bp
@@ -41,6 +41,9 @@
 
     visibility: [
         "//system/core/adb:__subpackages__",
+
+        // This needs to be visible to minadbd, even though it's removed via exclude_shared_libs.
+        "//bootable/recovery/minadbd:__subpackages__",
     ],
 
     stl: "libc++_static",
diff --git a/adb/tls/Android.bp b/adb/tls/Android.bp
index f2837e1..e5204f3 100644
--- a/adb/tls/Android.bp
+++ b/adb/tls/Android.bp
@@ -39,6 +39,7 @@
     recovery_available: true,
 
     visibility: [
+        "//bootable/recovery/minadbd:__subpackages__",
         "//system/core/adb:__subpackages__",
     ],
 
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 460faf0..61467cb 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1454,6 +1454,7 @@
 
 #endif
 
+#if ADB_HOST
 void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
                             unsigned writeable) {
     atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
@@ -1475,6 +1476,7 @@
 
     register_transport(t);
 }
+#endif
 
 #if ADB_HOST
 // This should only be used for transports with connection_state == kCsNoPerm.
diff --git a/adb/transport.h b/adb/transport.h
index 5d4e297..5bc1b5c 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -39,7 +39,6 @@
 #include "adb.h"
 #include "adb_unique_fd.h"
 #include "types.h"
-#include "usb.h"
 
 typedef std::unordered_set<std::string> FeatureSet;
 
@@ -202,20 +201,6 @@
     std::unique_ptr<adb::tls::TlsConnection> tls_;
 };
 
-struct UsbConnection : public BlockingConnection {
-    explicit UsbConnection(usb_handle* handle) : handle_(handle) {}
-    ~UsbConnection();
-
-    bool Read(apacket* packet) override final;
-    bool Write(apacket* packet) override final;
-    bool DoTlsHandshake(RSA* key, std::string* auth_key) override final;
-
-    void Close() override final;
-    virtual void Reset() override final;
-
-    usb_handle* handle_;
-};
-
 // Waits for a transport's connection to be not pending. This is a separate
 // object so that the transport can be destroyed and another thread can be
 // notified of it in a race-free way.
@@ -251,6 +236,10 @@
     Abort,
 };
 
+#if ADB_HOST
+struct usb_handle;
+#endif
+
 class atransport : public enable_weak_from_this<atransport> {
   public:
     // TODO(danalbert): We expose waaaaaaay too much stuff because this was
@@ -291,8 +280,10 @@
         return connection_;
     }
 
+#if ADB_HOST
     void SetUsbHandle(usb_handle* h) { usb_handle_ = h; }
     usb_handle* GetUsbHandle() { return usb_handle_; }
+#endif
 
     const TransportId id;
 
@@ -399,8 +390,10 @@
     // The underlying connection object.
     std::shared_ptr<Connection> connection_ GUARDED_BY(mutex_);
 
+#if ADB_HOST
     // USB handle for the connection, if available.
     usb_handle* usb_handle_ = nullptr;
+#endif
 
     // A callback that will be invoked when the atransport needs to reconnect.
     ReconnectCallback reconnect_;
@@ -441,8 +434,15 @@
 #endif
 
 void register_transport(atransport* transport);
-void register_usb_transport(usb_handle* h, const char* serial,
-                            const char* devpath, unsigned writeable);
+
+#if ADB_HOST
+void init_usb_transport(atransport* t, usb_handle* usb);
+void register_usb_transport(usb_handle* h, const char* serial, const char* devpath,
+                            unsigned writeable);
+
+// This should only be used for transports with connection_state == kCsNoPerm.
+void unregister_usb_transport(usb_handle* usb);
+#endif
 
 /* Connect to a network address and register it as a device */
 void connect_device(const std::string& address, std::string* response);
@@ -452,9 +452,6 @@
                                atransport::ReconnectCallback reconnect, bool use_tls,
                                int* error = nullptr);
 
-// This should only be used for transports with connection_state == kCsNoPerm.
-void unregister_usb_transport(usb_handle* usb);
-
 bool check_header(apacket* p, atransport* t);
 
 void close_usb_devices(bool reset = false);
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index a757d56..884856d 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -115,6 +115,7 @@
         "device/fastboot_device.cpp",
         "device/flashing.cpp",
         "device/main.cpp",
+        "device/usb.cpp",
         "device/usb_client.cpp",
         "device/utility.cpp",
         "device/variables.cpp",
@@ -125,7 +126,6 @@
         "android.hardware.boot@1.1",
         "android.hardware.fastboot@1.0",
         "android.hardware.health@2.0",
-        "libadbd",
         "libasyncio",
         "libbase",
         "libbootloader_message",
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index ca120c6..b8eee4a 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -31,6 +31,7 @@
 #include <cutils/android_reboot.h>
 #include <ext4_utils/wipe.h>
 #include <fs_mgr.h>
+#include <fs_mgr/roots.h>
 #include <libgsi/libgsi.h>
 #include <liblp/builder.h>
 #include <liblp/liblp.h>
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 31fc359..bb085c5 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -16,18 +16,22 @@
 
 #include "fastboot_device.h"
 
+#include <algorithm>
+
 #include <android-base/logging.h>
 #include <android-base/strings.h>
 #include <android/hardware/boot/1.0/IBootControl.h>
 #include <android/hardware/fastboot/1.0/IFastboot.h>
+#include <fs_mgr.h>
+#include <fs_mgr/roots.h>
 #include <healthhalutils/HealthHalUtils.h>
 
-#include <algorithm>
-
 #include "constants.h"
 #include "flashing.h"
 #include "usb_client.h"
 
+using android::fs_mgr::EnsurePathUnmounted;
+using android::fs_mgr::Fstab;
 using ::android::hardware::hidl_string;
 using ::android::hardware::boot::V1_0::IBootControl;
 using ::android::hardware::boot::V1_0::Slot;
@@ -64,6 +68,13 @@
     if (boot_control_hal_) {
         boot1_1_ = android::hardware::boot::V1_1::IBootControl::castFrom(boot_control_hal_);
     }
+
+    // Make sure cache is unmounted, since recovery will have mounted it for
+    // logging.
+    Fstab fstab;
+    if (ReadDefaultFstab(&fstab)) {
+        EnsurePathUnmounted(&fstab, "/cache");
+    }
 }
 
 FastbootDevice::~FastbootDevice() {
diff --git a/adb/daemon/usb_legacy.cpp b/fastboot/device/usb.cpp
similarity index 70%
rename from adb/daemon/usb_legacy.cpp
rename to fastboot/device/usb.cpp
index fe80e7d..4bee7b2 100644
--- a/adb/daemon/usb_legacy.cpp
+++ b/fastboot/device/usb.cpp
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-#define TRACE_TAG USB
-
-#include "sysdeps.h"
+#include "usb.h"
 
 #include <dirent.h>
 #include <errno.h>
@@ -41,12 +39,9 @@
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 
-#include "adb.h"
-#include "adbd/usb.h"
-#include "transport.h"
-
 using namespace std::chrono_literals;
 
+#define D(...)
 #define MAX_PACKET_SIZE_FS 64
 #define MAX_PACKET_SIZE_HS 512
 #define MAX_PACKET_SIZE_SS 1024
@@ -56,8 +51,6 @@
 // Number of buffers needed to fit MAX_PAYLOAD, with an extra for ZLPs.
 #define USB_FFS_NUM_BUFS ((4 * MAX_PAYLOAD / USB_FFS_BULK_SIZE) + 1)
 
-static unique_fd& dummy_fd = *new unique_fd();
-
 static void aio_block_init(aio_block* aiob, unsigned num_bufs) {
     aiob->iocb.resize(num_bufs);
     aiob->iocbs.resize(num_bufs);
@@ -82,46 +75,6 @@
     }
 }
 
-static bool init_functionfs(struct usb_handle* h) {
-    LOG(INFO) << "initializing functionfs";
-    if (!open_functionfs(&h->control, &h->bulk_out, &h->bulk_in)) {
-        return false;
-    }
-
-    h->read_aiob.fd = h->bulk_out.get();
-    h->write_aiob.fd = h->bulk_in.get();
-    h->reads_zero_packets = true;
-    return true;
-}
-
-static void usb_legacy_ffs_open_thread(usb_handle* usb) {
-    adb_thread_setname("usb legacy ffs open");
-
-    while (true) {
-        // wait until the USB device needs opening
-        std::unique_lock<std::mutex> lock(usb->lock);
-        while (!usb->open_new_connection) {
-            usb->notify.wait(lock);
-        }
-        usb->open_new_connection = false;
-        lock.unlock();
-
-        while (true) {
-            if (init_functionfs(usb)) {
-                LOG(INFO) << "functionfs successfully initialized";
-                break;
-            }
-            std::this_thread::sleep_for(1s);
-        }
-
-        LOG(INFO) << "registering usb transport";
-        register_usb_transport(usb, nullptr, nullptr, 1);
-    }
-
-    // never gets here
-    abort();
-}
-
 static int usb_ffs_write(usb_handle* h, const void* data, int len) {
     D("about to write (fd=%d, len=%d)", h->bulk_in.get(), len);
 
@@ -129,7 +82,7 @@
     int orig_len = len;
     while (len > 0) {
         int write_len = std::min(USB_FFS_BULK_SIZE, len);
-        int n = adb_write(h->bulk_in, buf, write_len);
+        int n = write(h->bulk_in, buf, write_len);
         if (n < 0) {
             D("ERROR: fd = %d, n = %d: %s", h->bulk_in.get(), n, strerror(errno));
             return -1;
@@ -150,7 +103,7 @@
     unsigned count = 0;
     while (len > 0) {
         int read_len = std::min(USB_FFS_BULK_SIZE, len);
-        int n = adb_read(h->bulk_out, buf, read_len);
+        int n = read(h->bulk_out, buf, read_len);
         if (n < 0) {
             D("ERROR: fd = %d, n = %d: %s", h->bulk_out.get(), n, strerror(errno));
             return -1;
@@ -232,7 +185,7 @@
     }
 }
 
-static int usb_ffs_aio_read(usb_handle* h, void* data, int len, bool allow_partial) {
+static int usb_ffs_aio_read(usb_handle* h, void* data, int len, bool /* allow_partial */) {
     return usb_ffs_do_aio(h, data, len, true);
 }
 
@@ -240,32 +193,9 @@
     return usb_ffs_do_aio(h, data, len, false);
 }
 
-static void usb_ffs_kick(usb_handle* h) {
-    int err;
-
-    err = ioctl(h->bulk_in.get(), FUNCTIONFS_CLEAR_HALT);
-    if (err < 0) {
-        D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in.get(), errno);
-    }
-
-    err = ioctl(h->bulk_out.get(), FUNCTIONFS_CLEAR_HALT);
-    if (err < 0) {
-        D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out.get(), errno);
-    }
-
-    // don't close ep0 here, since we may not need to reinitialize it with
-    // the same descriptors again. if however ep1/ep2 fail to re-open in
-    // init_functionfs, only then would we close and open ep0 again.
-    // Ditto the comment in usb_adb_kick.
-    h->kicked = true;
-    TEMP_FAILURE_RETRY(dup2(dummy_fd.get(), h->bulk_out.get()));
-    TEMP_FAILURE_RETRY(dup2(dummy_fd.get(), h->bulk_in.get()));
-}
-
 static void usb_ffs_close(usb_handle* h) {
     LOG(INFO) << "closing functionfs transport";
 
-    h->kicked = false;
     h->bulk_out.reset();
     h->bulk_in.reset();
 
@@ -291,37 +221,6 @@
         aio_block_init(&h->write_aiob, num_bufs);
     }
     h->io_size = io_size;
-    h->kick = usb_ffs_kick;
     h->close = usb_ffs_close;
     return h;
 }
-
-void usb_init_legacy() {
-    D("[ usb_init - using legacy FunctionFS ]");
-    dummy_fd.reset(adb_open("/dev/null", O_WRONLY | O_CLOEXEC));
-    CHECK_NE(-1, dummy_fd.get());
-
-    std::thread(usb_legacy_ffs_open_thread, create_usb_handle(USB_FFS_NUM_BUFS, USB_FFS_BULK_SIZE))
-            .detach();
-}
-
-int usb_write(usb_handle* h, const void* data, int len) {
-    return h->write(h, data, len);
-}
-
-int usb_read(usb_handle* h, void* data, int len) {
-    return h->read(h, data, len, false /* allow_partial */);
-}
-
-int usb_close(usb_handle* h) {
-    h->close(h);
-    return 0;
-}
-
-void usb_reset(usb_handle* h) {
-    usb_close(h);
-}
-
-void usb_kick(usb_handle* h) {
-    h->kick(h);
-}
diff --git a/adb/daemon/include/adbd/usb.h b/fastboot/device/usb.h
similarity index 84%
rename from adb/daemon/include/adbd/usb.h
rename to fastboot/device/usb.h
index 2204246..6c3f542 100644
--- a/adb/daemon/include/adbd/usb.h
+++ b/fastboot/device/usb.h
@@ -36,17 +36,14 @@
 };
 
 struct usb_handle {
-    usb_handle() : kicked(false) {
-    }
+    usb_handle() {}
 
     std::condition_variable notify;
     std::mutex lock;
-    std::atomic<bool> kicked;
     bool open_new_connection = true;
 
     int (*write)(usb_handle* h, const void* data, int len);
     int (*read)(usb_handle* h, void* data, int len, bool allow_partial);
-    void (*kick)(usb_handle* h);
     void (*close)(usb_handle* h);
 
     // FunctionFS
@@ -63,6 +60,4 @@
     size_t io_size;
 };
 
-usb_handle *create_usb_handle(unsigned num_bufs, unsigned io_size);
-bool open_functionfs(android::base::unique_fd* control, android::base::unique_fd* bulk_out,
-                     android::base::unique_fd* bulk_in);
+usb_handle* create_usb_handle(unsigned num_bufs, unsigned io_size);
diff --git a/fastboot/device/usb_client.h b/fastboot/device/usb_client.h
index e6a1a8b..e702a0d 100644
--- a/fastboot/device/usb_client.h
+++ b/fastboot/device/usb_client.h
@@ -17,7 +17,7 @@
 
 #include <memory>
 
-#include <adbd/usb.h>
+#include "usb.h"
 
 #include "transport.h"
 
diff --git a/init/oneshot_on_test.cpp b/init/oneshot_on_test.cpp
index 7e7cc36..650f065 100644
--- a/init/oneshot_on_test.cpp
+++ b/init/oneshot_on_test.cpp
@@ -26,6 +26,11 @@
 using namespace std::literals;
 
 TEST(init, oneshot_on) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Skipping test, must be run as root.";
+        return;
+    }
+
     // Bootanim shouldn't be running once the device has booted.
     ASSERT_EQ("stopped", GetProperty("init.svc.bootanim", ""));
 
diff --git a/libstats/pull/include/stats_pull_atom_callback.h b/libstats/pull/include/stats_pull_atom_callback.h
index c976c68..17df584 100644
--- a/libstats/pull/include/stats_pull_atom_callback.h
+++ b/libstats/pull/include/stats_pull_atom_callback.h
@@ -46,7 +46,8 @@
 
 /**
  * Set the cool down time of the pull in milliseconds. If two successive pulls are issued
- * within the cool down, a cached version of the first will be used for the second.
+ * within the cool down, a cached version of the first will be used for the second. The minimum
+ * allowed cool down is one second.
  */
 void AStatsManager_PullAtomMetadata_setCoolDownMillis(AStatsManager_PullAtomMetadata* metadata,
                                                       int64_t cool_down_millis);
@@ -58,6 +59,7 @@
 
 /**
  * Set the maximum time the pull can take in milliseconds.
+ * The maximum allowed timeout is 10 seconds.
  */
 void AStatsManager_PullAtomMetadata_setTimeoutMillis(AStatsManager_PullAtomMetadata* metadata,
                                                      int64_t timeout_millis);