Merge changes I86c3ec0f,I57d1a30a,Ib50d289b,I791a4f82,I316a8799, ... am: 216d158daf
am: ff7b56f917
Change-Id: I8dbbc43a2690cd35528dae59a3625c5288dc7a64
This commit is contained in:
commit
d575bc93a5
13 changed files with 285 additions and 218 deletions
170
adb/adb.cpp
170
adb/adb.cpp
|
@ -1018,9 +1018,10 @@ static int SendOkay(int fd, const std::string& s) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool handle_host_request(const char* service, TransportType type, const char* serial,
|
||||
TransportId transport_id, int reply_fd, asocket* s) {
|
||||
if (strcmp(service, "kill") == 0) {
|
||||
HostRequestResult handle_host_request(std::string_view service, TransportType type,
|
||||
const char* serial, TransportId transport_id, int reply_fd,
|
||||
asocket* s) {
|
||||
if (service == "kill") {
|
||||
fprintf(stderr, "adb server killed by remote request\n");
|
||||
fflush(stdout);
|
||||
|
||||
|
@ -1032,29 +1033,49 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
exit(0);
|
||||
}
|
||||
|
||||
// "transport:" is used for switching transport with a specified serial number
|
||||
// "transport-usb:" is used for switching transport to the only USB transport
|
||||
// "transport-local:" is used for switching transport to the only local transport
|
||||
// "transport-any:" is used for switching transport to the only transport
|
||||
if (!strncmp(service, "transport", strlen("transport"))) {
|
||||
LOG(DEBUG) << "handle_host_request(" << service << ")";
|
||||
|
||||
// Transport selection:
|
||||
if (service.starts_with("transport") || service.starts_with("tport:")) {
|
||||
TransportType type = kTransportAny;
|
||||
|
||||
if (!strncmp(service, "transport-id:", strlen("transport-id:"))) {
|
||||
service += strlen("transport-id:");
|
||||
transport_id = strtoll(service, const_cast<char**>(&service), 10);
|
||||
if (*service != '\0') {
|
||||
SendFail(reply_fd, "invalid transport id");
|
||||
return true;
|
||||
std::string serial_storage;
|
||||
bool legacy = true;
|
||||
|
||||
// New transport selection protocol:
|
||||
// This is essentially identical to the previous version, except it returns the selected
|
||||
// transport id to the caller as well.
|
||||
if (ConsumePrefix(&service, "tport:")) {
|
||||
legacy = false;
|
||||
if (ConsumePrefix(&service, "serial:")) {
|
||||
serial_storage = service;
|
||||
serial = serial_storage.c_str();
|
||||
} else if (service == "usb") {
|
||||
type = kTransportUsb;
|
||||
} else if (service == "local") {
|
||||
type = kTransportLocal;
|
||||
} else if (service == "any") {
|
||||
type = kTransportAny;
|
||||
}
|
||||
|
||||
// Selection by id is unimplemented, since you obviously already know the transport id
|
||||
// you're connecting to.
|
||||
} else {
|
||||
if (ConsumePrefix(&service, "transport-id:")) {
|
||||
if (!ParseUint(&transport_id, service)) {
|
||||
SendFail(reply_fd, "invalid transport id");
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
} else if (service == "transport-usb") {
|
||||
type = kTransportUsb;
|
||||
} else if (service == "transport-local") {
|
||||
type = kTransportLocal;
|
||||
} else if (service == "transport-any") {
|
||||
type = kTransportAny;
|
||||
} else if (ConsumePrefix(&service, "transport:")) {
|
||||
serial_storage = service;
|
||||
serial = serial_storage.c_str();
|
||||
}
|
||||
} else if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
|
||||
type = kTransportUsb;
|
||||
} else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
|
||||
type = kTransportLocal;
|
||||
} else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
|
||||
type = kTransportAny;
|
||||
} else if (!strncmp(service, "transport:", strlen("transport:"))) {
|
||||
service += strlen("transport:");
|
||||
serial = service;
|
||||
}
|
||||
|
||||
std::string error;
|
||||
|
@ -1063,27 +1084,29 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
s->transport = t;
|
||||
SendOkay(reply_fd);
|
||||
|
||||
// We succesfully handled the device selection, but there's another request coming.
|
||||
return false;
|
||||
if (!legacy) {
|
||||
// Nothing we can do if this fails.
|
||||
WriteFdExactly(reply_fd, &t->id, sizeof(t->id));
|
||||
}
|
||||
|
||||
return HostRequestResult::SwitchedTransport;
|
||||
} else {
|
||||
SendFail(reply_fd, error);
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
}
|
||||
|
||||
// return a list of all connected devices
|
||||
if (!strncmp(service, "devices", 7)) {
|
||||
bool long_listing = (strcmp(service+7, "-l") == 0);
|
||||
if (long_listing || service[7] == 0) {
|
||||
D("Getting device list...");
|
||||
std::string device_list = list_transports(long_listing);
|
||||
D("Sending device list...");
|
||||
SendOkay(reply_fd, device_list);
|
||||
}
|
||||
return true;
|
||||
if (service == "devices" || service == "devices-l") {
|
||||
bool long_listing = service == "devices-l";
|
||||
D("Getting device list...");
|
||||
std::string device_list = list_transports(long_listing);
|
||||
D("Sending device list...");
|
||||
SendOkay(reply_fd, device_list);
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
if (!strcmp(service, "reconnect-offline")) {
|
||||
if (service == "reconnect-offline") {
|
||||
std::string response;
|
||||
close_usb_devices([&response](const atransport* transport) {
|
||||
if (!ConnectionStateIsOnline(transport->GetConnectionState())) {
|
||||
|
@ -1096,10 +1119,10 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
response.resize(response.size() - 1);
|
||||
}
|
||||
SendOkay(reply_fd, response);
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
if (!strcmp(service, "features")) {
|
||||
if (service == "features") {
|
||||
std::string error;
|
||||
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||
if (t != nullptr) {
|
||||
|
@ -1107,10 +1130,10 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
} else {
|
||||
SendFail(reply_fd, error);
|
||||
}
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
if (!strcmp(service, "host-features")) {
|
||||
if (service == "host-features") {
|
||||
FeatureSet features = supported_features();
|
||||
// Abuse features to report libusb status.
|
||||
if (should_use_libusb()) {
|
||||
|
@ -1118,16 +1141,16 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
}
|
||||
features.insert(kFeaturePushSync);
|
||||
SendOkay(reply_fd, FeatureSetToString(features));
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
// remove TCP transport
|
||||
if (!strncmp(service, "disconnect:", 11)) {
|
||||
const std::string address(service + 11);
|
||||
if (service.starts_with("disconnect:")) {
|
||||
std::string address(service.substr(11));
|
||||
if (address.empty()) {
|
||||
kick_all_tcp_devices();
|
||||
SendOkay(reply_fd, "disconnected everything");
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
std::string serial;
|
||||
|
@ -1139,26 +1162,26 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
} else if (!android::base::ParseNetAddress(address, &host, &port, &serial, &error)) {
|
||||
SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
|
||||
address.c_str(), error.c_str()));
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
atransport* t = find_transport(serial.c_str());
|
||||
if (t == nullptr) {
|
||||
SendFail(reply_fd, android::base::StringPrintf("no such device '%s'", serial.c_str()));
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
kick_transport(t);
|
||||
SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str()));
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
// Returns our value for ADB_SERVER_VERSION.
|
||||
if (!strcmp(service, "version")) {
|
||||
if (service == "version") {
|
||||
SendOkay(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION));
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
// These always report "unknown" rather than the actual error, for scripts.
|
||||
if (!strcmp(service, "get-serialno")) {
|
||||
if (service == "get-serialno") {
|
||||
std::string error;
|
||||
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||
if (t) {
|
||||
|
@ -1166,9 +1189,9 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
} else {
|
||||
SendFail(reply_fd, error);
|
||||
}
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
if (!strcmp(service, "get-devpath")) {
|
||||
if (service == "get-devpath") {
|
||||
std::string error;
|
||||
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||
if (t) {
|
||||
|
@ -1176,9 +1199,9 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
} else {
|
||||
SendFail(reply_fd, error);
|
||||
}
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
if (!strcmp(service, "get-state")) {
|
||||
if (service == "get-state") {
|
||||
std::string error;
|
||||
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||
if (t) {
|
||||
|
@ -1186,39 +1209,46 @@ bool handle_host_request(const char* service, TransportType type, const char* se
|
|||
} else {
|
||||
SendFail(reply_fd, error);
|
||||
}
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
// Indicates a new emulator instance has started.
|
||||
if (!strncmp(service, "emulator:", 9)) {
|
||||
int port = atoi(service+9);
|
||||
local_connect(port);
|
||||
if (ConsumePrefix(&service, "emulator:")) {
|
||||
unsigned int port;
|
||||
if (!ParseUint(&port, service)) {
|
||||
LOG(ERROR) << "received invalid port for emulator: " << service;
|
||||
} else {
|
||||
local_connect(port);
|
||||
}
|
||||
|
||||
/* we don't even need to send a reply */
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
if (!strcmp(service, "reconnect")) {
|
||||
if (service == "reconnect") {
|
||||
std::string response;
|
||||
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &response, true);
|
||||
if (t != nullptr) {
|
||||
kick_transport(t);
|
||||
response =
|
||||
"reconnecting " + t->serial_name() + " [" + t->connection_state_name() + "]\n";
|
||||
"reconnecting " + t->serial_name() + " [" + t->connection_state_name() + "]\n";
|
||||
}
|
||||
SendOkay(reply_fd, response);
|
||||
return true;
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
if (handle_forward_request(service,
|
||||
[=](std::string* error) {
|
||||
return acquire_one_transport(type, serial, transport_id, nullptr,
|
||||
error);
|
||||
},
|
||||
reply_fd)) {
|
||||
return true;
|
||||
// TODO: Switch handle_forward_request to string_view.
|
||||
std::string service_str(service);
|
||||
if (handle_forward_request(
|
||||
service_str.c_str(),
|
||||
[=](std::string* error) {
|
||||
return acquire_one_transport(type, serial, transport_id, nullptr, error);
|
||||
},
|
||||
reply_fd)) {
|
||||
return HostRequestResult::Handled;
|
||||
}
|
||||
|
||||
return false;
|
||||
return HostRequestResult::Unhandled;
|
||||
}
|
||||
|
||||
static auto& init_mutex = *new std::mutex();
|
||||
|
|
16
adb/adb.h
16
adb/adb.h
|
@ -59,7 +59,7 @@ constexpr size_t LINUX_MAX_SOCKET_SIZE = 4194304;
|
|||
std::string adb_version();
|
||||
|
||||
// Increment this when we want to force users to start a new adb server.
|
||||
#define ADB_SERVER_VERSION 40
|
||||
#define ADB_SERVER_VERSION 41
|
||||
|
||||
using TransportId = uint64_t;
|
||||
class atransport;
|
||||
|
@ -145,7 +145,8 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* transport);
|
|||
#endif
|
||||
|
||||
#if ADB_HOST
|
||||
asocket* host_service_to_socket(const char* name, const char* serial, TransportId transport_id);
|
||||
asocket* host_service_to_socket(std::string_view name, std::string_view serial,
|
||||
TransportId transport_id);
|
||||
#endif
|
||||
|
||||
#if !ADB_HOST
|
||||
|
@ -218,8 +219,15 @@ extern const char* adb_device_banner;
|
|||
#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2)
|
||||
#endif
|
||||
|
||||
bool handle_host_request(const char* service, TransportType type, const char* serial,
|
||||
TransportId transport_id, int reply_fd, asocket* s);
|
||||
enum class HostRequestResult {
|
||||
Handled,
|
||||
SwitchedTransport,
|
||||
Unhandled,
|
||||
};
|
||||
|
||||
HostRequestResult handle_host_request(std::string_view service, TransportType type,
|
||||
const char* serial, TransportId transport_id, int reply_fd,
|
||||
asocket* s);
|
||||
|
||||
void handle_online(atransport* t);
|
||||
void handle_offline(atransport* t);
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "adb_utils.h"
|
||||
#include "sysdeps.h"
|
||||
|
||||
bool SendProtocolString(int fd, const std::string& s) {
|
||||
bool SendProtocolString(int fd, std::string_view s) {
|
||||
unsigned int length = s.size();
|
||||
if (length > MAX_PAYLOAD - 4) {
|
||||
errno = EMSGSIZE;
|
||||
|
@ -69,7 +69,7 @@ bool SendOkay(int fd) {
|
|||
return WriteFdExactly(fd, "OKAY", 4);
|
||||
}
|
||||
|
||||
bool SendFail(int fd, const std::string& reason) {
|
||||
bool SendFail(int fd, std::string_view reason) {
|
||||
return WriteFdExactly(fd, "FAIL", 4) && SendProtocolString(fd, reason);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "adb_unique_fd.h"
|
||||
|
||||
|
@ -27,10 +28,10 @@
|
|||
bool SendOkay(int fd);
|
||||
|
||||
// Sends the protocol "FAIL" message, with the given failure reason.
|
||||
bool SendFail(int fd, const std::string& reason);
|
||||
bool SendFail(int fd, std::string_view reason);
|
||||
|
||||
// Writes a protocol-format string; a four hex digit length followed by the string data.
|
||||
bool SendProtocolString(int fd, const std::string& s);
|
||||
bool SendProtocolString(int fd, std::string_view s);
|
||||
|
||||
// Reads a protocol-format string; a four hex digit length followed by the string data.
|
||||
bool ReadProtocolString(int fd, std::string* s, std::string* error);
|
||||
|
|
|
@ -110,7 +110,7 @@ inline std::string_view StripTrailingNulls(std::string_view str) {
|
|||
|
||||
// Base-10 stroll on a string_view.
|
||||
template <typename T>
|
||||
inline bool ParseUint(T* result, std::string_view str, std::string_view* remaining) {
|
||||
inline bool ParseUint(T* result, std::string_view str, std::string_view* remaining = nullptr) {
|
||||
if (str.empty() || !isdigit(str[0])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -135,6 +135,17 @@ inline bool ParseUint(T* result, std::string_view str, std::string_view* remaini
|
|||
*result = value;
|
||||
if (remaining) {
|
||||
*remaining = str.substr(it - str.begin());
|
||||
} else {
|
||||
return it == str.end();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool ConsumePrefix(std::string_view* str, std::string_view prefix) {
|
||||
if (str->starts_with(prefix)) {
|
||||
str->remove_prefix(prefix.size());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -206,6 +206,14 @@ void TestParseUint(std::string_view string, bool expected_success, uint32_t expe
|
|||
EXPECT_EQ(remaining, "foo");
|
||||
}
|
||||
}
|
||||
|
||||
// With trailing text, without remaining.
|
||||
{
|
||||
std::string text = std::string(string) + "foo";
|
||||
uint32_t value;
|
||||
bool success = ParseUint(&value, text, nullptr);
|
||||
EXPECT_EQ(success, false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(adb_utils, ParseUint) {
|
||||
|
|
|
@ -70,46 +70,60 @@ void adb_set_socket_spec(const char* socket_spec) {
|
|||
__adb_server_socket_spec = socket_spec;
|
||||
}
|
||||
|
||||
static int switch_socket_transport(int fd, std::string* error) {
|
||||
static std::optional<TransportId> switch_socket_transport(int fd, std::string* error) {
|
||||
TransportId result;
|
||||
bool read_transport = true;
|
||||
|
||||
std::string service;
|
||||
if (__adb_transport_id) {
|
||||
read_transport = false;
|
||||
service += "host:transport-id:";
|
||||
service += std::to_string(__adb_transport_id);
|
||||
result = __adb_transport_id;
|
||||
} else if (__adb_serial) {
|
||||
service += "host:transport:";
|
||||
service += "host:tport:serial:";
|
||||
service += __adb_serial;
|
||||
} else {
|
||||
const char* transport_type = "???";
|
||||
switch (__adb_transport) {
|
||||
case kTransportUsb:
|
||||
transport_type = "transport-usb";
|
||||
break;
|
||||
transport_type = "usb";
|
||||
break;
|
||||
case kTransportLocal:
|
||||
transport_type = "transport-local";
|
||||
break;
|
||||
transport_type = "local";
|
||||
break;
|
||||
case kTransportAny:
|
||||
transport_type = "transport-any";
|
||||
break;
|
||||
transport_type = "any";
|
||||
break;
|
||||
case kTransportHost:
|
||||
// no switch necessary
|
||||
return 0;
|
||||
}
|
||||
service += "host:";
|
||||
service += "host:tport:";
|
||||
service += transport_type;
|
||||
}
|
||||
|
||||
if (!SendProtocolString(fd, service)) {
|
||||
*error = perror_str("write failure during connection");
|
||||
return -1;
|
||||
return std::nullopt;
|
||||
}
|
||||
D("Switch transport in progress");
|
||||
|
||||
LOG(DEBUG) << "Switch transport in progress: " << service;
|
||||
|
||||
if (!adb_status(fd, error)) {
|
||||
D("Switch transport failed: %s", error->c_str());
|
||||
return -1;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (read_transport) {
|
||||
if (!ReadFdExactly(fd, &result, sizeof(result))) {
|
||||
*error = "failed to read transport id from server";
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
D("Switch transport success");
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool adb_status(int fd, std::string* error) {
|
||||
|
@ -133,11 +147,10 @@ bool adb_status(int fd, std::string* error) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int _adb_connect(const std::string& service, std::string* error) {
|
||||
D("_adb_connect: %s", service.c_str());
|
||||
static int _adb_connect(std::string_view service, TransportId* transport, std::string* error) {
|
||||
LOG(DEBUG) << "_adb_connect: " << service;
|
||||
if (service.empty() || service.size() > MAX_PAYLOAD) {
|
||||
*error = android::base::StringPrintf("bad service name length (%zd)",
|
||||
service.size());
|
||||
*error = android::base::StringPrintf("bad service name length (%zd)", service.size());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -149,8 +162,15 @@ static int _adb_connect(const std::string& service, std::string* error) {
|
|||
return -2;
|
||||
}
|
||||
|
||||
if (memcmp(&service[0], "host", 4) != 0 && switch_socket_transport(fd.get(), error)) {
|
||||
return -1;
|
||||
if (!service.starts_with("host")) {
|
||||
std::optional<TransportId> transport_result = switch_socket_transport(fd.get(), error);
|
||||
if (!transport_result) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (transport) {
|
||||
*transport = *transport_result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SendProtocolString(fd.get(), service)) {
|
||||
|
@ -190,11 +210,15 @@ bool adb_kill_server() {
|
|||
return true;
|
||||
}
|
||||
|
||||
int adb_connect(const std::string& service, std::string* error) {
|
||||
// first query the adb server's version
|
||||
unique_fd fd(_adb_connect("host:version", error));
|
||||
int adb_connect(std::string_view service, std::string* error) {
|
||||
return adb_connect(nullptr, service, error);
|
||||
}
|
||||
|
||||
D("adb_connect: service %s", service.c_str());
|
||||
int adb_connect(TransportId* transport, std::string_view service, std::string* error) {
|
||||
// first query the adb server's version
|
||||
unique_fd fd(_adb_connect("host:version", nullptr, error));
|
||||
|
||||
LOG(DEBUG) << "adb_connect: service: " << service;
|
||||
if (fd == -2 && !is_local_socket_spec(__adb_server_socket_spec)) {
|
||||
fprintf(stderr, "* cannot start server on remote host\n");
|
||||
// error is the original network connection error
|
||||
|
@ -216,7 +240,7 @@ int adb_connect(const std::string& service, std::string* error) {
|
|||
// Fall through to _adb_connect.
|
||||
} else {
|
||||
// If a server is already running, check its version matches.
|
||||
int version = ADB_SERVER_VERSION - 1;
|
||||
int version = 0;
|
||||
|
||||
// If we have a file descriptor, then parse version result.
|
||||
if (fd >= 0) {
|
||||
|
@ -254,7 +278,7 @@ int adb_connect(const std::string& service, std::string* error) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
fd.reset(_adb_connect(service, error));
|
||||
fd.reset(_adb_connect(service, transport, error));
|
||||
if (fd == -1) {
|
||||
D("_adb_connect error: %s", error->c_str());
|
||||
} else if(fd == -2) {
|
||||
|
@ -265,7 +289,6 @@ int adb_connect(const std::string& service, std::string* error) {
|
|||
return fd.release();
|
||||
}
|
||||
|
||||
|
||||
bool adb_command(const std::string& service) {
|
||||
std::string error;
|
||||
unique_fd fd(adb_connect(service, &error));
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
|
||||
// Connect to adb, connect to the named service, and return a valid fd for
|
||||
// interacting with that service upon success or a negative number on failure.
|
||||
int adb_connect(const std::string& service, std::string* _Nonnull error);
|
||||
int adb_connect(std::string_view service, std::string* _Nonnull error);
|
||||
|
||||
// Same as above, except returning the TransportId for the service that we've connected to.
|
||||
int adb_connect(TransportId* _Nullable id, std::string_view service, std::string* _Nonnull error);
|
||||
|
||||
// Kill the currently running adb server, if it exists.
|
||||
bool adb_kill_server();
|
||||
|
|
|
@ -190,8 +190,8 @@ static void help() {
|
|||
"scripting:\n"
|
||||
" wait-for[-TRANSPORT]-STATE\n"
|
||||
" wait for device to be in the given state\n"
|
||||
" State: device, recovery, sideload, or bootloader\n"
|
||||
" Transport: usb, local, or any [default=any]\n"
|
||||
" STATE: device, recovery, sideload, bootloader, or disconnect\n"
|
||||
" TRANSPORT: usb, local, or any [default=any]\n"
|
||||
" get-state print offline | bootloader | device\n"
|
||||
" get-serialno print <serial-number>\n"
|
||||
" get-devpath print <device-path>\n"
|
||||
|
@ -1031,10 +1031,11 @@ static bool wait_for_device(const char* service) {
|
|||
}
|
||||
|
||||
if (components[3] != "any" && components[3] != "bootloader" && components[3] != "device" &&
|
||||
components[3] != "recovery" && components[3] != "sideload") {
|
||||
components[3] != "recovery" && components[3] != "sideload" &&
|
||||
components[3] != "disconnect") {
|
||||
fprintf(stderr,
|
||||
"adb: unknown state %s; "
|
||||
"expected 'any', 'bootloader', 'device', 'recovery', or 'sideload'\n",
|
||||
"expected 'any', 'bootloader', 'device', 'recovery', 'sideload', or 'disconnect'\n",
|
||||
components[3].c_str());
|
||||
return false;
|
||||
}
|
||||
|
@ -1046,7 +1047,8 @@ static bool wait_for_device(const char* service) {
|
|||
static bool adb_root(const char* command) {
|
||||
std::string error;
|
||||
|
||||
unique_fd fd(adb_connect(android::base::StringPrintf("%s:", command), &error));
|
||||
TransportId transport_id;
|
||||
unique_fd fd(adb_connect(&transport_id, android::base::StringPrintf("%s:", command), &error));
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "adb: unable to connect for %s: %s\n", command, error.c_str());
|
||||
return false;
|
||||
|
@ -1079,9 +1081,9 @@ static bool adb_root(const char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Give adbd some time to kill itself and come back up.
|
||||
// We can't use wait-for-device because devices (e.g. adb over network) might not come back.
|
||||
std::this_thread::sleep_for(3s);
|
||||
// Wait for the device to go away.
|
||||
adb_set_transport(kTransportAny, nullptr, transport_id);
|
||||
wait_for_device("wait-for-disconnect");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "adb.h"
|
||||
#include "adb_io.h"
|
||||
#include "shell_service.h"
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <android-base/cmsg.h>
|
||||
#include <cmd.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "adb_io.h"
|
||||
#include "adb_utils.h"
|
||||
#include "shell_service.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -87,11 +87,9 @@ int main(int argc, char* const argv[]) {
|
|||
|
||||
std::string_view name = data;
|
||||
auto protocol = SubprocessProtocol::kShell;
|
||||
if (name.starts_with("abb:")) {
|
||||
name.remove_prefix(strlen("abb:"));
|
||||
if (ConsumePrefix(&name, "abb:")) {
|
||||
protocol = SubprocessProtocol::kShell;
|
||||
} else if (name.starts_with("abb_exec:")) {
|
||||
name.remove_prefix(strlen("abb_exec:"));
|
||||
} else if (ConsumePrefix(&name, "abb_exec:")) {
|
||||
protocol = SubprocessProtocol::kNone;
|
||||
} else {
|
||||
LOG(FATAL) << "Unknown command prefix for abb: " << data;
|
||||
|
|
|
@ -223,17 +223,15 @@ asocket* daemon_service_to_socket(std::string_view name) {
|
|||
return create_jdwp_service_socket();
|
||||
} else if (name == "track-jdwp") {
|
||||
return create_jdwp_tracker_service_socket();
|
||||
} else if (name.starts_with("sink:")) {
|
||||
name.remove_prefix(strlen("sink:"));
|
||||
} else if (ConsumePrefix(&name, "sink:")) {
|
||||
uint64_t byte_count = 0;
|
||||
if (!android::base::ParseUint(name.data(), &byte_count)) {
|
||||
if (!ParseUint(&byte_count, name)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new SinkSocket(byte_count);
|
||||
} else if (name.starts_with("source:")) {
|
||||
name.remove_prefix(strlen("source:"));
|
||||
} else if (ConsumePrefix(&name, "source:")) {
|
||||
uint64_t byte_count = 0;
|
||||
if (!android::base::ParseUint(name.data(), &byte_count)) {
|
||||
if (!ParseUint(&byte_count, name)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new SourceSocket(byte_count);
|
||||
|
@ -252,20 +250,19 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
|
|||
#if defined(__ANDROID__)
|
||||
if (name.starts_with("framebuffer:")) {
|
||||
return create_service_thread("fb", framebuffer_service);
|
||||
} else if (name.starts_with("remount:")) {
|
||||
std::string arg(name.begin() + strlen("remount:"), name.end());
|
||||
} else if (ConsumePrefix(&name, "remount:")) {
|
||||
std::string arg(name);
|
||||
return create_service_thread("remount",
|
||||
std::bind(remount_service, std::placeholders::_1, arg));
|
||||
} else if (name.starts_with("reboot:")) {
|
||||
std::string arg(name.begin() + strlen("reboot:"), name.end());
|
||||
} else if (ConsumePrefix(&name, "reboot:")) {
|
||||
std::string arg(name);
|
||||
return create_service_thread("reboot",
|
||||
std::bind(reboot_service, std::placeholders::_1, arg));
|
||||
} else if (name.starts_with("root:")) {
|
||||
return create_service_thread("root", restart_root_service);
|
||||
} else if (name.starts_with("unroot:")) {
|
||||
return create_service_thread("unroot", restart_unroot_service);
|
||||
} else if (name.starts_with("backup:")) {
|
||||
name.remove_prefix(strlen("backup:"));
|
||||
} else if (ConsumePrefix(&name, "backup:")) {
|
||||
std::string cmd = "/system/bin/bu backup ";
|
||||
cmd += name;
|
||||
return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
|
||||
|
@ -278,8 +275,7 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
|
|||
} 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:"));
|
||||
} else if (ConsumePrefix(&name, "tcpip:")) {
|
||||
std::string str(name);
|
||||
|
||||
int port;
|
||||
|
@ -293,24 +289,22 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (name.starts_with("dev:")) {
|
||||
name.remove_prefix(strlen("dev:"));
|
||||
if (ConsumePrefix(&name, "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"));
|
||||
} else if (ConsumePrefix(&name, "jdwp:")) {
|
||||
pid_t pid;
|
||||
if (!ParseUint(&pid, name)) {
|
||||
return unique_fd{};
|
||||
}
|
||||
return create_jdwp_connection_fd(pid);
|
||||
} else if (ConsumePrefix(&name, "shell")) {
|
||||
return ShellService(name, transport);
|
||||
} else if (name.starts_with("exec:")) {
|
||||
name.remove_prefix(strlen("exec:"));
|
||||
} else if (ConsumePrefix(&name, "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:"));
|
||||
} else if (ConsumePrefix(&name, "reverse:")) {
|
||||
return reverse_service(name, transport);
|
||||
} else if (name == "reconnect") {
|
||||
return create_service_thread(
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
@ -63,11 +64,11 @@ unique_fd create_service_thread(const char* service_name, std::function<void(uni
|
|||
adb_setsockopt(s[0], SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
|
||||
adb_setsockopt(s[1], SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
|
||||
}
|
||||
#endif // !ADB_HOST
|
||||
#endif // !ADB_HOST
|
||||
|
||||
std::thread(service_bootstrap_func, service_name, func, unique_fd(s[1])).detach();
|
||||
|
||||
D("service thread started, %d:%d",s[0], s[1]);
|
||||
D("service thread started, %d:%d", s[0], s[1]);
|
||||
return unique_fd(s[0]);
|
||||
}
|
||||
|
||||
|
@ -108,12 +109,21 @@ static void wait_for_state(int fd, state_info* sinfo) {
|
|||
const char* serial = sinfo->serial.length() ? sinfo->serial.c_str() : nullptr;
|
||||
atransport* t = acquire_one_transport(sinfo->transport_type, serial, sinfo->transport_id,
|
||||
&is_ambiguous, &error);
|
||||
if (t != nullptr && (sinfo->state == kCsAny || sinfo->state == t->GetConnectionState())) {
|
||||
if (sinfo->state == kCsOffline) {
|
||||
// wait-for-disconnect uses kCsOffline, we don't actually want to wait for 'offline'.
|
||||
if (t == nullptr) {
|
||||
SendOkay(fd);
|
||||
break;
|
||||
}
|
||||
} else if (t != nullptr &&
|
||||
(sinfo->state == kCsAny || sinfo->state == t->GetConnectionState())) {
|
||||
SendOkay(fd);
|
||||
break;
|
||||
} else if (!is_ambiguous) {
|
||||
adb_pollfd pfd = {.fd = fd, .events = POLLIN };
|
||||
int rc = adb_poll(&pfd, 1, 1000);
|
||||
}
|
||||
|
||||
if (!is_ambiguous) {
|
||||
adb_pollfd pfd = {.fd = fd, .events = POLLIN};
|
||||
int rc = adb_poll(&pfd, 1, 100);
|
||||
if (rc < 0) {
|
||||
SendFail(fd, error);
|
||||
break;
|
||||
|
@ -187,46 +197,44 @@ static void connect_service(unique_fd fd, std::string host) {
|
|||
#endif
|
||||
|
||||
#if ADB_HOST
|
||||
asocket* host_service_to_socket(const char* name, const char* serial, TransportId transport_id) {
|
||||
if (!strcmp(name,"track-devices")) {
|
||||
asocket* host_service_to_socket(std::string_view name, std::string_view serial,
|
||||
TransportId transport_id) {
|
||||
if (name == "track-devices") {
|
||||
return create_device_tracker(false);
|
||||
} else if (!strcmp(name, "track-devices-l")) {
|
||||
} else if (name == "track-devices-l") {
|
||||
return create_device_tracker(true);
|
||||
} else if (android::base::StartsWith(name, "wait-for-")) {
|
||||
name += strlen("wait-for-");
|
||||
|
||||
} else if (ConsumePrefix(&name, "wait-for-")) {
|
||||
std::shared_ptr<state_info> sinfo = std::make_shared<state_info>();
|
||||
if (sinfo == nullptr) {
|
||||
fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (serial) sinfo->serial = serial;
|
||||
sinfo->serial = serial;
|
||||
sinfo->transport_id = transport_id;
|
||||
|
||||
if (android::base::StartsWith(name, "local")) {
|
||||
name += strlen("local");
|
||||
if (ConsumePrefix(&name, "local")) {
|
||||
sinfo->transport_type = kTransportLocal;
|
||||
} else if (android::base::StartsWith(name, "usb")) {
|
||||
name += strlen("usb");
|
||||
} else if (ConsumePrefix(&name, "usb")) {
|
||||
sinfo->transport_type = kTransportUsb;
|
||||
} else if (android::base::StartsWith(name, "any")) {
|
||||
name += strlen("any");
|
||||
} else if (ConsumePrefix(&name, "any")) {
|
||||
sinfo->transport_type = kTransportAny;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "-device")) {
|
||||
if (name == "-device") {
|
||||
sinfo->state = kCsDevice;
|
||||
} else if (!strcmp(name, "-recovery")) {
|
||||
} else if (name == "-recovery") {
|
||||
sinfo->state = kCsRecovery;
|
||||
} else if (!strcmp(name, "-sideload")) {
|
||||
} else if (name == "-sideload") {
|
||||
sinfo->state = kCsSideload;
|
||||
} else if (!strcmp(name, "-bootloader")) {
|
||||
} else if (name == "-bootloader") {
|
||||
sinfo->state = kCsBootloader;
|
||||
} else if (!strcmp(name, "-any")) {
|
||||
} else if (name == "-any") {
|
||||
sinfo->state = kCsAny;
|
||||
} else if (name == "-disconnect") {
|
||||
sinfo->state = kCsOffline;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -235,8 +243,8 @@ asocket* host_service_to_socket(const char* name, const char* serial, TransportI
|
|||
wait_for_state(fd, sinfo.get());
|
||||
});
|
||||
return create_local_socket(std::move(fd));
|
||||
} else if (!strncmp(name, "connect:", 8)) {
|
||||
std::string host(name + strlen("connect:"));
|
||||
} else if (ConsumePrefix(&name, "connect:")) {
|
||||
std::string host(name);
|
||||
unique_fd fd = create_service_thread(
|
||||
"connect", std::bind(connect_service, std::placeholders::_1, host));
|
||||
return create_local_socket(std::move(fd));
|
||||
|
|
|
@ -426,22 +426,6 @@ asocket* create_local_service_socket(std::string_view name, atransport* transpor
|
|||
return s;
|
||||
}
|
||||
|
||||
#if ADB_HOST
|
||||
static asocket* create_host_service_socket(const char* name, const char* serial,
|
||||
TransportId transport_id) {
|
||||
asocket* s;
|
||||
|
||||
s = host_service_to_socket(name, serial, transport_id);
|
||||
|
||||
if (s != nullptr) {
|
||||
D("LS(%d) bound to '%s'", s->id, name);
|
||||
return s;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
#endif /* ADB_HOST */
|
||||
|
||||
static int remote_socket_enqueue(asocket* s, apacket::payload_type data) {
|
||||
D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
|
||||
apacket* p = get_apacket();
|
||||
|
@ -771,34 +755,27 @@ static int smart_socket_enqueue(asocket* s, apacket::payload_type data) {
|
|||
|
||||
#if ADB_HOST
|
||||
service = std::string_view(s->smart_socket_data).substr(4);
|
||||
if (service.starts_with("host-serial:")) {
|
||||
service.remove_prefix(strlen("host-serial:"));
|
||||
|
||||
if (ConsumePrefix(&service, "host-serial:")) {
|
||||
// serial number should follow "host:" and could be a host:port string.
|
||||
if (!internal::parse_host_service(&serial, &service, service)) {
|
||||
LOG(ERROR) << "SS(" << s->id << "): failed to parse host service: " << service;
|
||||
goto fail;
|
||||
}
|
||||
} else if (service.starts_with("host-transport-id:")) {
|
||||
service.remove_prefix(strlen("host-transport-id:"));
|
||||
} else if (ConsumePrefix(&service, "host-transport-id:")) {
|
||||
if (!ParseUint(&transport_id, service, &service)) {
|
||||
LOG(ERROR) << "SS(" << s->id << "): failed to parse host transport id: " << service;
|
||||
return -1;
|
||||
}
|
||||
if (!service.starts_with(":")) {
|
||||
if (!ConsumePrefix(&service, ":")) {
|
||||
LOG(ERROR) << "SS(" << s->id << "): host-transport-id without command";
|
||||
return -1;
|
||||
}
|
||||
service.remove_prefix(1);
|
||||
} else if (service.starts_with("host-usb:")) {
|
||||
} else if (ConsumePrefix(&service, "host-usb:")) {
|
||||
type = kTransportUsb;
|
||||
service.remove_prefix(strlen("host-usb:"));
|
||||
} else if (service.starts_with("host-local:")) {
|
||||
} else if (ConsumePrefix(&service, "host-local:")) {
|
||||
type = kTransportLocal;
|
||||
service.remove_prefix(strlen("host-local:"));
|
||||
} else if (service.starts_with("host:")) {
|
||||
} else if (ConsumePrefix(&service, "host:")) {
|
||||
type = kTransportAny;
|
||||
service.remove_prefix(strlen("host:"));
|
||||
} else {
|
||||
service = std::string_view{};
|
||||
}
|
||||
|
@ -808,17 +785,22 @@ static int smart_socket_enqueue(asocket* s, apacket::payload_type data) {
|
|||
|
||||
// Some requests are handled immediately -- in that case the handle_host_request() routine
|
||||
// has sent the OKAY or FAIL message and all we have to do is clean up.
|
||||
// TODO: Convert to string_view.
|
||||
if (handle_host_request(std::string(service).c_str(), type,
|
||||
serial.empty() ? nullptr : std::string(serial).c_str(),
|
||||
transport_id, s->peer->fd, s)) {
|
||||
LOG(VERBOSE) << "SS(" << s->id << "): handled host service '" << service << "'";
|
||||
goto fail;
|
||||
}
|
||||
if (service.starts_with("transport")) {
|
||||
D("SS(%d): okay transport", s->id);
|
||||
s->smart_socket_data.clear();
|
||||
return 0;
|
||||
auto host_request_result = handle_host_request(
|
||||
service, type, serial.empty() ? nullptr : std::string(serial).c_str(), transport_id,
|
||||
s->peer->fd, s);
|
||||
|
||||
switch (host_request_result) {
|
||||
case HostRequestResult::Handled:
|
||||
LOG(VERBOSE) << "SS(" << s->id << "): handled host service '" << service << "'";
|
||||
goto fail;
|
||||
|
||||
case HostRequestResult::SwitchedTransport:
|
||||
D("SS(%d): okay transport", s->id);
|
||||
s->smart_socket_data.clear();
|
||||
return 0;
|
||||
|
||||
case HostRequestResult::Unhandled:
|
||||
break;
|
||||
}
|
||||
|
||||
/* try to find a local service with this name.
|
||||
|
@ -826,8 +808,7 @@ static int smart_socket_enqueue(asocket* s, apacket::payload_type data) {
|
|||
** and tear down here.
|
||||
*/
|
||||
// TODO: Convert to string_view.
|
||||
s2 = create_host_service_socket(std::string(service).c_str(), std::string(serial).c_str(),
|
||||
transport_id);
|
||||
s2 = host_service_to_socket(service, serial, transport_id);
|
||||
if (s2 == nullptr) {
|
||||
LOG(VERBOSE) << "SS(" << s->id << "): couldn't create host service '" << service << "'";
|
||||
SendFail(s->peer->fd, "unknown host service");
|
||||
|
|
Loading…
Reference in a new issue