From 8a9277a243a03c9a40da5eb7a331a2be28c471d0 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Wed, 22 Apr 2020 17:30:06 -0700 Subject: [PATCH 1/3] adb: split transport_local.cpp into client/daemon. Improve coverage some more. Test: ./coverage/gen_coverage.sh && ./coverage/report.sh Change-Id: I014d7ad25b2793d5d836ce5e526d657d46687ea4 --- adb/Android.bp | 5 +- adb/{ => client}/transport_local.cpp | 95 ++-------------------- adb/daemon/transport_local.cpp | 117 +++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 89 deletions(-) rename adb/{ => client}/transport_local.cpp (79%) create mode 100644 adb/daemon/transport_local.cpp diff --git a/adb/Android.bp b/adb/Android.bp index 8779c0ab2..d6bc47e16 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -171,7 +171,6 @@ libadb_srcs = [ "sysdeps/errno.cpp", "transport.cpp", "transport_fd.cpp", - "transport_local.cpp", "types.cpp", ] @@ -217,6 +216,7 @@ cc_library_host_static { "client/adb_wifi.cpp", "client/usb_libusb.cpp", "client/usb_dispatch.cpp", + "client/transport_local.cpp", "client/transport_mdns.cpp", "client/transport_usb.cpp", "client/pairing/pairing_client.cpp", @@ -390,10 +390,11 @@ cc_library_static { compile_multilib: "both", srcs: libadb_srcs + libadb_linux_srcs + libadb_posix_srcs + [ + "daemon/adb_wifi.cpp", "daemon/auth.cpp", "daemon/jdwp_service.cpp", "daemon/logging.cpp", - "daemon/adb_wifi.cpp", + "daemon/transport_local.cpp", ], generated_headers: ["platform_tools_version"], diff --git a/adb/transport_local.cpp b/adb/client/transport_local.cpp similarity index 79% rename from adb/transport_local.cpp rename to adb/client/transport_local.cpp index 5ec8e1665..15a072466 100644 --- a/adb/transport_local.cpp +++ b/adb/client/transport_local.cpp @@ -38,10 +38,6 @@ #include #include -#if !ADB_HOST -#include -#endif - #include "adb.h" #include "adb_io.h" #include "adb_unique_fd.h" @@ -49,8 +45,6 @@ #include "socket_spec.h" #include "sysdeps/chrono.h" -#if ADB_HOST - // Android Wear has been using port 5601 in all of its documentation/tooling, // but we search for emulators on ports [5554, 5555 + ADB_LOCAL_TRANSPORT_MAX]. // Avoid stomping on their port by restricting the active scanning range. @@ -76,9 +70,8 @@ static void adb_local_transport_max_port_env_override() { // We keep a map from emulator port to transport. // TODO: weak_ptr? -static auto& local_transports GUARDED_BY(local_transports_lock) = - *new std::unordered_map(); -#endif /* ADB_HOST */ +static std::unordered_map local_transports + [[clang::no_destroy]] GUARDED_BY(local_transports_lock); bool local_connect(int port) { std::string dummy; @@ -140,21 +133,19 @@ void connect_device(const std::string& address, std::string* response) { } } - int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error) { unique_fd fd; -#if ADB_HOST if (find_emulator_transport_by_adb_port(adb_port) != nullptr || find_emulator_transport_by_console_port(console_port) != nullptr) { return -1; } - const char *host = getenv("ADBHOST"); + const char* host = getenv("ADBHOST"); if (host) { fd.reset(network_connect(host, adb_port, SOCK_STREAM, 0, error)); } -#endif + if (fd < 0) { fd.reset(network_loopback_client(adb_port, SOCK_STREAM, error)); } @@ -173,8 +164,6 @@ int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* e return -1; } -#if ADB_HOST - static void PollAllLocalPortsForEmulator() { // Try to connect to any number of running emulator instances. for (int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; port <= adb_local_transport_max_port; @@ -194,8 +183,8 @@ struct RetryPort { // Retry emulators just kicked. static std::vector& retry_ports = *new std::vector; -std::mutex &retry_ports_lock = *new std::mutex; -std::condition_variable &retry_ports_cond = *new std::condition_variable; +std::mutex& retry_ports_lock = *new std::mutex; +std::condition_variable& retry_ports_cond = *new std::condition_variable; static void client_socket_thread(std::string_view) { adb_thread_setname("client_socket_thread"); @@ -220,7 +209,7 @@ static void client_socket_thread(std::string_view) { std::vector next_ports; for (auto& port : ports) { VLOG(TRANSPORT) << "retry port " << port.port << ", last retry_count " - << port.retry_count; + << port.retry_count; if (local_connect(port.port)) { VLOG(TRANSPORT) << "retry port " << port.port << " successfully"; continue; @@ -240,77 +229,12 @@ static void client_socket_thread(std::string_view) { } } -#else // !ADB_HOST - -void server_socket_thread(std::function listen_func, - std::string_view addr) { - adb_thread_setname("server socket"); - - unique_fd serverfd; - std::string error; - - while (serverfd == -1) { - errno = 0; - serverfd = listen_func(addr, &error); - if (errno == EAFNOSUPPORT || errno == EINVAL || errno == EPROTONOSUPPORT) { - D("unrecoverable error: '%s'", error.c_str()); - return; - } else if (serverfd < 0) { - D("server: cannot bind socket yet: %s", error.c_str()); - std::this_thread::sleep_for(1s); - continue; - } - close_on_exec(serverfd.get()); - } - - while (true) { - D("server: trying to get new connection from fd %d", serverfd.get()); - unique_fd fd(adb_socket_accept(serverfd, nullptr, nullptr)); - if (fd >= 0) { - D("server: new connection on fd %d", fd.get()); - close_on_exec(fd.get()); - disable_tcp_nagle(fd.get()); - std::string serial = android::base::StringPrintf("host-%d", fd.get()); - // We don't care about port value in "register_socket_transport" as it is used - // only from ADB_HOST. "server_socket_thread" is never called from ADB_HOST. - register_socket_transport( - std::move(fd), std::move(serial), 0, 1, - [](atransport*) { return ReconnectResult::Abort; }, false); - } - } - D("transport: server_socket_thread() exiting"); -} - -#endif - -#if !ADB_HOST -unique_fd adb_listen(std::string_view addr, std::string* error) { - return unique_fd{socket_spec_listen(addr, error, nullptr)}; -} -#endif - void local_init(const std::string& addr) { -#if ADB_HOST D("transport: local client init"); std::thread(client_socket_thread, addr).detach(); adb_local_transport_max_port_env_override(); -#elif !defined(__ANDROID__) - // Host adbd. - D("transport: local server init"); - std::thread(server_socket_thread, adb_listen, addr).detach(); -#else - D("transport: local server init"); - // For the adbd daemon in the system image we need to distinguish - // between the device, and the emulator. - if (addr.starts_with("tcp:") && use_qemu_goldfish()) { - std::thread(qemu_socket_thread, addr).detach(); - } else { - std::thread(server_socket_thread, adb_listen, addr).detach(); - } -#endif // !ADB_HOST } -#if ADB_HOST struct EmulatorConnection : public FdConnection { EmulatorConnection(unique_fd fd, int local_port) : FdConnection(std::move(fd)), local_port_(local_port) {} @@ -336,7 +260,7 @@ struct EmulatorConnection : public FdConnection { /* Only call this function if you already hold local_transports_lock. */ static atransport* find_emulator_transport_by_adb_port_locked(int adb_port) - REQUIRES(local_transports_lock) { + REQUIRES(local_transports_lock) { auto it = local_transports.find(adb_port); if (it == local_transports.end()) { return nullptr; @@ -352,7 +276,6 @@ atransport* find_emulator_transport_by_adb_port(int adb_port) { atransport* find_emulator_transport_by_console_port(int console_port) { return find_transport(getEmulatorSerialString(console_port).c_str()); } -#endif std::string getEmulatorSerialString(int console_port) { return android::base::StringPrintf("emulator-%d", console_port); @@ -363,7 +286,6 @@ int init_socket_transport(atransport* t, unique_fd fd, int adb_port, int local) t->type = kTransportLocal; -#if ADB_HOST // Emulator connection. if (local) { auto emulator_connection = std::make_unique(std::move(fd), adb_port); @@ -380,7 +302,6 @@ int init_socket_transport(atransport* t, unique_fd fd, int adb_port, int local) return fail; } -#endif // Regular tcp connection. auto fd_connection = std::make_unique(std::move(fd)); diff --git a/adb/daemon/transport_local.cpp b/adb/daemon/transport_local.cpp new file mode 100644 index 000000000..9e0b88737 --- /dev/null +++ b/adb/daemon/transport_local.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TRACE_TAG TRANSPORT + +#include "sysdeps.h" +#include "transport.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !ADB_HOST +#include +#endif + +#include "adb.h" +#include "adb_io.h" +#include "adb_unique_fd.h" +#include "adb_utils.h" +#include "socket_spec.h" +#include "sysdeps/chrono.h" + +void server_socket_thread(std::function listen_func, + std::string_view addr) { + adb_thread_setname("server socket"); + + unique_fd serverfd; + std::string error; + + while (serverfd == -1) { + errno = 0; + serverfd = listen_func(addr, &error); + if (errno == EAFNOSUPPORT || errno == EINVAL || errno == EPROTONOSUPPORT) { + D("unrecoverable error: '%s'", error.c_str()); + return; + } else if (serverfd < 0) { + D("server: cannot bind socket yet: %s", error.c_str()); + std::this_thread::sleep_for(1s); + continue; + } + close_on_exec(serverfd.get()); + } + + while (true) { + D("server: trying to get new connection from fd %d", serverfd.get()); + unique_fd fd(adb_socket_accept(serverfd, nullptr, nullptr)); + if (fd >= 0) { + D("server: new connection on fd %d", fd.get()); + close_on_exec(fd.get()); + disable_tcp_nagle(fd.get()); + std::string serial = android::base::StringPrintf("host-%d", fd.get()); + // We don't care about port value in "register_socket_transport" as it is used + // only from ADB_HOST. "server_socket_thread" is never called from ADB_HOST. + register_socket_transport( + std::move(fd), std::move(serial), 0, 1, + [](atransport*) { return ReconnectResult::Abort; }, false); + } + } + D("transport: server_socket_thread() exiting"); +} + +unique_fd adb_listen(std::string_view addr, std::string* error) { + return unique_fd{socket_spec_listen(addr, error, nullptr)}; +} + +void local_init(const std::string& addr) { +#if !defined(__ANDROID__) + // Host adbd. + D("transport: local server init"); + std::thread(server_socket_thread, adb_listen, addr).detach(); +#else + D("transport: local server init"); + // For the adbd daemon in the system image we need to distinguish + // between the device, and the emulator. + if (addr.starts_with("tcp:") && use_qemu_goldfish()) { + std::thread(qemu_socket_thread, addr).detach(); + } else { + std::thread(server_socket_thread, adb_listen, addr).detach(); + } +#endif // !ADB_HOST +} + +int init_socket_transport(atransport* t, unique_fd fd, int adb_port, int local) { + t->type = kTransportLocal; + auto fd_connection = std::make_unique(std::move(fd)); + t->SetConnection(std::make_unique(std::move(fd_connection))); + return 0; +} From d5d5ba1644eabc64a449e73aad9fc50d186ef508 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Wed, 22 Apr 2020 17:33:00 -0700 Subject: [PATCH 2/3] adbd: don't use libc++_static. We have dependencies that use libc++_shared, which results in ODR violation manifesting as host adbd crashing on launch in libc++ locale initialization. Test: adbd on host Change-Id: I6c039b325308fb8c36dfe5c1d090ff4ebe9e3433 --- adb/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/adb/Android.bp b/adb/Android.bp index d6bc47e16..432770cd4 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -593,7 +593,6 @@ cc_library { cc_binary { name: "adbd", defaults: ["adbd_defaults", "host_adbd_supported", "libadbd_binary_dependencies"], - stl: "libc++_static", recovery_available: true, apex_available: ["com.android.adbd"], From 0e778dc79400d32c990da68f192681c0c8b94461 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Wed, 22 Apr 2020 17:33:25 -0700 Subject: [PATCH 3/3] adb: allow filtering by file in coverage/show.sh. Test: ./coverage.sh transport.cpp Change-Id: I5fd3b25d9b3edd7a9131dae902e1868ced0384cc --- adb/coverage/show.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/adb/coverage/show.sh b/adb/coverage/show.sh index 7ea7949ef..3b2faa304 100755 --- a/adb/coverage/show.sh +++ b/adb/coverage/show.sh @@ -5,8 +5,18 @@ set -euxo pipefail OUTPUT_DIR=$(realpath $(dirname "$0")) . "$OUTPUT_DIR"/include.sh +BASE_PATH=/proc/self/cwd/system/core/adb +PATHS="" +if [[ $# == 0 ]]; then + PATHS=$BASE_PATH +else + for arg in "$@"; do + PATHS="$PATHS $BASE_PATH/$arg" + done +fi + cd $ANDROID_BUILD_TOP llvm-cov show --instr-profile="$OUTPUT_DIR"/adbd.profdata \ $ANDROID_PRODUCT_OUT/apex/com.android.adbd/bin/adbd \ - /proc/self/cwd/system/core/adb \ + $PATHS \ $ADB_TEST_BINARIES