diff options
-rw-r--r-- | Makefile.android | 1 | ||||
-rw-r--r-- | android/cmdline-options.h | 4 | ||||
-rw-r--r-- | android/help.c | 12 | ||||
-rw-r--r-- | android/main.c | 143 | ||||
-rw-r--r-- | iolooper-select.c | 6 |
5 files changed, 163 insertions, 3 deletions
diff --git a/Makefile.android b/Makefile.android index 1d82197..97bfafb 100644 --- a/Makefile.android +++ b/Makefile.android @@ -1187,6 +1187,7 @@ VL_SOURCES := framebuffer.c \ qemu-timer-ui.c \ vl-android-ui.c \ console-ui.c \ + iolooper-select.c \ # Add common system libraries # diff --git a/android/cmdline-options.h b/android/cmdline-options.h index da8f375..1ae3121 100644 --- a/android/cmdline-options.h +++ b/android/cmdline-options.h @@ -152,6 +152,10 @@ OPT_PARAM( nand_limits, "<nlimits>", "enforce NAND/Flash read/write thresholds" OPT_PARAM( memcheck, "<flags>", "enable memory access checking" ) #endif // CONFIG_MEMCHECK +#ifdef CONFIG_STANDALONE_UI +OPT_PARAM( list_cores, "<host>", "list running core process" ) +#endif // CONFIG_STANDALONE_UI + #undef CFG_FLAG #undef CFG_PARAM #undef OPT_FLAG diff --git a/android/help.c b/android/help.c index f589b3e..2103b00 100644 --- a/android/help.c +++ b/android/help.c @@ -1010,6 +1010,18 @@ help_memcheck(stralloc_t* out) } #endif // CONFIG_MEMCHECK +#ifdef CONFIG_STANDALONE_UI +static void +help_list_cores(stralloc_t* out) +{ + PRINTF( + " use '-list-cores localhost to list emulator core processes running on this machine.\n" + " use '-list-cores host_name, or IP address to list emulator core processes running on\n" + " a remote machine.\n" + ); +} +#endif // CONFIG_STANDALONE_UI + static void help_show_kernel(stralloc_t* out) { diff --git a/android/main.c b/android/main.c index 6b3bea6..ffdd821 100644 --- a/android/main.c +++ b/android/main.c @@ -62,6 +62,7 @@ #include "android/snapshot.h" #include "framebuffer.h" +#include "iolooper.h" AndroidRotation android_framebuffer_rotation; @@ -734,6 +735,137 @@ _adjustPartitionSize( const char* description, return convertMBToBytes(imageMB); } +#ifdef CONFIG_STANDALONE_UI + +// Base console port +#define CORE_BASE_PORT 5554 + +// Maximum number of core porocesses running simultaneously on a machine. +#define MAX_CORE_PROCS 16 + +// Socket timeout in millisec (set to half a second) +#define CORE_PORT_TIMEOUT_MS 500 + +/* Checks if emulator core runs at the end of the given socket. + * Param: + * sockaddr Socket address addressing emulator's console. + * Return: + * 0 in case that core has been found for the socket, or -1 otherwise. + */ +static int +check_for_running_core(SockAddress* sockaddr) +{ + IoLooper* looper = iolooper_new(); + int connect_status; + char buf[512]; + int ret = -1; + + int fd = socket_create_inet(SOCKET_STREAM); + if (fd < 0) { + return -1; + } + + socket_set_xreuseaddr(fd); + socket_set_nonblock(fd); + connect_status = socket_connect(fd, sockaddr); + if (connect_status < 0 && errno == EINPROGRESS) { + // Wait till connection occurs. + iolooper_add_write(looper, fd); + connect_status = iolooper_wait(looper, CORE_PORT_TIMEOUT_MS); + if (connect_status > 0) { + iolooper_del_write(looper, fd); + } else { + connect_status = -1; + } + } + if (connect_status >= 0) { + iolooper_add_read(looper, fd); + // Read the handshake message from the core's console. + if (iolooper_wait(looper, CORE_PORT_TIMEOUT_MS) > 0 && + iolooper_is_read(looper, fd)) { + int read_bytes = read(fd, buf, sizeof(buf)); + // Check for the console handshake. + if (read_bytes > 15 && !strncmp(buf, "Android Console", 15)) { + ret = 0; + } + } + } + + socket_close( fd ); + iolooper_free(looper); + return ret; +} + +/* List emulator core processes running on the given machine. + * This routine is called from main() if -list-cores parameter is set in the + * command line. + * Param: + * host Value passed with -list-core parameter. Must be either "localhost", or + * an IP address of a machine where core processes must be enumerated. + */ +static void +list_running_cores(const char* host) +{ + int iter; + int port_iter; + int found_cores = 0; + + // Convert host name into socket address list. + SockAddress** sockaddr_list = sock_address_list_create(host, NULL, 0); + if (sockaddr_list == NULL) { + derror("Unable to resolve hostname %s: %s\n", host, errno_str); + return; + } + + /* Since core's console is not a UNIX socket, lets make sure that UNIX + * socket is not the only family in the list. */ + for (iter = 0; sockaddr_list[iter] != NULL; iter++) { + if (sock_address_get_family(sockaddr_list[iter]) != SOCKET_UNIX) { + break; + } + } + if (sockaddr_list[iter] == NULL) { + derror("Unix socket is an invalid parameter for -list-cores option.\n"); + sock_address_list_free(sockaddr_list); + return; + } + + /* List running core processes. To enum core processes we will loop + * through socket ports 5554-5584, where we assume that successful + * conection to a socket means that there is a core process running + * at the other end of that socket. In order to make sure that it's + * emulator console at the other end of that socket, we will read from + * the socket, expecting "Android Console" string at the beginning of + * the data read from the socket. */ + for (port_iter = 0; port_iter < MAX_CORE_PROCS; port_iter++) { + int port_num = CORE_BASE_PORT + port_iter * 2; + for (iter = 0; sockaddr_list[iter] != NULL; iter++) { + if (sock_address_get_family(sockaddr_list[iter]) == SOCKET_UNIX) { + continue; + } + sock_address_set_port(sockaddr_list[iter], port_num); + if (!check_for_running_core(sockaddr_list[iter])) { + // This is a core process at the other end of the socket. + found_cores++; + if (found_cores == 1) { + fprintf(stdout, "Running emulator core processes:\n"); + } + fprintf(stdout, "Emulator console port %d\n", port_num); + } + // Go through this loop just once, for a non-Unix socket address. + break; + } + } + + sock_address_list_free(sockaddr_list); + + if (!found_cores) { + fprintf(stdout, "There were no running emulator core processes found on %s.\n", + host); + } +} +#endif // CONFIG_STANDALONE_UI + int main(int argc, char **argv) { char tmp[MAX_PATH]; @@ -820,6 +952,17 @@ int main(int argc, char **argv) exit(1); } +#ifdef CONFIG_STANDALONE_UI + // Lets see if user just wants to list core process. + if (opts->list_cores) { + fprintf(stdout, "Enumerating running core processes.\n" + "This make take up to %d seconds...\n\n", + (MAX_CORE_PROCS * CORE_PORT_TIMEOUT_MS) / 1000 + 1); + list_running_cores(opts->list_cores); + exit(0); + } +#endif // CONFIG_STANDALONE_UI + if (android_charmap_setup(opts->charmap)) { exit(1); } diff --git a/iolooper-select.c b/iolooper-select.c index f5aecbd..000fa5d 100644 --- a/iolooper-select.c +++ b/iolooper-select.c @@ -21,7 +21,7 @@ struct IoLooper { IoLooper* iolooper_new(void) { - IoLooper* iol = qemu_malloc(sizeof(*iol)); + IoLooper* iol = malloc(sizeof(*iol)); iolooper_reset(iol); return iol; } @@ -29,7 +29,7 @@ iolooper_new(void) void iolooper_free( IoLooper* iol ) { - qemu_free(iol); + free(iol); } void @@ -110,7 +110,7 @@ iolooper_del_write( IoLooper* iol, int fd ) { if (fd >= 0) { iolooper_del_fd(iol, fd); - FD_CLR(fd, iol->reads); + FD_CLR(fd, iol->writes); } } |