adb host: add device state in "adb wait-for-*"
The current implementation of the host commands "adb wait-for-*" allows to specify only the transport layer (local, usb or any). This patch allows the specification of the expected device state (bootloader, recovery, device or sideload), this is usefull for scripting purposes. Use case: $ adb reboot sideload-auto-reboot $ adb wait-for-usb-sideload && adb sideload package.zip Change-Id: I276a6be4d82f8b7901f74e1e5395b86d16548e8f Signed-off-by: Leo Sartre <leox.sartre@intel.com>
This commit is contained in:
parent
461a29540c
commit
1fbc9dbd0f
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
if (sinfo == nullptr) {
|
||||
fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (serial)
|
||||
sinfo->serial = strdup(serial);
|
||||
else
|
||||
sinfo->serial = NULL;
|
||||
|
||||
} else if (android::base::StartsWith(name, "wait-for-")) {
|
||||
name += strlen("wait-for-");
|
||||
|
||||
if (!strncmp(name, "local", strlen("local"))) {
|
||||
sinfo->transport_type = kTransportLocal;
|
||||
sinfo->state = kCsDevice;
|
||||
} else if (!strncmp(name, "usb", strlen("usb"))) {
|
||||
sinfo->transport_type = kTransportUsb;
|
||||
sinfo->state = kCsDevice;
|
||||
} else if (!strncmp(name, "any", strlen("any"))) {
|
||||
sinfo->transport_type = kTransportAny;
|
||||
sinfo->state = kCsDevice;
|
||||
} else {
|
||||
if (sinfo->serial) {
|
||||
free(sinfo->serial);
|
||||
}
|
||||
free(sinfo);
|
||||
return NULL;
|
||||
std::unique_ptr<state_info> sinfo(new state_info);
|
||||
if (sinfo == nullptr) {
|
||||
fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int fd = create_service_thread(wait_for_state, sinfo);
|
||||
if (serial) sinfo->serial = serial;
|
||||
|
||||
if (android::base::StartsWith(name, "local")) {
|
||||
name += strlen("local");
|
||||
sinfo->transport_type = kTransportLocal;
|
||||
} else if (android::base::StartsWith(name, "usb")) {
|
||||
name += strlen("usb");
|
||||
sinfo->transport_type = kTransportUsb;
|
||||
} 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 {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue