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>
This commit is contained in:
Mike Lockwood 2009-08-24 15:58:40 -07:00
parent 90b06ac786
commit ff19670d48
6 changed files with 140 additions and 51 deletions

View File

@ -832,6 +832,7 @@ int adb_main(int is_daemon)
{
#if !ADB_HOST
int secure = 0;
int port;
char value[PROPERTY_VALUE_MAX];
#endif
@ -918,14 +919,17 @@ int adb_main(int is_daemon)
}
/* 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 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
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];

View File

@ -33,7 +33,7 @@
#define ADB_VERSION_MAJOR 1 // Used for help/version information
#define ADB_VERSION_MINOR 0 // Used for help/version information
#define ADB_SERVER_VERSION 23 // Increment this when we want to force users to start a new adb server
#define ADB_SERVER_VERSION 24 // Increment this when we want to force users to start a new adb server
typedef struct amessage amessage;
typedef struct apacket apacket;
@ -262,14 +262,14 @@ void run_transport_disconnects( atransport* t );
void kick_transport( atransport* t );
/* initialize a transport object's func pointers and state */
int init_socket_transport(atransport *t, int s, int port);
int init_socket_transport(atransport *t, int s, int port, int local);
void init_usb_transport(atransport *t, usb_handle *usb, int state);
/* for MacOS X cleanup */
void close_usb_devices();
/* cause new transports to be init'd and added to the list */
void register_socket_transport(int s, const char *serial, int port);
void register_socket_transport(int s, const char *serial, int port, int local);
void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable);
/* this should only be used for transports with connection_state == CS_NOPERM */

View File

@ -105,6 +105,7 @@ void help()
" environment variable is used, which must\n"
" be an absolute path.\n"
" devices - list all connected devices\n"
" connect <host>:<port> - connect to a device via TCP/IP"
"\n"
"device commands:\n"
" adb push <local> <remote> - copy file/dir to device\n"
@ -149,7 +150,9 @@ void help()
" adb status-window - continuously print device status for a specified device\n"
" adb remount - remounts the /system partition on the device read-write\n"
" adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
" adb root - restarts adb with root permissions\n"
" adb root - restarts the adbd daemon with root permissions\n"
" adb usb - restarts the adbd daemon listening on USB"
" adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
"\n"
"networking:\n"
" adb ppp <tty> [parameters] - Run PPP over USB.\n"
@ -850,6 +853,22 @@ top:
}
}
if(!strcmp(argv[0], "connect")) {
char *tmp;
if (argc != 2) {
fprintf(stderr, "Usage: adb connect <host>:<port>\n");
return 1;
}
snprintf(buf, sizeof buf, "host:%s:%s", argv[0], argv[1]);
tmp = adb_query(buf);
if(tmp) {
printf("%s\n", tmp);
return 0;
} else {
return 1;
}
}
if (!strcmp(argv[0], "emu")) {
return adb_send_emulator_command(argc, argv);
}
@ -908,35 +927,15 @@ top:
return 0;
}
if(!strcmp(argv[0], "remount")) {
int fd = adb_connect("remount:");
if(fd >= 0) {
read_and_dump(fd);
adb_close(fd);
return 0;
}
fprintf(stderr,"error: %s\n", adb_error());
return 1;
}
if(!strcmp(argv[0], "reboot")) {
int fd;
if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
|| !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
|| !strcmp(argv[0], "reboot")) {
char command[100];
if (argc > 1)
snprintf(buf, sizeof(buf), "reboot:%s", argv[1]);
snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
else
snprintf(buf, sizeof(buf), "reboot:");
fd = adb_connect(buf);
if(fd >= 0) {
read_and_dump(fd);
adb_close(fd);
return 0;
}
fprintf(stderr,"error: %s\n", adb_error());
return 1;
}
if(!strcmp(argv[0], "root")) {
int fd = adb_connect("root:");
snprintf(command, sizeof(command), "%s:", argv[0]);
int fd = adb_connect(command);
if(fd >= 0) {
read_and_dump(fd);
adb_close(fd);

View File

@ -120,6 +120,7 @@ void restart_root_service(int fd, void *cookie)
if (strcmp(value, "1") != 0) {
snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
writex(fd, buf, strlen(buf));
adb_close(fd);
return;
}
@ -134,13 +135,52 @@ void restart_root_service(int fd, void *cookie)
}
}
void reboot_service(int fd, char *arg)
void restart_tcp_service(int fd, void *cookie)
{
char buf[100];
char value[PROPERTY_VALUE_MAX];
int port = (int)cookie;
if (port <= 0) {
snprintf(buf, sizeof(buf), "invalid port\n");
writex(fd, buf, strlen(buf));
adb_close(fd);
return;
}
snprintf(value, sizeof(value), "%d", port);
property_set("service.adb.tcp.port", value);
snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
writex(fd, buf, strlen(buf));
adb_close(fd);
// quit, and init will restart us in TCP mode
sleep(1);
exit(1);
}
void restart_usb_service(int fd, void *cookie)
{
char buf[100];
property_set("service.adb.tcp.port", "0");
snprintf(buf, sizeof(buf), "restarting in USB mode\n");
writex(fd, buf, strlen(buf));
adb_close(fd);
// quit, and init will restart us in USB mode
sleep(1);
exit(1);
}
void reboot_service(int fd, void *arg)
{
char buf[100];
int ret;
sync();
ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, arg);
ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2, (char *)arg);
if (ret < 0) {
snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
writex(fd, buf, strlen(buf));
@ -415,12 +455,20 @@ int service_to_fd(const char *name)
} else if(!strncmp(name, "remount:", 8)) {
ret = create_service_thread(remount_service, NULL);
} else if(!strncmp(name, "reboot:", 7)) {
char* arg = name + 7;
const char* arg = name + 7;
if (*name == 0)
arg = NULL;
ret = create_service_thread(reboot_service, arg);
ret = create_service_thread(reboot_service, (void *)arg);
} else if(!strncmp(name, "root:", 5)) {
ret = create_service_thread(restart_root_service, NULL);
} else if(!strncmp(name, "tcpip:", 6)) {
int port;
if (sscanf(name + 6, "%d", &port) == 0) {
port = 0;
}
ret = create_service_thread(restart_tcp_service, (void *)port);
} else if(!strncmp(name, "usb:", 4)) {
ret = create_service_thread(restart_usb_service, NULL);
#endif
#if 0
} else if(!strncmp(name, "echo:", 5)){

View File

@ -849,11 +849,11 @@ void close_usb_devices()
}
#endif // ADB_HOST
void register_socket_transport(int s, const char *serial, int port)
void register_socket_transport(int s, const char *serial, int port, int local)
{
atransport *t = calloc(1, sizeof(atransport));
D("transport: %p init'ing for socket %d, on port %d\n", t, s, port);
if ( init_socket_transport(t, s, port) < 0 ) {
if ( init_socket_transport(t, s, port, local) < 0 ) {
adb_close(s);
free(t);
return;

View File

@ -122,7 +122,7 @@ int local_connect(int port)
close_on_exec(fd);
disable_tcp_nagle(fd);
snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, port - 1);
register_socket_transport(fd, buf, port);
register_socket_transport(fd, buf, port, 1);
return 0;
}
return -1;
@ -147,17 +147,18 @@ static void *client_socket_thread(void *x)
return 0;
}
static void *server_socket_thread(void *x)
static void *server_socket_thread(void * arg)
{
int serverfd, fd;
struct sockaddr addr;
socklen_t alen;
int port = (int)arg;
D("transport: server_socket_thread() starting\n");
serverfd = -1;
for(;;) {
if(serverfd == -1) {
serverfd = socket_inaddr_any_server(ADB_LOCAL_TRANSPORT_PORT, SOCK_STREAM);
serverfd = socket_inaddr_any_server(port, SOCK_STREAM);
if(serverfd < 0) {
D("server: cannot bind socket yet\n");
adb_sleep_ms(1000);
@ -167,20 +168,20 @@ static void *server_socket_thread(void *x)
}
alen = sizeof(addr);
D("server: trying to get new connection from %d\n", ADB_LOCAL_TRANSPORT_PORT);
D("server: trying to get new connection from %d\n", port);
fd = adb_socket_accept(serverfd, &addr, &alen);
if(fd >= 0) {
D("server: new connection on fd %d\n", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
register_socket_transport(fd,"host",ADB_LOCAL_TRANSPORT_PORT);
register_socket_transport(fd, "host", port, 1);
}
}
D("transport: server_socket_thread() exiting\n");
return 0;
}
void local_init(void)
void local_init(int port)
{
adb_thread_t thr;
void* (*func)(void *);
@ -193,7 +194,7 @@ void local_init(void)
D("transport: local %s init\n", HOST ? "client" : "server");
if(adb_thread_create(&thr, func, 0)) {
if(adb_thread_create(&thr, func, (void *)port)) {
fatal_errno("cannot create local socket %s thread",
HOST ? "client" : "server");
}
@ -225,7 +226,7 @@ static void remote_close(atransport *t)
adb_close(t->fd);
}
int init_socket_transport(atransport *t, int s, int port)
int init_socket_transport(atransport *t, int s, int port, int local)
{
int fail = 0;
@ -239,7 +240,7 @@ int init_socket_transport(atransport *t, int s, int port)
t->type = kTransportLocal;
#if ADB_HOST
if (HOST) {
if (HOST && local) {
adb_mutex_lock( &local_transports_lock );
{
int index = (port - ADB_LOCAL_TRANSPORT_PORT)/2;