summaryrefslogtreecommitdiffstats
path: root/adb
diff options
context:
space:
mode:
Diffstat (limited to 'adb')
-rw-r--r--adb/commandline.cpp41
-rw-r--r--adb/services.cpp57
2 files changed, 66 insertions, 32 deletions
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 8575c8636..bc58c9107 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -204,7 +204,10 @@ static void help() {
" adb version - show version num\n"
"\n"
"scripting:\n"
- " adb wait-for-device - block until device is online\n"
+ " adb wait-for[-<transport>]-<state>\n"
+ " - wait for device to be in the given state:\n"
+ " device, recovery, sideload, or bootloader\n"
+ " Transport is: usb, local or any [default=any]\n"
" adb start-server - ensure that there is a server running\n"
" adb kill-server - kill the server if it is running\n"
" adb get-state - prints: offline | bootloader | device\n"
@@ -1010,19 +1013,49 @@ static int ppp(int argc, const char** argv) {
#endif /* !defined(_WIN32) */
}
+static bool check_wait_for_device_syntax(const char* service) {
+ // TODO: when we have libc++ for Windows, use a regular expression instead.
+ // wait-for-((any|local|usb)-)?(bootloader|device|recovery|sideload)
+
+ char type[20];
+ char state[20];
+ int length = 0;
+ if (sscanf(service, "wait-for-%20[a-z]-%20[a-z]%n", type, state, &length) < 2 ||
+ length != static_cast<int>(strlen(service))) {
+ fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
+ return false;
+ }
+
+ if (strcmp(type, "any") != 0 && strcmp(type, "local") != 0 && strcmp(type, "usb") != 0) {
+ fprintf(stderr, "adb: unknown type %s; expected 'any', 'local', or 'usb'\n", type);
+ return false;
+ }
+ if (strcmp(state, "bootloader") != 0 && strcmp(state, "device") != 0 &&
+ strcmp(state, "recovery") != 0 && strcmp(state, "sideload") != 0) {
+ fprintf(stderr, "adb: unknown state %s; "
+ "expected 'bootloader', 'device', 'recovery', or 'sideload'\n", state);
+ return false;
+ }
+ return true;
+}
+
static bool wait_for_device(const char* service, TransportType t, const char* serial) {
// 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 (strcmp(service, "wait-for-device") == 0) {
if (t == kTransportUsb) {
- service = "wait-for-usb";
+ service = "wait-for-usb-device";
} else if (t == kTransportLocal) {
- service = "wait-for-local";
+ service = "wait-for-local-device";
} else {
- service = "wait-for-any";
+ service = "wait-for-any-device";
}
}
+ if (!check_wait_for_device_syntax(service)) {
+ return false;
+ }
+
std::string cmd = format_host_command(service, t, serial);
return adb_command(cmd);
}
diff --git a/adb/services.cpp b/adb/services.cpp
index 523353a46..20166cef7 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -356,19 +356,19 @@ int service_to_fd(const char* name, const atransport* transport) {
#if ADB_HOST
struct state_info {
TransportType transport_type;
- char* serial;
+ std::string serial;
ConnectionState state;
};
-static void wait_for_state(int fd, void* cookie) {
- state_info* sinfo = reinterpret_cast<state_info*>(cookie);
+static void wait_for_state(int fd, void* data) {
+ std::unique_ptr<state_info> sinfo(reinterpret_cast<state_info*>(data));
D("wait_for_state %d", sinfo->state);
while (true) {
bool is_ambiguous = false;
std::string error = "unknown error";
- atransport* t = acquire_one_transport(sinfo->transport_type, sinfo->serial,
+ atransport* t = acquire_one_transport(sinfo->transport_type, sinfo->serial.c_str(),
&is_ambiguous, &error);
if (t != nullptr && t->connection_state == sinfo->state) {
SendOkay(fd);
@@ -382,10 +382,6 @@ static void wait_for_state(int fd, void* cookie) {
}
}
- if (sinfo->serial) {
- free(sinfo->serial);
- }
- free(sinfo);
adb_close(fd);
D("wait_for_state is done");
}
@@ -491,38 +487,43 @@ static void connect_service(int fd, void* data) {
asocket* host_service_to_socket(const char* name, const char* serial) {
if (!strcmp(name,"track-devices")) {
return create_device_tracker();
- } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
- auto sinfo = reinterpret_cast<state_info*>(malloc(sizeof(state_info)));
+ } else if (android::base::StartsWith(name, "wait-for-")) {
+ name += strlen("wait-for-");
+
+ std::unique_ptr<state_info> sinfo(new state_info);
if (sinfo == nullptr) {
fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
- return NULL;
+ return nullptr;
}
- if (serial)
- sinfo->serial = strdup(serial);
- else
- sinfo->serial = NULL;
-
- name += strlen("wait-for-");
+ if (serial) sinfo->serial = serial;
- if (!strncmp(name, "local", strlen("local"))) {
+ if (android::base::StartsWith(name, "local")) {
+ name += strlen("local");
sinfo->transport_type = kTransportLocal;
- sinfo->state = kCsDevice;
- } else if (!strncmp(name, "usb", strlen("usb"))) {
+ } else if (android::base::StartsWith(name, "usb")) {
+ name += strlen("usb");
sinfo->transport_type = kTransportUsb;
- sinfo->state = kCsDevice;
- } else if (!strncmp(name, "any", strlen("any"))) {
+ } else if (android::base::StartsWith(name, "any")) {
+ name += strlen("any");
sinfo->transport_type = kTransportAny;
+ } else {
+ return nullptr;
+ }
+
+ if (!strcmp(name, "-device")) {
sinfo->state = kCsDevice;
+ } else if (!strcmp(name, "-recovery")) {
+ sinfo->state = kCsRecovery;
+ } else if (!strcmp(name, "-sideload")) {
+ sinfo->state = kCsSideload;
+ } else if (!strcmp(name, "-bootloader")) {
+ sinfo->state = kCsBootloader;
} else {
- if (sinfo->serial) {
- free(sinfo->serial);
- }
- free(sinfo);
- return NULL;
+ return nullptr;
}
- int fd = create_service_thread(wait_for_state, sinfo);
+ int fd = create_service_thread(wait_for_state, sinfo.release());
return create_local_socket(fd);
} else if (!strncmp(name, "connect:", 8)) {
char* host = strdup(name + 8);