Merge changes I12d46493,I0ed00441,I55e5dc5a,If61296ff into oc-mr1-dev
* changes: adb: add lock to remove_socket. Revert "adb: fix deadlock between transport_unref and usb_close." adb: allow selection of a specific transport. adb: fix deadlock in kick_all_transports.
This commit is contained in:
commit
c03127ef5c
14 changed files with 318 additions and 233 deletions
34
adb/adb.cpp
34
adb/adb.cpp
|
|
@ -956,8 +956,8 @@ int launch_server(const std::string& socket_spec) {
|
||||||
// Try to handle a network forwarding request.
|
// Try to handle a network forwarding request.
|
||||||
// This returns 1 on success, 0 on failure, and -1 to indicate this is not
|
// This returns 1 on success, 0 on failure, and -1 to indicate this is not
|
||||||
// a forwarding-related request.
|
// a forwarding-related request.
|
||||||
int handle_forward_request(const char* service, TransportType type, const char* serial, int reply_fd)
|
int handle_forward_request(const char* service, TransportType type, const char* serial,
|
||||||
{
|
TransportId transport_id, int reply_fd) {
|
||||||
if (!strcmp(service, "list-forward")) {
|
if (!strcmp(service, "list-forward")) {
|
||||||
// Create the list of forward redirections.
|
// Create the list of forward redirections.
|
||||||
std::string listeners = format_listeners();
|
std::string listeners = format_listeners();
|
||||||
|
|
@ -1010,7 +1010,8 @@ int handle_forward_request(const char* service, TransportType type, const char*
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string error_msg;
|
std::string error_msg;
|
||||||
atransport* transport = acquire_one_transport(type, serial, nullptr, &error_msg);
|
atransport* transport =
|
||||||
|
acquire_one_transport(type, serial, transport_id, nullptr, &error_msg);
|
||||||
if (!transport) {
|
if (!transport) {
|
||||||
SendFail(reply_fd, error_msg);
|
SendFail(reply_fd, error_msg);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -1068,8 +1069,8 @@ static int SendOkay(int fd, const std::string& s) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_host_request(const char* service, TransportType type,
|
int handle_host_request(const char* service, TransportType type, const char* serial,
|
||||||
const char* serial, int reply_fd, asocket* s) {
|
TransportId transport_id, int reply_fd, asocket* s) {
|
||||||
if (strcmp(service, "kill") == 0) {
|
if (strcmp(service, "kill") == 0) {
|
||||||
fprintf(stderr, "adb server killed by remote request\n");
|
fprintf(stderr, "adb server killed by remote request\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
@ -1089,7 +1090,14 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
if (!strncmp(service, "transport", strlen("transport"))) {
|
if (!strncmp(service, "transport", strlen("transport"))) {
|
||||||
TransportType type = kTransportAny;
|
TransportType type = kTransportAny;
|
||||||
|
|
||||||
if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
|
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 1;
|
||||||
|
}
|
||||||
|
} else if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
|
||||||
type = kTransportUsb;
|
type = kTransportUsb;
|
||||||
} else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
|
} else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
|
||||||
type = kTransportLocal;
|
type = kTransportLocal;
|
||||||
|
|
@ -1101,7 +1109,7 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string error;
|
std::string error;
|
||||||
atransport* t = acquire_one_transport(type, serial, nullptr, &error);
|
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||||
if (t != nullptr) {
|
if (t != nullptr) {
|
||||||
s->transport = t;
|
s->transport = t;
|
||||||
SendOkay(reply_fd);
|
SendOkay(reply_fd);
|
||||||
|
|
@ -1144,7 +1152,7 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
|
|
||||||
if (!strcmp(service, "features")) {
|
if (!strcmp(service, "features")) {
|
||||||
std::string error;
|
std::string error;
|
||||||
atransport* t = acquire_one_transport(type, serial, nullptr, &error);
|
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||||
if (t != nullptr) {
|
if (t != nullptr) {
|
||||||
SendOkay(reply_fd, FeatureSetToString(t->features()));
|
SendOkay(reply_fd, FeatureSetToString(t->features()));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1197,7 +1205,7 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
// These always report "unknown" rather than the actual error, for scripts.
|
// These always report "unknown" rather than the actual error, for scripts.
|
||||||
if (!strcmp(service, "get-serialno")) {
|
if (!strcmp(service, "get-serialno")) {
|
||||||
std::string error;
|
std::string error;
|
||||||
atransport* t = acquire_one_transport(type, serial, nullptr, &error);
|
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||||
if (t) {
|
if (t) {
|
||||||
return SendOkay(reply_fd, t->serial ? t->serial : "unknown");
|
return SendOkay(reply_fd, t->serial ? t->serial : "unknown");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1206,7 +1214,7 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
}
|
}
|
||||||
if (!strcmp(service, "get-devpath")) {
|
if (!strcmp(service, "get-devpath")) {
|
||||||
std::string error;
|
std::string error;
|
||||||
atransport* t = acquire_one_transport(type, serial, nullptr, &error);
|
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||||
if (t) {
|
if (t) {
|
||||||
return SendOkay(reply_fd, t->devpath ? t->devpath : "unknown");
|
return SendOkay(reply_fd, t->devpath ? t->devpath : "unknown");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1215,7 +1223,7 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
}
|
}
|
||||||
if (!strcmp(service, "get-state")) {
|
if (!strcmp(service, "get-state")) {
|
||||||
std::string error;
|
std::string error;
|
||||||
atransport* t = acquire_one_transport(type, serial, nullptr, &error);
|
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
|
||||||
if (t) {
|
if (t) {
|
||||||
return SendOkay(reply_fd, t->connection_state_name());
|
return SendOkay(reply_fd, t->connection_state_name());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1233,7 +1241,7 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
|
|
||||||
if (!strcmp(service, "reconnect")) {
|
if (!strcmp(service, "reconnect")) {
|
||||||
std::string response;
|
std::string response;
|
||||||
atransport* t = acquire_one_transport(type, serial, nullptr, &response, true);
|
atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &response, true);
|
||||||
if (t != nullptr) {
|
if (t != nullptr) {
|
||||||
kick_transport(t);
|
kick_transport(t);
|
||||||
response =
|
response =
|
||||||
|
|
@ -1242,7 +1250,7 @@ int handle_host_request(const char* service, TransportType type,
|
||||||
return SendOkay(reply_fd, response);
|
return SendOkay(reply_fd, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = handle_forward_request(service, type, serial, reply_fd);
|
int ret = handle_forward_request(service, type, serial, transport_id, reply_fd);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
return ret - 1;
|
return ret - 1;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ std::string adb_version();
|
||||||
// Increment this when we want to force users to start a new adb server.
|
// Increment this when we want to force users to start a new adb server.
|
||||||
#define ADB_SERVER_VERSION 39
|
#define ADB_SERVER_VERSION 39
|
||||||
|
|
||||||
|
using TransportId = uint64_t;
|
||||||
class atransport;
|
class atransport;
|
||||||
|
|
||||||
struct amessage {
|
struct amessage {
|
||||||
|
|
@ -149,7 +150,7 @@ atransport* find_emulator_transport_by_console_port(int console_port);
|
||||||
|
|
||||||
int service_to_fd(const char* name, const atransport* transport);
|
int service_to_fd(const char* name, const atransport* transport);
|
||||||
#if ADB_HOST
|
#if ADB_HOST
|
||||||
asocket *host_service_to_socket(const char* name, const char *serial);
|
asocket* host_service_to_socket(const char* name, const char* serial, TransportId transport_id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !ADB_HOST
|
#if !ADB_HOST
|
||||||
|
|
@ -159,7 +160,8 @@ asocket* create_jdwp_tracker_service_socket();
|
||||||
int create_jdwp_connection_fd(int jdwp_pid);
|
int create_jdwp_connection_fd(int jdwp_pid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int handle_forward_request(const char* service, TransportType type, const char* serial, int reply_fd);
|
int handle_forward_request(const char* service, TransportType type, const char* serial,
|
||||||
|
TransportId transport_id, int reply_fd);
|
||||||
|
|
||||||
#if !ADB_HOST
|
#if !ADB_HOST
|
||||||
void framebuffer_service(int fd, void *cookie);
|
void framebuffer_service(int fd, void *cookie);
|
||||||
|
|
@ -216,7 +218,8 @@ extern int SHELL_EXIT_NOTIFY_FD;
|
||||||
#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2)
|
#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int handle_host_request(const char* service, TransportType type, const char* serial, int reply_fd, asocket *s);
|
int handle_host_request(const char* service, TransportType type, const char* serial,
|
||||||
|
TransportId transport_id, int reply_fd, asocket* s);
|
||||||
|
|
||||||
void handle_online(atransport *t);
|
void handle_online(atransport *t);
|
||||||
void handle_offline(atransport *t);
|
void handle_offline(atransport *t);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "adb_client.h"
|
#include "adb_client.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -46,12 +47,20 @@
|
||||||
|
|
||||||
static TransportType __adb_transport = kTransportAny;
|
static TransportType __adb_transport = kTransportAny;
|
||||||
static const char* __adb_serial = NULL;
|
static const char* __adb_serial = NULL;
|
||||||
|
static TransportId __adb_transport_id = 0;
|
||||||
|
|
||||||
static const char* __adb_server_socket_spec;
|
static const char* __adb_server_socket_spec;
|
||||||
|
|
||||||
void adb_set_transport(TransportType type, const char* serial) {
|
void adb_set_transport(TransportType type, const char* serial, TransportId transport_id) {
|
||||||
__adb_transport = type;
|
__adb_transport = type;
|
||||||
__adb_serial = serial;
|
__adb_serial = serial;
|
||||||
|
__adb_transport_id = transport_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void adb_get_transport(TransportType* type, const char** serial, TransportId* transport_id) {
|
||||||
|
if (type) *type = __adb_transport;
|
||||||
|
if (serial) *serial = __adb_serial;
|
||||||
|
if (transport_id) *transport_id = __adb_transport_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adb_set_socket_spec(const char* socket_spec) {
|
void adb_set_socket_spec(const char* socket_spec) {
|
||||||
|
|
@ -63,7 +72,10 @@ void adb_set_socket_spec(const char* socket_spec) {
|
||||||
|
|
||||||
static int switch_socket_transport(int fd, std::string* error) {
|
static int switch_socket_transport(int fd, std::string* error) {
|
||||||
std::string service;
|
std::string service;
|
||||||
if (__adb_serial) {
|
if (__adb_transport_id) {
|
||||||
|
service += "host:transport-id:";
|
||||||
|
service += std::to_string(__adb_transport_id);
|
||||||
|
} else if (__adb_serial) {
|
||||||
service += "host:transport:";
|
service += "host:transport:";
|
||||||
service += __adb_serial;
|
service += __adb_serial;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -292,15 +304,18 @@ bool adb_query(const std::string& service, std::string* result, std::string* err
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string format_host_command(const char* command, TransportType type, const char* serial) {
|
std::string format_host_command(const char* command) {
|
||||||
if (serial) {
|
if (__adb_transport_id) {
|
||||||
return android::base::StringPrintf("host-serial:%s:%s", serial, command);
|
return android::base::StringPrintf("host-transport-id:%" PRIu64 ":%s", __adb_transport_id,
|
||||||
|
command);
|
||||||
|
} else if (__adb_serial) {
|
||||||
|
return android::base::StringPrintf("host-serial:%s:%s", __adb_serial, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* prefix = "host";
|
const char* prefix = "host";
|
||||||
if (type == kTransportUsb) {
|
if (__adb_transport == kTransportUsb) {
|
||||||
prefix = "host-usb";
|
prefix = "host-usb";
|
||||||
} else if (type == kTransportLocal) {
|
} else if (__adb_transport == kTransportLocal) {
|
||||||
prefix = "host-local";
|
prefix = "host-local";
|
||||||
}
|
}
|
||||||
return android::base::StringPrintf("%s:%s", prefix, command);
|
return android::base::StringPrintf("%s:%s", prefix, command);
|
||||||
|
|
@ -308,7 +323,7 @@ std::string format_host_command(const char* command, TransportType type, const c
|
||||||
|
|
||||||
bool adb_get_feature_set(FeatureSet* feature_set, std::string* error) {
|
bool adb_get_feature_set(FeatureSet* feature_set, std::string* error) {
|
||||||
std::string result;
|
std::string result;
|
||||||
if (adb_query(format_host_command("features", __adb_transport, __adb_serial), &result, error)) {
|
if (adb_query(format_host_command("features"), &result, error)) {
|
||||||
*feature_set = StringToFeatureSet(result);
|
*feature_set = StringToFeatureSet(result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,9 @@ bool adb_query(const std::string& service, std::string* _Nonnull result,
|
||||||
std::string* _Nonnull error);
|
std::string* _Nonnull error);
|
||||||
|
|
||||||
// Set the preferred transport to connect to.
|
// Set the preferred transport to connect to.
|
||||||
void adb_set_transport(TransportType type, const char* _Nullable serial);
|
void adb_set_transport(TransportType type, const char* _Nullable serial, TransportId transport_id);
|
||||||
|
void adb_get_transport(TransportType* _Nullable type, const char* _Nullable* _Nullable serial,
|
||||||
|
TransportId* _Nullable transport_id);
|
||||||
|
|
||||||
// Set the socket specification for the adb server.
|
// Set the socket specification for the adb server.
|
||||||
// This function can only be called once, and the argument must live to the end of the process.
|
// This function can only be called once, and the argument must live to the end of the process.
|
||||||
|
|
@ -57,8 +59,7 @@ int adb_send_emulator_command(int argc, const char* _Nonnull* _Nonnull argv,
|
||||||
bool adb_status(int fd, std::string* _Nonnull error);
|
bool adb_status(int fd, std::string* _Nonnull error);
|
||||||
|
|
||||||
// Create a host command corresponding to selected transport type/serial.
|
// Create a host command corresponding to selected transport type/serial.
|
||||||
std::string format_host_command(const char* _Nonnull command, TransportType type,
|
std::string format_host_command(const char* _Nonnull command);
|
||||||
const char* _Nullable serial);
|
|
||||||
|
|
||||||
// Get the feature set of the current preferred transport.
|
// Get the feature set of the current preferred transport.
|
||||||
bool adb_get_feature_set(FeatureSet* _Nonnull feature_set, std::string* _Nonnull error);
|
bool adb_get_feature_set(FeatureSet* _Nonnull feature_set, std::string* _Nonnull error);
|
||||||
|
|
|
||||||
|
|
@ -195,13 +195,13 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface
|
||||||
DISALLOW_COPY_AND_ASSIGN(BugreportStandardStreamsCallback);
|
DISALLOW_COPY_AND_ASSIGN(BugreportStandardStreamsCallback);
|
||||||
};
|
};
|
||||||
|
|
||||||
int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, const char** argv) {
|
int Bugreport::DoIt(int argc, const char** argv) {
|
||||||
if (argc > 2) return syntax_error("adb bugreport [PATH]");
|
if (argc > 2) return syntax_error("adb bugreport [PATH]");
|
||||||
|
|
||||||
// Gets bugreportz version.
|
// Gets bugreportz version.
|
||||||
std::string bugz_stdout, bugz_stderr;
|
std::string bugz_stdout, bugz_stderr;
|
||||||
DefaultStandardStreamsCallback version_callback(&bugz_stdout, &bugz_stderr);
|
DefaultStandardStreamsCallback version_callback(&bugz_stdout, &bugz_stderr);
|
||||||
int status = SendShellCommand(transport_type, serial, "bugreportz -v", false, &version_callback);
|
int status = SendShellCommand("bugreportz -v", false, &version_callback);
|
||||||
std::string bugz_version = android::base::Trim(bugz_stderr);
|
std::string bugz_version = android::base::Trim(bugz_stderr);
|
||||||
std::string bugz_output = android::base::Trim(bugz_stdout);
|
std::string bugz_output = android::base::Trim(bugz_stdout);
|
||||||
|
|
||||||
|
|
@ -214,7 +214,7 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc,
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Failed to get bugreportz version, which is only available on devices "
|
"Failed to get bugreportz version, which is only available on devices "
|
||||||
"running Android 7.0 or later.\nTrying a plain-text bug report instead.\n");
|
"running Android 7.0 or later.\nTrying a plain-text bug report instead.\n");
|
||||||
return SendShellCommand(transport_type, serial, "bugreport", false);
|
return SendShellCommand("bugreport", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// But if user explicitly asked for a zipped bug report, fails instead (otherwise calling
|
// But if user explicitly asked for a zipped bug report, fails instead (otherwise calling
|
||||||
|
|
@ -265,7 +265,7 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc,
|
||||||
bugz_command = "bugreportz";
|
bugz_command = "bugreportz";
|
||||||
}
|
}
|
||||||
BugreportStandardStreamsCallback bugz_callback(dest_dir, dest_file, show_progress, this);
|
BugreportStandardStreamsCallback bugz_callback(dest_dir, dest_file, show_progress, this);
|
||||||
return SendShellCommand(transport_type, serial, bugz_command, false, &bugz_callback);
|
return SendShellCommand(bugz_command, false, &bugz_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bugreport::UpdateProgress(const std::string& message, int progress_percentage) {
|
void Bugreport::UpdateProgress(const std::string& message, int progress_percentage) {
|
||||||
|
|
@ -274,10 +274,9 @@ void Bugreport::UpdateProgress(const std::string& message, int progress_percenta
|
||||||
LinePrinter::INFO);
|
LinePrinter::INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Bugreport::SendShellCommand(TransportType transport_type, const char* serial,
|
int Bugreport::SendShellCommand(const std::string& command, bool disable_shell_protocol,
|
||||||
const std::string& command, bool disable_shell_protocol,
|
|
||||||
StandardStreamsCallbackInterface* callback) {
|
StandardStreamsCallbackInterface* callback) {
|
||||||
return send_shell_command(transport_type, serial, command, disable_shell_protocol, callback);
|
return send_shell_command(command, disable_shell_protocol, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bugreport::DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
|
bool Bugreport::DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,13 @@ class Bugreport {
|
||||||
public:
|
public:
|
||||||
Bugreport() : line_printer_() {
|
Bugreport() : line_printer_() {
|
||||||
}
|
}
|
||||||
int DoIt(TransportType transport_type, const char* serial, int argc, const char** argv);
|
int DoIt(int argc, const char** argv);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Functions below are abstractions of external functions so they can be
|
// Functions below are abstractions of external functions so they can be
|
||||||
// mocked on tests.
|
// mocked on tests.
|
||||||
virtual int SendShellCommand(
|
virtual int SendShellCommand(
|
||||||
TransportType transport_type, const char* serial, const std::string& command,
|
const std::string& command, bool disable_shell_protocol,
|
||||||
bool disable_shell_protocol,
|
|
||||||
StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
|
StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
|
||||||
|
|
||||||
virtual bool DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
|
virtual bool DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool co
|
||||||
// Empty functions so tests don't need to be linked against commandline.cpp
|
// Empty functions so tests don't need to be linked against commandline.cpp
|
||||||
DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
|
DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
|
||||||
|
|
||||||
int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
|
int send_shell_command(const std::string& command, bool disable_shell_protocol,
|
||||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
|
StandardStreamsCallbackInterface* callback) {
|
||||||
ADD_FAILURE() << "send_shell_command() should have been mocked";
|
ADD_FAILURE() << "send_shell_command() should have been mocked";
|
||||||
return -42;
|
return -42;
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ enum StreamType {
|
||||||
kStreamStderr,
|
kStreamStderr,
|
||||||
};
|
};
|
||||||
|
|
||||||
// gmock black magic to provide a WithArg<4>(WriteOnStdout(output)) matcher
|
// gmock black magic to provide a WithArg<2>(WriteOnStdout(output)) matcher
|
||||||
typedef void OnStandardStreamsCallbackFunction(StandardStreamsCallbackInterface*);
|
typedef void OnStandardStreamsCallbackFunction(StandardStreamsCallbackInterface*);
|
||||||
|
|
||||||
class OnStandardStreamsCallbackAction : public ActionInterface<OnStandardStreamsCallbackFunction> {
|
class OnStandardStreamsCallbackAction : public ActionInterface<OnStandardStreamsCallbackFunction> {
|
||||||
|
|
@ -118,9 +118,8 @@ Action<CallbackDoneFunction> ReturnCallbackDone(int status = -1337) {
|
||||||
|
|
||||||
class BugreportMock : public Bugreport {
|
class BugreportMock : public Bugreport {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD5(SendShellCommand,
|
MOCK_METHOD3(SendShellCommand, int(const std::string& command, bool disable_shell_protocol,
|
||||||
int(TransportType transport_type, const char* serial, const std::string& command,
|
StandardStreamsCallbackInterface* callback));
|
||||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback));
|
|
||||||
MOCK_METHOD4(DoSyncPull, bool(const std::vector<const char*>& srcs, const char* dst,
|
MOCK_METHOD4(DoSyncPull, bool(const std::vector<const char*>& srcs, const char* dst,
|
||||||
bool copy_attrs, const char* name));
|
bool copy_attrs, const char* name));
|
||||||
MOCK_METHOD2(UpdateProgress, void(const std::string&, int));
|
MOCK_METHOD2(UpdateProgress, void(const std::string&, int));
|
||||||
|
|
@ -136,10 +135,9 @@ class BugreportTest : public ::testing::Test {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpectBugreportzVersion(const std::string& version) {
|
void ExpectBugreportzVersion(const std::string& version) {
|
||||||
EXPECT_CALL(br_,
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _))
|
||||||
SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
|
.WillOnce(DoAll(WithArg<2>(WriteOnStderr(version.c_str())),
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStderr(version.c_str())),
|
WithArg<2>(ReturnCallbackDone(0))));
|
||||||
WithArg<4>(ReturnCallbackDone(0))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpectProgress(int progress_percentage, const std::string& file = "file.zip") {
|
void ExpectProgress(int progress_percentage, const std::string& file = "file.zip") {
|
||||||
|
|
@ -153,26 +151,26 @@ class BugreportTest : public ::testing::Test {
|
||||||
// Tests when called with invalid number of arguments
|
// Tests when called with invalid number of arguments
|
||||||
TEST_F(BugreportTest, InvalidNumberArgs) {
|
TEST_F(BugreportTest, InvalidNumberArgs) {
|
||||||
const char* args[] = {"bugreport", "to", "principal"};
|
const char* args[] = {"bugreport", "to", "principal"};
|
||||||
ASSERT_EQ(1, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args));
|
ASSERT_EQ(1, br_.DoIt(3, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests the 'adb bugreport' option when the device does not support 'bugreportz' - it falls back
|
// Tests the 'adb bugreport' option when the device does not support 'bugreportz' - it falls back
|
||||||
// to the flat-file format ('bugreport' binary on device)
|
// to the flat-file format ('bugreport' binary on device)
|
||||||
TEST_F(BugreportTest, NoArgumentsPreNDevice) {
|
TEST_F(BugreportTest, NoArgumentsPreNDevice) {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStderr("")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStderr("")),
|
||||||
// Write some bogus output on stdout to make sure it's ignored
|
// Write some bogus output on stdout to make sure it's ignored
|
||||||
WithArg<4>(WriteOnStdout("Dude, where is my bugreportz?")),
|
WithArg<2>(WriteOnStdout("Dude, where is my bugreportz?")),
|
||||||
WithArg<4>(ReturnCallbackDone(0))));
|
WithArg<2>(ReturnCallbackDone(0))));
|
||||||
// clang-format on
|
// clang-format on
|
||||||
std::string bugreport = "Reported the bug was.";
|
std::string bugreport = "Reported the bug was.";
|
||||||
CaptureStdout();
|
CaptureStdout();
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreport", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreport", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout(bugreport)), Return(0)));
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout(bugreport)), Return(0)));
|
||||||
|
|
||||||
const char* args[] = {"bugreport"};
|
const char* args[] = {"bugreport"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
|
ASSERT_EQ(0, br_.DoIt(1, args));
|
||||||
ASSERT_THAT(GetCapturedStdout(), StrEq(bugreport));
|
ASSERT_THAT(GetCapturedStdout(), StrEq(bugreport));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -183,15 +181,15 @@ TEST_F(BugreportTest, NoArgumentsNDevice) {
|
||||||
|
|
||||||
std::string dest_file =
|
std::string dest_file =
|
||||||
android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
|
android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||||
true, StrEq("pulling da_bugreport.zip")))
|
true, StrEq("pulling da_bugreport.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport"};
|
const char* args[] = {"bugreport"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
|
ASSERT_EQ(0, br_.DoIt(1, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.1 - it will
|
// Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.1 - it will
|
||||||
|
|
@ -201,47 +199,47 @@ TEST_F(BugreportTest, NoArgumentsPostNDevice) {
|
||||||
std::string dest_file =
|
std::string dest_file =
|
||||||
android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
|
android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
|
||||||
ExpectProgress(50, "da_bugreport.zip");
|
ExpectProgress(50, "da_bugreport.zip");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:50/100\n")),
|
WithArg<2>(WriteOnStdout("PROGRESS:50/100\n")),
|
||||||
WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
|
WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||||
true, StrEq("pulling da_bugreport.zip")))
|
true, StrEq("pulling da_bugreport.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport"};
|
const char* args[] = {"bugreport"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
|
ASSERT_EQ(0, br_.DoIt(1, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when it succeeds and device does not support progress.
|
// Tests 'adb bugreport file.zip' when it succeeds and device does not support progress.
|
||||||
TEST_F(BugreportTest, OkNDevice) {
|
TEST_F(BugreportTest, OkNDevice) {
|
||||||
ExpectBugreportzVersion("1.0");
|
ExpectBugreportzVersion("1.0");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||||
true, StrEq("pulling file.zip")))
|
true, StrEq("pulling file.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when it succeeds but response was sent in
|
// Tests 'adb bugreport file.zip' when it succeeds but response was sent in
|
||||||
// multiple buffer writers and without progress updates.
|
// multiple buffer writers and without progress updates.
|
||||||
TEST_F(BugreportTest, OkNDeviceSplitBuffer) {
|
TEST_F(BugreportTest, OkNDeviceSplitBuffer) {
|
||||||
ExpectBugreportzVersion("1.0");
|
ExpectBugreportzVersion("1.0");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device")),
|
||||||
WithArg<4>(WriteOnStdout("/bugreport.zip")),
|
WithArg<2>(WriteOnStdout("/bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||||
true, StrEq("pulling file.zip")))
|
true, StrEq("pulling file.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when it succeeds and displays progress.
|
// Tests 'adb bugreport file.zip' when it succeeds and displays progress.
|
||||||
|
|
@ -252,32 +250,32 @@ TEST_F(BugreportTest, OkProgress) {
|
||||||
ExpectProgress(50);
|
ExpectProgress(50);
|
||||||
ExpectProgress(99);
|
ExpectProgress(99);
|
||||||
// clang-format off
|
// clang-format off
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
// NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
|
// NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
|
||||||
.WillOnce(DoAll(
|
.WillOnce(DoAll(
|
||||||
// Name might change on OK, so make sure the right one is picked.
|
// Name might change on OK, so make sure the right one is picked.
|
||||||
WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport___NOT.zip\n")),
|
WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport___NOT.zip\n")),
|
||||||
// Progress line in one write
|
// Progress line in one write
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")),
|
WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")),
|
||||||
// Add some bogus lines
|
// Add some bogus lines
|
||||||
WithArg<4>(WriteOnStdout("\nDUDE:SWEET\n\nBLA\n\nBLA\nBLA\n\n")),
|
WithArg<2>(WriteOnStdout("\nDUDE:SWEET\n\nBLA\n\nBLA\nBLA\n\n")),
|
||||||
// Multiple progress lines in one write
|
// Multiple progress lines in one write
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:10/100\nPROGRESS:50/100\n")),
|
WithArg<2>(WriteOnStdout("PROGRESS:10/100\nPROGRESS:50/100\n")),
|
||||||
// Progress line in multiple writes
|
// Progress line in multiple writes
|
||||||
WithArg<4>(WriteOnStdout("PROG")),
|
WithArg<2>(WriteOnStdout("PROG")),
|
||||||
WithArg<4>(WriteOnStdout("RESS:99")),
|
WithArg<2>(WriteOnStdout("RESS:99")),
|
||||||
WithArg<4>(WriteOnStdout("/100\n")),
|
WithArg<2>(WriteOnStdout("/100\n")),
|
||||||
// Split last message as well, just in case
|
// Split last message as well, just in case
|
||||||
WithArg<4>(WriteOnStdout("OK:/device/bugreport")),
|
WithArg<2>(WriteOnStdout("OK:/device/bugreport")),
|
||||||
WithArg<4>(WriteOnStdout(".zip")),
|
WithArg<2>(WriteOnStdout(".zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
// clang-format on
|
// clang-format on
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||||
true, StrEq("pulling file.zip")))
|
true, StrEq("pulling file.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when it succeeds and displays progress, even if progress recedes.
|
// Tests 'adb bugreport file.zip' when it succeeds and displays progress, even if progress recedes.
|
||||||
|
|
@ -287,28 +285,28 @@ TEST_F(BugreportTest, OkProgressAlwaysForward) {
|
||||||
ExpectProgress(50);
|
ExpectProgress(50);
|
||||||
ExpectProgress(75);
|
ExpectProgress(75);
|
||||||
// clang-format off
|
// clang-format off
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
// NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
|
// NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
|
||||||
.WillOnce(DoAll(
|
.WillOnce(DoAll(
|
||||||
WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:50/100\n")), // 50%
|
WithArg<2>(WriteOnStdout("PROGRESS:50/100\n")), // 50%
|
||||||
// 25% should be ignored becaused it receded.
|
// 25% should be ignored becaused it receded.
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:25/100\n")), // 25%
|
WithArg<2>(WriteOnStdout("PROGRESS:25/100\n")), // 25%
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
|
WithArg<2>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
|
||||||
// 75% should be ignored becaused it didn't change.
|
// 75% should be ignored becaused it didn't change.
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
|
WithArg<2>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
|
||||||
// Try a receeding percentage with a different max progress
|
// Try a receeding percentage with a different max progress
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:700/1000\n")), // 70%
|
WithArg<2>(WriteOnStdout("PROGRESS:700/1000\n")), // 70%
|
||||||
WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
// clang-format on
|
// clang-format on
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||||
true, StrEq("pulling file.zip")))
|
true, StrEq("pulling file.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when it succeeds and displays the initial progress of 0%
|
// Tests 'adb bugreport file.zip' when it succeeds and displays the initial progress of 0%
|
||||||
|
|
@ -317,21 +315,21 @@ TEST_F(BugreportTest, OkProgressZeroPercentIsNotIgnored) {
|
||||||
ExpectProgress(0);
|
ExpectProgress(0);
|
||||||
ExpectProgress(1);
|
ExpectProgress(1);
|
||||||
// clang-format off
|
// clang-format off
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
// NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
|
// NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
|
||||||
.WillOnce(DoAll(
|
.WillOnce(DoAll(
|
||||||
WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100000\n")),
|
WithArg<2>(WriteOnStdout("PROGRESS:1/100000\n")),
|
||||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
||||||
WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
// clang-format on
|
// clang-format on
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||||
true, StrEq("pulling file.zip")))
|
true, StrEq("pulling file.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport dir' when it succeeds and destination is a directory.
|
// Tests 'adb bugreport dir' when it succeeds and destination is a directory.
|
||||||
|
|
@ -341,30 +339,30 @@ TEST_F(BugreportTest, OkDirectory) {
|
||||||
std::string dest_file =
|
std::string dest_file =
|
||||||
android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
|
android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
|
||||||
|
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||||
WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||||
true, StrEq("pulling da_bugreport.zip")))
|
true, StrEq("pulling da_bugreport.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", td.path};
|
const char* args[] = {"bugreport", td.path};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file' when it succeeds
|
// Tests 'adb bugreport file' when it succeeds
|
||||||
TEST_F(BugreportTest, OkNoExtension) {
|
TEST_F(BugreportTest, OkNoExtension) {
|
||||||
ExpectBugreportzVersion("1.1");
|
ExpectBugreportzVersion("1.1");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip\n")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||||
true, StrEq("pulling file.zip")))
|
true, StrEq("pulling file.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file"};
|
const char* args[] = {"bugreport", "file"};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport dir' when it succeeds and destination is a directory and device runs N.
|
// Tests 'adb bugreport dir' when it succeeds and destination is a directory and device runs N.
|
||||||
|
|
@ -374,28 +372,28 @@ TEST_F(BugreportTest, OkNDeviceDirectory) {
|
||||||
std::string dest_file =
|
std::string dest_file =
|
||||||
android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
|
android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
|
||||||
|
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||||
WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||||
true, StrEq("pulling da_bugreport.zip")))
|
true, StrEq("pulling da_bugreport.zip")))
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", td.path};
|
const char* args[] = {"bugreport", td.path};
|
||||||
ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(0, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when the bugreport itself failed
|
// Tests 'adb bugreport file.zip' when the bugreport itself failed
|
||||||
TEST_F(BugreportTest, BugreportzReturnedFail) {
|
TEST_F(BugreportTest, BugreportzReturnedFail) {
|
||||||
ExpectBugreportzVersion("1.1");
|
ExpectBugreportzVersion("1.1");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
.WillOnce(
|
.WillOnce(
|
||||||
DoAll(WithArg<4>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<4>(ReturnCallbackDone())));
|
DoAll(WithArg<2>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<2>(ReturnCallbackDone())));
|
||||||
|
|
||||||
CaptureStderr();
|
CaptureStderr();
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(-1, br_.DoIt(2, args));
|
||||||
ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
|
ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -404,13 +402,13 @@ TEST_F(BugreportTest, BugreportzReturnedFail) {
|
||||||
// multiple buffer writes
|
// multiple buffer writes
|
||||||
TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
|
TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
|
||||||
ExpectBugreportzVersion("1.1");
|
ExpectBugreportzVersion("1.1");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL")), WithArg<4>(WriteOnStdout(":D'OH!\n")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("FAIL")), WithArg<2>(WriteOnStdout(":D'OH!\n")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
|
|
||||||
CaptureStderr();
|
CaptureStderr();
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(-1, br_.DoIt(2, args));
|
||||||
ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
|
ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,23 +416,22 @@ TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
|
||||||
// response.
|
// response.
|
||||||
TEST_F(BugreportTest, BugreportzReturnedUnsupported) {
|
TEST_F(BugreportTest, BugreportzReturnedUnsupported) {
|
||||||
ExpectBugreportzVersion("1.1");
|
ExpectBugreportzVersion("1.1");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("bugreportz? What am I, a zombie?")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("bugreportz? What am I, a zombie?")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
|
|
||||||
CaptureStderr();
|
CaptureStderr();
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(-1, br_.DoIt(2, args));
|
||||||
ASSERT_THAT(GetCapturedStderr(), HasSubstr("bugreportz? What am I, a zombie?"));
|
ASSERT_THAT(GetCapturedStderr(), HasSubstr("bugreportz? What am I, a zombie?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when the bugreportz -v command failed
|
// Tests 'adb bugreport file.zip' when the bugreportz -v command failed
|
||||||
TEST_F(BugreportTest, BugreportzVersionFailed) {
|
TEST_F(BugreportTest, BugreportzVersionFailed) {
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _)).WillOnce(Return(666));
|
||||||
.WillOnce(Return(666));
|
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(666, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(666, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when the bugreportz -v returns status 0 but with no output.
|
// Tests 'adb bugreport file.zip' when the bugreportz -v returns status 0 but with no output.
|
||||||
|
|
@ -442,29 +439,28 @@ TEST_F(BugreportTest, BugreportzVersionEmpty) {
|
||||||
ExpectBugreportzVersion("");
|
ExpectBugreportzVersion("");
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(-1, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when the main bugreportz command failed
|
// Tests 'adb bugreport file.zip' when the main bugreportz command failed
|
||||||
TEST_F(BugreportTest, BugreportzFailed) {
|
TEST_F(BugreportTest, BugreportzFailed) {
|
||||||
ExpectBugreportzVersion("1.1");
|
ExpectBugreportzVersion("1.1");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _)).WillOnce(Return(666));
|
||||||
.WillOnce(Return(666));
|
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(666, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(666, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests 'adb bugreport file.zip' when the bugreport could not be pulled
|
// Tests 'adb bugreport file.zip' when the bugreport could not be pulled
|
||||||
TEST_F(BugreportTest, PullFails) {
|
TEST_F(BugreportTest, PullFails) {
|
||||||
ExpectBugreportzVersion("1.1");
|
ExpectBugreportzVersion("1.1");
|
||||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||||
WithArg<4>(ReturnCallbackDone())));
|
WithArg<2>(ReturnCallbackDone())));
|
||||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||||
true, HasSubstr("file.zip")))
|
true, HasSubstr("file.zip")))
|
||||||
.WillOnce(Return(false));
|
.WillOnce(Return(false));
|
||||||
|
|
||||||
const char* args[] = {"bugreport", "file.zip"};
|
const char* args[] = {"bugreport", "file.zip"};
|
||||||
ASSERT_EQ(1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
ASSERT_EQ(1, br_.DoIt(2, args));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -412,8 +412,13 @@ static void device_disconnected(libusb_device* device) {
|
||||||
if (it != usb_handles.end()) {
|
if (it != usb_handles.end()) {
|
||||||
if (!it->second->device_handle) {
|
if (!it->second->device_handle) {
|
||||||
// If the handle is null, we were never able to open the device.
|
// If the handle is null, we were never able to open the device.
|
||||||
unregister_usb_transport(it->second.get());
|
|
||||||
|
// Temporarily release the usb handles mutex to avoid deadlock.
|
||||||
|
std::unique_ptr<usb_handle> handle = std::move(it->second);
|
||||||
usb_handles.erase(it);
|
usb_handles.erase(it);
|
||||||
|
lock.unlock();
|
||||||
|
unregister_usb_transport(handle.get());
|
||||||
|
lock.lock();
|
||||||
} else {
|
} else {
|
||||||
// Closure of the transport will erase the usb_handle.
|
// Closure of the transport will erase the usb_handle.
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,11 @@
|
||||||
#include "shell_service.h"
|
#include "shell_service.h"
|
||||||
#include "sysdeps/chrono.h"
|
#include "sysdeps/chrono.h"
|
||||||
|
|
||||||
static int install_app(TransportType t, const char* serial, int argc, const char** argv);
|
static int install_app(int argc, const char** argv);
|
||||||
static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
|
static int install_multiple_app(int argc, const char** argv);
|
||||||
static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
|
static int uninstall_app(int argc, const char** argv);
|
||||||
static int install_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
|
static int install_app_legacy(int argc, const char** argv);
|
||||||
static int uninstall_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
|
static int uninstall_app_legacy(int argc, const char** argv);
|
||||||
|
|
||||||
extern int gListenAll;
|
extern int gListenAll;
|
||||||
|
|
||||||
|
|
@ -90,6 +90,7 @@ static void help() {
|
||||||
" -d use USB device (error if multiple devices connected)\n"
|
" -d use USB device (error if multiple devices connected)\n"
|
||||||
" -e use TCP/IP device (error if multiple TCP/IP devices available)\n"
|
" -e use TCP/IP device (error if multiple TCP/IP devices available)\n"
|
||||||
" -s SERIAL use device with given serial (overrides $ANDROID_SERIAL)\n"
|
" -s SERIAL use device with given serial (overrides $ANDROID_SERIAL)\n"
|
||||||
|
" -t ID use device with given transport id\n"
|
||||||
" -H name of adb server host [default=localhost]\n"
|
" -H name of adb server host [default=localhost]\n"
|
||||||
" -P port of adb server [default=5037]\n"
|
" -P port of adb server [default=5037]\n"
|
||||||
" -L SOCKET listen on given socket for adb server [default=tcp:localhost:5037]\n"
|
" -L SOCKET listen on given socket for adb server [default=tcp:localhost:5037]\n"
|
||||||
|
|
@ -986,13 +987,16 @@ static int ppp(int argc, const char** argv) {
|
||||||
#endif /* !defined(_WIN32) */
|
#endif /* !defined(_WIN32) */
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wait_for_device(const char* service, TransportType t, const char* serial) {
|
static bool wait_for_device(const char* service) {
|
||||||
std::vector<std::string> components = android::base::Split(service, "-");
|
std::vector<std::string> components = android::base::Split(service, "-");
|
||||||
if (components.size() < 3 || components.size() > 4) {
|
if (components.size() < 3 || components.size() > 4) {
|
||||||
fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
|
fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransportType t;
|
||||||
|
adb_get_transport(&t, nullptr, nullptr);
|
||||||
|
|
||||||
// Was the caller vague about what they'd like us to wait for?
|
// Was the caller vague about what they'd like us to wait for?
|
||||||
// If so, check they weren't more specific in their choice of transport type.
|
// If so, check they weren't more specific in their choice of transport type.
|
||||||
if (components.size() == 3) {
|
if (components.size() == 3) {
|
||||||
|
|
@ -1019,7 +1023,7 @@ static bool wait_for_device(const char* service, TransportType t, const char* se
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cmd = format_host_command(android::base::Join(components, "-").c_str(), t, serial);
|
std::string cmd = format_host_command(android::base::Join(components, "-").c_str());
|
||||||
return adb_command(cmd);
|
return adb_command(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1065,8 +1069,8 @@ static bool adb_root(const char* command) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
|
int send_shell_command(const std::string& command, bool disable_shell_protocol,
|
||||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
|
StandardStreamsCallbackInterface* callback) {
|
||||||
int fd;
|
int fd;
|
||||||
bool use_shell_protocol = false;
|
bool use_shell_protocol = false;
|
||||||
|
|
||||||
|
|
@ -1097,7 +1101,7 @@ int send_shell_command(TransportType transport_type, const char* serial, const s
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "- waiting for device -\n");
|
fprintf(stderr, "- waiting for device -\n");
|
||||||
if (!wait_for_device("wait-for-device", transport_type, serial)) {
|
if (!wait_for_device("wait-for-device")) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1111,7 +1115,7 @@ int send_shell_command(TransportType transport_type, const char* serial, const s
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
|
static int logcat(int argc, const char** argv) {
|
||||||
char* log_tags = getenv("ANDROID_LOG_TAGS");
|
char* log_tags = getenv("ANDROID_LOG_TAGS");
|
||||||
std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
|
std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
|
||||||
|
|
||||||
|
|
@ -1128,7 +1132,7 @@ static int logcat(TransportType transport, const char* serial, int argc, const c
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need for shell protocol with logcat, always disable for simplicity.
|
// No need for shell protocol with logcat, always disable for simplicity.
|
||||||
return send_shell_command(transport, serial, cmd, true);
|
return send_shell_command(cmd, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_zeros(int bytes, int fd) {
|
static void write_zeros(int bytes, int fd) {
|
||||||
|
|
@ -1340,6 +1344,7 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
|
|
||||||
// We need to check for -d and -e before we look at $ANDROID_SERIAL.
|
// We need to check for -d and -e before we look at $ANDROID_SERIAL.
|
||||||
const char* serial = nullptr;
|
const char* serial = nullptr;
|
||||||
|
TransportId transport_id = 0;
|
||||||
|
|
||||||
while (argc > 0) {
|
while (argc > 0) {
|
||||||
if (!strcmp(argv[0],"server")) {
|
if (!strcmp(argv[0],"server")) {
|
||||||
|
|
@ -1359,7 +1364,7 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
|
fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (argv[0][0]=='-' && argv[0][1]=='s') {
|
} else if (!strncmp(argv[0], "-s", 2)) {
|
||||||
if (isdigit(argv[0][2])) {
|
if (isdigit(argv[0][2])) {
|
||||||
serial = argv[0] + 2;
|
serial = argv[0] + 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1368,6 +1373,19 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
|
} else if (!strncmp(argv[0], "-t", 2)) {
|
||||||
|
const char* id;
|
||||||
|
if (isdigit(argv[0][2])) {
|
||||||
|
id = argv[0] + 2;
|
||||||
|
} else {
|
||||||
|
id = argv[1];
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
transport_id = strtoll(id, const_cast<char**>(&id), 10);
|
||||||
|
if (*id != '\0') {
|
||||||
|
return syntax_error("invalid transport id");
|
||||||
|
}
|
||||||
} else if (!strcmp(argv[0],"-d")) {
|
} else if (!strcmp(argv[0],"-d")) {
|
||||||
transport_type = kTransportUsb;
|
transport_type = kTransportUsb;
|
||||||
} else if (!strcmp(argv[0],"-e")) {
|
} else if (!strcmp(argv[0],"-e")) {
|
||||||
|
|
@ -1451,7 +1469,7 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
serial = getenv("ANDROID_SERIAL");
|
serial = getenv("ANDROID_SERIAL");
|
||||||
}
|
}
|
||||||
|
|
||||||
adb_set_transport(transport_type, serial);
|
adb_set_transport(transport_type, serial, transport_id);
|
||||||
|
|
||||||
if (is_server) {
|
if (is_server) {
|
||||||
if (no_daemon || is_daemon) {
|
if (no_daemon || is_daemon) {
|
||||||
|
|
@ -1478,7 +1496,7 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
|
if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
|
||||||
const char* service = argv[0];
|
const char* service = argv[0];
|
||||||
|
|
||||||
if (!wait_for_device(service, transport_type, serial)) {
|
if (!wait_for_device(service)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1589,7 +1607,7 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
return adb_root(argv[0]) ? 0 : 1;
|
return adb_root(argv[0]) ? 0 : 1;
|
||||||
} else if (!strcmp(argv[0], "bugreport")) {
|
} else if (!strcmp(argv[0], "bugreport")) {
|
||||||
Bugreport bugreport;
|
Bugreport bugreport;
|
||||||
return bugreport.DoIt(transport_type, serial, argc, argv);
|
return bugreport.DoIt(argc, argv);
|
||||||
} else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
|
} else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
|
||||||
bool reverse = !strcmp(argv[0], "reverse");
|
bool reverse = !strcmp(argv[0], "reverse");
|
||||||
++argv;
|
++argv;
|
||||||
|
|
@ -1685,20 +1703,20 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
else if (!strcmp(argv[0], "install")) {
|
else if (!strcmp(argv[0], "install")) {
|
||||||
if (argc < 2) return syntax_error("install requires an argument");
|
if (argc < 2) return syntax_error("install requires an argument");
|
||||||
if (_use_legacy_install()) {
|
if (_use_legacy_install()) {
|
||||||
return install_app_legacy(transport_type, serial, argc, argv);
|
return install_app_legacy(argc, argv);
|
||||||
}
|
}
|
||||||
return install_app(transport_type, serial, argc, argv);
|
return install_app(argc, argv);
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[0], "install-multiple")) {
|
else if (!strcmp(argv[0], "install-multiple")) {
|
||||||
if (argc < 2) return syntax_error("install-multiple requires an argument");
|
if (argc < 2) return syntax_error("install-multiple requires an argument");
|
||||||
return install_multiple_app(transport_type, serial, argc, argv);
|
return install_multiple_app(argc, argv);
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[0], "uninstall")) {
|
else if (!strcmp(argv[0], "uninstall")) {
|
||||||
if (argc < 2) return syntax_error("uninstall requires an argument");
|
if (argc < 2) return syntax_error("uninstall requires an argument");
|
||||||
if (_use_legacy_install()) {
|
if (_use_legacy_install()) {
|
||||||
return uninstall_app_legacy(transport_type, serial, argc, argv);
|
return uninstall_app_legacy(argc, argv);
|
||||||
}
|
}
|
||||||
return uninstall_app(transport_type, serial, argc, argv);
|
return uninstall_app(argc, argv);
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[0], "sync")) {
|
else if (!strcmp(argv[0], "sync")) {
|
||||||
std::string src;
|
std::string src;
|
||||||
|
|
@ -1752,11 +1770,11 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
!strcmp(argv[0],"get-serialno") ||
|
!strcmp(argv[0],"get-serialno") ||
|
||||||
!strcmp(argv[0],"get-devpath"))
|
!strcmp(argv[0],"get-devpath"))
|
||||||
{
|
{
|
||||||
return adb_query_command(format_host_command(argv[0], transport_type, serial));
|
return adb_query_command(format_host_command(argv[0]));
|
||||||
}
|
}
|
||||||
/* other commands */
|
/* other commands */
|
||||||
else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
|
else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
|
||||||
return logcat(transport_type, serial, argc, argv);
|
return logcat(argc, argv);
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[0],"ppp")) {
|
else if (!strcmp(argv[0],"ppp")) {
|
||||||
return ppp(argc, argv);
|
return ppp(argc, argv);
|
||||||
|
|
@ -1819,7 +1837,7 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
return adb_query_command("host:host-features");
|
return adb_query_command("host:host-features");
|
||||||
} else if (!strcmp(argv[0], "reconnect")) {
|
} else if (!strcmp(argv[0], "reconnect")) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
return adb_query_command(format_host_command(argv[0], transport_type, serial));
|
return adb_query_command(format_host_command(argv[0]));
|
||||||
} else if (argc == 2) {
|
} else if (argc == 2) {
|
||||||
if (!strcmp(argv[1], "device")) {
|
if (!strcmp(argv[1], "device")) {
|
||||||
std::string err;
|
std::string err;
|
||||||
|
|
@ -1838,7 +1856,7 @@ int adb_commandline(int argc, const char** argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
|
static int uninstall_app(int argc, const char** argv) {
|
||||||
// 'adb uninstall' takes the same arguments as 'cmd package uninstall' on device
|
// 'adb uninstall' takes the same arguments as 'cmd package uninstall' on device
|
||||||
std::string cmd = "cmd package";
|
std::string cmd = "cmd package";
|
||||||
while (argc-- > 0) {
|
while (argc-- > 0) {
|
||||||
|
|
@ -1854,10 +1872,10 @@ static int uninstall_app(TransportType transport, const char* serial, int argc,
|
||||||
cmd += " " + escape_arg(*argv++);
|
cmd += " " + escape_arg(*argv++);
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_shell_command(transport, serial, cmd, false);
|
return send_shell_command(cmd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
|
static int install_app(int argc, const char** argv) {
|
||||||
// The last argument must be the APK file
|
// The last argument must be the APK file
|
||||||
const char* file = argv[argc - 1];
|
const char* file = argv[argc - 1];
|
||||||
if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
|
if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
|
||||||
|
|
@ -1910,9 +1928,7 @@ static int install_app(TransportType transport, const char* serial, int argc, co
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int install_multiple_app(TransportType transport, const char* serial, int argc,
|
static int install_multiple_app(int argc, const char** argv) {
|
||||||
const char** argv)
|
|
||||||
{
|
|
||||||
// Find all APK arguments starting at end.
|
// Find all APK arguments starting at end.
|
||||||
// All other arguments passed through verbatim.
|
// All other arguments passed through verbatim.
|
||||||
int first_apk = -1;
|
int first_apk = -1;
|
||||||
|
|
@ -2037,17 +2053,17 @@ finalize_session:
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
|
static int pm_command(int argc, const char** argv) {
|
||||||
std::string cmd = "pm";
|
std::string cmd = "pm";
|
||||||
|
|
||||||
while (argc-- > 0) {
|
while (argc-- > 0) {
|
||||||
cmd += " " + escape_arg(*argv++);
|
cmd += " " + escape_arg(*argv++);
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_shell_command(transport, serial, cmd, false);
|
return send_shell_command(cmd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uninstall_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
|
static int uninstall_app_legacy(int argc, const char** argv) {
|
||||||
/* if the user choose the -k option, we refuse to do it until devices are
|
/* if the user choose the -k option, we refuse to do it until devices are
|
||||||
out with the option to uninstall the remaining data somehow (adb/ui) */
|
out with the option to uninstall the remaining data somehow (adb/ui) */
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -2063,15 +2079,15 @@ static int uninstall_app_legacy(TransportType transport, const char* serial, int
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
|
/* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
|
||||||
return pm_command(transport, serial, argc, argv);
|
return pm_command(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
|
static int delete_file(const std::string& filename) {
|
||||||
std::string cmd = "rm -f " + escape_arg(filename);
|
std::string cmd = "rm -f " + escape_arg(filename);
|
||||||
return send_shell_command(transport, serial, cmd, false);
|
return send_shell_command(cmd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
|
static int install_app_legacy(int argc, const char** argv) {
|
||||||
static const char *const DATA_DEST = "/data/local/tmp/%s";
|
static const char *const DATA_DEST = "/data/local/tmp/%s";
|
||||||
static const char *const SD_DEST = "/sdcard/tmp/%s";
|
static const char *const SD_DEST = "/sdcard/tmp/%s";
|
||||||
const char* where = DATA_DEST;
|
const char* where = DATA_DEST;
|
||||||
|
|
@ -2100,9 +2116,9 @@ static int install_app_legacy(TransportType transport, const char* serial, int a
|
||||||
where, android::base::Basename(argv[last_apk]).c_str());
|
where, android::base::Basename(argv[last_apk]).c_str());
|
||||||
if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
|
if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
|
||||||
argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
|
argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
|
||||||
result = pm_command(transport, serial, argc, argv);
|
result = pm_command(argc, argv);
|
||||||
|
|
||||||
cleanup_apk:
|
cleanup_apk:
|
||||||
delete_file(transport, serial, apk_dest);
|
delete_file(apk_dest);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,8 @@ int adb_commandline(int argc, const char** argv);
|
||||||
// Connects to the device "shell" service with |command| and prints the
|
// Connects to the device "shell" service with |command| and prints the
|
||||||
// resulting output.
|
// resulting output.
|
||||||
// if |callback| is non-null, stdout/stderr output will be handled by it.
|
// if |callback| is non-null, stdout/stderr output will be handled by it.
|
||||||
int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
|
int send_shell_command(
|
||||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback =
|
const std::string& command, bool disable_shell_protocol,
|
||||||
&DEFAULT_STANDARD_STREAMS_CALLBACK);
|
StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
|
||||||
|
|
||||||
#endif // COMMANDLINE_H
|
#endif // COMMANDLINE_H
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,7 @@ int reverse_service(const char* command) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
VLOG(SERVICES) << "service socketpair: " << s[0] << ", " << s[1];
|
VLOG(SERVICES) << "service socketpair: " << s[0] << ", " << s[1];
|
||||||
if (handle_forward_request(command, kTransportAny, nullptr, s[1]) < 0) {
|
if (handle_forward_request(command, kTransportAny, nullptr, 0, s[1]) < 0) {
|
||||||
SendFail(s[1], "not a reverse forwarding command");
|
SendFail(s[1], "not a reverse forwarding command");
|
||||||
}
|
}
|
||||||
adb_close(s[1]);
|
adb_close(s[1]);
|
||||||
|
|
@ -334,6 +334,7 @@ int service_to_fd(const char* name, const atransport* transport) {
|
||||||
struct state_info {
|
struct state_info {
|
||||||
TransportType transport_type;
|
TransportType transport_type;
|
||||||
std::string serial;
|
std::string serial;
|
||||||
|
TransportId transport_id;
|
||||||
ConnectionState state;
|
ConnectionState state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -346,7 +347,8 @@ static void wait_for_state(int fd, void* data) {
|
||||||
bool is_ambiguous = false;
|
bool is_ambiguous = false;
|
||||||
std::string error = "unknown error";
|
std::string error = "unknown error";
|
||||||
const char* serial = sinfo->serial.length() ? sinfo->serial.c_str() : NULL;
|
const char* serial = sinfo->serial.length() ? sinfo->serial.c_str() : NULL;
|
||||||
atransport* t = acquire_one_transport(sinfo->transport_type, serial, &is_ambiguous, &error);
|
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 (t != nullptr && (sinfo->state == kCsAny || sinfo->state == t->GetConnectionState())) {
|
||||||
SendOkay(fd);
|
SendOkay(fd);
|
||||||
break;
|
break;
|
||||||
|
|
@ -437,7 +439,7 @@ static void connect_service(int fd, void* data) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ADB_HOST
|
#if ADB_HOST
|
||||||
asocket* host_service_to_socket(const char* name, const char* serial) {
|
asocket* host_service_to_socket(const char* name, const char* serial, TransportId transport_id) {
|
||||||
if (!strcmp(name,"track-devices")) {
|
if (!strcmp(name,"track-devices")) {
|
||||||
return create_device_tracker();
|
return create_device_tracker();
|
||||||
} else if (android::base::StartsWith(name, "wait-for-")) {
|
} else if (android::base::StartsWith(name, "wait-for-")) {
|
||||||
|
|
@ -450,6 +452,7 @@ asocket* host_service_to_socket(const char* name, const char* serial) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serial) sinfo->serial = serial;
|
if (serial) sinfo->serial = serial;
|
||||||
|
sinfo->transport_id = transport_id;
|
||||||
|
|
||||||
if (android::base::StartsWith(name, "local")) {
|
if (android::base::StartsWith(name, "local")) {
|
||||||
name += strlen("local");
|
name += strlen("local");
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ void install_local_socket(asocket* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_socket(asocket* s) {
|
void remove_socket(asocket* s) {
|
||||||
// socket_list_lock should already be held
|
std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
|
||||||
if (s->prev && s->next) {
|
if (s->prev && s->next) {
|
||||||
s->prev->next = s->next;
|
s->prev->next = s->next;
|
||||||
s->next->prev = s->prev;
|
s->next->prev = s->prev;
|
||||||
|
|
@ -430,10 +430,11 @@ asocket* create_local_service_socket(const char* name, const atransport* transpo
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ADB_HOST
|
#if ADB_HOST
|
||||||
static asocket* create_host_service_socket(const char* name, const char* serial) {
|
static asocket* create_host_service_socket(const char* name, const char* serial,
|
||||||
|
TransportId transport_id) {
|
||||||
asocket* s;
|
asocket* s;
|
||||||
|
|
||||||
s = host_service_to_socket(name, serial);
|
s = host_service_to_socket(name, serial, transport_id);
|
||||||
|
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
D("LS(%d) bound to '%s'", s->id, name);
|
D("LS(%d) bound to '%s'", s->id, name);
|
||||||
|
|
@ -658,6 +659,7 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
||||||
#if ADB_HOST
|
#if ADB_HOST
|
||||||
char* service = nullptr;
|
char* service = nullptr;
|
||||||
char* serial = nullptr;
|
char* serial = nullptr;
|
||||||
|
TransportId transport_id = 0;
|
||||||
TransportType type = kTransportAny;
|
TransportType type = kTransportAny;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -715,6 +717,14 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
||||||
serial = service;
|
serial = service;
|
||||||
service = serial_end + 1;
|
service = serial_end + 1;
|
||||||
}
|
}
|
||||||
|
} else if (!strncmp(service, "host-transport-id:", strlen("host-transport-id:"))) {
|
||||||
|
service += strlen("host-transport-id:");
|
||||||
|
transport_id = strtoll(service, &service, 10);
|
||||||
|
|
||||||
|
if (*service != ':') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
service++;
|
||||||
} else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
|
} else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
|
||||||
type = kTransportUsb;
|
type = kTransportUsb;
|
||||||
service += strlen("host-usb:");
|
service += strlen("host-usb:");
|
||||||
|
|
@ -736,7 +746,7 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
||||||
** the OKAY or FAIL message and all we have to do
|
** the OKAY or FAIL message and all we have to do
|
||||||
** is clean up.
|
** is clean up.
|
||||||
*/
|
*/
|
||||||
if (handle_host_request(service, type, serial, s->peer->fd, s) == 0) {
|
if (handle_host_request(service, type, serial, transport_id, s->peer->fd, s) == 0) {
|
||||||
/* XXX fail message? */
|
/* XXX fail message? */
|
||||||
D("SS(%d): handled host service '%s'", s->id, service);
|
D("SS(%d): handled host service '%s'", s->id, service);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -751,7 +761,7 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
||||||
** if no such service exists, we'll fail out
|
** if no such service exists, we'll fail out
|
||||||
** and tear down here.
|
** and tear down here.
|
||||||
*/
|
*/
|
||||||
s2 = create_host_service_socket(service, serial);
|
s2 = create_host_service_socket(service, serial, transport_id);
|
||||||
if (s2 == 0) {
|
if (s2 == 0) {
|
||||||
D("SS(%d): couldn't create host service '%s'", s->id, service);
|
D("SS(%d): couldn't create host service '%s'", s->id, service);
|
||||||
SendFail(s->peer->fd, "unknown host service");
|
SendFail(s->peer->fd, "unknown host service");
|
||||||
|
|
@ -783,7 +793,7 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
||||||
#else /* !ADB_HOST */
|
#else /* !ADB_HOST */
|
||||||
if (s->transport == nullptr) {
|
if (s->transport == nullptr) {
|
||||||
std::string error_msg = "unknown failure";
|
std::string error_msg = "unknown failure";
|
||||||
s->transport = acquire_one_transport(kTransportAny, nullptr, nullptr, &error_msg);
|
s->transport = acquire_one_transport(kTransportAny, nullptr, 0, nullptr, &error_msg);
|
||||||
if (s->transport == nullptr) {
|
if (s->transport == nullptr) {
|
||||||
SendFail(s->peer->fd, error_msg);
|
SendFail(s->peer->fd, error_msg);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -36,6 +37,7 @@
|
||||||
#include <android-base/quick_exit.h>
|
#include <android-base/quick_exit.h>
|
||||||
#include <android-base/stringprintf.h>
|
#include <android-base/stringprintf.h>
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
|
#include <android-base/thread_annotations.h>
|
||||||
|
|
||||||
#include "adb.h"
|
#include "adb.h"
|
||||||
#include "adb_auth.h"
|
#include "adb_auth.h"
|
||||||
|
|
@ -46,10 +48,11 @@
|
||||||
|
|
||||||
static void transport_unref(atransport *t);
|
static void transport_unref(atransport *t);
|
||||||
|
|
||||||
|
// TODO: unordered_map<TransportId, atransport*>
|
||||||
static auto& transport_list = *new std::list<atransport*>();
|
static auto& transport_list = *new std::list<atransport*>();
|
||||||
static auto& pending_list = *new std::list<atransport*>();
|
static auto& pending_list = *new std::list<atransport*>();
|
||||||
|
|
||||||
static std::mutex& transport_lock = *new std::mutex();
|
static auto& transport_lock = *new std::recursive_mutex();
|
||||||
|
|
||||||
const char* const kFeatureShell2 = "shell_v2";
|
const char* const kFeatureShell2 = "shell_v2";
|
||||||
const char* const kFeatureCmd = "cmd";
|
const char* const kFeatureCmd = "cmd";
|
||||||
|
|
@ -57,6 +60,11 @@ const char* const kFeatureStat2 = "stat_v2";
|
||||||
const char* const kFeatureLibusb = "libusb";
|
const char* const kFeatureLibusb = "libusb";
|
||||||
const char* const kFeaturePushSync = "push_sync";
|
const char* const kFeaturePushSync = "push_sync";
|
||||||
|
|
||||||
|
TransportId NextTransportId() {
|
||||||
|
static std::atomic<TransportId> next(1);
|
||||||
|
return next++;
|
||||||
|
}
|
||||||
|
|
||||||
static std::string dump_packet(const char* name, const char* func, apacket* p) {
|
static std::string dump_packet(const char* name, const char* func, apacket* p) {
|
||||||
unsigned command = p->msg.command;
|
unsigned command = p->msg.command;
|
||||||
int len = p->msg.data_length;
|
int len = p->msg.data_length;
|
||||||
|
|
@ -298,9 +306,11 @@ static void write_transport_thread(void* _t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void kick_transport(atransport* t) {
|
void kick_transport(atransport* t) {
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
// As kick_transport() can be called from threads without guarantee that t is valid,
|
// As kick_transport() can be called from threads without guarantee that t is valid,
|
||||||
// check if the transport is in transport_list first.
|
// check if the transport is in transport_list first.
|
||||||
|
//
|
||||||
|
// TODO(jmgao): WTF? Is this actually true?
|
||||||
if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
|
if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
|
||||||
t->Kick();
|
t->Kick();
|
||||||
}
|
}
|
||||||
|
|
@ -330,7 +340,7 @@ static void device_tracker_remove(device_tracker* tracker) {
|
||||||
device_tracker** pnode = &device_tracker_list;
|
device_tracker** pnode = &device_tracker_list;
|
||||||
device_tracker* node = *pnode;
|
device_tracker* node = *pnode;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
while (node) {
|
while (node) {
|
||||||
if (node == tracker) {
|
if (node == tracker) {
|
||||||
*pnode = node->next;
|
*pnode = node->next;
|
||||||
|
|
@ -403,7 +413,7 @@ asocket* create_device_tracker(void) {
|
||||||
|
|
||||||
// Check if all of the USB transports are connected.
|
// Check if all of the USB transports are connected.
|
||||||
bool iterate_transports(std::function<bool(const atransport*)> fn) {
|
bool iterate_transports(std::function<bool(const atransport*)> fn) {
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
for (const auto& t : transport_list) {
|
for (const auto& t : transport_list) {
|
||||||
if (!fn(t)) {
|
if (!fn(t)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -507,7 +517,7 @@ static void transport_registration_func(int _fd, unsigned ev, void* data) {
|
||||||
adb_close(t->fd);
|
adb_close(t->fd);
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
transport_list.remove(t);
|
transport_list.remove(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -546,7 +556,7 @@ static void transport_registration_func(int _fd, unsigned ev, void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
pending_list.remove(t);
|
pending_list.remove(t);
|
||||||
transport_list.push_front(t);
|
transport_list.push_front(t);
|
||||||
}
|
}
|
||||||
|
|
@ -573,7 +583,7 @@ void init_transport_registration(void) {
|
||||||
|
|
||||||
void kick_all_transports() {
|
void kick_all_transports() {
|
||||||
// To avoid only writing part of a packet to a transport after exit, kick all transports.
|
// To avoid only writing part of a packet to a transport after exit, kick all transports.
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
for (auto t : transport_list) {
|
for (auto t : transport_list) {
|
||||||
t->Kick();
|
t->Kick();
|
||||||
}
|
}
|
||||||
|
|
@ -603,15 +613,15 @@ static void remove_transport(atransport* transport) {
|
||||||
static void transport_unref(atransport* t) {
|
static void transport_unref(atransport* t) {
|
||||||
CHECK(t != nullptr);
|
CHECK(t != nullptr);
|
||||||
|
|
||||||
size_t old_refcount = t->ref_count--;
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
CHECK_GT(old_refcount, 0u);
|
CHECK_GT(t->ref_count, 0u);
|
||||||
|
t->ref_count--;
|
||||||
if (old_refcount == 1u) {
|
if (t->ref_count == 0) {
|
||||||
D("transport: %s unref (kicking and closing)", t->serial);
|
D("transport: %s unref (kicking and closing)", t->serial);
|
||||||
t->close(t);
|
t->close(t);
|
||||||
remove_transport(t);
|
remove_transport(t);
|
||||||
} else {
|
} else {
|
||||||
D("transport: %s unref (count=%zu)", t->serial, old_refcount - 1);
|
D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -638,11 +648,15 @@ static int qual_match(const char* to_test, const char* prefix, const char* qual,
|
||||||
return !*to_test;
|
return !*to_test;
|
||||||
}
|
}
|
||||||
|
|
||||||
atransport* acquire_one_transport(TransportType type, const char* serial, bool* is_ambiguous,
|
atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
|
||||||
std::string* error_out, bool accept_any_state) {
|
bool* is_ambiguous, std::string* error_out,
|
||||||
|
bool accept_any_state) {
|
||||||
atransport* result = nullptr;
|
atransport* result = nullptr;
|
||||||
|
|
||||||
if (serial) {
|
if (transport_id != 0) {
|
||||||
|
*error_out =
|
||||||
|
android::base::StringPrintf("no device with transport id '%" PRIu64 "'", transport_id);
|
||||||
|
} else if (serial) {
|
||||||
*error_out = android::base::StringPrintf("device '%s' not found", serial);
|
*error_out = android::base::StringPrintf("device '%s' not found", serial);
|
||||||
} else if (type == kTransportLocal) {
|
} else if (type == kTransportLocal) {
|
||||||
*error_out = "no emulators found";
|
*error_out = "no emulators found";
|
||||||
|
|
@ -652,7 +666,7 @@ atransport* acquire_one_transport(TransportType type, const char* serial, bool*
|
||||||
*error_out = "no devices found";
|
*error_out = "no devices found";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(transport_lock);
|
std::unique_lock<std::recursive_mutex> lock(transport_lock);
|
||||||
for (const auto& t : transport_list) {
|
for (const auto& t : transport_list) {
|
||||||
if (t->GetConnectionState() == kCsNoPerm) {
|
if (t->GetConnectionState() == kCsNoPerm) {
|
||||||
#if ADB_HOST
|
#if ADB_HOST
|
||||||
|
|
@ -661,8 +675,12 @@ atransport* acquire_one_transport(TransportType type, const char* serial, bool*
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for matching serial number.
|
if (transport_id) {
|
||||||
if (serial) {
|
if (t->id == transport_id) {
|
||||||
|
result = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (serial) {
|
||||||
if (t->MatchesTarget(serial)) {
|
if (t->MatchesTarget(serial)) {
|
||||||
if (result) {
|
if (result) {
|
||||||
*error_out = "more than one device";
|
*error_out = "more than one device";
|
||||||
|
|
@ -889,18 +907,23 @@ bool atransport::MatchesTarget(const std::string& target) const {
|
||||||
|
|
||||||
#if ADB_HOST
|
#if ADB_HOST
|
||||||
|
|
||||||
|
// We use newline as our delimiter, make sure to never output it.
|
||||||
|
static std::string sanitize(std::string str, bool alphanumeric) {
|
||||||
|
auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
|
||||||
|
: [](const char c) { return c == '\n'; };
|
||||||
|
std::replace_if(str.begin(), str.end(), pred, '_');
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
static void append_transport_info(std::string* result, const char* key, const char* value,
|
static void append_transport_info(std::string* result, const char* key, const char* value,
|
||||||
bool sanitize) {
|
bool alphanumeric) {
|
||||||
if (value == nullptr || *value == '\0') {
|
if (value == nullptr || *value == '\0') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result += ' ';
|
*result += ' ';
|
||||||
*result += key;
|
*result += key;
|
||||||
|
*result += sanitize(value, alphanumeric);
|
||||||
for (const char* p = value; *p; ++p) {
|
|
||||||
result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void append_transport(const atransport* t, std::string* result, bool long_listing) {
|
static void append_transport(const atransport* t, std::string* result, bool long_listing) {
|
||||||
|
|
@ -920,6 +943,11 @@ static void append_transport(const atransport* t, std::string* result, bool long
|
||||||
append_transport_info(result, "product:", t->product, false);
|
append_transport_info(result, "product:", t->product, false);
|
||||||
append_transport_info(result, "model:", t->model, true);
|
append_transport_info(result, "model:", t->model, true);
|
||||||
append_transport_info(result, "device:", t->device, false);
|
append_transport_info(result, "device:", t->device, false);
|
||||||
|
|
||||||
|
// Put id at the end, so that anyone parsing the output here can always find it by scanning
|
||||||
|
// backwards from newlines, even with hypothetical devices named 'transport_id:1'.
|
||||||
|
*result += " transport_id:";
|
||||||
|
*result += std::to_string(t->id);
|
||||||
}
|
}
|
||||||
*result += '\n';
|
*result += '\n';
|
||||||
}
|
}
|
||||||
|
|
@ -927,7 +955,7 @@ static void append_transport(const atransport* t, std::string* result, bool long
|
||||||
std::string list_transports(bool long_listing) {
|
std::string list_transports(bool long_listing) {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
for (const auto& t : transport_list) {
|
for (const auto& t : transport_list) {
|
||||||
append_transport(t, &result, long_listing);
|
append_transport(t, &result, long_listing);
|
||||||
}
|
}
|
||||||
|
|
@ -935,7 +963,7 @@ std::string list_transports(bool long_listing) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_usb_devices(std::function<bool(const atransport*)> predicate) {
|
void close_usb_devices(std::function<bool(const atransport*)> predicate) {
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
for (auto& t : transport_list) {
|
for (auto& t : transport_list) {
|
||||||
if (predicate(t)) {
|
if (predicate(t)) {
|
||||||
t->Kick();
|
t->Kick();
|
||||||
|
|
@ -964,7 +992,7 @@ int register_socket_transport(int s, const char* serial, int port, int local) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(transport_lock);
|
std::unique_lock<std::recursive_mutex> lock(transport_lock);
|
||||||
for (const auto& transport : pending_list) {
|
for (const auto& transport : pending_list) {
|
||||||
if (transport->serial && strcmp(serial, transport->serial) == 0) {
|
if (transport->serial && strcmp(serial, transport->serial) == 0) {
|
||||||
VLOG(TRANSPORT) << "socket transport " << transport->serial
|
VLOG(TRANSPORT) << "socket transport " << transport->serial
|
||||||
|
|
@ -996,7 +1024,7 @@ int register_socket_transport(int s, const char* serial, int port, int local) {
|
||||||
atransport* find_transport(const char* serial) {
|
atransport* find_transport(const char* serial) {
|
||||||
atransport* result = nullptr;
|
atransport* result = nullptr;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
for (auto& t : transport_list) {
|
for (auto& t : transport_list) {
|
||||||
if (t->serial && strcmp(serial, t->serial) == 0) {
|
if (t->serial && strcmp(serial, t->serial) == 0) {
|
||||||
result = t;
|
result = t;
|
||||||
|
|
@ -1008,7 +1036,7 @@ atransport* find_transport(const char* serial) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void kick_all_tcp_devices() {
|
void kick_all_tcp_devices() {
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
for (auto& t : transport_list) {
|
for (auto& t : transport_list) {
|
||||||
if (t->IsTcpDevice()) {
|
if (t->IsTcpDevice()) {
|
||||||
// Kicking breaks the read_transport thread of this transport out of any read, then
|
// Kicking breaks the read_transport thread of this transport out of any read, then
|
||||||
|
|
@ -1037,7 +1065,7 @@ void register_usb_transport(usb_handle* usb, const char* serial, const char* dev
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
pending_list.push_front(t);
|
pending_list.push_front(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1046,7 +1074,7 @@ void register_usb_transport(usb_handle* usb, const char* serial, const char* dev
|
||||||
|
|
||||||
// This should only be used for transports with connection_state == kCsNoPerm.
|
// This should only be used for transports with connection_state == kCsNoPerm.
|
||||||
void unregister_usb_transport(usb_handle* usb) {
|
void unregister_usb_transport(usb_handle* usb) {
|
||||||
std::lock_guard<std::mutex> lock(transport_lock);
|
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||||
transport_list.remove_if(
|
transport_list.remove_if(
|
||||||
[usb](atransport* t) { return t->usb == usb && t->GetConnectionState() == kCsNoPerm; });
|
[usb](atransport* t) { return t->usb == usb && t->GetConnectionState() == kCsNoPerm; });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,17 @@ extern const char* const kFeatureLibusb;
|
||||||
// The server supports `push --sync`.
|
// The server supports `push --sync`.
|
||||||
extern const char* const kFeaturePushSync;
|
extern const char* const kFeaturePushSync;
|
||||||
|
|
||||||
|
TransportId NextTransportId();
|
||||||
|
|
||||||
class atransport {
|
class atransport {
|
||||||
public:
|
public:
|
||||||
// TODO(danalbert): We expose waaaaaaay too much stuff because this was
|
// TODO(danalbert): We expose waaaaaaay too much stuff because this was
|
||||||
// historically just a struct, but making the whole thing a more idiomatic
|
// historically just a struct, but making the whole thing a more idiomatic
|
||||||
// class in one go is a very large change. Given how bad our testing is,
|
// class in one go is a very large change. Given how bad our testing is,
|
||||||
// it's better to do this piece by piece.
|
// it's better to do this piece by piece.
|
||||||
|
|
||||||
atransport(ConnectionState state = kCsOffline) : ref_count(0), connection_state_(state) {
|
atransport(ConnectionState state = kCsOffline)
|
||||||
|
: id(NextTransportId()), connection_state_(state) {
|
||||||
transport_fde = {};
|
transport_fde = {};
|
||||||
protocol_version = A_VERSION;
|
protocol_version = A_VERSION;
|
||||||
max_payload = MAX_PAYLOAD;
|
max_payload = MAX_PAYLOAD;
|
||||||
|
|
@ -72,12 +75,8 @@ public:
|
||||||
void (*close)(atransport* t) = nullptr;
|
void (*close)(atransport* t) = nullptr;
|
||||||
|
|
||||||
void SetWriteFunction(int (*write_func)(apacket*, atransport*)) { write_func_ = write_func; }
|
void SetWriteFunction(int (*write_func)(apacket*, atransport*)) { write_func_ = write_func; }
|
||||||
void SetKickFunction(void (*kick_func)(atransport*)) {
|
void SetKickFunction(void (*kick_func)(atransport*)) { kick_func_ = kick_func; }
|
||||||
kick_func_ = kick_func;
|
bool IsKicked() { return kicked_; }
|
||||||
}
|
|
||||||
bool IsKicked() {
|
|
||||||
return kicked_;
|
|
||||||
}
|
|
||||||
int Write(apacket* p);
|
int Write(apacket* p);
|
||||||
void Kick();
|
void Kick();
|
||||||
|
|
||||||
|
|
@ -85,10 +84,11 @@ public:
|
||||||
ConnectionState GetConnectionState() const;
|
ConnectionState GetConnectionState() const;
|
||||||
void SetConnectionState(ConnectionState state);
|
void SetConnectionState(ConnectionState state);
|
||||||
|
|
||||||
|
const TransportId id;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int transport_socket = -1;
|
int transport_socket = -1;
|
||||||
fdevent transport_fde;
|
fdevent transport_fde;
|
||||||
std::atomic<size_t> ref_count;
|
size_t ref_count = 0;
|
||||||
uint32_t sync_token = 0;
|
uint32_t sync_token = 0;
|
||||||
bool online = false;
|
bool online = false;
|
||||||
TransportType type = kTransportAny;
|
TransportType type = kTransportAny;
|
||||||
|
|
@ -191,12 +191,14 @@ private:
|
||||||
/*
|
/*
|
||||||
* Obtain a transport from the available transports.
|
* Obtain a transport from the available transports.
|
||||||
* If serial is non-null then only the device with that serial will be chosen.
|
* If serial is non-null then only the device with that serial will be chosen.
|
||||||
|
* If transport_id is non-zero then only the device with that transport ID will be chosen.
|
||||||
* If multiple devices/emulators would match, *is_ambiguous (if non-null)
|
* If multiple devices/emulators would match, *is_ambiguous (if non-null)
|
||||||
* is set to true and nullptr returned.
|
* is set to true and nullptr returned.
|
||||||
* If no suitable transport is found, error is set and nullptr returned.
|
* If no suitable transport is found, error is set and nullptr returned.
|
||||||
*/
|
*/
|
||||||
atransport* acquire_one_transport(TransportType type, const char* serial, bool* is_ambiguous,
|
atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
|
||||||
std::string* error_out, bool accept_any_state = false);
|
bool* is_ambiguous, std::string* error_out,
|
||||||
|
bool accept_any_state = false);
|
||||||
void kick_transport(atransport* t);
|
void kick_transport(atransport* t);
|
||||||
void update_transports(void);
|
void update_transports(void);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue