TEST(transport, SetFeatures) { atransport t; ASSERT_EQ(0U, t.features().size()); t.SetFeatures(FeatureSetToString(FeatureSet{"foo"})); ASSERT_EQ(1U, t.features().size()); ASSERT_TRUE(t.has_feature("foo")); t.SetFeatures(FeatureSetToString(FeatureSet{"foo", "bar"})); ASSERT_EQ(2U, t.features().size()); ASSERT_TRUE(t.has_feature("foo")); ASSERT_TRUE(t.has_feature("bar")); t.SetFeatures(FeatureSetToString(FeatureSet{"foo", "bar", "foo"})); ASSERT_EQ(2U, t.features().size()); ASSERT_TRUE(t.has_feature("foo")); ASSERT_TRUE(t.has_feature("bar")); t.SetFeatures(FeatureSetToString(FeatureSet{"bar", "baz"})); ASSERT_EQ(2U, t.features().size()); ASSERT_FALSE(t.has_feature("foo")); ASSERT_TRUE(t.has_feature("bar")); ASSERT_TRUE(t.has_feature("baz")); t.SetFeatures(""); ASSERT_EQ(0U, t.features().size()); }
std::string get_connection_string() { std::vector<std::string> connection_properties; #if !ADB_HOST static const char* cnxn_props[] = { "ro.product.name", "ro.product.model", "ro.product.device", }; for (const auto& prop : cnxn_props) { std::string value = std::string(prop) + "=" + android::base::GetProperty(prop, ""); connection_properties.push_back(value); } #endif connection_properties.push_back(android::base::StringPrintf( "features=%s", FeatureSetToString(supported_features()).c_str())); return android::base::StringPrintf( "%s::%s", adb_device_banner, android::base::Join(connection_properties, ';').c_str()); }
int handle_host_request(const char* service, TransportType type, const char* serial, int reply_fd, asocket* s) { if (strcmp(service, "kill") == 0) { fprintf(stderr, "adb server killed by remote request\n"); fflush(stdout); SendOkay(reply_fd); // On Windows, if the process exits with open sockets that // shutdown(SD_SEND) has not been called on, TCP RST segments will be // sent to the peers which will cause their next recv() to error-out // with WSAECONNRESET. In the case of this code, that means the client // may not read the OKAY sent above. adb_shutdown(reply_fd); exit(0); } #if ADB_HOST // "transport:" is used for switching transport with a specified serial number // "transport-usb:" is used for switching transport to the only USB transport // "transport-local:" is used for switching transport to the only local transport // "transport-any:" is used for switching transport to the only transport if (!strncmp(service, "transport", strlen("transport"))) { TransportType type = kTransportAny; if (!strncmp(service, "transport-usb", strlen("transport-usb"))) { type = kTransportUsb; } else if (!strncmp(service, "transport-local", strlen("transport-local"))) { type = kTransportLocal; } else if (!strncmp(service, "transport-any", strlen("transport-any"))) { type = kTransportAny; } else if (!strncmp(service, "transport:", strlen("transport:"))) { service += strlen("transport:"); serial = service; } std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t != nullptr) { s->transport = t; SendOkay(reply_fd); } else { SendFail(reply_fd, error); } return 1; } // return a list of all connected devices if (!strncmp(service, "devices", 7)) { bool long_listing = (strcmp(service+7, "-l") == 0); if (long_listing || service[7] == 0) { D("Getting device list..."); std::string device_list = list_transports(long_listing); D("Sending device list..."); return SendOkay(reply_fd, device_list); } return 1; } if (!strcmp(service, "features")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t != nullptr) { SendOkay(reply_fd, FeatureSetToString(t->features())); } else { SendFail(reply_fd, error); } return 0; } // remove TCP transport if (!strncmp(service, "disconnect:", 11)) { const std::string address(service + 11); if (address.empty()) { kick_all_tcp_devices(); return SendOkay(reply_fd, "disconnected everything"); } std::string serial; std::string host; int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; std::string error; if (!android::base::ParseNetAddress(address, &host, &port, &serial, &error)) { return SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s", address.c_str(), error.c_str())); } atransport* t = find_transport(serial.c_str()); if (t == nullptr) { return SendFail(reply_fd, android::base::StringPrintf("no such device '%s'", serial.c_str())); } kick_transport(t); return SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str())); } // Returns our value for ADB_SERVER_VERSION. if (!strcmp(service, "version")) { return SendOkay(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION)); } // 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); if (t) { return SendOkay(reply_fd, t->serial ? t->serial : "unknown"); } else { return SendFail(reply_fd, error); } } if (!strcmp(service, "get-devpath")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t) { return SendOkay(reply_fd, t->devpath ? t->devpath : "unknown"); } else { return SendFail(reply_fd, error); } } if (!strcmp(service, "get-state")) { std::string error; atransport* t = acquire_one_transport(type, serial, nullptr, &error); if (t) { return SendOkay(reply_fd, t->connection_state_name()); } else { return SendFail(reply_fd, error); } } // Indicates a new emulator instance has started. if (!strncmp(service, "emulator:", 9)) { int port = atoi(service+9); local_connect(port); /* we don't even need to send a reply */ return 0; } if (!strcmp(service, "reconnect")) { if (s->transport != nullptr) { kick_transport(s->transport); } return SendOkay(reply_fd, "done"); } #endif // ADB_HOST int ret = handle_forward_request(service, type, serial, reply_fd); if (ret >= 0) return ret - 1; return -1; }