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:
parent
90b06ac786
commit
ff19670d48
51
adb/adb.c
51
adb/adb.c
|
@ -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];
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)){
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue