diff options
-rw-r--r-- | adb/adb.cpp | 34 | ||||
-rw-r--r-- | adb/adb.h | 9 | ||||
-rw-r--r-- | adb/adb_client.cpp | 31 | ||||
-rw-r--r-- | adb/adb_client.h | 7 | ||||
-rw-r--r-- | adb/bugreport.cpp | 13 | ||||
-rw-r--r-- | adb/bugreport.h | 5 | ||||
-rw-r--r-- | adb/bugreport_test.cpp | 202 | ||||
-rw-r--r-- | adb/commandline.cpp | 94 | ||||
-rw-r--r-- | adb/commandline.h | 6 | ||||
-rw-r--r-- | adb/services.cpp | 13 | ||||
-rw-r--r-- | adb/sockets.cpp | 20 | ||||
-rw-r--r-- | adb/transport.cpp | 62 | ||||
-rw-r--r-- | adb/transport.h | 24 |
13 files changed, 302 insertions, 218 deletions
diff --git a/adb/adb.cpp b/adb/adb.cpp index ff7b71f81..8c24bbba3 100644 --- a/adb/adb.cpp +++ b/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); diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp index e533a00eb..849a6e772 100644 --- a/adb/adb_client.cpp +++ b/adb/adb_client.cpp @@ -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; } diff --git a/adb/adb_client.h b/adb/adb_client.h index fabec0050..fca435e38 100644 --- a/adb/adb_client.h +++ b/adb/adb_client.h @@ -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); diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp index 372a3b4aa..f63ac08a6 100644 --- a/adb/bugreport.cpp +++ b/adb/bugreport.cpp @@ -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, diff --git a/adb/bugreport.h b/adb/bugreport.h index d9a4468d5..413439b74 100644 --- a/adb/bugreport.h +++ b/adb/bugreport.h @@ -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, diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp index d3787b40a..758f24a06 100644 --- a/adb/bugreport_test.cpp +++ b/adb/bugreport_test.cpp @@ -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)); } diff --git a/adb/commandline.cpp b/adb/commandline.cpp index e465c3f73..9f234737b 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -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" @@ -990,13 +991,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) { @@ -1023,7 +1027,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); } @@ -1069,8 +1073,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; @@ -1101,7 +1105,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; } } @@ -1115,7 +1119,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); @@ -1132,7 +1136,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) { @@ -1344,6 +1348,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")) { @@ -1363,7 +1368,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 { @@ -1372,6 +1377,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")) { @@ -1455,7 +1473,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) { @@ -1482,7 +1500,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; } @@ -1593,7 +1611,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; @@ -1689,20 +1707,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; @@ -1756,11 +1774,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); @@ -1823,7 +1841,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; @@ -1842,7 +1860,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) { @@ -1858,10 +1876,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")) { @@ -1914,9 +1932,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; @@ -2041,17 +2057,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; @@ -2067,15 +2083,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; @@ -2104,9 +2120,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; } diff --git a/adb/commandline.h b/adb/commandline.h index 9ba69a396..36cd79841 100644 --- a/adb/commandline.h +++ b/adb/commandline.h @@ -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 diff --git a/adb/services.cpp b/adb/services.cpp index 55cb6a1ed..dbf71d36d 100644 --- a/adb/services.cpp +++ b/adb/services.cpp @@ -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,9 +439,11 @@ 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(); + return create_device_tracker(false); + } else if (!strcmp(name, "track-devices-l")) { + return create_device_tracker(true); } else if (android::base::StartsWith(name, "wait-for-")) { name += strlen("wait-for-"); @@ -450,6 +454,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"); diff --git a/adb/sockets.cpp b/adb/sockets.cpp index e0143c611..f28a3df50 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -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; diff --git a/adb/transport.cpp b/adb/transport.cpp index c26252e43..b2e03a057 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -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(); } @@ -319,7 +329,8 @@ static fdevent transport_registration_fde; */ struct device_tracker { asocket socket; - int update_needed; + bool update_needed; + bool long_output; device_tracker* next; }; @@ -376,15 +387,15 @@ static void device_tracker_ready(asocket* socket) { // We want to send the device list when the tracker connects // for the first time, even if no update occurred. - if (tracker->update_needed > 0) { - tracker->update_needed = 0; + if (tracker->update_needed) { + tracker->update_needed = false; - std::string transports = list_transports(false); + std::string transports = list_transports(tracker->long_output); device_tracker_send(tracker, transports); } } -asocket* create_device_tracker(void) { +asocket* create_device_tracker(bool long_output) { device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker))); if (tracker == nullptr) fatal("cannot allocate device tracker"); @@ -393,7 +404,8 @@ asocket* create_device_tracker(void) { tracker->socket.enqueue = device_tracker_enqueue; tracker->socket.ready = device_tracker_ready; tracker->socket.close = device_tracker_close; - tracker->update_needed = 1; + tracker->update_needed = true; + tracker->long_output = long_output; tracker->next = device_tracker_list; device_tracker_list = tracker; @@ -638,11 +650,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 +677,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 +909,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 +945,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'; } diff --git a/adb/transport.h b/adb/transport.h index 4a89ed993..00fad5646 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -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); @@ -231,6 +233,6 @@ void close_usb_devices(std::function<bool(const atransport*)> predicate); void send_packet(apacket* p, atransport* t); -asocket* create_device_tracker(void); +asocket* create_device_tracker(bool long_output); #endif /* __TRANSPORT_H */ |