static bool reboot_service_impl(int fd, const char* arg) { const char* reboot_arg = arg; bool auto_reboot = false; if (strcmp(reboot_arg, "sideload-auto-reboot") == 0) { auto_reboot = true; reboot_arg = "sideload"; } // It reboots into sideload mode by setting "--sideload" or "--sideload_auto_reboot" // in the command file. if (strcmp(reboot_arg, "sideload") == 0) { if (getuid() != 0) { WriteFdExactly(fd, "'adb root' is required for 'adb reboot sideload'.\n"); return false; } const std::vector<std::string> options = { auto_reboot ? "--sideload_auto_reboot" : "--sideload" }; std::string err; if (!write_bootloader_message(options, &err)) { D("Failed to set bootloader message: %s", err.c_str()); return false; } reboot_arg = "recovery"; } sync(); std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg); if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) { WriteFdFmt(fd, "reboot (%s) failed\n", reboot_string.c_str()); return false; } return true; }
static int write_data_link(int fd, const char *path, syncsendbuf *sbuf) { int len, ret; len = readlink(path, sbuf->data, SYNC_DATA_MAX-1); if(len < 0) { fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno)); return -1; } sbuf->data[len] = '\0'; sbuf->size = htoll(len + 1); sbuf->id = ID_DATA; ret = !WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + len + 1); if(ret) return -1; total_bytes += len + 1; return 0; }
TEST_F(LocalSocketTest, smoke) { const size_t PIPE_COUNT = 100; const size_t MESSAGE_LOOP_COUNT = 100; const std::string MESSAGE = "socket_test"; int fd_pair1[2]; int fd_pair2[2]; ASSERT_EQ(0, adb_socketpair(fd_pair1)); ASSERT_EQ(0, adb_socketpair(fd_pair2)); pthread_t thread; ThreadArg thread_arg; thread_arg.first_read_fd = fd_pair1[0]; thread_arg.last_write_fd = fd_pair2[1]; thread_arg.middle_pipe_count = PIPE_COUNT; int writer = fd_pair1[1]; int reader = fd_pair2[0]; ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(FdEventThreadFunc), &thread_arg)); usleep(1000); for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) { std::string read_buffer = MESSAGE; std::string write_buffer(MESSAGE.size(), 'a'); ASSERT_TRUE(WriteFdExactly(writer, read_buffer.c_str(), read_buffer.size())); ASSERT_TRUE(ReadFdExactly(reader, &write_buffer[0], write_buffer.size())); ASSERT_EQ(read_buffer, write_buffer); } ASSERT_EQ(0, adb_close(writer)); ASSERT_EQ(0, adb_close(reader)); // Wait until the local sockets are closed. sleep(1); ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); ASSERT_EQ(0, pthread_join(thread, nullptr)); }
void restart_usb_service(int fd, void *cookie) { android::base::SetProperty("service.adb.tcp.port", "0"); WriteFdExactly(fd, "restarting in USB mode\n"); adb_close(fd); }
/* A worker thread that monitors host connections, and registers a transport for * every new host connection. This thread replaces server_socket_thread on * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD * pipe to communicate with adbd daemon inside the guest. This is done in order * to provide more robust communication channel between ADB host and guest. The * main issue with server_socket_thread approach is that it runs on top of TCP, * and thus is sensitive to network disruptions. For instance, the * ConnectionManager may decide to reset all network connections, in which case * the connection between ADB host and guest will be lost. To make ADB traffic * independent from the network, we use here 'adb' QEMUD service to transfer data * between the host, and the guest. See external/qemu/android/adb-*.* that * implements the emulator's side of the protocol. Another advantage of using * QEMUD approach is that ADB will be up much sooner, since it doesn't depend * anymore on network being set up. * The guest side of the protocol contains the following phases: * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service * is opened, and it becomes clear whether or not emulator supports that * protocol. * - Wait for the ADB host to create connection with the guest. This is done by * sending an 'accept' request to the adb QEMUD service, and waiting on * response. * - When new ADB host connection is accepted, the connection with adb QEMUD * service is registered as the transport, and a 'start' request is sent to the * adb QEMUD service, indicating that the guest is ready to receive messages. * Note that the guest will ignore messages sent down from the emulator before * the transport registration is completed. That's why we need to send the * 'start' request after the transport is registered. */ static void qemu_socket_thread(void* arg) { /* 'accept' request to the adb QEMUD service. */ static const char _accept_req[] = "accept"; /* 'start' request to the adb QEMUD service. */ static const char _start_req[] = "start"; /* 'ok' reply from the adb QEMUD service. */ static const char _ok_resp[] = "ok"; const int port = (int) (uintptr_t) arg; int fd; char tmp[256]; char con_name[32]; adb_thread_setname("qemu socket"); D("transport: qemu_socket_thread() starting"); /* adb QEMUD service connection request. */ snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port); /* Connect to the adb QEMUD service. */ fd = qemu_pipe_open(con_name); if (fd < 0) { /* This could be an older version of the emulator, that doesn't * implement adb QEMUD service. Fall back to the old TCP way. */ D("adb service is not available. Falling back to TCP socket."); adb_thread_create(server_socket_thread, arg); return; } for(;;) { /* * Wait till the host creates a new connection. */ /* Send the 'accept' request. */ if (WriteFdExactly(fd, _accept_req, strlen(_accept_req))) { /* Wait for the response. In the response we expect 'ok' on success, * or 'ko' on failure. */ if (!ReadFdExactly(fd, tmp, 2) || memcmp(tmp, _ok_resp, 2)) { D("Accepting ADB host connection has failed."); adb_close(fd); } else { /* Host is connected. Register the transport, and start the * exchange. */ std::string serial = android::base::StringPrintf("host-%d", fd); register_socket_transport(fd, serial.c_str(), port, 1); if (!WriteFdExactly(fd, _start_req, strlen(_start_req))) { adb_close(fd); } } /* Prepare for accepting of the next ADB host connection. */ fd = qemu_pipe_open(con_name); if (fd < 0) { D("adb service become unavailable."); return; } } else { D("Unable to send the '%s' request to ADB service.", _accept_req); return; } } D("transport: qemu_socket_thread() exiting"); return; }
bool SendFail(int fd, const std::string& reason) { return WriteFdExactly(fd, "FAIL", 4) && SendProtocolString(fd, reason); }
bool SendOkay(int fd) { return WriteFdExactly(fd, "OKAY", 4); }
bool WriteFdExactly(int fd, const std::string& str) { return WriteFdExactly(fd, str.c_str(), str.size()); }
void framebuffer_service(unique_fd fd) { struct fbinfo fbinfo; unsigned int i, bsize; char buf[640]; int fd_screencap; int w, h, f, c; int fds[2]; pid_t pid; if (pipe2(fds, O_CLOEXEC) < 0) return; pid = fork(); if (pid < 0) goto done; if (pid == 0) { dup2(fds[1], STDOUT_FILENO); adb_close(fds[0]); adb_close(fds[1]); const char* command = "screencap"; const char *args[2] = {command, nullptr}; execvp(command, (char**)args); perror_exit("exec screencap failed"); } adb_close(fds[1]); fd_screencap = fds[0]; /* read w, h, format & color space */ if(!ReadFdExactly(fd_screencap, &w, 4)) goto done; if(!ReadFdExactly(fd_screencap, &h, 4)) goto done; if(!ReadFdExactly(fd_screencap, &f, 4)) goto done; if(!ReadFdExactly(fd_screencap, &c, 4)) goto done; fbinfo.version = DDMS_RAWIMAGE_VERSION; fbinfo.colorSpace = c; /* see hardware/hardware.h */ switch (f) { case 1: /* RGBA_8888 */ fbinfo.bpp = 32; fbinfo.size = w * h * 4; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 0; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 16; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 8; break; case 2: /* RGBX_8888 */ fbinfo.bpp = 32; fbinfo.size = w * h * 4; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 0; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 16; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 0; break; case 3: /* RGB_888 */ fbinfo.bpp = 24; fbinfo.size = w * h * 3; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 0; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 16; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 0; break; case 4: /* RGB_565 */ fbinfo.bpp = 16; fbinfo.size = w * h * 2; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 11; fbinfo.red_length = 5; fbinfo.green_offset = 5; fbinfo.green_length = 6; fbinfo.blue_offset = 0; fbinfo.blue_length = 5; fbinfo.alpha_offset = 0; fbinfo.alpha_length = 0; break; case 5: /* BGRA_8888 */ fbinfo.bpp = 32; fbinfo.size = w * h * 4; fbinfo.width = w; fbinfo.height = h; fbinfo.red_offset = 16; fbinfo.red_length = 8; fbinfo.green_offset = 8; fbinfo.green_length = 8; fbinfo.blue_offset = 0; fbinfo.blue_length = 8; fbinfo.alpha_offset = 24; fbinfo.alpha_length = 8; break; default: goto done; } /* write header */ if (!WriteFdExactly(fd.get(), &fbinfo, sizeof(fbinfo))) goto done; /* write data */ for(i = 0; i < fbinfo.size; i += bsize) { bsize = sizeof(buf); if (i + bsize > fbinfo.size) bsize = fbinfo.size - i; if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done; if (!WriteFdExactly(fd.get(), buf, bsize)) goto done; } done: adb_close(fds[0]); TEMP_FAILURE_RETRY(waitpid(pid, nullptr, 0)); }
static int sync_recv(int fd, const char* rpath, const char* lpath, bool show_progress) { syncmsg msg; int len; int lfd = -1; char *buffer = send_buffer.data; unsigned id; unsigned long long size = 0; len = strlen(rpath); if(len > 1024) return -1; if (show_progress) { // Determine remote file size. syncmsg stat_msg; stat_msg.req.id = ID_STAT; stat_msg.req.namelen = htoll(len); if (!WriteFdExactly(fd, &stat_msg.req, sizeof(stat_msg.req)) || !WriteFdExactly(fd, rpath, len)) { return -1; } if (!ReadFdExactly(fd, &stat_msg.stat, sizeof(stat_msg.stat))) { return -1; } if (stat_msg.stat.id != ID_STAT) return -1; size = ltohl(stat_msg.stat.size); } msg.req.id = ID_RECV; msg.req.namelen = htoll(len); if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || !WriteFdExactly(fd, rpath, len)) { return -1; } if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; if((id == ID_DATA) || (id == ID_DONE)) { adb_unlink(lpath); mkdirs(lpath); lfd = adb_creat(lpath, 0644); if(lfd < 0) { fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno)); return -1; } goto handle_data; } else { goto remote_error; } for(;;) { if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; handle_data: len = ltohl(msg.data.size); if(id == ID_DONE) break; if(id != ID_DATA) goto remote_error; if(len > SYNC_DATA_MAX) { fprintf(stderr,"data overrun\n"); adb_close(lfd); return -1; } if(!ReadFdExactly(fd, buffer, len)) { adb_close(lfd); return -1; } if(!WriteFdExactly(lfd, buffer, len)) { fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno)); adb_close(lfd); return -1; } total_bytes += len; if (show_progress) { print_transfer_progress(total_bytes, size); } } adb_close(lfd); return 0; remote_error: adb_close(lfd); adb_unlink(lpath); if(id == ID_FAIL) { len = ltohl(msg.data.size); if(len > 256) len = 256; if(!ReadFdExactly(fd, buffer, len)) { return -1; } buffer[len] = 0; } else { memcpy(buffer, &id, 4); buffer[4] = 0; } fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer); return 0; }
static int sync_send(int fd, const char *lpath, const char *rpath, unsigned mtime, mode_t mode, bool show_progress) { syncmsg msg; int len, r; syncsendbuf *sbuf = &send_buffer; char* file_buffer = NULL; int size = 0; char tmp[64]; len = strlen(rpath); if(len > 1024) goto fail; snprintf(tmp, sizeof(tmp), ",%d", mode); r = strlen(tmp); msg.req.id = ID_SEND; msg.req.namelen = htoll(len + r); if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || !WriteFdExactly(fd, rpath, len) || !WriteFdExactly(fd, tmp, r)) { free(file_buffer); goto fail; } if (file_buffer) { write_data_buffer(fd, file_buffer, size, sbuf, show_progress); free(file_buffer); } else if (S_ISREG(mode)) write_data_file(fd, lpath, sbuf, show_progress); else if (S_ISLNK(mode)) write_data_link(fd, lpath, sbuf); else goto fail; msg.data.id = ID_DONE; msg.data.size = htoll(mtime); if(!WriteFdExactly(fd, &msg.data, sizeof(msg.data))) goto fail; if(!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) return -1; if(msg.status.id != ID_OKAY) { if(msg.status.id == ID_FAIL) { len = ltohl(msg.status.msglen); if(len > 256) len = 256; if(!ReadFdExactly(fd, sbuf->data, len)) { return -1; } sbuf->data[len] = 0; } else strcpy(sbuf->data, "unknown reason"); fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data); return -1; } return 0; fail: fprintf(stderr,"protocol failure\n"); adb_close(fd); return -1; }
static void close_adb(void* data) { adb_data* ad = reinterpret_cast<adb_data*>(data); WriteFdExactly(ad->sfd, "DONEDONE"); }
static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, mode_t mode, std::vector<char>& buffer, bool do_unlink) { syncmsg msg; unsigned int timestamp = 0; int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); if (fd < 0 && errno == ENOENT) { if (!secure_mkdirs(path)) { SendSyncFailErrno(s, "secure_mkdirs failed"); goto fail; } fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); } if (fd < 0 && errno == EEXIST) { fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode); } if (fd < 0) { SendSyncFailErrno(s, "couldn't create file"); goto fail; } else { if (fchown(fd, uid, gid) == -1) { SendSyncFailErrno(s, "fchown failed"); goto fail; } // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(path, 0); // fchown clears the setuid bit - restore it if present. // Ignore the result of calling fchmod. It's not supported // by all filesystems. b/12441485 fchmod(fd, mode); } while (true) { unsigned int len; if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id != ID_DATA) { if (msg.data.id == ID_DONE) { timestamp = msg.data.size; break; } SendSyncFail(s, "invalid data message"); goto fail; } len = msg.data.size; if (len > buffer.size()) { // TODO: resize buffer? SendSyncFail(s, "oversize data message"); goto fail; } if (!ReadFdExactly(s, &buffer[0], len)) goto fail; if (!WriteFdExactly(fd, &buffer[0], len)) { SendSyncFailErrno(s, "write failed"); goto fail; } } adb_close(fd); utimbuf u; u.actime = timestamp; u.modtime = timestamp; utime(path, &u); msg.status.id = ID_OKAY; msg.status.msglen = 0; return WriteFdExactly(s, &msg.status, sizeof(msg.status)); fail: if (fd >= 0) adb_close(fd); if (do_unlink) adb_unlink(path); return false; }
static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, uint64_t capabilities, mode_t mode, std::vector<char>& buffer, bool do_unlink) { syncmsg msg; unsigned int timestamp = 0; __android_log_security_bswrite(SEC_TAG_ADB_SEND_FILE, path); int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); if (fd < 0 && errno == ENOENT) { if (!secure_mkdirs(adb_dirname(path))) { SendSyncFailErrno(s, "secure_mkdirs failed"); goto fail; } fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); } if (fd < 0 && errno == EEXIST) { fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode); } if (fd < 0) { SendSyncFailErrno(s, "couldn't create file"); goto fail; } else { if (fchown(fd, uid, gid) == -1) { SendSyncFailErrno(s, "fchown failed"); goto fail; } // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(path, 0); // fchown clears the setuid bit - restore it if present. // Ignore the result of calling fchmod. It's not supported // by all filesystems, so we don't check for success. b/12441485 fchmod(fd, mode); if (!update_capabilities(path, capabilities)) { SendSyncFailErrno(s, "update_capabilities failed"); goto fail; } } while (true) { if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id != ID_DATA) { if (msg.data.id == ID_DONE) { timestamp = msg.data.size; break; } SendSyncFail(s, "invalid data message"); goto abort; } if (msg.data.size > buffer.size()) { // TODO: resize buffer? SendSyncFail(s, "oversize data message"); goto abort; } if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort; if (!WriteFdExactly(fd, &buffer[0], msg.data.size)) { SendSyncFailErrno(s, "write failed"); goto fail; } } adb_close(fd); utimbuf u; u.actime = timestamp; u.modtime = timestamp; utime(path, &u); msg.status.id = ID_OKAY; msg.status.msglen = 0; return WriteFdExactly(s, &msg.status, sizeof(msg.status)); fail: // If there's a problem on the device, we'll send an ID_FAIL message and // close the socket. Unfortunately the kernel will sometimes throw that // data away if the other end keeps writing without reading (which is // the case with old versions of adb). To maintain compatibility, keep // reading and throwing away ID_DATA packets until the other side notices // that we've reported an error. while (true) { if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id == ID_DONE) { goto abort; } else if (msg.data.id != ID_DATA) { char id[5]; memcpy(id, &msg.data.id, sizeof(msg.data.id)); id[4] = '\0'; D("handle_send_fail received unexpected id '%s' during failure", id); goto abort; } if (msg.data.size > buffer.size()) { D("handle_send_fail received oversized packet of length '%u' during failure", msg.data.size); goto abort; } if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort; } abort: if (fd >= 0) adb_close(fd); if (do_unlink) adb_unlink(path); return false; }
static void reconnect_service(int fd, void* arg) { WriteFdExactly(fd, "done"); adb_close(fd); atransport* t = static_cast<atransport*>(arg); kick_transport(t); }
bool WriteFdExactly(int fd, const char* str) { return WriteFdExactly(fd, str, strlen(str)); }
void restart_usb_service(int fd, void *cookie) { property_set("service.adb.tcp.port", "0"); WriteFdExactly(fd, "restarting in USB mode\n"); adb_close(fd); }
int adb_send_emulator_command(int argc, const char** argv, const char* serial) { int fd = connect_to_console(serial); if (fd == -1) { return 1; } std::string commands = adb_construct_auth_command(); for (int i = 1; i < argc; i++) { commands.append(argv[i]); commands.push_back(i == argc - 1 ? '\n' : ' '); } commands.append("quit\n"); if (!WriteFdExactly(fd, commands)) { fprintf(stderr, "error: cannot write to emulator: %s\n", strerror(errno)); adb_close(fd); return 1; } // Drain output that the emulator console has sent us to prevent a problem // on Windows where if adb closes the socket without reading all the data, // the emulator's next call to recv() will have an ECONNABORTED error, // preventing the emulator from reading the command that adb has sent. // https://code.google.com/p/android/issues/detail?id=21021 int result; std::string emulator_output; do { char buf[BUFSIZ]; result = adb_read(fd, buf, sizeof(buf)); // Keep reading until zero bytes (orderly/graceful shutdown) or an // error. If 'adb emu kill' is executed, the emulator calls exit() with // the socket open (and shutdown(SD_SEND) was not called), which causes // Windows to send a TCP RST segment which causes adb to get ECONNRESET. // Any other emu command is followed by the quit command that we // appended above, and that causes the emulator to close the socket // which should cause zero bytes (orderly/graceful shutdown) to be // returned. if (result > 0) emulator_output.append(buf, result); } while (result > 0); // Note: the following messages are expected to be quite stable from emulator. // // Emulator console will send the following message upon connection: // // Android Console: Authentication required // Android Console: type 'auth <auth_token>' to authenticate // Android Console: you can find your <auth_token> in // '/<path-to-home>/.emulator_console_auth_token' // OK\r\n // // and the following after authentication: // Android Console: type 'help' for a list of commands // OK\r\n // // So try search and skip first two "OK\r\n", print the rest. // const std::string delims = "OK\r\n"; size_t found = 0; for (int i = 0; i < 2; ++i) { const size_t result = emulator_output.find(delims, found); if (result == std::string::npos) { break; } else { found = result + delims.size(); } } printf("%s", emulator_output.c_str() + found); adb_close(fd); return 0; }