adb: allow selection of a specific transport.
Extend device selection to allow selecting a specific transport via
monotonically increasing identifier (visible in devices -l).
This is useful when using multiple devices (like hikey960...) that
have identical bogus serial numbers like 0123456789ABCDEF.
Bug: http://b/37043226
Bug: 65419665
Test: adb -t {1, 2, 9999999} {get-serialno, shell, features}
Change-Id: I55e5dc5a406a4eeee0012e39b52e8cd232e608a6
(cherry picked from commit b122b17555
)
This commit is contained in:
parent
39103b95c8
commit
1bd8498fc8
13 changed files with 290 additions and 210 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.
|
||||
// This returns 1 on success, 0 on failure, and -1 to indicate this is not
|
||||
// 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")) {
|
||||
// Create the list of forward redirections.
|
||||
std::string listeners = format_listeners();
|
||||
|
@ -1010,7 +1010,8 @@ int handle_forward_request(const char* service, TransportType type, const char*
|
|||
}
|
||||
|
||||
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) {
|
||||
SendFail(reply_fd, error_msg);
|
||||
return 1;
|
||||
|
@ -1068,8 +1069,8 @@ static int SendOkay(int fd, const std::string& s) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (strcmp(service, "kill") == 0) {
|
||||
fprintf(stderr, "adb server killed by remote request\n");
|
||||
fflush(stdout);
|
||||
|
@ -1089,7 +1090,14 @@ int handle_host_request(const char* service, TransportType type,
|
|||
if (!strncmp(service, "transport", strlen("transport"))) {
|
||||
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;
|
||||
} else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
|
||||
type = kTransportLocal;
|
||||
|
@ -1101,7 +1109,7 @@ int handle_host_request(const char* service, TransportType type,
|
|||
}
|
||||
|
||||
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) {
|
||||
s->transport = t;
|
||||
SendOkay(reply_fd);
|
||||
|
@ -1144,7 +1152,7 @@ int handle_host_request(const char* service, TransportType type,
|
|||
|
||||
if (!strcmp(service, "features")) {
|
||||
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) {
|
||||
SendOkay(reply_fd, FeatureSetToString(t->features()));
|
||||
} 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.
|
||||
if (!strcmp(service, "get-serialno")) {
|
||||
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) {
|
||||
return SendOkay(reply_fd, t->serial ? t->serial : "unknown");
|
||||
} else {
|
||||
|
@ -1206,7 +1214,7 @@ int handle_host_request(const char* service, TransportType type,
|
|||
}
|
||||
if (!strcmp(service, "get-devpath")) {
|
||||
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) {
|
||||
return SendOkay(reply_fd, t->devpath ? t->devpath : "unknown");
|
||||
} else {
|
||||
|
@ -1215,7 +1223,7 @@ int handle_host_request(const char* service, TransportType type,
|
|||
}
|
||||
if (!strcmp(service, "get-state")) {
|
||||
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) {
|
||||
return SendOkay(reply_fd, t->connection_state_name());
|
||||
} else {
|
||||
|
@ -1233,7 +1241,7 @@ int handle_host_request(const char* service, TransportType type,
|
|||
|
||||
if (!strcmp(service, "reconnect")) {
|
||||
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) {
|
||||
kick_transport(t);
|
||||
response =
|
||||
|
@ -1242,7 +1250,7 @@ int handle_host_request(const char* service, TransportType type,
|
|||
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)
|
||||
return ret - 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.
|
||||
#define ADB_SERVER_VERSION 39
|
||||
|
||||
using TransportId = uint64_t;
|
||||
class atransport;
|
||||
|
||||
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);
|
||||
#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
|
||||
|
||||
#if !ADB_HOST
|
||||
|
@ -159,7 +160,8 @@ asocket* create_jdwp_tracker_service_socket();
|
|||
int create_jdwp_connection_fd(int jdwp_pid);
|
||||
#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
|
||||
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)
|
||||
#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_offline(atransport *t);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "adb_client.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
@ -46,12 +47,20 @@
|
|||
|
||||
static TransportType __adb_transport = kTransportAny;
|
||||
static const char* __adb_serial = NULL;
|
||||
static TransportId __adb_transport_id = 0;
|
||||
|
||||
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_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) {
|
||||
|
@ -63,7 +72,10 @@ void adb_set_socket_spec(const char* socket_spec) {
|
|||
|
||||
static int switch_socket_transport(int fd, std::string* error) {
|
||||
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 += __adb_serial;
|
||||
} else {
|
||||
|
@ -292,15 +304,18 @@ bool adb_query(const std::string& service, std::string* result, std::string* err
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string format_host_command(const char* command, TransportType type, const char* serial) {
|
||||
if (serial) {
|
||||
return android::base::StringPrintf("host-serial:%s:%s", serial, command);
|
||||
std::string format_host_command(const char* command) {
|
||||
if (__adb_transport_id) {
|
||||
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";
|
||||
if (type == kTransportUsb) {
|
||||
if (__adb_transport == kTransportUsb) {
|
||||
prefix = "host-usb";
|
||||
} else if (type == kTransportLocal) {
|
||||
} else if (__adb_transport == kTransportLocal) {
|
||||
prefix = "host-local";
|
||||
}
|
||||
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) {
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,9 @@ bool adb_query(const std::string& service, std::string* _Nonnull result,
|
|||
std::string* _Nonnull error);
|
||||
|
||||
// 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.
|
||||
// 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);
|
||||
|
||||
// Create a host command corresponding to selected transport type/serial.
|
||||
std::string format_host_command(const char* _Nonnull command, TransportType type,
|
||||
const char* _Nullable serial);
|
||||
std::string format_host_command(const char* _Nonnull command);
|
||||
|
||||
// Get the feature set of the current preferred transport.
|
||||
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);
|
||||
};
|
||||
|
||||
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]");
|
||||
|
||||
// Gets bugreportz version.
|
||||
std::string 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_output = android::base::Trim(bugz_stdout);
|
||||
|
||||
|
@ -214,7 +214,7 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc,
|
|||
fprintf(stderr,
|
||||
"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");
|
||||
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
|
||||
|
@ -265,7 +265,7 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc,
|
|||
bugz_command = "bugreportz";
|
||||
}
|
||||
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) {
|
||||
|
@ -274,10 +274,9 @@ void Bugreport::UpdateProgress(const std::string& message, int progress_percenta
|
|||
LinePrinter::INFO);
|
||||
}
|
||||
|
||||
int Bugreport::SendShellCommand(TransportType transport_type, const char* serial,
|
||||
const std::string& command, bool disable_shell_protocol,
|
||||
int Bugreport::SendShellCommand(const std::string& command, bool disable_shell_protocol,
|
||||
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,
|
||||
|
|
|
@ -29,14 +29,13 @@ class Bugreport {
|
|||
public:
|
||||
Bugreport() : line_printer_() {
|
||||
}
|
||||
int DoIt(TransportType transport_type, const char* serial, int argc, const char** argv);
|
||||
int DoIt(int argc, const char** argv);
|
||||
|
||||
protected:
|
||||
// Functions below are abstractions of external functions so they can be
|
||||
// mocked on tests.
|
||||
virtual int SendShellCommand(
|
||||
TransportType transport_type, const char* serial, const std::string& command,
|
||||
bool disable_shell_protocol,
|
||||
const std::string& command, bool disable_shell_protocol,
|
||||
StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
|
||||
|
||||
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
|
||||
DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
|
||||
|
||||
int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
|
||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
|
||||
int send_shell_command(const std::string& command, bool disable_shell_protocol,
|
||||
StandardStreamsCallbackInterface* callback) {
|
||||
ADD_FAILURE() << "send_shell_command() should have been mocked";
|
||||
return -42;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ enum StreamType {
|
|||
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*);
|
||||
|
||||
class OnStandardStreamsCallbackAction : public ActionInterface<OnStandardStreamsCallbackFunction> {
|
||||
|
@ -118,9 +118,8 @@ Action<CallbackDoneFunction> ReturnCallbackDone(int status = -1337) {
|
|||
|
||||
class BugreportMock : public Bugreport {
|
||||
public:
|
||||
MOCK_METHOD5(SendShellCommand,
|
||||
int(TransportType transport_type, const char* serial, const std::string& command,
|
||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback));
|
||||
MOCK_METHOD3(SendShellCommand, int(const std::string& command, bool disable_shell_protocol,
|
||||
StandardStreamsCallbackInterface* callback));
|
||||
MOCK_METHOD4(DoSyncPull, bool(const std::vector<const char*>& srcs, const char* dst,
|
||||
bool copy_attrs, const char* name));
|
||||
MOCK_METHOD2(UpdateProgress, void(const std::string&, int));
|
||||
|
@ -136,10 +135,9 @@ class BugreportTest : public ::testing::Test {
|
|||
}
|
||||
|
||||
void ExpectBugreportzVersion(const std::string& version) {
|
||||
EXPECT_CALL(br_,
|
||||
SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStderr(version.c_str())),
|
||||
WithArg<4>(ReturnCallbackDone(0))));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStderr(version.c_str())),
|
||||
WithArg<2>(ReturnCallbackDone(0))));
|
||||
}
|
||||
|
||||
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
|
||||
TEST_F(BugreportTest, InvalidNumberArgs) {
|
||||
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
|
||||
// to the flat-file format ('bugreport' binary on device)
|
||||
TEST_F(BugreportTest, NoArgumentsPreNDevice) {
|
||||
// clang-format off
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStderr("")),
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStderr("")),
|
||||
// Write some bogus output on stdout to make sure it's ignored
|
||||
WithArg<4>(WriteOnStdout("Dude, where is my bugreportz?")),
|
||||
WithArg<4>(ReturnCallbackDone(0))));
|
||||
WithArg<2>(WriteOnStdout("Dude, where is my bugreportz?")),
|
||||
WithArg<2>(ReturnCallbackDone(0))));
|
||||
// clang-format on
|
||||
std::string bugreport = "Reported the bug was.";
|
||||
CaptureStdout();
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreport", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout(bugreport)), Return(0)));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreport", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout(bugreport)), Return(0)));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -183,15 +181,15 @@ TEST_F(BugreportTest, NoArgumentsNDevice) {
|
|||
|
||||
std::string dest_file =
|
||||
android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||
true, StrEq("pulling da_bugreport.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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
|
||||
|
@ -201,47 +199,47 @@ TEST_F(BugreportTest, NoArgumentsPostNDevice) {
|
|||
std::string dest_file =
|
||||
android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
|
||||
ExpectProgress(50, "da_bugreport.zip");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:50/100\n")),
|
||||
WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:50/100\n")),
|
||||
WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||
true, StrEq("pulling da_bugreport.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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.
|
||||
TEST_F(BugreportTest, OkNDevice) {
|
||||
ExpectBugreportzVersion("1.0");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||
true, StrEq("pulling file.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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
|
||||
// multiple buffer writers and without progress updates.
|
||||
TEST_F(BugreportTest, OkNDeviceSplitBuffer) {
|
||||
ExpectBugreportzVersion("1.0");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device")),
|
||||
WithArg<4>(WriteOnStdout("/bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device")),
|
||||
WithArg<2>(WriteOnStdout("/bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||
true, StrEq("pulling file.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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.
|
||||
|
@ -252,32 +250,32 @@ TEST_F(BugreportTest, OkProgress) {
|
|||
ExpectProgress(50);
|
||||
ExpectProgress(99);
|
||||
// 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...
|
||||
.WillOnce(DoAll(
|
||||
// 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
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")),
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")),
|
||||
// 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
|
||||
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
|
||||
WithArg<4>(WriteOnStdout("PROG")),
|
||||
WithArg<4>(WriteOnStdout("RESS:99")),
|
||||
WithArg<4>(WriteOnStdout("/100\n")),
|
||||
WithArg<2>(WriteOnStdout("PROG")),
|
||||
WithArg<2>(WriteOnStdout("RESS:99")),
|
||||
WithArg<2>(WriteOnStdout("/100\n")),
|
||||
// Split last message as well, just in case
|
||||
WithArg<4>(WriteOnStdout("OK:/device/bugreport")),
|
||||
WithArg<4>(WriteOnStdout(".zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
WithArg<2>(WriteOnStdout("OK:/device/bugreport")),
|
||||
WithArg<2>(WriteOnStdout(".zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
// clang-format on
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||
true, StrEq("pulling file.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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.
|
||||
|
@ -287,28 +285,28 @@ TEST_F(BugreportTest, OkProgressAlwaysForward) {
|
|||
ExpectProgress(50);
|
||||
ExpectProgress(75);
|
||||
// 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...
|
||||
.WillOnce(DoAll(
|
||||
WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:50/100\n")), // 50%
|
||||
WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:50/100\n")), // 50%
|
||||
// 25% should be ignored becaused it receded.
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:25/100\n")), // 25%
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:25/100\n")), // 25%
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
|
||||
// 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
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:700/1000\n")), // 70%
|
||||
WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:700/1000\n")), // 70%
|
||||
WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
// clang-format on
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||
true, StrEq("pulling file.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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%
|
||||
|
@ -317,21 +315,21 @@ TEST_F(BugreportTest, OkProgressZeroPercentIsNotIgnored) {
|
|||
ExpectProgress(0);
|
||||
ExpectProgress(1);
|
||||
// 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...
|
||||
.WillOnce(DoAll(
|
||||
WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100000\n")),
|
||||
WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
||||
WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:1/100000\n")),
|
||||
WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
|
||||
WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
// clang-format on
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||
true, StrEq("pulling file.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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.
|
||||
|
@ -341,30 +339,30 @@ TEST_F(BugreportTest, OkDirectory) {
|
|||
std::string dest_file =
|
||||
android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
|
||||
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||
WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||
WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||
true, StrEq("pulling da_bugreport.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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
|
||||
TEST_F(BugreportTest, OkNoExtension) {
|
||||
ExpectBugreportzVersion("1.1");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip\n")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||
true, StrEq("pulling file.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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.
|
||||
|
@ -374,28 +372,28 @@ TEST_F(BugreportTest, OkNDeviceDirectory) {
|
|||
std::string dest_file =
|
||||
android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
|
||||
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||
WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
|
||||
WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
|
||||
true, StrEq("pulling da_bugreport.zip")))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
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
|
||||
TEST_F(BugreportTest, BugreportzReturnedFail) {
|
||||
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:D'OH!\n")), WithArg<4>(ReturnCallbackDone())));
|
||||
DoAll(WithArg<2>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<2>(ReturnCallbackDone())));
|
||||
|
||||
CaptureStderr();
|
||||
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!"));
|
||||
}
|
||||
|
||||
|
@ -404,13 +402,13 @@ TEST_F(BugreportTest, BugreportzReturnedFail) {
|
|||
// multiple buffer writes
|
||||
TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
|
||||
ExpectBugreportzVersion("1.1");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL")), WithArg<4>(WriteOnStdout(":D'OH!\n")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("FAIL")), WithArg<2>(WriteOnStdout(":D'OH!\n")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
|
||||
CaptureStderr();
|
||||
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!"));
|
||||
}
|
||||
|
||||
|
@ -418,23 +416,22 @@ TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
|
|||
// response.
|
||||
TEST_F(BugreportTest, BugreportzReturnedUnsupported) {
|
||||
ExpectBugreportzVersion("1.1");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("bugreportz? What am I, a zombie?")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("bugreportz? What am I, a zombie?")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
|
||||
CaptureStderr();
|
||||
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?"));
|
||||
}
|
||||
|
||||
// Tests 'adb bugreport file.zip' when the bugreportz -v command failed
|
||||
TEST_F(BugreportTest, BugreportzVersionFailed) {
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
|
||||
.WillOnce(Return(666));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _)).WillOnce(Return(666));
|
||||
|
||||
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.
|
||||
|
@ -442,29 +439,28 @@ TEST_F(BugreportTest, BugreportzVersionEmpty) {
|
|||
ExpectBugreportzVersion("");
|
||||
|
||||
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
|
||||
TEST_F(BugreportTest, BugreportzFailed) {
|
||||
ExpectBugreportzVersion("1.1");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
||||
.WillOnce(Return(666));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _)).WillOnce(Return(666));
|
||||
|
||||
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
|
||||
TEST_F(BugreportTest, PullFails) {
|
||||
ExpectBugreportzVersion("1.1");
|
||||
EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<4>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
|
||||
.WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
|
||||
WithArg<2>(ReturnCallbackDone())));
|
||||
EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
|
||||
true, HasSubstr("file.zip")))
|
||||
.WillOnce(Return(false));
|
||||
|
||||
const char* args[] = {"bugreport", "file.zip"};
|
||||
ASSERT_EQ(1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
|
||||
ASSERT_EQ(1, br_.DoIt(2, args));
|
||||
}
|
||||
|
|
|
@ -62,11 +62,11 @@
|
|||
#include "shell_service.h"
|
||||
#include "sysdeps/chrono.h"
|
||||
|
||||
static int install_app(TransportType t, const char* serial, int argc, const char** argv);
|
||||
static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
|
||||
static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
|
||||
static int install_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
|
||||
static int uninstall_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
|
||||
static int install_app(int argc, const char** argv);
|
||||
static int install_multiple_app(int argc, const char** argv);
|
||||
static int uninstall_app(int argc, const char** argv);
|
||||
static int install_app_legacy(int argc, const char** argv);
|
||||
static int uninstall_app_legacy(int argc, const char** argv);
|
||||
|
||||
extern int gListenAll;
|
||||
|
||||
|
@ -90,6 +90,7 @@ static void help() {
|
|||
" -d use USB device (error if multiple devices connected)\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"
|
||||
" -t ID use device with given transport id\n"
|
||||
" -H name of adb server host [default=localhost]\n"
|
||||
" -P port of adb server [default=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) */
|
||||
}
|
||||
|
||||
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, "-");
|
||||
if (components.size() < 3 || components.size() > 4) {
|
||||
fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
|
||||
return false;
|
||||
}
|
||||
|
||||
TransportType t;
|
||||
adb_get_transport(&t, nullptr, nullptr);
|
||||
|
||||
// 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 (components.size() == 3) {
|
||||
|
@ -1019,7 +1023,7 @@ static bool wait_for_device(const char* service, TransportType t, const char* se
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -1065,8 +1069,8 @@ static bool adb_root(const char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
|
||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
|
||||
int send_shell_command(const std::string& command, bool disable_shell_protocol,
|
||||
StandardStreamsCallbackInterface* callback) {
|
||||
int fd;
|
||||
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");
|
||||
if (!wait_for_device("wait-for-device", transport_type, serial)) {
|
||||
if (!wait_for_device("wait-for-device")) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -1111,7 +1115,7 @@ int send_shell_command(TransportType transport_type, const char* serial, const s
|
|||
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");
|
||||
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.
|
||||
return send_shell_command(transport, serial, cmd, true);
|
||||
return send_shell_command(cmd, true);
|
||||
}
|
||||
|
||||
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.
|
||||
const char* serial = nullptr;
|
||||
TransportId transport_id = 0;
|
||||
|
||||
while (argc > 0) {
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
} else if (argv[0][0]=='-' && argv[0][1]=='s') {
|
||||
} else if (!strncmp(argv[0], "-s", 2)) {
|
||||
if (isdigit(argv[0][2])) {
|
||||
serial = argv[0] + 2;
|
||||
} else {
|
||||
|
@ -1368,6 +1373,19 @@ int adb_commandline(int argc, const char** argv) {
|
|||
argc--;
|
||||
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")) {
|
||||
transport_type = kTransportUsb;
|
||||
} else if (!strcmp(argv[0],"-e")) {
|
||||
|
@ -1451,7 +1469,7 @@ int adb_commandline(int argc, const char** argv) {
|
|||
serial = getenv("ANDROID_SERIAL");
|
||||
}
|
||||
|
||||
adb_set_transport(transport_type, serial);
|
||||
adb_set_transport(transport_type, serial, transport_id);
|
||||
|
||||
if (is_server) {
|
||||
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-"))) {
|
||||
const char* service = argv[0];
|
||||
|
||||
if (!wait_for_device(service, transport_type, serial)) {
|
||||
if (!wait_for_device(service)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1589,7 +1607,7 @@ int adb_commandline(int argc, const char** argv) {
|
|||
return adb_root(argv[0]) ? 0 : 1;
|
||||
} else if (!strcmp(argv[0], "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")) {
|
||||
bool reverse = !strcmp(argv[0], "reverse");
|
||||
++argv;
|
||||
|
@ -1685,20 +1703,20 @@ int adb_commandline(int argc, const char** argv) {
|
|||
else if (!strcmp(argv[0], "install")) {
|
||||
if (argc < 2) return syntax_error("install requires an argument");
|
||||
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")) {
|
||||
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")) {
|
||||
if (argc < 2) return syntax_error("uninstall requires an argument");
|
||||
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")) {
|
||||
std::string src;
|
||||
|
@ -1752,11 +1770,11 @@ int adb_commandline(int argc, const char** argv) {
|
|||
!strcmp(argv[0],"get-serialno") ||
|
||||
!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 */
|
||||
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")) {
|
||||
return ppp(argc, argv);
|
||||
|
@ -1819,7 +1837,7 @@ int adb_commandline(int argc, const char** argv) {
|
|||
return adb_query_command("host:host-features");
|
||||
} else if (!strcmp(argv[0], "reconnect")) {
|
||||
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) {
|
||||
if (!strcmp(argv[1], "device")) {
|
||||
std::string err;
|
||||
|
@ -1838,7 +1856,7 @@ int adb_commandline(int argc, const char** argv) {
|
|||
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
|
||||
std::string cmd = "cmd package";
|
||||
while (argc-- > 0) {
|
||||
|
@ -1854,10 +1872,10 @@ static int uninstall_app(TransportType transport, const char* serial, int argc,
|
|||
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
|
||||
const char* file = argv[argc - 1];
|
||||
if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
|
||||
|
@ -1910,9 +1928,7 @@ static int install_app(TransportType transport, const char* serial, int argc, co
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int install_multiple_app(TransportType transport, const char* serial, int argc,
|
||||
const char** argv)
|
||||
{
|
||||
static int install_multiple_app(int argc, const char** argv) {
|
||||
// Find all APK arguments starting at end.
|
||||
// All other arguments passed through verbatim.
|
||||
int first_apk = -1;
|
||||
|
@ -2037,17 +2053,17 @@ finalize_session:
|
|||
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";
|
||||
|
||||
while (argc-- > 0) {
|
||||
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
|
||||
out with the option to uninstall the remaining data somehow (adb/ui) */
|
||||
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 */
|
||||
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);
|
||||
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 SD_DEST = "/sdcard/tmp/%s";
|
||||
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());
|
||||
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 */
|
||||
result = pm_command(transport, serial, argc, argv);
|
||||
result = pm_command(argc, argv);
|
||||
|
||||
cleanup_apk:
|
||||
delete_file(transport, serial, apk_dest);
|
||||
delete_file(apk_dest);
|
||||
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
|
||||
// resulting output.
|
||||
// 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,
|
||||
bool disable_shell_protocol, StandardStreamsCallbackInterface* callback =
|
||||
&DEFAULT_STANDARD_STREAMS_CALLBACK);
|
||||
int send_shell_command(
|
||||
const std::string& command, bool disable_shell_protocol,
|
||||
StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
|
||||
|
||||
#endif // COMMANDLINE_H
|
||||
|
|
|
@ -187,7 +187,7 @@ int reverse_service(const char* command) {
|
|||
return -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");
|
||||
}
|
||||
adb_close(s[1]);
|
||||
|
@ -334,6 +334,7 @@ int service_to_fd(const char* name, const atransport* transport) {
|
|||
struct state_info {
|
||||
TransportType transport_type;
|
||||
std::string serial;
|
||||
TransportId transport_id;
|
||||
ConnectionState state;
|
||||
};
|
||||
|
||||
|
@ -346,7 +347,8 @@ static void wait_for_state(int fd, void* data) {
|
|||
bool is_ambiguous = false;
|
||||
std::string error = "unknown error";
|
||||
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())) {
|
||||
SendOkay(fd);
|
||||
break;
|
||||
|
@ -437,7 +439,7 @@ static void connect_service(int fd, void* data) {
|
|||
#endif
|
||||
|
||||
#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")) {
|
||||
return create_device_tracker();
|
||||
} 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;
|
||||
sinfo->transport_id = transport_id;
|
||||
|
||||
if (android::base::StartsWith(name, "local")) {
|
||||
name += strlen("local");
|
||||
|
|
|
@ -430,10 +430,11 @@ asocket* create_local_service_socket(const char* name, const atransport* transpo
|
|||
}
|
||||
|
||||
#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;
|
||||
|
||||
s = host_service_to_socket(name, serial);
|
||||
s = host_service_to_socket(name, serial, transport_id);
|
||||
|
||||
if (s != NULL) {
|
||||
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
|
||||
char* service = nullptr;
|
||||
char* serial = nullptr;
|
||||
TransportId transport_id = 0;
|
||||
TransportType type = kTransportAny;
|
||||
#endif
|
||||
|
||||
|
@ -715,6 +717,14 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
|||
serial = service;
|
||||
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:"))) {
|
||||
type = kTransportUsb;
|
||||
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
|
||||
** 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? */
|
||||
D("SS(%d): handled host service '%s'", s->id, service);
|
||||
goto fail;
|
||||
|
@ -751,7 +761,7 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
|||
** if no such service exists, we'll fail out
|
||||
** and tear down here.
|
||||
*/
|
||||
s2 = create_host_service_socket(service, serial);
|
||||
s2 = create_host_service_socket(service, serial, transport_id);
|
||||
if (s2 == 0) {
|
||||
D("SS(%d): couldn't create host service '%s'", s->id, service);
|
||||
SendFail(s->peer->fd, "unknown host service");
|
||||
|
@ -783,7 +793,7 @@ static int smart_socket_enqueue(asocket* s, apacket* p) {
|
|||
#else /* !ADB_HOST */
|
||||
if (s->transport == nullptr) {
|
||||
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) {
|
||||
SendFail(s->peer->fd, error_msg);
|
||||
goto fail;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -36,6 +37,7 @@
|
|||
#include <android-base/quick_exit.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/thread_annotations.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "adb_auth.h"
|
||||
|
@ -46,6 +48,7 @@
|
|||
|
||||
static void transport_unref(atransport *t);
|
||||
|
||||
// TODO: unordered_map<TransportId, atransport*>
|
||||
static auto& transport_list = *new std::list<atransport*>();
|
||||
static auto& pending_list = *new std::list<atransport*>();
|
||||
|
||||
|
@ -57,6 +60,11 @@ const char* const kFeatureStat2 = "stat_v2";
|
|||
const char* const kFeatureLibusb = "libusb";
|
||||
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) {
|
||||
unsigned command = p->msg.command;
|
||||
int len = p->msg.data_length;
|
||||
|
@ -301,6 +309,8 @@ void kick_transport(atransport* t) {
|
|||
std::lock_guard<std::recursive_mutex> lock(transport_lock);
|
||||
// As kick_transport() can be called from threads without guarantee that t is valid,
|
||||
// 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()) {
|
||||
t->Kick();
|
||||
}
|
||||
|
@ -638,11 +648,15 @@ static int qual_match(const char* to_test, const char* prefix, const char* qual,
|
|||
return !*to_test;
|
||||
}
|
||||
|
||||
atransport* acquire_one_transport(TransportType type, const char* serial, bool* is_ambiguous,
|
||||
std::string* error_out, bool accept_any_state) {
|
||||
atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
|
||||
bool* is_ambiguous, std::string* error_out,
|
||||
bool accept_any_state) {
|
||||
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);
|
||||
} else if (type == kTransportLocal) {
|
||||
*error_out = "no emulators found";
|
||||
|
@ -661,8 +675,12 @@ atransport* acquire_one_transport(TransportType type, const char* serial, bool*
|
|||
continue;
|
||||
}
|
||||
|
||||
// Check for matching serial number.
|
||||
if (serial) {
|
||||
if (transport_id) {
|
||||
if (t->id == transport_id) {
|
||||
result = t;
|
||||
break;
|
||||
}
|
||||
} else if (serial) {
|
||||
if (t->MatchesTarget(serial)) {
|
||||
if (result) {
|
||||
*error_out = "more than one device";
|
||||
|
@ -889,18 +907,23 @@ bool atransport::MatchesTarget(const std::string& target) const {
|
|||
|
||||
#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,
|
||||
bool sanitize) {
|
||||
bool alphanumeric) {
|
||||
if (value == nullptr || *value == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
*result += ' ';
|
||||
*result += key;
|
||||
|
||||
for (const char* p = value; *p; ++p) {
|
||||
result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
|
||||
}
|
||||
*result += sanitize(value, alphanumeric);
|
||||
}
|
||||
|
||||
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, "model:", t->model, true);
|
||||
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';
|
||||
}
|
||||
|
|
|
@ -54,14 +54,17 @@ extern const char* const kFeatureLibusb;
|
|||
// The server supports `push --sync`.
|
||||
extern const char* const kFeaturePushSync;
|
||||
|
||||
TransportId NextTransportId();
|
||||
|
||||
class atransport {
|
||||
public:
|
||||
public:
|
||||
// TODO(danalbert): We expose waaaaaaay too much stuff because this was
|
||||
// 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,
|
||||
// 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()), ref_count(0), connection_state_(state) {
|
||||
transport_fde = {};
|
||||
protocol_version = A_VERSION;
|
||||
max_payload = MAX_PAYLOAD;
|
||||
|
@ -72,12 +75,8 @@ public:
|
|||
void (*close)(atransport* t) = nullptr;
|
||||
|
||||
void SetWriteFunction(int (*write_func)(apacket*, atransport*)) { write_func_ = write_func; }
|
||||
void SetKickFunction(void (*kick_func)(atransport*)) {
|
||||
kick_func_ = kick_func;
|
||||
}
|
||||
bool IsKicked() {
|
||||
return kicked_;
|
||||
}
|
||||
void SetKickFunction(void (*kick_func)(atransport*)) { kick_func_ = kick_func; }
|
||||
bool IsKicked() { return kicked_; }
|
||||
int Write(apacket* p);
|
||||
void Kick();
|
||||
|
||||
|
@ -85,6 +84,7 @@ public:
|
|||
ConnectionState GetConnectionState() const;
|
||||
void SetConnectionState(ConnectionState state);
|
||||
|
||||
const TransportId id;
|
||||
int fd = -1;
|
||||
int transport_socket = -1;
|
||||
fdevent transport_fde;
|
||||
|
@ -191,12 +191,14 @@ private:
|
|||
/*
|
||||
* Obtain a transport from the available transports.
|
||||
* 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)
|
||||
* is set to true 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,
|
||||
std::string* error_out, bool accept_any_state = false);
|
||||
atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
|
||||
bool* is_ambiguous, std::string* error_out,
|
||||
bool accept_any_state = false);
|
||||
void kick_transport(atransport* t);
|
||||
void update_transports(void);
|
||||
|
||||
|
|
Loading…
Reference in a new issue