Merge "init: expand_props for onrestart commands."
diff --git a/adb/Android.mk b/adb/Android.mk
index 7977009..355bb7f 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -48,6 +48,11 @@
$(ADB_COMMON_CFLAGS) \
-fvisibility=hidden \
+LIBADB_linux_CFLAGS := \
+ -std=c++14 \
+
+LIBADB_CFLAGS += $(LIBADB_$(HOST_OS)_CFLAGS)
+
LIBADB_darwin_SRC_FILES := \
fdevent.cpp \
get_my_path_darwin.cpp \
diff --git a/adb/adb.h b/adb/adb.h
index 357be51..309b0e9 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -22,6 +22,8 @@
#include <base/macros.h>
+#include <string>
+
#include "adb_trace.h"
#include "fdevent.h"
@@ -357,8 +359,8 @@
void local_init(int port);
-int local_connect(int port);
-int local_connect_arbitrary_ports(int console_port, int adb_port);
+void local_connect(int port);
+int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
/* usb host/client interface */
void usb_init();
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 75e888d..418662c 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -33,8 +33,10 @@
#include <base/stringprintf.h>
#include <base/strings.h>
+#include <cutils/sockets.h>
#include "adb_io.h"
+#include "adb_utils.h"
static TransportType __adb_transport = kTransportAny;
static const char* __adb_serial = NULL;
@@ -152,13 +154,20 @@
int fd;
if (__adb_server_name) {
- fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
+ std::string reason;
+ fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
+ if (fd == -1) {
+ *error = android::base::StringPrintf("can't connect to %s:%d: %s",
+ __adb_server_name, __adb_server_port,
+ reason.c_str());
+ return -2;
+ }
} else {
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
- }
- if (fd < 0) {
- *error = perror_str("cannot connect to daemon");
- return -2;
+ if (fd == -1) {
+ *error = perror_str("cannot connect to daemon");
+ return -2;
+ }
}
if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index a15c513..bb45022 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <base/stringprintf.h>
+#include <cutils/sockets.h>
#include "sysdeps.h"
#include "transport.h"
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index e2af045..cd3c7bc 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -28,10 +28,17 @@
#include <base/logging.h>
#include <base/stringprintf.h>
#include <base/strings.h>
+#include <cutils/sockets.h>
#include "adb_trace.h"
#include "sysdeps.h"
+#if defined(_WIN32)
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#endif
+
bool getcwd(std::string* s) {
char* cwd = getcwd(nullptr, 0);
if (cwd != nullptr) *s = cwd;
@@ -158,3 +165,18 @@
<< " (" << *canonical_address << ")";
return true;
}
+
+int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
+ int getaddrinfo_error = 0;
+ int fd = socket_network_client_timeout(host.c_str(), port, type, timeout, &getaddrinfo_error);
+ if (fd != -1) {
+ return fd;
+ }
+ if (getaddrinfo_error != 0) {
+ // TODO: gai_strerror is not thread safe on Win32.
+ *error = gai_strerror(getaddrinfo_error);
+ } else {
+ *error = strerror(errno);
+ }
+ return -1;
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index e0aa1ba..d1a3f5f 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -39,4 +39,6 @@
std::string* host, int* port,
std::string* error);
+int network_connect(const std::string& host, int port, int type, int timeout, std::string* error);
+
#endif
diff --git a/adb/console.cpp b/adb/console.cpp
index 0707960..b7f5345 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -18,9 +18,10 @@
#include <stdio.h>
-#include "base/file.h"
-#include "base/logging.h"
-#include "base/strings.h"
+#include <base/file.h>
+#include <base/logging.h>
+#include <base/strings.h>
+#include <cutils/sockets.h>
#include "adb.h"
#include "adb_client.h"
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index a2e0f88..06e7780 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -22,6 +22,7 @@
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
diff --git a/adb/services.cpp b/adb/services.cpp
index 2e3ad98..82efb1c 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -39,6 +39,7 @@
#include <base/file.h>
#include <base/stringprintf.h>
#include <base/strings.h>
+#include <cutils/sockets.h>
#if !ADB_HOST
#include "cutils/android_reboot.h"
@@ -436,7 +437,8 @@
disable_tcp_nagle(ret);
} else {
#if ADB_HOST
- ret = socket_network_client(name + 1, port, SOCK_STREAM);
+ std::string error;
+ ret = network_connect(name + 1, port, SOCK_STREAM, 0, &error);
#else
return -1;
#endif
@@ -555,10 +557,11 @@
return;
}
- int fd = socket_network_client_timeout(host.c_str(), port, SOCK_STREAM, 10);
+ std::string error;
+ int fd = network_connect(host.c_str(), port, SOCK_STREAM, 10, &error);
if (fd == -1) {
*response = android::base::StringPrintf("unable to connect to %s: %s",
- serial.c_str(), strerror(errno));
+ serial.c_str(), error.c_str());
return;
}
@@ -612,12 +615,13 @@
}
// Preconditions met, try to connect to the emulator.
- if (!local_connect_arbitrary_ports(console_port, adb_port)) {
+ std::string error;
+ if (!local_connect_arbitrary_ports(console_port, adb_port, &error)) {
*response = android::base::StringPrintf("Connected to emulator on ports %d,%d",
console_port, adb_port);
} else {
- *response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d",
- console_port, adb_port);
+ *response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d: %s",
+ console_port, adb_port, error.c_str());
}
}
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 5efdab5..6160923 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -24,6 +24,8 @@
# undef _WIN32
#endif
+#include <errno.h>
+
/*
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
* <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
@@ -185,14 +187,6 @@
/* normally provided by <cutils/misc.h> */
extern void* load_file(const char* pathname, unsigned* psize);
-/* normally provided by <cutils/sockets.h> */
-extern int socket_loopback_client(int port, int type);
-extern int socket_network_client(const char *host, int port, int type);
-extern int socket_network_client_timeout(const char *host, int port, int type,
- int timeout);
-extern int socket_loopback_server(int port, int type);
-extern int socket_inaddr_any_server(int port, int type);
-
/* normally provided by "fdevent.h" */
#define FDE_READ 0x0001
@@ -274,7 +268,6 @@
#else /* !_WIN32 a.k.a. Unix */
#include "fdevent.h"
-#include <cutils/sockets.h>
#include <cutils/misc.h>
#include <cutils/threads.h>
#include <signal.h>
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index bdc6027..a274892 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <stdlib.h>
+#include <cutils/sockets.h>
+
#include "adb.h"
extern void fatal(const char *fmt, ...);
@@ -668,55 +670,45 @@
}
-int socket_network_client(const char *host, int port, int type)
-{
+int socket_network_client_timeout(const char *host, int port, int type, int timeout,
+ int* getaddrinfo_error) {
FH f = _fh_alloc( &_fh_socket_class );
- struct hostent *hp;
- struct sockaddr_in addr;
- SOCKET s;
+ if (!f) return -1;
- if (!f)
- return -1;
+ if (!_winsock_init) _init_winsock();
- if (!_winsock_init)
- _init_winsock();
-
- hp = gethostbyname(host);
+ hostent* hp = gethostbyname(host);
if(hp == 0) {
_fh_close(f);
return -1;
}
+ sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = hp->h_addrtype;
addr.sin_port = htons(port);
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
- s = socket(hp->h_addrtype, type, 0);
+ SOCKET s = socket(hp->h_addrtype, type, 0);
if(s == INVALID_SOCKET) {
_fh_close(f);
return -1;
}
f->fh_socket = s;
+ // TODO: implement timeouts for Windows.
+
if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
_fh_close(f);
return -1;
}
snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
- D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
+ D( "socket_network_client_timeout: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
return _fh_to_int(f);
}
-int socket_network_client_timeout(const char *host, int port, int type, int timeout)
-{
- // TODO: implement timeouts for Windows.
- return socket_network_client(host, port, type);
-}
-
-
int socket_inaddr_any_server(int port, int type)
{
FH f = _fh_alloc( &_fh_socket_class );
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index 3099554..7739633 100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -1,4 +1,6 @@
#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+
"""Simple conformance test for adb.
This script will use the available adb in path and run simple
@@ -336,6 +338,21 @@
self.assertEqual(1, status_code)
self.assertIn("error", output)
+ def test_unicode_paths(self):
+ """Ensure that we can support non-ASCII paths, even on Windows."""
+ adb = AdbWrapper()
+ name = u'로보카 폴리'.encode('utf-8')
+
+ # push.
+ tf = tempfile.NamedTemporaryFile("wb", suffix=name)
+ adb.push(tf.name, "/data/local/tmp/adb-test-{}".format(name))
+
+ # pull.
+ adb.shell("rm \"'/data/local/tmp/adb-test-*'\"".format(name))
+ adb.shell("touch \"'/data/local/tmp/adb-test-{}'\"".format(name))
+ tf = tempfile.NamedTemporaryFile("wb", suffix=name)
+ adb.pull("/data/local/tmp/adb-test-{}".format(name), tf.name)
+
class AdbFile(unittest.TestCase):
SCRATCH_DIR = "/data/local/tmp"
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 1adc69e..0dc9581 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <base/stringprintf.h>
+#include <cutils/sockets.h>
#if !ADB_HOST
#include "cutils/properties.h"
@@ -33,6 +34,7 @@
#include "adb.h"
#include "adb_io.h"
+#include "adb_utils.h"
#if ADB_HOST
/* we keep a list of opened transports. The atransport struct knows to which
@@ -83,19 +85,18 @@
return 0;
}
-
-int local_connect(int port) {
- return local_connect_arbitrary_ports(port-1, port);
+void local_connect(int port) {
+ std::string dummy;
+ local_connect_arbitrary_ports(port-1, port, &dummy);
}
-int local_connect_arbitrary_ports(int console_port, int adb_port)
-{
- int fd = -1;
+int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error) {
+ int fd = -1;
#if ADB_HOST
const char *host = getenv("ADBHOST");
if (host) {
- fd = socket_network_client(host, adb_port, SOCK_STREAM);
+ fd = network_connect(host, adb_port, SOCK_STREAM, 0, error);
}
#endif
if (fd < 0) {
@@ -126,7 +127,7 @@
/* this is only done when ADB starts up. later, each new emulator */
/* will send a message to ADB to indicate that is is starting up */
for ( ; count > 0; count--, port += 2 ) {
- (void) local_connect(port);
+ local_connect(port);
}
#endif
return 0;
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index 439826a..e570ef5 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -22,6 +22,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <linux/usb/ch9.h>
#include <linux/usbdevice_fs.h>
#include <linux/version.h>
#include <stdio.h>
@@ -31,7 +32,12 @@
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
-#include <linux/usb/ch9.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <list>
+#include <mutex>
+#include <string>
#include <base/file.h>
#include <base/stringprintf.h>
@@ -40,110 +46,92 @@
#include "adb.h"
#include "transport.h"
+using namespace std::literals;
+
/* usb scan debugging is waaaay too verbose */
#define DBGX(x...)
-ADB_MUTEX_DEFINE( usb_lock );
+struct usb_handle {
+ ~usb_handle() {
+ if (fd != -1) unix_close(fd);
+ }
-struct usb_handle
-{
- usb_handle *prev;
- usb_handle *next;
-
- char fname[64];
- int desc;
+ std::string path;
+ int fd = -1;
unsigned char ep_in;
unsigned char ep_out;
unsigned zero_mask;
- unsigned writeable;
+ unsigned writeable = 1;
- struct usbdevfs_urb urb_in;
- struct usbdevfs_urb urb_out;
+ usbdevfs_urb urb_in;
+ usbdevfs_urb urb_out;
- int urb_in_busy;
- int urb_out_busy;
- int dead;
+ bool urb_in_busy = false;
+ bool urb_out_busy = false;
+ bool dead = false;
- adb_cond_t notify;
- adb_mutex_t lock;
+ std::condition_variable cv;
+ std::mutex mutex;
// for garbage collecting disconnected devices
- int mark;
+ bool mark;
// ID of thread currently in REAPURB
- pthread_t reaper_thread;
+ pthread_t reaper_thread = 0;
};
-static usb_handle handle_list = {
- .prev = &handle_list,
- .next = &handle_list,
-};
+static std::mutex g_usb_handles_mutex;
+static std::list<usb_handle*> g_usb_handles;
-static int known_device(const char *dev_name)
-{
- usb_handle *usb;
-
- adb_mutex_lock(&usb_lock);
- for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
- if(!strcmp(usb->fname, dev_name)) {
+static int is_known_device(const char* dev_name) {
+ std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
+ for (usb_handle* usb : g_usb_handles) {
+ if (usb->path == dev_name) {
// set mark flag to indicate this device is still alive
- usb->mark = 1;
- adb_mutex_unlock(&usb_lock);
+ usb->mark = true;
return 1;
}
}
- adb_mutex_unlock(&usb_lock);
return 0;
}
-static void kick_disconnected_devices()
-{
- usb_handle *usb;
-
- adb_mutex_lock(&usb_lock);
+static void kick_disconnected_devices() {
+ std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
// kick any devices in the device list that were not found in the device scan
- for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
- if (usb->mark == 0) {
+ for (usb_handle* usb : g_usb_handles) {
+ if (!usb->mark) {
usb_kick(usb);
} else {
- usb->mark = 0;
+ usb->mark = false;
}
}
- adb_mutex_unlock(&usb_lock);
-
}
-static inline int badname(const char *name)
-{
- while(*name) {
- if(!isdigit(*name++)) return 1;
+static inline bool contains_non_digit(const char* name) {
+ while (*name) {
+ if (!isdigit(*name++)) return true;
}
- return 0;
+ return false;
}
-static void find_usb_device(const char *base,
+static void find_usb_device(const std::string& base,
void (*register_device_callback)
- (const char *, const char *, unsigned char, unsigned char, int, int, unsigned))
+ (const char*, const char*, unsigned char, unsigned char, int, int, unsigned))
{
- char busname[32], devname[32];
- unsigned char local_ep_in, local_ep_out;
- DIR *busdir , *devdir ;
- struct dirent *de;
- int fd ;
+ std::unique_ptr<DIR, int(*)(DIR*)> bus_dir(opendir(base.c_str()), closedir);
+ if (!bus_dir) return;
- busdir = opendir(base);
- if(busdir == 0) return;
+ dirent* de;
+ while ((de = readdir(bus_dir.get())) != 0) {
+ if (contains_non_digit(de->d_name)) continue;
- while((de = readdir(busdir)) != 0) {
- if(badname(de->d_name)) continue;
+ std::string bus_name = base + "/" + de->d_name;
- snprintf(busname, sizeof busname, "%s/%s", base, de->d_name);
- devdir = opendir(busname);
- if(devdir == 0) continue;
+ std::unique_ptr<DIR, int(*)(DIR*)> dev_dir(opendir(bus_name.c_str()), closedir);
+ if (!dev_dir) continue;
-// DBGX("[ scanning %s ]\n", busname);
- while((de = readdir(devdir))) {
+ while ((de = readdir(dev_dir.get()))) {
unsigned char devdesc[4096];
unsigned char* bufptr = devdesc;
unsigned char* bufend;
@@ -153,22 +141,20 @@
struct usb_endpoint_descriptor *ep1, *ep2;
unsigned zero_mask = 0;
unsigned vid, pid;
- size_t desclength;
- if(badname(de->d_name)) continue;
- snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
+ if (contains_non_digit(de->d_name)) continue;
- if(known_device(devname)) {
- DBGX("skipping %s\n", devname);
+ std::string dev_name = bus_name + "/" + de->d_name;
+ if (is_known_device(dev_name.c_str())) {
continue;
}
-// DBGX("[ scanning %s ]\n", devname);
- if((fd = unix_open(devname, O_RDONLY | O_CLOEXEC)) < 0) {
+ int fd = unix_open(dev_name.c_str(), O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
continue;
}
- desclength = unix_read(fd, devdesc, sizeof(devdesc));
+ size_t desclength = unix_read(fd, devdesc, sizeof(devdesc));
bufend = bufptr + desclength;
// should have device and configuration descriptors, and atleast two endpoints
@@ -188,7 +174,7 @@
vid = device->idVendor;
pid = device->idProduct;
- DBGX("[ %s is V:%04x P:%04x ]\n", devname, vid, pid);
+ DBGX("[ %s is V:%04x P:%04x ]\n", dev_name.c_str(), vid, pid);
// should have config descriptor next
config = (struct usb_config_descriptor *)bufptr;
@@ -225,7 +211,7 @@
struct stat st;
char pathbuf[128];
char link[256];
- char *devpath = NULL;
+ char *devpath = nullptr;
DBGX("looking for bulk endpoints\n");
// looks like ADB...
@@ -267,6 +253,7 @@
}
// we have a match. now we just need to figure out which is in and which is out.
+ unsigned char local_ep_in, local_ep_out;
if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
local_ep_in = ep1->bEndpointAddress;
local_ep_out = ep2->bEndpointAddress;
@@ -293,7 +280,7 @@
}
}
- register_device_callback(devname, devpath,
+ register_device_callback(dev_name.c_str(), devpath,
local_ep_in, local_ep_out,
interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
break;
@@ -304,72 +291,54 @@
} // end of while
unix_close(fd);
- } // end of devdir while
- closedir(devdir);
- } //end of busdir while
- closedir(busdir);
+ }
+ }
}
-static int usb_bulk_write(usb_handle *h, const void *data, int len)
-{
- struct usbdevfs_urb *urb = &h->urb_out;
- int res;
- struct timeval tv;
- struct timespec ts;
+static int usb_bulk_write(usb_handle* h, const void* data, int len) {
+ std::unique_lock<std::mutex> lock(h->mutex);
+ D("++ usb_bulk_write ++\n");
+ usbdevfs_urb* urb = &h->urb_out;
memset(urb, 0, sizeof(*urb));
urb->type = USBDEVFS_URB_TYPE_BULK;
urb->endpoint = h->ep_out;
urb->status = -1;
- urb->buffer = (void*) data;
+ urb->buffer = const_cast<void*>(data);
urb->buffer_length = len;
- D("++ write ++\n");
-
- adb_mutex_lock(&h->lock);
- if(h->dead) {
- res = -1;
- goto fail;
- }
- do {
- res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
- } while((res < 0) && (errno == EINTR));
-
- if(res < 0) {
- goto fail;
+ if (h->dead) {
+ errno = EINVAL;
+ return -1;
}
- res = -1;
- h->urb_out_busy = 1;
- for(;;) {
- /* time out after five seconds */
- gettimeofday(&tv, NULL);
- ts.tv_sec = tv.tv_sec + 5;
- ts.tv_nsec = tv.tv_usec * 1000L;
- res = pthread_cond_timedwait(&h->notify, &h->lock, &ts);
- if(res < 0 || h->dead) {
- break;
+ if (TEMP_FAILURE_RETRY(ioctl(h->fd, USBDEVFS_SUBMITURB, urb)) == -1) {
+ return -1;
+ }
+
+ h->urb_out_busy = true;
+ while (true) {
+ auto now = std::chrono::system_clock::now();
+ if (h->cv.wait_until(lock, now + 5s) == std::cv_status::timeout || h->dead) {
+ // TODO: call USBDEVFS_DISCARDURB?
+ errno = ETIMEDOUT;
+ return -1;
}
- if(h->urb_out_busy == 0) {
- if(urb->status == 0) {
- res = urb->actual_length;
+ if (!h->urb_out_busy) {
+ if (urb->status != 0) {
+ errno = -urb->status;
+ return -1;
}
- break;
+ return urb->actual_length;
}
}
-fail:
- adb_mutex_unlock(&h->lock);
- D("-- write --\n");
- return res;
}
-static int usb_bulk_read(usb_handle *h, void *data, int len)
-{
- struct usbdevfs_urb *urb = &h->urb_in;
- struct usbdevfs_urb *out = NULL;
- int res;
-
+static int usb_bulk_read(usb_handle* h, void* data, int len) {
+ std::unique_lock<std::mutex> lock(h->mutex);
D("++ usb_bulk_read ++\n");
+
+ usbdevfs_urb* urb = &h->urb_in;
memset(urb, 0, sizeof(*urb));
urb->type = USBDEVFS_URB_TYPE_BULK;
urb->endpoint = h->ep_in;
@@ -377,63 +346,58 @@
urb->buffer = data;
urb->buffer_length = len;
-
- adb_mutex_lock(&h->lock);
- if(h->dead) {
- res = -1;
- goto fail;
- }
- do {
- res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
- } while((res < 0) && (errno == EINTR));
-
- if(res < 0) {
- goto fail;
+ if (h->dead) {
+ errno = EINVAL;
+ return -1;
}
- h->urb_in_busy = 1;
- for(;;) {
+ if (TEMP_FAILURE_RETRY(ioctl(h->fd, USBDEVFS_SUBMITURB, urb)) == -1) {
+ return -1;
+ }
+
+ h->urb_in_busy = true;
+ while (true) {
D("[ reap urb - wait ]\n");
h->reaper_thread = pthread_self();
- adb_mutex_unlock(&h->lock);
- res = ioctl(h->desc, USBDEVFS_REAPURB, &out);
+ int fd = h->fd;
+ lock.unlock();
+
+ // This ioctl must not have TEMP_FAILURE_RETRY because we send SIGALRM to break out.
+ usbdevfs_urb* out = nullptr;
+ int res = ioctl(fd, USBDEVFS_REAPURB, &out);
int saved_errno = errno;
- adb_mutex_lock(&h->lock);
+
+ lock.lock();
h->reaper_thread = 0;
- if(h->dead) {
- res = -1;
- break;
+ if (h->dead) {
+ errno = EINVAL;
+ return -1;
}
- if(res < 0) {
- if(saved_errno == EINTR) {
+ if (res < 0) {
+ if (saved_errno == EINTR) {
continue;
}
D("[ reap urb - error ]\n");
- break;
+ errno = saved_errno;
+ return -1;
}
- D("[ urb @%p status = %d, actual = %d ]\n",
- out, out->status, out->actual_length);
+ D("[ urb @%p status = %d, actual = %d ]\n", out, out->status, out->actual_length);
- if(out == &h->urb_in) {
+ if (out == &h->urb_in) {
D("[ reap urb - IN complete ]\n");
- h->urb_in_busy = 0;
- if(urb->status == 0) {
- res = urb->actual_length;
- } else {
- res = -1;
+ h->urb_in_busy = false;
+ if (urb->status != 0) {
+ errno = -urb->status;
+ return -1;
}
- break;
+ return urb->actual_length;
}
- if(out == &h->urb_out) {
+ if (out == &h->urb_out) {
D("[ reap urb - OUT compelete ]\n");
- h->urb_out_busy = 0;
- adb_cond_broadcast(&h->notify);
+ h->urb_out_busy = false;
+ h->cv.notify_all();
}
}
-fail:
- adb_mutex_unlock(&h->lock);
- D("-- usb_bulk_read --\n");
- return res;
}
@@ -443,19 +407,15 @@
unsigned char *data = (unsigned char*) _data;
int n = usb_bulk_write(h, data, len);
- if(n != len) {
- D("ERROR: n = %d, errno = %d (%s)\n",
- n, errno, strerror(errno));
+ if (n != len) {
+ D("ERROR: n = %d, errno = %d (%s)\n", n, errno, strerror(errno));
return -1;
}
- if(h->zero_mask && !(len & h->zero_mask)) {
- /* if we need 0-markers and our transfer
- ** is an even multiple of the packet size,
- ** then send the zero markers.
- */
- n = usb_bulk_write(h, _data, 0);
- return n;
+ if (h->zero_mask && !(len & h->zero_mask)) {
+ // If we need 0-markers and our transfer is an even multiple of the packet size,
+ // then send a zero marker.
+ return usb_bulk_write(h, _data, 0);
}
D("-- usb_write --\n");
@@ -471,11 +431,11 @@
while(len > 0) {
int xfer = len;
- D("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
+ D("[ usb read %d fd = %d], path=%s\n", xfer, h->fd, h->path.c_str());
n = usb_bulk_read(h, data, xfer);
- D("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname);
+ D("[ usb read %d ] = %d, path=%s\n", xfer, n, h->path.c_str());
if(n != xfer) {
- if((errno == ETIMEDOUT) && (h->desc != -1)) {
+ if((errno == ETIMEDOUT) && (h->fd != -1)) {
D("[ timeout ]\n");
if(n > 0){
data += n;
@@ -496,12 +456,11 @@
return 0;
}
-void usb_kick(usb_handle *h)
-{
- D("[ kicking %p (fd = %d) ]\n", h, h->desc);
- adb_mutex_lock(&h->lock);
- if(h->dead == 0) {
- h->dead = 1;
+void usb_kick(usb_handle* h) {
+ std::lock_guard<std::mutex> lock(h->mutex);
+ D("[ kicking %p (fd = %d) ]\n", h, h->fd);
+ if (!h->dead) {
+ h->dead = true;
if (h->writeable) {
/* HACK ALERT!
@@ -517,34 +476,27 @@
** but this ensures that a reader blocked on REAPURB
** will get unblocked
*/
- ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_in);
- ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_out);
+ ioctl(h->fd, USBDEVFS_DISCARDURB, &h->urb_in);
+ ioctl(h->fd, USBDEVFS_DISCARDURB, &h->urb_out);
h->urb_in.status = -ENODEV;
h->urb_out.status = -ENODEV;
- h->urb_in_busy = 0;
- h->urb_out_busy = 0;
- adb_cond_broadcast(&h->notify);
+ h->urb_in_busy = false;
+ h->urb_out_busy = false;
+ h->cv.notify_all();
} else {
unregister_usb_transport(h);
}
}
- adb_mutex_unlock(&h->lock);
}
-int usb_close(usb_handle *h)
-{
- D("++ usb close ++\n");
- adb_mutex_lock(&usb_lock);
- h->next->prev = h->prev;
- h->prev->next = h->next;
- h->prev = 0;
- h->next = 0;
+int usb_close(usb_handle* h) {
+ std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
+ g_usb_handles.remove(h);
- unix_close(h->desc);
- D("-- usb closed %p (fd = %d) --\n", h, h->desc);
- adb_mutex_unlock(&usb_lock);
+ D("-- usb close %p (fd = %d) --\n", h, h->fd);
- free(h);
+ delete h;
+
return 0;
}
@@ -557,54 +509,44 @@
// from the list when we're finally closed and everything will work out
// fine.
//
- // If we have a usb_handle on the list 'o handles with a matching name, we
+ // If we have a usb_handle on the list of handles with a matching name, we
// have no further work to do.
- adb_mutex_lock(&usb_lock);
- for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
- if (!strcmp(usb->fname, dev_name)) {
- adb_mutex_unlock(&usb_lock);
- return;
+ {
+ std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
+ for (usb_handle* usb: g_usb_handles) {
+ if (usb->path == dev_name) {
+ return;
+ }
}
}
- adb_mutex_unlock(&usb_lock);
D("[ usb located new device %s (%d/%d/%d) ]\n", dev_name, ep_in, ep_out, interface);
- usb_handle* usb = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
- if (usb == nullptr) fatal("couldn't allocate usb_handle");
- strcpy(usb->fname, dev_name);
+ std::unique_ptr<usb_handle> usb(new usb_handle);
+ usb->path = dev_name;
usb->ep_in = ep_in;
usb->ep_out = ep_out;
usb->zero_mask = zero_mask;
- usb->writeable = 1;
- adb_cond_init(&usb->notify, 0);
- adb_mutex_init(&usb->lock, 0);
- // Initialize mark to 1 so we don't get garbage collected after the device
- // scan.
- usb->mark = 1;
- usb->reaper_thread = 0;
+ // Initialize mark so we don't get garbage collected after the device scan.
+ usb->mark = true;
- usb->desc = unix_open(usb->fname, O_RDWR | O_CLOEXEC);
- if (usb->desc == -1) {
+ usb->fd = unix_open(usb->path.c_str(), O_RDWR | O_CLOEXEC);
+ if (usb->fd == -1) {
// Opening RW failed, so see if we have RO access.
- usb->desc = unix_open(usb->fname, O_RDONLY | O_CLOEXEC);
- if (usb->desc == -1) {
- D("[ usb open %s failed: %s]\n", usb->fname, strerror(errno));
- free(usb);
+ usb->fd = unix_open(usb->path.c_str(), O_RDONLY | O_CLOEXEC);
+ if (usb->fd == -1) {
+ D("[ usb open %s failed: %s]\n", usb->path.c_str(), strerror(errno));
return;
}
usb->writeable = 0;
}
- D("[ usb opened %s%s, fd=%d]\n", usb->fname,
- (usb->writeable ? "" : " (read-only)"), usb->desc);
+ D("[ usb opened %s%s, fd=%d]\n",
+ usb->path.c_str(), (usb->writeable ? "" : " (read-only)"), usb->fd);
if (usb->writeable) {
- if (ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface) != 0) {
- D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]\n",
- usb->desc, strerror(errno));
- unix_close(usb->desc);
- free(usb);
+ if (ioctl(usb->fd, USBDEVFS_CLAIMINTERFACE, &interface) != 0) {
+ D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]\n", usb->fd, strerror(errno));
return;
}
}
@@ -623,14 +565,12 @@
serial = android::base::Trim(serial);
// Add to the end of the active handles.
- adb_mutex_lock(&usb_lock);
- usb->next = &handle_list;
- usb->prev = handle_list.prev;
- usb->prev->next = usb;
- usb->next->prev = usb;
- adb_mutex_unlock(&usb_lock);
-
- register_usb_transport(usb, serial.c_str(), dev_path, usb->writeable);
+ usb_handle* done_usb = usb.release();
+ {
+ std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
+ g_usb_handles.push_back(done_usb);
+ }
+ register_usb_transport(done_usb, serial.c_str(), dev_path, done_usb->writeable);
}
static void* device_poll_thread(void* unused) {
@@ -644,19 +584,13 @@
return nullptr;
}
-static void sigalrm_handler(int signo) {
- // don't need to do anything here
-}
-
-void usb_init()
-{
- struct sigaction actions;
-
+void usb_init() {
+ struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
- actions.sa_handler = sigalrm_handler;
- sigaction(SIGALRM,& actions, NULL);
+ actions.sa_handler = [](int) {};
+ sigaction(SIGALRM, &actions, nullptr);
if (!adb_thread_create(device_poll_thread, nullptr)) {
fatal_errno("cannot create input thread");
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index f8076ca..07d1351 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -77,7 +77,7 @@
extern int socket_loopback_client(int port, int type);
extern int socket_network_client(const char *host, int port, int type);
extern int socket_network_client_timeout(const char *host, int port, int type,
- int timeout);
+ int timeout, int* getaddrinfo_error);
extern int socket_loopback_server(int port, int type);
extern int socket_local_server(const char *name, int namespaceId, int type);
extern int socket_local_server_bind(int s, const char *name, int namespaceId);
diff --git a/libcutils/socket_network_client.c b/libcutils/socket_network_client.c
index 2610254..3610f1b 100644
--- a/libcutils/socket_network_client.c
+++ b/libcutils/socket_network_client.c
@@ -41,7 +41,10 @@
// Connect to the given host and port.
// 'timeout' is in seconds (0 for no timeout).
// Returns a file descriptor or -1 on error.
-int socket_network_client_timeout(const char* host, int port, int type, int timeout) {
+// On error, check *getaddrinfo_error (for use with gai_strerror) first;
+// if that's 0, use errno instead.
+int socket_network_client_timeout(const char* host, int port, int type, int timeout,
+ int* getaddrinfo_error) {
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
@@ -51,7 +54,8 @@
snprintf(port_str, sizeof(port_str), "%d", port);
struct addrinfo* addrs;
- if (getaddrinfo(host, port_str, &hints, &addrs) != 0) {
+ *getaddrinfo_error = getaddrinfo(host, port_str, &hints, &addrs);
+ if (getaddrinfo_error != 0) {
return -1;
}
@@ -116,5 +120,6 @@
}
int socket_network_client(const char* host, int port, int type) {
- return socket_network_client_timeout(host, port, type, 0);
+ int getaddrinfo_error;
+ return socket_network_client_timeout(host, port, type, 0, &getaddrinfo_error);
}