diff --git a/adb/Android.bp b/adb/Android.bp index 36bfad433..8199fff10 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -22,35 +22,16 @@ cc_defaults { "-Wexit-time-destructors", "-Wno-unused-parameter", "-Wno-missing-field-initializers", + "-Wthread-safety", "-Wvla", + "-DADB_HOST=1", // overridden by adbd_defaults ], cpp_std: "experimental", use_version_lib: true, - compile_multilib: "first", - product_variables: { - debuggable: { - cflags: [ - "-DALLOW_ADBD_ROOT", - "-DALLOW_ADBD_DISABLE_VERITY", - "-DALLOW_ADBD_NO_AUTH", - ], - }, - }, target: { - android: { - cflags: [ - "-DADB_HOST=0", - "-Wthread-safety", - ], - }, - - host: { - cflags: ["-DADB_HOST=1"], - }, - darwin: { host_ldlibs: [ "-lpthread", @@ -76,6 +57,9 @@ cc_defaults { // MinGW hides some things behind _POSIX_SOURCE. "-D_POSIX_SOURCE", + + // Not supported yet. + "-Wno-thread-safety", ], host_ldlibs: [ @@ -84,15 +68,46 @@ cc_defaults { "-luserenv", ], }, + }, +} - not_windows: { +cc_defaults { + name: "adbd_defaults", + defaults: ["adb_defaults"], + + cflags: ["-UADB_HOST", "-DADB_HOST=0"], + product_variables: { + debuggable: { cflags: [ - "-Wthread-safety", + "-DALLOW_ADBD_ROOT", + "-DALLOW_ADBD_DISABLE_VERITY", + "-DALLOW_ADBD_NO_AUTH", ], }, }, } +cc_defaults { + name: "host_adbd_supported", + + host_supported: true, + target: { + linux: { + enabled: true, + host_ldlibs: [ + "-lresolv", // b64_pton + "-lutil", // forkpty + ], + }, + darwin: { + enabled: false, + }, + windows: { + enabled: false, + }, + }, +} + // libadb // ========================================================= // These files are compiled for both the host and the device. @@ -313,7 +328,7 @@ cc_binary_host { // libadbd_core contains the common sources to build libadbd and libadbd_services. cc_library_static { name: "libadbd_core", - defaults: ["adb_defaults"], + defaults: ["adbd_defaults", "host_adbd_supported"], recovery_available: true, // libminadbd wants both, as it's used to build native tests. @@ -322,9 +337,6 @@ cc_library_static { srcs: libadb_srcs + libadb_posix_srcs + [ "daemon/auth.cpp", "daemon/jdwp_service.cpp", - "daemon/usb.cpp", - "daemon/usb_ffs.cpp", - "daemon/usb_legacy.cpp", ], local_include_dirs: [ @@ -335,7 +347,6 @@ cc_library_static { static_libs: [ "libdiagnose_usb", - "libqemu_pipe", ], shared_libs: [ @@ -346,22 +357,36 @@ cc_library_static { "libcutils", "liblog", ], + + target: { + android: { + whole_static_libs: [ + "libqemu_pipe", + ], + srcs: [ + "daemon/transport_qemu.cpp", + "daemon/usb.cpp", + "daemon/usb_ffs.cpp", + "daemon/usb_legacy.cpp", + ] + }, + linux_glibc: { + srcs: [ + "daemon/usb_dummy.cpp", + ] + } + }, } cc_library { name: "libadbd_services", - defaults: ["adb_defaults"], + defaults: ["adbd_defaults", "host_adbd_supported"], recovery_available: true, compile_multilib: "both", srcs: [ - "daemon/abb_service.cpp", "daemon/file_sync_service.cpp", - "daemon/framebuffer_service.cpp", - "daemon/mdns.cpp", - "daemon/remount_service.cpp", "daemon/services.cpp", - "daemon/set_verity_enable_state_service.cpp", "daemon/shell_service.cpp", "shell_service_protocol.cpp", ], @@ -373,27 +398,41 @@ cc_library { static_libs: [ "libadbd_core", - "libavb_user", "libdiagnose_usb", - "libqemu_pipe", ], shared_libs: [ "libasyncio", "libbase", - "libbootloader_message", "libcrypto", "libcrypto_utils", "libcutils", - "libext4_utils", - "libfec", - "libfs_mgr", "liblog", - "libmdnssd", - "libselinux", ], target: { + android: { + srcs: [ + "daemon/abb_service.cpp", + "daemon/framebuffer_service.cpp", + "daemon/mdns.cpp", + "daemon/reboot_service.cpp", + "daemon/remount_service.cpp", + "daemon/restart_service.cpp", + "daemon/set_verity_enable_state_service.cpp", + ], + static_libs: [ + "libavb_user", + ], + shared_libs: [ + "libbootloader_message", + "libmdnssd", + "libext4_utils", + "libfec", + "libfs_mgr", + "libselinux", + ], + }, recovery: { exclude_srcs: [ "daemon/abb_service.cpp", @@ -404,7 +443,7 @@ cc_library { cc_library { name: "libadbd", - defaults: ["adb_defaults"], + defaults: ["adbd_defaults", "host_adbd_supported"], recovery_available: true, // Avoid getting duplicate symbol of android::build::GetBuildNumber(). @@ -435,7 +474,7 @@ cc_library { cc_binary { name: "adbd", - defaults: ["adb_defaults"], + defaults: ["adbd_defaults", "host_adbd_supported"], recovery_available: true, srcs: [ @@ -467,7 +506,7 @@ cc_binary { cc_binary { name: "abb", - defaults: ["adb_defaults"], + defaults: ["adbd_defaults"], recovery_available: false, srcs: [ @@ -500,7 +539,7 @@ cc_binary { cc_test { name: "adbd_test", - defaults: ["adb_defaults"], + defaults: ["adbd_defaults"], srcs: libadb_test_srcs + [ "daemon/services.cpp", "daemon/shell_service.cpp", diff --git a/adb/adb_trace.cpp b/adb/adb_trace.cpp index 2bd6a3ea1..80f146c3f 100644 --- a/adb/adb_trace.cpp +++ b/adb/adb_trace.cpp @@ -32,7 +32,9 @@ #if !ADB_HOST const char* adb_device_banner = "device"; +#if defined(__ANDROID__) static android::base::LogdLogger gLogdLogger; +#endif #else const char* adb_device_banner = "host"; #endif @@ -46,7 +48,7 @@ void AdbLogger(android::base::LogId id, android::base::LogSeverity severity, fflush(stderr); #endif -#if !ADB_HOST +#if !ADB_HOST && defined(__ANDROID__) // Only print logs of INFO or higher to logcat, so that `adb logcat` with adbd tracing on // doesn't result in exponential logging. if (severity >= android::base::INFO) { diff --git a/adb/daemon/auth.cpp b/adb/daemon/auth.cpp index 180df8f21..1800f84b9 100644 --- a/adb/daemon/auth.cpp +++ b/adb/daemon/auth.cpp @@ -67,7 +67,7 @@ bool adbd_auth_verify(const char* token, size_t token_size, const std::string& s // b64_pton requires one additional byte in the target buffer for // decoding to succeed. See http://b/28035006 for details. uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1]; - if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) { + if (b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) { LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path; continue; } diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp index d55096aa8..62c18c57d 100644 --- a/adb/daemon/file_sync_service.cpp +++ b/adb/daemon/file_sync_service.cpp @@ -22,13 +22,11 @@ #include #include -#include #include #include #include #include #include -#include #include #include @@ -37,11 +35,17 @@ #include #include +#include #include #include + #include #include + +#if defined(__ANDROID__) #include +#include +#endif #include "adb.h" #include "adb_io.h" @@ -55,11 +59,17 @@ using android::base::Dirname; using android::base::StringPrintf; static bool should_use_fs_config(const std::string& path) { +#if defined(__ANDROID__) // TODO: use fs_config to configure permissions on /data too. return !android::base::StartsWith(path, "/data/"); +#else + UNUSED(path); + return false; +#endif } static bool update_capabilities(const char* path, uint64_t capabilities) { +#if defined(__ANDROID__) if (capabilities == 0) { // Ensure we clean up in case the capabilities weren't 0 in the past. removexattr(path, XATTR_NAME_CAPS); @@ -73,6 +83,10 @@ static bool update_capabilities(const char* path, uint64_t capabilities) { cap_data.data[1].permitted = (capabilities >> 32); cap_data.data[1].inheritable = 0; return setxattr(path, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) != -1; +#else + UNUSED(path, capabilities); + return true; +#endif } static bool secure_mkdirs(const std::string& path) { @@ -105,8 +119,10 @@ static bool secure_mkdirs(const std::string& path) { } else { if (chown(partial_path.c_str(), uid, gid) == -1) return false; +#if defined(__ANDROID__) // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(partial_path.c_str(), 0); +#endif if (!update_capabilities(partial_path.c_str(), capabilities)) return false; } @@ -242,8 +258,10 @@ static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, uint goto fail; } +#if defined(__ANDROID__) // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(path, 0); +#endif // fchown clears the setuid bit - restore it if present. // Ignore the result of calling fchmod. It's not supported diff --git a/adb/daemon/framebuffer_service.h b/adb/daemon/framebuffer_service.h index 264da597e..bab44be36 100644 --- a/adb/daemon/framebuffer_service.h +++ b/adb/daemon/framebuffer_service.h @@ -18,4 +18,6 @@ #include "adb_unique_fd.h" +#if defined(__ANDROID__) void framebuffer_service(unique_fd fd); +#endif diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp index f6f1acc31..fce3a4fb5 100644 --- a/adb/daemon/main.cpp +++ b/adb/daemon/main.cpp @@ -18,7 +18,10 @@ #include "sysdeps.h" +#if defined(__BIONIC__) #include +#endif + #include #include #include @@ -34,12 +37,15 @@ #include #include #include + +#if defined(__ANDROID__) #include #include #include #include #include "selinux/android.h" +#endif #include "adb.h" #include "adb_auth.h" @@ -49,6 +55,7 @@ #include "mdns.h" +#if defined(__ANDROID__) static const char* root_seclabel = nullptr; static bool should_drop_capabilities_bounding_set() { @@ -167,10 +174,14 @@ static void drop_privileges(int server_port) { } } } +#endif static void setup_port(int port) { + LOG(INFO) << "adbd listening on port " << port; local_init(port); +#if defined(__ANDROID__) setup_mdns(port); +#endif } int adbd_main(int server_port) { @@ -178,10 +189,12 @@ int adbd_main(int server_port) { signal(SIGPIPE, SIG_IGN); +#if defined(__BIONIC__) auto fdsan_level = android_fdsan_get_error_level(); if (fdsan_level == ANDROID_FDSAN_ERROR_LEVEL_DISABLED) { android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE); } +#endif init_transport_registration(); @@ -206,14 +219,19 @@ int adbd_main(int server_port) { " unchanged.\n"); } +#if defined(__ANDROID__) drop_privileges(server_port); +#endif bool is_usb = false; + +#if defined(__ANDROID__) if (access(USB_FFS_ADB_EP0, F_OK) == 0) { // Listen on USB. usb_init(); is_usb = true; } +#endif // If one of these properties is set, also listen on that port. // If one of the properties isn't set and we couldn't listen on usb, listen @@ -244,8 +262,10 @@ int adbd_main(int server_port) { } int main(int argc, char** argv) { +#if defined(__BIONIC__) // Set M_DECAY_TIME so that our allocations aren't immediately purged on free. mallopt(M_DECAY_TIME, 1); +#endif while (true) { static struct option opts[] = { @@ -261,19 +281,21 @@ int main(int argc, char** argv) { } switch (c) { - case 's': - root_seclabel = optarg; - break; - case 'b': - adb_device_banner = optarg; - break; - case 'v': - printf("Android Debug Bridge Daemon version %d.%d.%d\n", ADB_VERSION_MAJOR, - ADB_VERSION_MINOR, ADB_SERVER_VERSION); - return 0; - default: - // getopt already prints "adbd: invalid option -- %c" for us. - return 1; +#if defined(__ANDROID__) + case 's': + root_seclabel = optarg; + break; +#endif + case 'b': + adb_device_banner = optarg; + break; + case 'v': + printf("Android Debug Bridge Daemon version %d.%d.%d\n", ADB_VERSION_MAJOR, + ADB_VERSION_MINOR, ADB_SERVER_VERSION); + return 0; + default: + // getopt already prints "adbd: invalid option -- %c" for us. + return 1; } } diff --git a/adb/daemon/reboot_service.cpp b/adb/daemon/reboot_service.cpp new file mode 100644 index 000000000..a5a11b866 --- /dev/null +++ b/adb/daemon/reboot_service.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 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 SERVICES + +#include "sysdeps.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "adb_io.h" +#include "adb_unique_fd.h" + +void reboot_service(unique_fd fd, const std::string& arg) { + std::string reboot_arg = arg; + sync(); + + if (reboot_arg.empty()) reboot_arg = "adb"; + std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str()); + + if (reboot_arg == "fastboot" && + android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) && + access("/dev/socket/recovery", F_OK) == 0) { + LOG(INFO) << "Recovery specific reboot fastboot"; + /* + * The socket is created to allow switching between recovery and + * fastboot. + */ + android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0)); + if (sock < 0) { + WriteFdFmt(fd, "reboot (%s) create\n", strerror(errno)); + PLOG(ERROR) << "Creating recovery socket failed"; + return; + } + + sockaddr_un addr = {.sun_family = AF_UNIX}; + strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1); + if (connect(sock, reinterpret_cast(&addr), sizeof(addr)) == -1) { + WriteFdFmt(fd, "reboot (%s) connect\n", strerror(errno)); + PLOG(ERROR) << "Couldn't connect to recovery socket"; + return; + } + const char msg_switch_to_fastboot = 'f'; + auto ret = adb_write(sock, &msg_switch_to_fastboot, sizeof(msg_switch_to_fastboot)); + if (ret != sizeof(msg_switch_to_fastboot)) { + WriteFdFmt(fd, "reboot (%s) write\n", strerror(errno)); + PLOG(ERROR) << "Couldn't write message to recovery socket to switch to fastboot"; + return; + } + } else { + if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) { + WriteFdFmt(fd.get(), "reboot (%s) failed\n", reboot_string.c_str()); + return; + } + } + // Don't return early. Give the reboot command time to take effect + // to avoid messing up scripts which do "adb reboot && adb wait-for-device" + while (true) { + pause(); + } +} diff --git a/adb/daemon/reboot_service.h b/adb/daemon/reboot_service.h new file mode 100644 index 000000000..f68913e83 --- /dev/null +++ b/adb/daemon/reboot_service.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 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 + +#include "adb_unique_fd.h" + +#if defined(__ANDROID__) +void reboot_service(unique_fd fd, const std::string& arg); +#endif diff --git a/adb/daemon/remount_service.h b/adb/daemon/remount_service.h index e4e2550d4..c84740315 100644 --- a/adb/daemon/remount_service.h +++ b/adb/daemon/remount_service.h @@ -20,5 +20,7 @@ #include "adb_unique_fd.h" +#if defined(__ANDROID__) bool make_block_device_writable(const std::string&); void remount_service(unique_fd, const std::string&); +#endif diff --git a/adb/daemon/restart_service.cpp b/adb/daemon/restart_service.cpp new file mode 100644 index 000000000..6803d93d7 --- /dev/null +++ b/adb/daemon/restart_service.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#define TRACE_TAG SERVICES + +#include "sysdeps.h" + +#include + +#include +#include +#include + +#include "adb_io.h" +#include "adb_unique_fd.h" + +void restart_root_service(unique_fd fd) { + if (getuid() == 0) { + WriteFdExactly(fd.get(), "adbd is already running as root\n"); + return; + } + if (!__android_log_is_debuggable()) { + WriteFdExactly(fd.get(), "adbd cannot run as root in production builds\n"); + return; + } + + android::base::SetProperty("service.adb.root", "1"); + WriteFdExactly(fd.get(), "restarting adbd as root\n"); +} + +void restart_unroot_service(unique_fd fd) { + if (getuid() != 0) { + WriteFdExactly(fd.get(), "adbd not running as root\n"); + return; + } + android::base::SetProperty("service.adb.root", "0"); + WriteFdExactly(fd.get(), "restarting adbd as non root\n"); +} + +void restart_tcp_service(unique_fd fd, int port) { + if (port <= 0) { + WriteFdFmt(fd.get(), "invalid port %d\n", port); + return; + } + + android::base::SetProperty("service.adb.tcp.port", android::base::StringPrintf("%d", port)); + WriteFdFmt(fd.get(), "restarting in TCP mode port: %d\n", port); +} + +void restart_usb_service(unique_fd fd) { + android::base::SetProperty("service.adb.tcp.port", "0"); + WriteFdExactly(fd.get(), "restarting in USB mode\n"); +} diff --git a/adb/daemon/restart_service.h b/adb/daemon/restart_service.h new file mode 100644 index 000000000..19840bd58 --- /dev/null +++ b/adb/daemon/restart_service.h @@ -0,0 +1,26 @@ +/* + * 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. + */ + +#pragma once + +#include "adb_unique_fd.h" + +#if defined(__ANDROID__) +void restart_root_service(unique_fd fd); +void restart_unroot_service(unique_fd fd); +void restart_tcp_service(unique_fd fd, int port); +void restart_usb_service(unique_fd fd); +#endif diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp index 5ae210f7c..d1f034507 100644 --- a/adb/daemon/services.cpp +++ b/adb/daemon/services.cpp @@ -39,8 +39,6 @@ #include #include #include -#include -#include #include #include @@ -55,96 +53,12 @@ #include "daemon/file_sync_service.h" #include "daemon/framebuffer_service.h" +#include "daemon/reboot_service.h" #include "daemon/remount_service.h" +#include "daemon/restart_service.h" #include "daemon/set_verity_enable_state_service.h" #include "daemon/shell_service.h" -void restart_root_service(unique_fd fd) { - if (getuid() == 0) { - WriteFdExactly(fd.get(), "adbd is already running as root\n"); - return; - } - if (!__android_log_is_debuggable()) { - WriteFdExactly(fd.get(), "adbd cannot run as root in production builds\n"); - return; - } - - android::base::SetProperty("service.adb.root", "1"); - WriteFdExactly(fd.get(), "restarting adbd as root\n"); -} - -void restart_unroot_service(unique_fd fd) { - if (getuid() != 0) { - WriteFdExactly(fd.get(), "adbd not running as root\n"); - return; - } - android::base::SetProperty("service.adb.root", "0"); - WriteFdExactly(fd.get(), "restarting adbd as non root\n"); -} - -void restart_tcp_service(unique_fd fd, int port) { - if (port <= 0) { - WriteFdFmt(fd.get(), "invalid port %d\n", port); - return; - } - - android::base::SetProperty("service.adb.tcp.port", android::base::StringPrintf("%d", port)); - WriteFdFmt(fd.get(), "restarting in TCP mode port: %d\n", port); -} - -void restart_usb_service(unique_fd fd) { - android::base::SetProperty("service.adb.tcp.port", "0"); - WriteFdExactly(fd.get(), "restarting in USB mode\n"); -} - -void reboot_service(unique_fd fd, const std::string& arg) { - std::string reboot_arg = arg; - sync(); - - if (reboot_arg.empty()) reboot_arg = "adb"; - std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str()); - - if (reboot_arg == "fastboot" && - android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) && - access("/dev/socket/recovery", F_OK) == 0) { - LOG(INFO) << "Recovery specific reboot fastboot"; - /* - * The socket is created to allow switching between recovery and - * fastboot. - */ - android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0)); - if (sock < 0) { - WriteFdFmt(fd, "reboot (%s) create\n", strerror(errno)); - PLOG(ERROR) << "Creating recovery socket failed"; - return; - } - - sockaddr_un addr = {.sun_family = AF_UNIX}; - strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1); - if (connect(sock, reinterpret_cast(&addr), sizeof(addr)) == -1) { - WriteFdFmt(fd, "reboot (%s) connect\n", strerror(errno)); - PLOG(ERROR) << "Couldn't connect to recovery socket"; - return; - } - const char msg_switch_to_fastboot = 'f'; - auto ret = adb_write(sock, &msg_switch_to_fastboot, sizeof(msg_switch_to_fastboot)); - if (ret != sizeof(msg_switch_to_fastboot)) { - WriteFdFmt(fd, "reboot (%s) write\n", strerror(errno)); - PLOG(ERROR) << "Couldn't write message to recovery socket to switch to fastboot"; - return; - } - } else { - if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) { - WriteFdFmt(fd.get(), "reboot (%s) failed\n", reboot_string.c_str()); - return; - } - } - // Don't return early. Give the reboot command time to take effect - // to avoid messing up scripts which do "adb reboot && adb wait-for-device" - while (true) { - pause(); - } -} void reconnect_service(unique_fd fd, atransport* t) { WriteFdExactly(fd.get(), "done"); @@ -221,7 +135,8 @@ static void spin_service(unique_fd fd) { } fdevent_run_on_main_thread([fd = pipe_read.release()]() { - fdevent* fde = fdevent_create(fd, [](int, unsigned, void*) {}, nullptr); + fdevent* fde = fdevent_create( + fd, [](int, unsigned, void*) {}, nullptr); fdevent_add(fde, FDE_READ); }); @@ -328,31 +243,16 @@ asocket* daemon_service_to_socket(std::string_view name) { } unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) { -#ifndef __ANDROID_RECOVERY__ +#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) if (name.starts_with("abb:")) { name.remove_prefix(strlen("abb:")); return execute_binder_command(name); } #endif - if (name.starts_with("dev:")) { - name.remove_prefix(strlen("dev:")); - return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)}; - } else if (name.starts_with("framebuffer:")) { +#if defined(__ANDROID__) + if (name.starts_with("framebuffer:")) { return create_service_thread("fb", framebuffer_service); - } else if (name.starts_with("jdwp:")) { - name.remove_prefix(strlen("jdwp:")); - std::string str(name); - return create_jdwp_connection_fd(atoi(str.c_str())); - } else if (name.starts_with("shell")) { - name.remove_prefix(strlen("shell")); - return ShellService(name, transport); - } else if (name.starts_with("exec:")) { - name.remove_prefix(strlen("exec:")); - return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw, - SubprocessProtocol::kNone); - } else if (name.starts_with("sync:")) { - return create_service_thread("sync", file_sync_service); } else if (name.starts_with("remount:")) { std::string arg(name.begin() + strlen("remount:"), name.end()); return create_service_thread("remount", @@ -373,6 +273,12 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) { } else if (name.starts_with("restore:")) { return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone); + } else if (name.starts_with("disable-verity:")) { + return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service, + std::placeholders::_1, false)); + } else if (name.starts_with("enable-verity:")) { + return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service, + std::placeholders::_1, true)); } else if (name.starts_with("tcpip:")) { name.remove_prefix(strlen("tcpip:")); std::string str(name); @@ -385,15 +291,28 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) { std::bind(restart_tcp_service, std::placeholders::_1, port)); } else if (name.starts_with("usb:")) { return create_service_thread("usb", restart_usb_service); + } +#endif + + if (name.starts_with("dev:")) { + name.remove_prefix(strlen("dev:")); + return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)}; + } else if (name.starts_with("jdwp:")) { + name.remove_prefix(strlen("jdwp:")); + std::string str(name); + return create_jdwp_connection_fd(atoi(str.c_str())); + } else if (name.starts_with("shell")) { + name.remove_prefix(strlen("shell")); + return ShellService(name, transport); + } else if (name.starts_with("exec:")) { + name.remove_prefix(strlen("exec:")); + return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw, + SubprocessProtocol::kNone); + } else if (name.starts_with("sync:")) { + return create_service_thread("sync", file_sync_service); } else if (name.starts_with("reverse:")) { name.remove_prefix(strlen("reverse:")); return reverse_service(name, transport); - } else if (name.starts_with("disable-verity:")) { - return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service, - std::placeholders::_1, false)); - } else if (name.starts_with("enable-verity:")) { - return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service, - std::placeholders::_1, true)); } else if (name == "reconnect") { return create_service_thread( "reconnect", std::bind(reconnect_service, std::placeholders::_1, transport)); diff --git a/adb/daemon/set_verity_enable_state_service.h b/adb/daemon/set_verity_enable_state_service.h index c1413c8e0..c0ed98e87 100644 --- a/adb/daemon/set_verity_enable_state_service.h +++ b/adb/daemon/set_verity_enable_state_service.h @@ -18,4 +18,6 @@ #include "adb_unique_fd.h" +#if defined(__ANDROID__) void set_verity_enabled_state_service(unique_fd fd, bool enable); +#endif diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp index 455595f66..0794bcdae 100644 --- a/adb/daemon/shell_service.cpp +++ b/adb/daemon/shell_service.cpp @@ -98,7 +98,10 @@ #include #include #include + +#if defined(__ANDROID__) #include +#endif #include "adb.h" #include "adb_io.h" diff --git a/adb/daemon/transport_qemu.cpp b/adb/daemon/transport_qemu.cpp new file mode 100644 index 000000000..8ad25729a --- /dev/null +++ b/adb/daemon/transport_qemu.cpp @@ -0,0 +1,136 @@ +/* + * 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 qemu_pipe.h before sysdeps, since it has inlined references to open, read, write. +#include + +#define TRACE_TAG TRANSPORT +#include "sysdeps.h" +#include "transport.h" + +#include + +#include "adb_io.h" +#include "adb_trace.h" +#include "adb_unique_fd.h" + +/* A worker thread that monitors host connections, and registers a transport for + * every new host connection. This thread replaces server_socket_thread on + * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD + * pipe to communicate with adbd daemon inside the guest. This is done in order + * to provide more robust communication channel between ADB host and guest. The + * main issue with server_socket_thread approach is that it runs on top of TCP, + * and thus is sensitive to network disruptions. For instance, the + * ConnectionManager may decide to reset all network connections, in which case + * the connection between ADB host and guest will be lost. To make ADB traffic + * independent from the network, we use here 'adb' QEMUD service to transfer data + * between the host, and the guest. See external/qemu/android/adb-*.* that + * implements the emulator's side of the protocol. Another advantage of using + * QEMUD approach is that ADB will be up much sooner, since it doesn't depend + * anymore on network being set up. + * The guest side of the protocol contains the following phases: + * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service + * is opened, and it becomes clear whether or not emulator supports that + * protocol. + * - Wait for the ADB host to create connection with the guest. This is done by + * sending an 'accept' request to the adb QEMUD service, and waiting on + * response. + * - When new ADB host connection is accepted, the connection with adb QEMUD + * service is registered as the transport, and a 'start' request is sent to the + * adb QEMUD service, indicating that the guest is ready to receive messages. + * Note that the guest will ignore messages sent down from the emulator before + * the transport registration is completed. That's why we need to send the + * 'start' request after the transport is registered. + */ +void qemu_socket_thread(int port) { + /* 'accept' request to the adb QEMUD service. */ + static const char _accept_req[] = "accept"; + /* 'start' request to the adb QEMUD service. */ + static const char _start_req[] = "start"; + /* 'ok' reply from the adb QEMUD service. */ + static const char _ok_resp[] = "ok"; + + char tmp[256]; + char con_name[32]; + + adb_thread_setname("qemu socket"); + D("transport: qemu_socket_thread() starting"); + + /* adb QEMUD service connection request. */ + snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port); + + /* Connect to the adb QEMUD service. */ + unique_fd fd(qemu_pipe_open(con_name)); + if (fd < 0) { + /* This could be an older version of the emulator, that doesn't + * implement adb QEMUD service. Fall back to the old TCP way. */ + D("adb service is not available. Falling back to TCP socket."); + std::thread(server_socket_thread, port).detach(); + return; + } + + while (true) { + /* + * Wait till the host creates a new connection. + */ + + /* Send the 'accept' request. */ + if (WriteFdExactly(fd.get(), _accept_req, strlen(_accept_req))) { + /* Wait for the response. In the response we expect 'ok' on success, + * or 'ko' on failure. */ + if (!ReadFdExactly(fd.get(), tmp, 2) || memcmp(tmp, _ok_resp, 2)) { + D("Accepting ADB host connection has failed."); + } else { + /* Host is connected. Register the transport, and start the + * exchange. */ + std::string serial = android::base::StringPrintf("host-%d", fd.get()); + WriteFdExactly(fd.get(), _start_req, strlen(_start_req)); + register_socket_transport(std::move(fd), std::move(serial), port, 1, + [](atransport*) { return ReconnectResult::Abort; }); + } + + /* Prepare for accepting of the next ADB host connection. */ + fd.reset(qemu_pipe_open(con_name)); + if (fd < 0) { + D("adb service become unavailable."); + return; + } + } else { + D("Unable to send the '%s' request to ADB service.", _accept_req); + return; + } + } + D("transport: qemu_socket_thread() exiting"); + return; +} + +// If adbd is running inside the emulator, it will normally use QEMUD pipe (aka +// goldfish) as the transport. This can either be explicitly set by the +// service.adb.transport property, or be inferred from ro.kernel.qemu that is +// set to "1" for ranchu/goldfish. +bool use_qemu_goldfish() { + // Legacy way to detect if adbd should use the goldfish pipe is to check for + // ro.kernel.qemu, keep that behaviour for backward compatibility. + if (android::base::GetBoolProperty("ro.kernel.qemu", false)) { + return true; + } + // If service.adb.transport is present and is set to "goldfish", use the + // QEMUD pipe. + if (android::base::GetProperty("service.adb.transport", "") == "goldfish") { + return true; + } + return false; +} diff --git a/adb/daemon/usb_dummy.cpp b/adb/daemon/usb_dummy.cpp new file mode 100644 index 000000000..984bc25ef --- /dev/null +++ b/adb/daemon/usb_dummy.cpp @@ -0,0 +1,38 @@ +/* + * 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 + +#include + +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_kick(usb_handle*) { + LOG(FATAL) << "unimplemented"; +} diff --git a/adb/transport.h b/adb/transport.h index 6f53e6ec3..3baeb1cf7 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -399,4 +399,14 @@ void send_packet(apacket* p, atransport* t); asocket* create_device_tracker(bool long_output); +#if !ADB_HOST +void server_socket_thread(int port); + +#if defined(__ANDROID__) +void qemu_socket_thread(int port); +bool use_qemu_goldfish(); +#endif + +#endif + #endif /* __TRANSPORT_H */ diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp index b384085c7..8885db489 100644 --- a/adb/transport_local.cpp +++ b/adb/transport_local.cpp @@ -229,9 +229,9 @@ static void client_socket_thread(int) { } } -#else // ADB_HOST +#else // !ADB_HOST -static void server_socket_thread(int port) { +void server_socket_thread(int port) { unique_fd serverfd; adb_thread_setname("server socket"); @@ -263,143 +263,19 @@ static void server_socket_thread(int port) { D("transport: server_socket_thread() exiting"); } -/* This is relevant only for ADB daemon running inside the emulator. */ -/* - * Redefine open and write for qemu_pipe.h that contains inlined references - * to those routines. We will redefine them back after qemu_pipe.h inclusion. - */ -#undef open -#undef read -#undef write -#define open adb_open -#define read adb_read -#define write adb_write -#include -#undef open -#undef read -#undef write -#define open ___xxx_open -#define read ___xxx_read -#define write ___xxx_write +#endif -/* A worker thread that monitors host connections, and registers a transport for - * every new host connection. This thread replaces server_socket_thread on - * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD - * pipe to communicate with adbd daemon inside the guest. This is done in order - * to provide more robust communication channel between ADB host and guest. The - * main issue with server_socket_thread approach is that it runs on top of TCP, - * and thus is sensitive to network disruptions. For instance, the - * ConnectionManager may decide to reset all network connections, in which case - * the connection between ADB host and guest will be lost. To make ADB traffic - * independent from the network, we use here 'adb' QEMUD service to transfer data - * between the host, and the guest. See external/qemu/android/adb-*.* that - * implements the emulator's side of the protocol. Another advantage of using - * QEMUD approach is that ADB will be up much sooner, since it doesn't depend - * anymore on network being set up. - * The guest side of the protocol contains the following phases: - * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service - * is opened, and it becomes clear whether or not emulator supports that - * protocol. - * - Wait for the ADB host to create connection with the guest. This is done by - * sending an 'accept' request to the adb QEMUD service, and waiting on - * response. - * - When new ADB host connection is accepted, the connection with adb QEMUD - * service is registered as the transport, and a 'start' request is sent to the - * adb QEMUD service, indicating that the guest is ready to receive messages. - * Note that the guest will ignore messages sent down from the emulator before - * the transport registration is completed. That's why we need to send the - * 'start' request after the transport is registered. - */ -static void qemu_socket_thread(int port) { - /* 'accept' request to the adb QEMUD service. */ - static const char _accept_req[] = "accept"; - /* 'start' request to the adb QEMUD service. */ - static const char _start_req[] = "start"; - /* 'ok' reply from the adb QEMUD service. */ - static const char _ok_resp[] = "ok"; - - char tmp[256]; - char con_name[32]; - - adb_thread_setname("qemu socket"); - D("transport: qemu_socket_thread() starting"); - - /* adb QEMUD service connection request. */ - snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port); - - /* Connect to the adb QEMUD service. */ - unique_fd fd(qemu_pipe_open(con_name)); - if (fd < 0) { - /* This could be an older version of the emulator, that doesn't - * implement adb QEMUD service. Fall back to the old TCP way. */ - D("adb service is not available. Falling back to TCP socket."); - std::thread(server_socket_thread, port).detach(); - return; - } - - while (true) { - /* - * Wait till the host creates a new connection. - */ - - /* Send the 'accept' request. */ - if (WriteFdExactly(fd.get(), _accept_req, strlen(_accept_req))) { - /* Wait for the response. In the response we expect 'ok' on success, - * or 'ko' on failure. */ - if (!ReadFdExactly(fd.get(), tmp, 2) || memcmp(tmp, _ok_resp, 2)) { - D("Accepting ADB host connection has failed."); - } else { - /* Host is connected. Register the transport, and start the - * exchange. */ - std::string serial = android::base::StringPrintf("host-%d", fd.get()); - WriteFdExactly(fd.get(), _start_req, strlen(_start_req)); - register_socket_transport(std::move(fd), std::move(serial), port, 1, - [](atransport*) { return ReconnectResult::Abort; }); - } - - /* Prepare for accepting of the next ADB host connection. */ - fd.reset(qemu_pipe_open(con_name)); - if (fd < 0) { - D("adb service become unavailable."); - return; - } - } else { - D("Unable to send the '%s' request to ADB service.", _accept_req); - return; - } - } - D("transport: qemu_socket_thread() exiting"); - return; -} - -// If adbd is running inside the emulator, it will normally use QEMUD pipe (aka -// goldfish) as the transport. This can either be explicitly set by the -// service.adb.transport property, or be inferred from ro.kernel.qemu that is -// set to "1" for ranchu/goldfish. -static bool use_qemu_goldfish() { - // Legacy way to detect if adbd should use the goldfish pipe is to check for - // ro.kernel.qemu, keep that behaviour for backward compatibility. - if (android::base::GetBoolProperty("ro.kernel.qemu", false)) { - return true; - } - // If service.adb.transport is present and is set to "goldfish", use the - // QEMUD pipe. - if (android::base::GetProperty("service.adb.transport", "") == "goldfish") { - return true; - } - return false; -} - -#endif // !ADB_HOST - -void local_init(int port) -{ +void local_init(int port) { void (*func)(int); const char* debug_name = ""; #if ADB_HOST func = client_socket_thread; debug_name = "client"; +#elif !defined(__ANDROID__) + // Host adbd. + func = server_socket_thread; + debug_name = "server"; #else // For the adbd daemon in the system image we need to distinguish // between the device, and the emulator.