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:
parent
9af7878ec5
commit
3ec7be7a84
5 changed files with 99 additions and 3 deletions
42
adb/SOCKET-ACTIVATION.txt
Normal file
42
adb/SOCKET-ACTIVATION.txt
Normal 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.
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(),
|
||||
|
|
Loading…
Reference in a new issue