summaryrefslogtreecommitdiffstats
path: root/adb/services.c
diff options
context:
space:
mode:
Diffstat (limited to 'adb/services.c')
-rw-r--r--adb/services.c240
1 files changed, 137 insertions, 103 deletions
diff --git a/adb/services.c b/adb/services.c
index 54d21a8..f0d5878 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -34,6 +35,7 @@
# endif
#else
# include <cutils/android_reboot.h>
+# include <cutils/properties.h>
#endif
typedef struct stinfo stinfo;
@@ -53,59 +55,7 @@ void *service_bootstrap_func(void *x)
return 0;
}
-#if ADB_HOST
-ADB_MUTEX_DEFINE( dns_lock );
-
-static void dns_service(int fd, void *cookie)
-{
- char *hostname = cookie;
- struct hostent *hp;
- unsigned zero = 0;
-
- adb_mutex_lock(&dns_lock);
- hp = gethostbyname(hostname);
- free(cookie);
- if(hp == 0) {
- writex(fd, &zero, 4);
- } else {
- writex(fd, hp->h_addr, 4);
- }
- adb_mutex_unlock(&dns_lock);
- adb_close(fd);
-}
-#else
-extern int recovery_mode;
-
-static void recover_service(int s, void *cookie)
-{
- unsigned char buf[4096];
- unsigned count = (unsigned) cookie;
- int fd;
-
- fd = adb_creat("/tmp/update", 0644);
- if(fd < 0) {
- adb_close(s);
- return;
- }
-
- while(count > 0) {
- unsigned xfer = (count > 4096) ? 4096 : count;
- if(readx(s, buf, xfer)) break;
- if(writex(fd, buf, xfer)) break;
- count -= xfer;
- }
-
- if(count == 0) {
- writex(s, "OKAY", 4);
- } else {
- writex(s, "FAIL", 4);
- }
- adb_close(fd);
- adb_close(s);
-
- fd = adb_creat("/tmp/update.begin", 0644);
- adb_close(fd);
-}
+#if !ADB_HOST
void restart_root_service(int fd, void *cookie)
{
@@ -165,6 +115,7 @@ void restart_usb_service(int fd, void *cookie)
void reboot_service(int fd, void *arg)
{
char buf[100];
+ char property_val[PROPERTY_VALUE_MAX];
int pid, ret;
sync();
@@ -182,51 +133,25 @@ void reboot_service(int fd, void *arg)
waitpid(pid, &ret, 0);
}
- ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
+ ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg);
+ if (ret >= (int) sizeof(property_val)) {
+ snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
+ writex(fd, buf, strlen(buf));
+ goto cleanup;
+ }
+
+ ret = property_set(ANDROID_RB_PROPERTY, property_val);
if (ret < 0) {
- snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
+ snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
writex(fd, buf, strlen(buf));
}
+cleanup:
free(arg);
adb_close(fd);
}
#endif
-#if 0
-static void echo_service(int fd, void *cookie)
-{
- char buf[4096];
- int r;
- char *p;
- int c;
-
- for(;;) {
- r = adb_read(fd, buf, 4096);
- if(r == 0) goto done;
- if(r < 0) {
- if(errno == EINTR) continue;
- else goto done;
- }
-
- c = r;
- p = buf;
- while(c > 0) {
- r = write(fd, p, c);
- if(r > 0) {
- c -= r;
- p += r;
- continue;
- }
- if((r < 0) && (errno == EINTR)) continue;
- goto done;
- }
- }
-done:
- close(fd);
-}
-#endif
-
static int create_service_thread(void (*func)(int, void *), void *cookie)
{
stinfo *sti;
@@ -413,9 +338,7 @@ int service_to_fd(const char *name)
disable_tcp_nagle(ret);
} else {
#if ADB_HOST
- adb_mutex_lock(&dns_lock);
ret = socket_network_client(name + 1, port, SOCK_STREAM);
- adb_mutex_unlock(&dns_lock);
#else
return -1;
#endif
@@ -434,18 +357,11 @@ int service_to_fd(const char *name)
ret = socket_local_client(name + 16,
ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
#endif
-#if ADB_HOST
- } else if(!strncmp("dns:", name, 4)){
- char *n = strdup(name + 4);
- if(n == 0) return -1;
- ret = create_service_thread(dns_service, n);
-#else /* !ADB_HOST */
+#if !ADB_HOST
} else if(!strncmp("dev:", name, 4)) {
ret = unix_open(name + 4, O_RDWR);
} else if(!strncmp(name, "framebuffer:", 12)) {
ret = create_service_thread(framebuffer_service, 0);
- } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
- ret = create_service_thread(recover_service, (void*) atoi(name + 8));
} else if (!strncmp(name, "jdwp:", 5)) {
ret = create_jdwp_connection_fd(atoi(name+5));
} else if (!strncmp(name, "log:", 4)) {
@@ -481,10 +397,6 @@ int service_to_fd(const char *name)
} else if(!strncmp(name, "usb:", 4)) {
ret = create_service_thread(restart_usb_service, NULL);
#endif
-#if 0
- } else if(!strncmp(name, "echo:", 5)){
- ret = create_service_thread(echo_service, 0);
-#endif
}
if (ret >= 0) {
close_on_exec(ret);
@@ -519,6 +431,124 @@ static void wait_for_state(int fd, void* cookie)
adb_close(fd);
D("wait_for_state is done\n");
}
+
+static void connect_device(char* host, char* buffer, int buffer_size)
+{
+ int port, fd;
+ char* portstr = strchr(host, ':');
+ char hostbuf[100];
+ char serial[100];
+ int ret;
+
+ strncpy(hostbuf, host, sizeof(hostbuf) - 1);
+ if (portstr) {
+ if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
+ snprintf(buffer, buffer_size, "bad host name %s", host);
+ return;
+ }
+ // zero terminate the host at the point we found the colon
+ hostbuf[portstr - host] = 0;
+ if (sscanf(portstr + 1, "%d", &port) == 0) {
+ snprintf(buffer, buffer_size, "bad port number %s", portstr);
+ return;
+ }
+ } else {
+ port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+ }
+
+ snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
+
+ fd = socket_network_client(hostbuf, port, SOCK_STREAM);
+ if (fd < 0) {
+ snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
+ return;
+ }
+
+ D("client: connected on remote on fd %d\n", fd);
+ close_on_exec(fd);
+ disable_tcp_nagle(fd);
+
+ ret = register_socket_transport(fd, serial, port, 0);
+ if (ret < 0) {
+ adb_close(fd);
+ snprintf(buffer, buffer_size, "already connected to %s", serial);
+ } else {
+ snprintf(buffer, buffer_size, "connected to %s", serial);
+ }
+}
+
+void connect_emulator(char* port_spec, char* buffer, int buffer_size)
+{
+ char* port_separator = strchr(port_spec, ',');
+ if (!port_separator) {
+ snprintf(buffer, buffer_size,
+ "unable to parse '%s' as <console port>,<adb port>",
+ port_spec);
+ return;
+ }
+
+ // Zero-terminate console port and make port_separator point to 2nd port.
+ *port_separator++ = 0;
+ int console_port = strtol(port_spec, NULL, 0);
+ int adb_port = strtol(port_separator, NULL, 0);
+ if (!(console_port > 0 && adb_port > 0)) {
+ *(port_separator - 1) = ',';
+ snprintf(buffer, buffer_size,
+ "Invalid port numbers: Expected positive numbers, got '%s'",
+ port_spec);
+ return;
+ }
+
+ /* Check if the emulator is already known.
+ * Note: There's a small but harmless race condition here: An emulator not
+ * present just yet could be registered by another invocation right
+ * after doing this check here. However, local_connect protects
+ * against double-registration too. From here, a better error message
+ * can be produced. In the case of the race condition, the very specific
+ * error message won't be shown, but the data doesn't get corrupted. */
+ atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
+ if (known_emulator != NULL) {
+ snprintf(buffer, buffer_size,
+ "Emulator on port %d already registered.", adb_port);
+ return;
+ }
+
+ /* Check if more emulators can be registered. Similar unproblematic
+ * race condition as above. */
+ int candidate_slot = get_available_local_transport_index();
+ if (candidate_slot < 0) {
+ snprintf(buffer, buffer_size, "Cannot accept more emulators.");
+ return;
+ }
+
+ /* Preconditions met, try to connect to the emulator. */
+ if (!local_connect_arbitrary_ports(console_port, adb_port)) {
+ snprintf(buffer, buffer_size,
+ "Connected to emulator on ports %d,%d", console_port, adb_port);
+ } else {
+ snprintf(buffer, buffer_size,
+ "Could not connect to emulator on ports %d,%d",
+ console_port, adb_port);
+ }
+}
+
+static void connect_service(int fd, void* cookie)
+{
+ char buf[4096];
+ char resp[4096];
+ char *host = cookie;
+
+ if (!strncmp(host, "emu:", 4)) {
+ connect_emulator(host + 4, buf, sizeof(buf));
+ } else {
+ connect_device(host, buf, sizeof(buf));
+ }
+
+ // Send response for emulator and device
+ snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
+ writex(fd, resp, strlen(resp));
+ adb_close(fd);
+}
#endif
#if ADB_HOST
@@ -552,6 +582,10 @@ asocket* host_service_to_socket(const char* name, const char *serial)
int fd = create_service_thread(wait_for_state, sinfo);
return create_local_socket(fd);
+ } else if (!strncmp(name, "connect:", 8)) {
+ const char *host = name + 8;
+ int fd = create_service_thread(connect_service, (void *)host);
+ return create_local_socket(fd);
}
return NULL;
}