adb: Improved support for running adb over TCP/IP

Added new commands:

adb connect <host>:<port> (to connect to a device via TCP/IP)
adb tcpip <port>          (to restart adbd on the device to listen on TCP/IP)
adb usb                   (to restart adbd on the device to listen USB)

Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/adb/adb.c b/adb/adb.c
index e8d2c8f..9980bad 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -832,6 +832,7 @@
 {
 #if !ADB_HOST
     int secure = 0;
+    int port;
     char value[PROPERTY_VALUE_MAX];
 #endif
 
@@ -918,14 +919,17 @@
     }
 
         /* for the device, start the usb transport if the
-        ** android usb device exists, otherwise start the
-        ** network transport.
+        ** android usb device exists and "service.adb.tcp"
+        ** is not set, otherwise start the network transport.
         */
-    if(access("/dev/android_adb", F_OK) == 0 ||
-       access("/dev/android", F_OK) == 0) {
+    property_get("service.adb.tcp.port", value, "0");
+    if (sscanf(value, "%d", &port) == 0) {
+        port = 0;
+    }
+    if (port == 0 && access("/dev/android_adb", F_OK) == 0) {
         usb_init();
     } else {
-        local_init();
+        local_init(port);
     }
     init_jdwp();
 #endif
@@ -1006,6 +1010,43 @@
         return 0;
     }
 
+    // add a new TCP transport
+    if (!strncmp(service, "connect:", 8)) {
+        char buffer[4096];
+        int port, fd;
+        char* host = service + 8;
+        char* portstr = strchr(host, ':');
+
+        if (!portstr) {
+            snprintf(buffer, sizeof(buffer), "unable to parse %s as <host>:<port>\n", host);
+            goto done;
+        }
+        // zero terminate host by overwriting the ':'
+        *portstr++ = 0;
+        if (sscanf(portstr, "%d", &port) == 0) {
+            snprintf(buffer, sizeof(buffer), "bad port number %s\n", portstr);
+            goto done;
+        }
+
+        fd = socket_network_client(host, port, SOCK_STREAM);
+        if (fd < 0) {
+            snprintf(buffer, sizeof(buffer), "unable to connect to %s:%d\n", host, port);
+            goto done;
+        }
+
+        D("client: connected on remote on fd %d\n", fd);
+        close_on_exec(fd);
+        disable_tcp_nagle(fd);
+        snprintf(buf, sizeof buf, "%s:%d", host, port);
+        register_socket_transport(fd, buf, port, 0);
+        snprintf(buffer, sizeof(buffer), "connected to %s:%d\n", host, port);
+
+done:
+        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
+        writex(reply_fd, buf, strlen(buf));
+        return 0;
+    }
+
     // returns our value for ADB_SERVER_VERSION
     if (!strcmp(service, "version")) {
         char version[12];