Revert "Revert "Support socket activation of adb server""

Test: actually build both device and client adb this time

This reverts commit c77904e3c5.

Change-Id: I8c2b8f24884ff36ff2460dab2500bad777100dfd
This commit is contained in:
Daniel Colascione 2019-11-13 17:49:37 -08:00
parent 9af7878ec5
commit 3ec7be7a84
5 changed files with 99 additions and 3 deletions

42
adb/SOCKET-ACTIVATION.txt Normal file
View file

@ -0,0 +1,42 @@
adb can be configured to work with systemd-style socket activation,
allowing the daemon to start automatically when the adb control port
is forwarded across a network. You need two files, placed in the usual
systemd service directories (e.g., ~/.config/systemd/user for a user
service).
adb.service:
--- START adb.service CUT HERE ---
[Unit]
Description=adb
After=adb.socket
Requires=adb.socket
[Service]
Type=simple
# FD 3 is part of the systemd interface
ExecStart=/path/to/adb server nodaemon -L acceptfd:3
--- END adb.service CUT HERE ---
--- START adb.socket CUT HERE ---
[Unit]
Description=adb
PartOf=adb.service
[Socket]
ListenStream=127.0.0.1:5037
Accept=no
[Install]
WantedBy=sockets.target
--- END adb.socket CUT HERE ---
After installing the adb service, the adb server will be started
automatically on any connection to 127.0.0.1:5037 (the default adb
control port), even after adb kill-server kills the server.
Other "superserver" launcher systems (like macOS launchd) can be
configured analogously. The important part is that adb be started with
"server" and "nodaemon" command line arguments and that the listen
address (passed to -L) name a file descriptor that's ready to
accept(2) connections and that's already bound to the desired address
and listening. inetd-style pre-accepted sockets do _not_ work in this
configuration: the file descriptor passed to acceptfd must be the
serve socket, not the accepted connection socket.

View file

@ -222,7 +222,7 @@ std::optional<std::string> adb_get_server_executable_path() {
int port;
std::string error;
if (!parse_tcp_socket_spec(__adb_server_socket_spec, nullptr, &port, nullptr, &error)) {
LOG(FATAL) << "failed to parse server socket spec: " << error;
return {};
}
return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adb." + std::to_string(port);

View file

@ -107,6 +107,7 @@ static void help() {
" localfilesystem:<unix domain socket name>\n"
" dev:<character device name>\n"
" jdwp:<process pid> (remote only)\n"
" acceptfd:<fd> (listen only)\n"
" forward --remove LOCAL remove specific forward socket connection\n"
" forward --remove-all remove all forward socket connections\n"
" ppp TTY [PARAMETER...] run PPP over USB\n"

View file

@ -16,6 +16,7 @@
#include "socket_spec.h"
#include <limits>
#include <string>
#include <string_view>
#include <unordered_map>
@ -28,10 +29,12 @@
#include <cutils/sockets.h>
#include "adb.h"
#include "adb_utils.h"
#include "sysdeps.h"
using namespace std::string_literals;
using android::base::ConsumePrefix;
using android::base::StringPrintf;
#if defined(__linux__)
@ -131,7 +134,7 @@ bool is_socket_spec(std::string_view spec) {
return true;
}
}
return spec.starts_with("tcp:");
return spec.starts_with("tcp:") || spec.starts_with("acceptfd:");
}
bool is_local_socket_spec(std::string_view spec) {
@ -235,6 +238,9 @@ bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std
*error = "vsock is only supported on linux";
return false;
#endif // ADB_LINUX
} else if (address.starts_with("acceptfd:")) {
*error = "cannot connect to acceptfd";
return false;
}
for (const auto& it : kLocalSocketTypes) {
@ -334,6 +340,46 @@ int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_
*error = "vsock is only supported on linux";
return -1;
#endif // ADB_LINUX
} else if (ConsumePrefix(&spec, "acceptfd:")) {
#if ADB_WINDOWS
*error = "socket activation not supported under Windows";
return -1;
#else
// We inherited the socket from some kind of launcher. It's already bound and
// listening. Return a copy of the FD instead of the FD itself so we implement the
// normal "listen" contract and can succeed more than once.
unsigned int fd_u;
if (!ParseUint(&fd_u, spec) || fd_u > std::numeric_limits<int>::max()) {
*error = "invalid fd";
return -1;
}
int fd = static_cast<int>(fd_u);
int flags = get_fd_flags(fd);
if (flags < 0) {
*error = android::base::StringPrintf("could not get flags of inherited fd %d: '%s'", fd,
strerror(errno));
return -1;
}
if (flags & FD_CLOEXEC) {
*error = android::base::StringPrintf("fd %d was not inherited from parent", fd);
return -1;
}
int dummy_sock_type;
socklen_t dummy_sock_type_size = sizeof(dummy_sock_type);
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &dummy_sock_type, &dummy_sock_type_size)) {
*error = android::base::StringPrintf("fd %d does not refer to a socket", fd);
return -1;
}
int new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
if (new_fd < 0) {
*error = android::base::StringPrintf("could not dup inherited fd %d: '%s'", fd,
strerror(errno));
return -1;
}
return new_fd;
#endif
}
for (const auto& it : kLocalSocketTypes) {

View file

@ -349,8 +349,15 @@ static __inline__ bool adb_is_separator(char c) {
return c == '/';
}
static __inline__ int get_fd_flags(borrowed_fd fd) {
return fcntl(fd.get(), F_GETFD);
}
static __inline__ void close_on_exec(borrowed_fd fd) {
fcntl(fd.get(), F_SETFD, FD_CLOEXEC);
int flags = get_fd_flags(fd);
if (flags >= 0 && (flags & FD_CLOEXEC) == 0) {
fcntl(fd.get(), F_SETFD, flags | FD_CLOEXEC);
}
}
// Open a file and return a file descriptor that may be used with unix_read(),