services.c revision 252586941934d23073a8d167ec240b221062505f
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stddef.h> 18#include <stdlib.h> 19#include <stdio.h> 20#include <unistd.h> 21#include <string.h> 22#include <errno.h> 23 24#include "sysdeps.h" 25 26#define TRACE_TAG TRACE_SERVICES 27#include "adb.h" 28#include "file_sync_service.h" 29 30#if ADB_HOST 31# ifndef HAVE_WINSOCK 32# include <netinet/in.h> 33# include <netdb.h> 34# include <sys/ioctl.h> 35# endif 36#else 37# include <cutils/android_reboot.h> 38# include <cutils/properties.h> 39#endif 40 41typedef struct stinfo stinfo; 42 43struct stinfo { 44 void (*func)(int fd, void *cookie); 45 int fd; 46 void *cookie; 47}; 48 49 50void *service_bootstrap_func(void *x) 51{ 52 stinfo *sti = x; 53 sti->func(sti->fd, sti->cookie); 54 free(sti); 55 return 0; 56} 57 58#if !ADB_HOST 59 60void restart_root_service(int fd, void *cookie) 61{ 62 char buf[100]; 63 char value[PROPERTY_VALUE_MAX]; 64 65 if (getuid() == 0) { 66 snprintf(buf, sizeof(buf), "adbd is already running as root\n"); 67 writex(fd, buf, strlen(buf)); 68 adb_close(fd); 69 } else { 70 property_get("ro.debuggable", value, ""); 71 if (strcmp(value, "1") != 0) { 72 snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n"); 73 writex(fd, buf, strlen(buf)); 74 adb_close(fd); 75 return; 76 } 77 78 property_set("service.adb.root", "1"); 79 snprintf(buf, sizeof(buf), "restarting adbd as root\n"); 80 writex(fd, buf, strlen(buf)); 81 adb_close(fd); 82 } 83} 84 85void restart_tcp_service(int fd, void *cookie) 86{ 87 char buf[100]; 88 char value[PROPERTY_VALUE_MAX]; 89 int port = (int) (uintptr_t) cookie; 90 91 if (port <= 0) { 92 snprintf(buf, sizeof(buf), "invalid port\n"); 93 writex(fd, buf, strlen(buf)); 94 adb_close(fd); 95 return; 96 } 97 98 snprintf(value, sizeof(value), "%d", port); 99 property_set("service.adb.tcp.port", value); 100 snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port); 101 writex(fd, buf, strlen(buf)); 102 adb_close(fd); 103} 104 105void restart_usb_service(int fd, void *cookie) 106{ 107 char buf[100]; 108 109 property_set("service.adb.tcp.port", "0"); 110 snprintf(buf, sizeof(buf), "restarting in USB mode\n"); 111 writex(fd, buf, strlen(buf)); 112 adb_close(fd); 113} 114 115void reboot_service(int fd, void *arg) 116{ 117 char buf[100]; 118 char property_val[PROPERTY_VALUE_MAX]; 119 int pid, ret; 120 121 sync(); 122 123 /* Attempt to unmount the SD card first. 124 * No need to bother checking for errors. 125 */ 126 pid = fork(); 127 if (pid == 0) { 128 /* ask vdc to unmount it */ 129 execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount", 130 getenv("EXTERNAL_STORAGE"), "force", NULL); 131 } else if (pid > 0) { 132 /* wait until vdc succeeds or fails */ 133 waitpid(pid, &ret, 0); 134 } 135 136 ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg); 137 if (ret >= (int) sizeof(property_val)) { 138 snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret); 139 writex(fd, buf, strlen(buf)); 140 goto cleanup; 141 } 142 143 ret = property_set(ANDROID_RB_PROPERTY, property_val); 144 if (ret < 0) { 145 snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret); 146 writex(fd, buf, strlen(buf)); 147 goto cleanup; 148 } 149 // Don't return early. Give the reboot command time to take effect 150 // to avoid messing up scripts which do "adb reboot && adb wait-for-device" 151 while(1) { pause(); } 152cleanup: 153 free(arg); 154 adb_close(fd); 155} 156 157void reverse_service(int fd, void* arg) 158{ 159 const char* command = arg; 160 161 if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) { 162 sendfailmsg(fd, "not a reverse forwarding command"); 163 } 164 free(arg); 165 adb_close(fd); 166} 167 168#endif 169 170static int create_service_thread(void (*func)(int, void *), void *cookie) 171{ 172 stinfo *sti; 173 adb_thread_t t; 174 int s[2]; 175 176 if(adb_socketpair(s)) { 177 printf("cannot create service socket pair\n"); 178 return -1; 179 } 180 181 sti = malloc(sizeof(stinfo)); 182 if(sti == 0) fatal("cannot allocate stinfo"); 183 sti->func = func; 184 sti->cookie = cookie; 185 sti->fd = s[1]; 186 187 if(adb_thread_create( &t, service_bootstrap_func, sti)){ 188 free(sti); 189 adb_close(s[0]); 190 adb_close(s[1]); 191 printf("cannot create service thread\n"); 192 return -1; 193 } 194 195 D("service thread started, %d:%d\n",s[0], s[1]); 196 return s[0]; 197} 198 199#if !ADB_HOST 200static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) 201{ 202#ifdef HAVE_WIN32_PROC 203 D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); 204 fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); 205 return -1; 206#else /* !HAVE_WIN32_PROC */ 207 char *devname; 208 int ptm; 209 210 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); 211 if(ptm < 0){ 212 printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); 213 return -1; 214 } 215 fcntl(ptm, F_SETFD, FD_CLOEXEC); 216 217 if(grantpt(ptm) || unlockpt(ptm) || 218 ((devname = (char*) ptsname(ptm)) == 0)){ 219 printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); 220 adb_close(ptm); 221 return -1; 222 } 223 224 *pid = fork(); 225 if(*pid < 0) { 226 printf("- fork failed: %s -\n", strerror(errno)); 227 adb_close(ptm); 228 return -1; 229 } 230 231 if(*pid == 0){ 232 int pts; 233 234 setsid(); 235 236 pts = unix_open(devname, O_RDWR); 237 if(pts < 0) { 238 fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname); 239 exit(-1); 240 } 241 242 dup2(pts, 0); 243 dup2(pts, 1); 244 dup2(pts, 2); 245 246 adb_close(pts); 247 adb_close(ptm); 248 249 // set OOM adjustment to zero 250 char text[64]; 251 snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); 252 int fd = adb_open(text, O_WRONLY); 253 if (fd >= 0) { 254 adb_write(fd, "0", 1); 255 adb_close(fd); 256 } else { 257 D("adb: unable to open %s\n", text); 258 } 259 execl(cmd, cmd, arg0, arg1, NULL); 260 fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", 261 cmd, strerror(errno), errno); 262 exit(-1); 263 } else { 264 // Don't set child's OOM adjustment to zero. 265 // Let the child do it itself, as sometimes the parent starts 266 // running before the child has a /proc/pid/oom_adj. 267 // """adb: unable to open /proc/644/oom_adj""" seen in some logs. 268 return ptm; 269 } 270#endif /* !HAVE_WIN32_PROC */ 271} 272#endif /* !ABD_HOST */ 273 274#if ADB_HOST 275#define SHELL_COMMAND "/bin/sh" 276#else 277#define SHELL_COMMAND "/system/bin/sh" 278#endif 279 280#if !ADB_HOST 281static void subproc_waiter_service(int fd, void *cookie) 282{ 283 pid_t pid = (pid_t) (uintptr_t) cookie; 284 285 D("entered. fd=%d of pid=%d\n", fd, pid); 286 for (;;) { 287 int status; 288 pid_t p = waitpid(pid, &status, 0); 289 if (p == pid) { 290 D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status); 291 if (WIFSIGNALED(status)) { 292 D("*** Killed by signal %d\n", WTERMSIG(status)); 293 break; 294 } else if (!WIFEXITED(status)) { 295 D("*** Didn't exit!!. status %d\n", status); 296 break; 297 } else if (WEXITSTATUS(status) >= 0) { 298 D("*** Exit code %d\n", WEXITSTATUS(status)); 299 break; 300 } 301 } 302 } 303 D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno); 304 if (SHELL_EXIT_NOTIFY_FD >=0) { 305 int res; 306 res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd)); 307 D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n", 308 SHELL_EXIT_NOTIFY_FD, pid, res, errno); 309 } 310} 311 312static int create_subproc_thread(const char *name) 313{ 314 stinfo *sti; 315 adb_thread_t t; 316 int ret_fd; 317 pid_t pid; 318 if(name) { 319 ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid); 320 } else { 321 ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid); 322 } 323 D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); 324 325 sti = malloc(sizeof(stinfo)); 326 if(sti == 0) fatal("cannot allocate stinfo"); 327 sti->func = subproc_waiter_service; 328 sti->cookie = (void*) (uintptr_t) pid; 329 sti->fd = ret_fd; 330 331 if(adb_thread_create( &t, service_bootstrap_func, sti)){ 332 free(sti); 333 adb_close(ret_fd); 334 printf("cannot create service thread\n"); 335 return -1; 336 } 337 338 D("service thread started, fd=%d pid=%d\n",ret_fd, pid); 339 return ret_fd; 340} 341#endif 342 343int service_to_fd(const char *name) 344{ 345 int ret = -1; 346 347 if(!strncmp(name, "tcp:", 4)) { 348 int port = atoi(name + 4); 349 name = strchr(name + 4, ':'); 350 if(name == 0) { 351 ret = socket_loopback_client(port, SOCK_STREAM); 352 if (ret >= 0) 353 disable_tcp_nagle(ret); 354 } else { 355#if ADB_HOST 356 ret = socket_network_client(name + 1, port, SOCK_STREAM); 357#else 358 return -1; 359#endif 360 } 361#ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */ 362 } else if(!strncmp(name, "local:", 6)) { 363 ret = socket_local_client(name + 6, 364 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 365 } else if(!strncmp(name, "localreserved:", 14)) { 366 ret = socket_local_client(name + 14, 367 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 368 } else if(!strncmp(name, "localabstract:", 14)) { 369 ret = socket_local_client(name + 14, 370 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); 371 } else if(!strncmp(name, "localfilesystem:", 16)) { 372 ret = socket_local_client(name + 16, 373 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); 374#endif 375#if !ADB_HOST 376 } else if(!strncmp("dev:", name, 4)) { 377 ret = unix_open(name + 4, O_RDWR); 378 } else if(!strncmp(name, "framebuffer:", 12)) { 379 ret = create_service_thread(framebuffer_service, 0); 380 } else if (!strncmp(name, "jdwp:", 5)) { 381 ret = create_jdwp_connection_fd(atoi(name+5)); 382 } else if(!HOST && !strncmp(name, "shell:", 6)) { 383 if(name[6]) { 384 ret = create_subproc_thread(name + 6); 385 } else { 386 ret = create_subproc_thread(0); 387 } 388 } else if(!strncmp(name, "sync:", 5)) { 389 ret = create_service_thread(file_sync_service, NULL); 390 } else if(!strncmp(name, "remount:", 8)) { 391 ret = create_service_thread(remount_service, NULL); 392 } else if(!strncmp(name, "reboot:", 7)) { 393 void* arg = strdup(name + 7); 394 if(arg == 0) return -1; 395 ret = create_service_thread(reboot_service, arg); 396 } else if(!strncmp(name, "root:", 5)) { 397 ret = create_service_thread(restart_root_service, NULL); 398 } else if(!strncmp(name, "backup:", 7)) { 399 char* arg = strdup(name+7); 400 if (arg == NULL) return -1; 401 ret = backup_service(BACKUP, arg); 402 } else if(!strncmp(name, "restore:", 8)) { 403 ret = backup_service(RESTORE, NULL); 404 } else if(!strncmp(name, "tcpip:", 6)) { 405 int port; 406 if (sscanf(name + 6, "%d", &port) == 0) { 407 port = 0; 408 } 409 ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port); 410 } else if(!strncmp(name, "usb:", 4)) { 411 ret = create_service_thread(restart_usb_service, NULL); 412 } else if (!strncmp(name, "reverse:", 8)) { 413 char* cookie = strdup(name + 8); 414 if (cookie == NULL) { 415 ret = -1; 416 } else { 417 ret = create_service_thread(reverse_service, cookie); 418 if (ret < 0) { 419 free(cookie); 420 } 421 } 422#endif 423 } 424 if (ret >= 0) { 425 close_on_exec(ret); 426 } 427 return ret; 428} 429 430#if ADB_HOST 431struct state_info { 432 transport_type transport; 433 char* serial; 434 int state; 435}; 436 437static void wait_for_state(int fd, void* cookie) 438{ 439 struct state_info* sinfo = cookie; 440 char* err = "unknown error"; 441 442 D("wait_for_state %d\n", sinfo->state); 443 444 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); 445 if(t != 0) { 446 writex(fd, "OKAY", 4); 447 } else { 448 sendfailmsg(fd, err); 449 } 450 451 if (sinfo->serial) 452 free(sinfo->serial); 453 free(sinfo); 454 adb_close(fd); 455 D("wait_for_state is done\n"); 456} 457 458static void connect_device(char* host, char* buffer, int buffer_size) 459{ 460 int port, fd; 461 char* portstr = strchr(host, ':'); 462 char hostbuf[100]; 463 char serial[100]; 464 int ret; 465 466 strncpy(hostbuf, host, sizeof(hostbuf) - 1); 467 if (portstr) { 468 if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) { 469 snprintf(buffer, buffer_size, "bad host name %s", host); 470 return; 471 } 472 // zero terminate the host at the point we found the colon 473 hostbuf[portstr - host] = 0; 474 if (sscanf(portstr + 1, "%d", &port) == 0) { 475 snprintf(buffer, buffer_size, "bad port number %s", portstr); 476 return; 477 } 478 } else { 479 port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; 480 } 481 482 snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port); 483 484 fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10); 485 if (fd < 0) { 486 snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port); 487 return; 488 } 489 490 D("client: connected on remote on fd %d\n", fd); 491 close_on_exec(fd); 492 disable_tcp_nagle(fd); 493 494 ret = register_socket_transport(fd, serial, port, 0); 495 if (ret < 0) { 496 adb_close(fd); 497 snprintf(buffer, buffer_size, "already connected to %s", serial); 498 } else { 499 snprintf(buffer, buffer_size, "connected to %s", serial); 500 } 501} 502 503void connect_emulator(char* port_spec, char* buffer, int buffer_size) 504{ 505 char* port_separator = strchr(port_spec, ','); 506 if (!port_separator) { 507 snprintf(buffer, buffer_size, 508 "unable to parse '%s' as <console port>,<adb port>", 509 port_spec); 510 return; 511 } 512 513 // Zero-terminate console port and make port_separator point to 2nd port. 514 *port_separator++ = 0; 515 int console_port = strtol(port_spec, NULL, 0); 516 int adb_port = strtol(port_separator, NULL, 0); 517 if (!(console_port > 0 && adb_port > 0)) { 518 *(port_separator - 1) = ','; 519 snprintf(buffer, buffer_size, 520 "Invalid port numbers: Expected positive numbers, got '%s'", 521 port_spec); 522 return; 523 } 524 525 /* Check if the emulator is already known. 526 * Note: There's a small but harmless race condition here: An emulator not 527 * present just yet could be registered by another invocation right 528 * after doing this check here. However, local_connect protects 529 * against double-registration too. From here, a better error message 530 * can be produced. In the case of the race condition, the very specific 531 * error message won't be shown, but the data doesn't get corrupted. */ 532 atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port); 533 if (known_emulator != NULL) { 534 snprintf(buffer, buffer_size, 535 "Emulator on port %d already registered.", adb_port); 536 return; 537 } 538 539 /* Check if more emulators can be registered. Similar unproblematic 540 * race condition as above. */ 541 int candidate_slot = get_available_local_transport_index(); 542 if (candidate_slot < 0) { 543 snprintf(buffer, buffer_size, "Cannot accept more emulators."); 544 return; 545 } 546 547 /* Preconditions met, try to connect to the emulator. */ 548 if (!local_connect_arbitrary_ports(console_port, adb_port)) { 549 snprintf(buffer, buffer_size, 550 "Connected to emulator on ports %d,%d", console_port, adb_port); 551 } else { 552 snprintf(buffer, buffer_size, 553 "Could not connect to emulator on ports %d,%d", 554 console_port, adb_port); 555 } 556} 557 558static void connect_service(int fd, void* cookie) 559{ 560 char buf[4096]; 561 char resp[4096]; 562 char *host = cookie; 563 564 if (!strncmp(host, "emu:", 4)) { 565 connect_emulator(host + 4, buf, sizeof(buf)); 566 } else { 567 connect_device(host, buf, sizeof(buf)); 568 } 569 570 // Send response for emulator and device 571 snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf); 572 writex(fd, resp, strlen(resp)); 573 adb_close(fd); 574} 575#endif 576 577#if ADB_HOST 578asocket* host_service_to_socket(const char* name, const char *serial) 579{ 580 if (!strcmp(name,"track-devices")) { 581 return create_device_tracker(); 582 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) { 583 struct state_info* sinfo = malloc(sizeof(struct state_info)); 584 585 if (serial) 586 sinfo->serial = strdup(serial); 587 else 588 sinfo->serial = NULL; 589 590 name += strlen("wait-for-"); 591 592 if (!strncmp(name, "local", strlen("local"))) { 593 sinfo->transport = kTransportLocal; 594 sinfo->state = CS_DEVICE; 595 } else if (!strncmp(name, "usb", strlen("usb"))) { 596 sinfo->transport = kTransportUsb; 597 sinfo->state = CS_DEVICE; 598 } else if (!strncmp(name, "any", strlen("any"))) { 599 sinfo->transport = kTransportAny; 600 sinfo->state = CS_DEVICE; 601 } else { 602 free(sinfo); 603 return NULL; 604 } 605 606 int fd = create_service_thread(wait_for_state, sinfo); 607 return create_local_socket(fd); 608 } else if (!strncmp(name, "connect:", 8)) { 609 const char *host = name + 8; 610 int fd = create_service_thread(connect_service, (void *)host); 611 return create_local_socket(fd); 612 } 613 return NULL; 614} 615#endif /* ADB_HOST */ 616