static void server_socket_thread(void* arg) { int serverfd, fd; int port = (int) (uintptr_t) arg; adb_thread_setname("server socket"); D("transport: server_socket_thread() starting"); serverfd = -1; for(;;) { if(serverfd == -1) { std::string error; serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error); if(serverfd < 0) { D("server: cannot bind socket yet: %s", error.c_str()); std::this_thread::sleep_for(1s); continue; } close_on_exec(serverfd); } D("server: trying to get new connection from %d", port); fd = adb_socket_accept(serverfd, nullptr, nullptr); if(fd >= 0) { D("server: new connection on fd %d", fd); close_on_exec(fd); disable_tcp_nagle(fd); std::string serial = android::base::StringPrintf("host-%d", fd); if (register_socket_transport(fd, serial.c_str(), port, 1) != 0) { adb_close(fd); } } } D("transport: server_socket_thread() exiting"); }
static void server_socket_thread(void* arg) { int serverfd, fd; sockaddr_storage ss; sockaddr *addrp = reinterpret_cast<sockaddr*>(&ss); socklen_t alen; int port = (int) (uintptr_t) arg; adb_thread_setname("server socket"); D("transport: server_socket_thread() starting"); serverfd = -1; for(;;) { if(serverfd == -1) { std::string error; serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error); if(serverfd < 0) { D("server: cannot bind socket yet: %s", error.c_str()); adb_sleep_ms(1000); continue; } close_on_exec(serverfd); } alen = sizeof(ss); D("server: trying to get new connection from %d", port); fd = adb_socket_accept(serverfd, addrp, &alen); if(fd >= 0) { D("server: new connection on fd %d", fd); close_on_exec(fd); disable_tcp_nagle(fd); register_socket_transport(fd, "host", port, 1); } } D("transport: server_socket_thread() exiting"); }
void *service_bootstrap_func(void *x) { stinfo* sti = reinterpret_cast<stinfo*>(x); adb_thread_setname(android::base::StringPrintf("service %d", sti->fd)); sti->func(sti->fd, sti->cookie); free(sti); return 0; }
void device_poll_thread() { adb_thread_setname("Device Poll"); D("Created device thread"); while (true) { find_devices(); std::this_thread::sleep_for(1s); } }
// The transport is opened by transport_register_func before // the read_transport and write_transport threads are started. // // The read_transport thread issues a SYNC(1, token) message to let // the write_transport thread know to start things up. In the event // of transport IO failure, the read_transport thread will post a // SYNC(0,0) message to ensure shutdown. // // The transport will not actually be closed until both threads exit, but the threads // will kick the transport on their way out to disconnect the underlying device. // // read_transport thread reads data from a transport (representing a usb/tcp connection), // and makes the main thread call handle_packet(). static void *read_transport_thread(void *_t) { atransport *t = reinterpret_cast<atransport*>(_t); apacket *p; adb_thread_setname(android::base::StringPrintf("<-%s", (t->serial != nullptr ? t->serial : "transport"))); D("%s: starting read_transport thread on fd %d, SYNC online (%d)", t->serial, t->fd, t->sync_token + 1); p = get_apacket(); p->msg.command = A_SYNC; p->msg.arg0 = 1; p->msg.arg1 = ++(t->sync_token); p->msg.magic = A_SYNC ^ 0xffffffff; if(write_packet(t->fd, t->serial, &p)) { put_apacket(p); D("%s: failed to write SYNC packet", t->serial); goto oops; } D("%s: data pump started", t->serial); for(;;) { p = get_apacket(); if(t->read_from_remote(p, t) == 0){ D("%s: received remote packet, sending to transport", t->serial); if(write_packet(t->fd, t->serial, &p)){ put_apacket(p); D("%s: failed to write apacket to transport", t->serial); goto oops; } } else { D("%s: remote read failed for transport", t->serial); put_apacket(p); break; } } D("%s: SYNC offline for transport", t->serial); p = get_apacket(); p->msg.command = A_SYNC; p->msg.arg0 = 0; p->msg.arg1 = 0; p->msg.magic = A_SYNC ^ 0xffffffff; if(write_packet(t->fd, t->serial, &p)) { put_apacket(p); D("%s: failed to write SYNC apacket to transport", t->serial); } oops: D("%s: read_transport thread is exiting", t->serial); kick_transport(t); transport_unref(t); return 0; }
static void _power_notification_thread() { // This uses a thread with its own window message pump to get power // notifications. If adb runs from a non-interactive service account, this // might not work (not sure). If that happens to not work, we could use // heavyweight WMI APIs to get power notifications. But for the common case // of a developer's interactive session, a window message pump is more // appropriate. D("Created power notification thread"); adb_thread_setname("Power Notifier"); // Window class names are process specific. static const WCHAR kPowerNotificationWindowClassName[] = L"PowerNotificationWindow"; // Get the HINSTANCE corresponding to the module that _power_window_proc // is in (the main module). const HINSTANCE instance = GetModuleHandleW(nullptr); if (!instance) { // This is such a common API call that this should never fail. LOG(FATAL) << "GetModuleHandleW failed: " << android::base::SystemErrorCodeToString(GetLastError()); } WNDCLASSEXW wndclass; memset(&wndclass, 0, sizeof(wndclass)); wndclass.cbSize = sizeof(wndclass); wndclass.lpfnWndProc = _power_window_proc; wndclass.hInstance = instance; wndclass.lpszClassName = kPowerNotificationWindowClassName; if (!RegisterClassExW(&wndclass)) { LOG(FATAL) << "RegisterClassExW failed: " << android::base::SystemErrorCodeToString(GetLastError()); } if (!CreateWindowExW(WS_EX_NOACTIVATE, kPowerNotificationWindowClassName, L"ADB Power Notification Window", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, instance, nullptr)) { LOG(FATAL) << "CreateWindowExW failed: " << android::base::SystemErrorCodeToString(GetLastError()); } MSG msg; while (GetMessageW(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); } // GetMessageW() will return false if a quit message is posted. We don't // do that, but it might be possible for that to occur when logging off or // shutting down. Not a big deal since the whole process will be going away // soon anyway. D("Power notification thread exiting"); }
static void client_socket_thread(void* x) { adb_thread_setname("client_socket_thread"); D("transport: client_socket_thread() starting"); while (true) { int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; int count = ADB_LOCAL_TRANSPORT_MAX; // Try to connect to any number of running emulator instances. for ( ; count > 0; count--, port += 2 ) { local_connect(port); } sleep(1); } }
// write_transport thread gets packets sent by the main thread (through send_packet()), // and writes to a transport (representing a usb/tcp connection). static void *write_transport_thread(void *_t) { atransport *t = reinterpret_cast<atransport*>(_t); apacket *p; int active = 0; adb_thread_setname(android::base::StringPrintf("->%s", (t->serial != nullptr ? t->serial : "transport"))); D("%s: starting write_transport thread, reading from fd %d", t->serial, t->fd); for(;;){ if(read_packet(t->fd, t->serial, &p)) { D("%s: failed to read apacket from transport on fd %d", t->serial, t->fd ); break; } if(p->msg.command == A_SYNC){ if(p->msg.arg0 == 0) { D("%s: transport SYNC offline", t->serial); put_apacket(p); break; } else { if(p->msg.arg1 == t->sync_token) { D("%s: transport SYNC online", t->serial); active = 1; } else { D("%s: transport ignoring SYNC %d != %d", t->serial, p->msg.arg1, t->sync_token); } } } else { if(active) { D("%s: transport got packet, sending to remote", t->serial); t->write_to_remote(p, t); } else { D("%s: transport ignoring packet while offline", t->serial); } } put_apacket(p); } D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd); kick_transport(t); transport_unref(t); return 0; }
static void client_socket_thread(void* x) { adb_thread_setname("client_socket_thread"); D("transport: client_socket_thread() starting"); PollAllLocalPortsForEmulator(); while (true) { std::vector<RetryPort> ports; // Collect retry ports. { std::unique_lock<std::mutex> lock(retry_ports_lock); while (retry_ports.empty()) { retry_ports_cond.wait(lock); } retry_ports.swap(ports); } // Sleep here instead of the end of loop, because if we immediately try to reconnect // the emulator just kicked, the adbd on the emulator may not have time to remove the // just kicked transport. adb_sleep_ms(LOCAL_PORT_RETRY_INTERVAL_IN_MS); // Try connecting retry ports. std::vector<RetryPort> next_ports; for (auto& port : ports) { VLOG(TRANSPORT) << "retry port " << port.port << ", last retry_count " << port.retry_count; if (local_connect(port.port)) { VLOG(TRANSPORT) << "retry port " << port.port << " successfully"; continue; } if (--port.retry_count > 0) { next_ports.push_back(port); } else { VLOG(TRANSPORT) << "stop retrying port " << port.port; } } // Copy back left retry ports. { std::unique_lock<std::mutex> lock(retry_ports_lock); retry_ports.insert(retry_ports.end(), next_ports.begin(), next_ports.end()); } } }
/* 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; }
static unsigned __stdcall _redirect_stderr_thread(HANDLE h) { adb_thread_setname("stderr redirect"); return _redirect_pipe_thread(h, STD_ERROR_HANDLE); }
static unsigned __stdcall _redirect_stdout_thread(HANDLE h) { adb_thread_setname("stdout redirect"); return _redirect_pipe_thread(h, STD_OUTPUT_HANDLE); }
static void service_bootstrap_func(void* x) { stinfo* sti = reinterpret_cast<stinfo*>(x); adb_thread_setname(android::base::StringPrintf("%s svc %d", sti->service_name, sti->fd)); sti->func(sti->fd, sti->cookie); free(sti); }