intadb_connect(const std::string& service, std::string* error){ // first query the adb server's version int fd = _adb_connect("host:version", error);
D("adb_connect: service %s", service.c_str()); if (fd == -2 && !is_local_socket_spec(__adb_server_socket_spec)) { fprintf(stderr, "* cannot start server on remote host\n"); // error is the original network connection error return fd; } elseif (fd == -2) { fprintf(stderr, "* daemon not running; starting now at %s\n", __adb_server_socket_spec); start_server: if (launch_server(__adb_server_socket_spec)) { fprintf(stderr, "* failed to start daemon\n"); // launch_server() has already printed detailed error info, so just // return a generic error string about the overall adb_connect() // that the caller requested. *error = "cannot connect to daemon"; return-1; } else { fprintf(stderr, "* daemon started successfully\n"); } // The server will wait until it detects all of its connected devices before acking. // Fall through to _adb_connect. } else { // If a server is already running, check its version matches. int version = ADB_SERVER_VERSION - 1;
// If we have a file descriptor, then parse version result. if (fd >= 0) { std::string version_string; if (!ReadProtocolString(fd, &version_string, error)) { adb_close(fd); return-1; }
ReadOrderlyShutdown(fd); adb_close(fd);
if (sscanf(&version_string[0], "%04x", &version) != 1) { *error = android::base::StringPrintf("cannot parse version string: %s", version_string.c_str()); return-1; } } else { // If fd is -1 check for "unknown host service" which would // indicate a version of adb that does not support the // version command, in which case we should fall-through to kill it. if (*error != "unknown host service") { return fd; } }
if (version != ADB_SERVER_VERSION) { fprintf(stderr, "adb server version (%d) doesn't match this client (%d); killing...\n", version, ADB_SERVER_VERSION); adb_kill_server(); goto start_server; } }
// if the command is start-server, we are done. if (service == "host:start-server") { return0; }
fd = _adb_connect(service, error); if (fd == -1) { D("_adb_connect error: %s", error->c_str()); } elseif(fd == -2) { fprintf(stderr, "* daemon still not running\n"); } D("adb_connect: return fd %d", fd);
// If we told a previous adb server to quit because of version mismatch, we can get to this // point before it's finished exiting. Retry for a while to give it some time. while (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error) != INSTALL_STATUS_OK) { if (std::chrono::steady_clock::now() - start > 0.5s) { fatal("could not install *smartsocket* listener: %s", error.c_str()); }
std::this_thread::sleep_for(100ms); }
adb_auth_init();
if (is_daemon) { // Start a new session for the daemon. Do this here instead of after the fork so // that a ctrl-c between the "starting server" and "done starting server" messages // gets a chance to terminate the server. // setsid will fail with EPERM if it's already been a lead process of new session. // Ignore such error. if (setsid() == -1 && errno != EPERM) { fatal("setsid() failed: %s", strerror(errno)); }
// Wait for the USB scan to complete before notifying the parent that we're up. // We need to perform this in a thread, because we would otherwise block the event loop. std::thread notify_thread([ack_reply_fd]() { adb_wait_for_device_initialization(); // Any error output written to stderr now goes to adb.log. We could // keep around a copy of the stderr fd and use that to write any errors // encountered by the following code, but that is probably overkill. // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not // "OKAY". if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) { fatal_errno("error writing ACK to fd %d", ack_reply_fd); } unix_close(ack_reply_fd); }); notify_thread.detach(); }
/* Never bind to the CD-Rom emulation interface */ if (iface_desc->bInterfaceClass == 0x08) return -ENODEV;
/* * Don't bind reserved interfaces (like network ones) which often have * the same class/subclass/protocol as the serial interfaces. Look at * the Windows driver .INF files for reserved interface numbers. */ if (device_flags & RSVD(iface_desc->bInterfaceNumber)) return -ENODEV; /* * Don't bind network interface on Samsung GT-B3730, it is handled by * a separate module. */ if (dev_desc->idVendor == cpu_to_le16(SAMSUNG_VENDOR_ID) && dev_desc->idProduct == cpu_to_le16(SAMSUNG_PRODUCT_GT_B3730) && iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; ... }