Merge "ueventd: add a test for ueventd_parser.cpp"
diff --git a/adb/Android.bp b/adb/Android.bp
index c0e4c57..2a9a579 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -299,6 +299,10 @@
         "libqemu_pipe",
         "libbase",
     ],
+
+    export_include_dirs: [
+        "daemon/include",
+    ],
 }
 
 cc_binary {
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 46c3f58..10b6090 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -589,7 +589,7 @@
 
     int rc = perform_usb_transfer(h, info, std::move(lock));
     LOG(DEBUG) << "usb_write(" << len << ") = " << rc;
-    return rc;
+    return info->transfer->actual_length;
 }
 
 int usb_read(usb_handle* h, void* d, int len) {
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index 76f5d78..869e858 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -418,11 +418,11 @@
     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);
+        return usb_bulk_write(h, _data, 0) == 0 ? n : -1;
     }
 
     D("-- usb_write --");
-    return 0;
+    return n;
 }
 
 int usb_read(usb_handle *h, void *_data, int len)
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index 8a95a19..49baf36 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -497,8 +497,8 @@
         }
     }
 
-    if (0 == result)
-        return 0;
+    if (!result)
+        return len;
 
     LOG(ERROR) << "usb_write failed with status: " << std::hex << result;
     return -1;
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index 026703d..e928377 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -365,7 +365,7 @@
         }
     }
 
-    return 0;
+    return written;
 
 fail:
     // Any failure should cause us to kick the device instead of leaving it a
diff --git a/adb/daemon/usb.h b/adb/daemon/include/adbd/usb.h
similarity index 92%
rename from adb/daemon/usb.h
rename to adb/daemon/include/adbd/usb.h
index 15a7f65..7905d9d 100644
--- a/adb/daemon/usb.h
+++ b/adb/daemon/include/adbd/usb.h
@@ -19,6 +19,7 @@
 #include <atomic>
 #include <condition_variable>
 #include <mutex>
+#include <vector>
 
 #include <asyncio/AsyncIO.h>
 
@@ -54,5 +55,9 @@
     // read and write threads.
     struct aio_block read_aiob;
     struct aio_block write_aiob;
+
+    bool reads_zero_packets;
+    size_t io_size;
 };
 
+usb_handle *create_usb_handle(unsigned num_bufs, unsigned io_size);
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 51ad5f5..c79d6fc 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -41,7 +41,7 @@
 #include <android-base/properties.h>
 
 #include "adb.h"
-#include "daemon/usb.h"
+#include "adbd/usb.h"
 #include "transport.h"
 
 using namespace std::chrono_literals;
@@ -53,7 +53,7 @@
 #define USB_FFS_BULK_SIZE 16384
 
 // Number of buffers needed to fit MAX_PAYLOAD, with an extra for ZLPs.
-#define USB_FFS_NUM_BUFS ((MAX_PAYLOAD / USB_FFS_BULK_SIZE) + 1)
+#define USB_FFS_NUM_BUFS ((4 * MAX_PAYLOAD / USB_FFS_BULK_SIZE) + 1)
 
 #define cpu_to_le16(x) htole16(x)
 #define cpu_to_le32(x) htole32(x)
@@ -226,16 +226,16 @@
     },
 };
 
-static void aio_block_init(aio_block* aiob) {
-    aiob->iocb.resize(USB_FFS_NUM_BUFS);
-    aiob->iocbs.resize(USB_FFS_NUM_BUFS);
-    aiob->events.resize(USB_FFS_NUM_BUFS);
+static void aio_block_init(aio_block* aiob, unsigned num_bufs) {
+    aiob->iocb.resize(num_bufs);
+    aiob->iocbs.resize(num_bufs);
+    aiob->events.resize(num_bufs);
     aiob->num_submitted = 0;
-    for (unsigned i = 0; i < USB_FFS_NUM_BUFS; i++) {
+    for (unsigned i = 0; i < num_bufs; i++) {
         aiob->iocbs[i] = &aiob->iocb[i];
     }
     memset(&aiob->ctx, 0, sizeof(aiob->ctx));
-    if (io_setup(USB_FFS_NUM_BUFS, &aiob->ctx)) {
+    if (io_setup(num_bufs, &aiob->ctx)) {
         D("[ aio: got error on io_setup (%d) ]", errno);
     }
 }
@@ -250,7 +250,7 @@
     }
 }
 
-bool init_functionfs(struct usb_handle* h) {
+static bool init_functionfs(struct usb_handle* h) {
     LOG(INFO) << "initializing functionfs";
 
     ssize_t ret;
@@ -318,6 +318,7 @@
 
     h->read_aiob.fd = h->bulk_out;
     h->write_aiob.fd = h->bulk_in;
+    h->reads_zero_packets = true;
     return true;
 
 err:
@@ -336,9 +337,7 @@
     return false;
 }
 
-static void usb_ffs_open_thread(void* x) {
-    struct usb_handle* usb = (struct usb_handle*)x;
-
+static void usb_ffs_open_thread(usb_handle *usb) {
     adb_thread_setname("usb ffs open");
 
     while (true) {
@@ -370,6 +369,7 @@
     D("about to write (fd=%d, len=%d)", h->bulk_in, len);
 
     const char* buf = static_cast<const char*>(data);
+    int orig_len = len;
     while (len > 0) {
         int write_len = std::min(USB_FFS_BULK_SIZE, len);
         int n = adb_write(h->bulk_in, buf, write_len);
@@ -382,13 +382,14 @@
     }
 
     D("[ done fd=%d ]", h->bulk_in);
-    return 0;
+    return orig_len;
 }
 
 static int usb_ffs_read(usb_handle* h, void* data, int len) {
     D("about to read (fd=%d, len=%d)", h->bulk_out, len);
 
     char* buf = static_cast<char*>(data);
+    int orig_len = len;
     while (len > 0) {
         int read_len = std::min(USB_FFS_BULK_SIZE, len);
         int n = adb_read(h->bulk_out, buf, read_len);
@@ -401,14 +402,14 @@
     }
 
     D("[ done fd=%d ]", h->bulk_out);
-    return 0;
+    return orig_len;
 }
 
 static int usb_ffs_do_aio(usb_handle* h, const void* data, int len, bool read) {
     aio_block* aiob = read ? &h->read_aiob : &h->write_aiob;
     bool zero_packet = false;
 
-    int num_bufs = len / USB_FFS_BULK_SIZE + (len % USB_FFS_BULK_SIZE == 0 ? 0 : 1);
+    int num_bufs = len / h->io_size + (len % h->io_size == 0 ? 0 : 1);
     const char* cur_data = reinterpret_cast<const char*>(data);
     int packet_size = getMaxPacketSize(aiob->fd);
 
@@ -418,7 +419,7 @@
     }
 
     for (int i = 0; i < num_bufs; i++) {
-        int buf_len = std::min(len, USB_FFS_BULK_SIZE);
+        int buf_len = std::min(len, static_cast<int>(h->io_size));
         io_prep(&aiob->iocb[i], aiob->fd, cur_data, buf_len, 0, read);
 
         len -= buf_len;
@@ -427,7 +428,7 @@
         if (len == 0 && buf_len % packet_size == 0 && read) {
             // adb does not expect the device to send a zero packet after data transfer,
             // but the host *does* send a zero packet for the device to read.
-            zero_packet = true;
+            zero_packet = h->reads_zero_packets;
         }
     }
     if (zero_packet) {
@@ -449,6 +450,7 @@
         if (num_bufs == 1 && aiob->events[0].res == -EINTR) {
             continue;
         }
+        int ret = 0;
         for (int i = 0; i < num_bufs; i++) {
             if (aiob->events[i].res < 0) {
                 errno = -aiob->events[i].res;
@@ -456,8 +458,9 @@
                             << " total bufs " << num_bufs;
                 return -1;
             }
+            ret += aiob->events[i].res;
         }
-        return 0;
+        return ret;
     }
 }
 
@@ -505,9 +508,7 @@
     h->notify.notify_one();
 }
 
-static void usb_ffs_init() {
-    D("[ usb_init - using FunctionFS ]");
-
+usb_handle *create_usb_handle(unsigned num_bufs, unsigned io_size) {
     usb_handle* h = new usb_handle();
 
     if (android::base::GetBoolProperty("sys.usb.ffs.aio_compat", false)) {
@@ -518,20 +519,21 @@
     } else {
         h->write = usb_ffs_aio_write;
         h->read = usb_ffs_aio_read;
-        aio_block_init(&h->read_aiob);
-        aio_block_init(&h->write_aiob);
+        aio_block_init(&h->read_aiob, num_bufs);
+        aio_block_init(&h->write_aiob, num_bufs);
     }
+    h->io_size = io_size;
     h->kick = usb_ffs_kick;
     h->close = usb_ffs_close;
-
-    D("[ usb_init - starting thread ]");
-    std::thread(usb_ffs_open_thread, h).detach();
+    return h;
 }
 
 void usb_init() {
+    D("[ usb_init - using FunctionFS ]");
     dummy_fd = adb_open("/dev/null", O_WRONLY);
     CHECK_NE(dummy_fd, -1);
-    usb_ffs_init();
+
+    std::thread(usb_ffs_open_thread, create_usb_handle(USB_FFS_NUM_BUFS, USB_FFS_BULK_SIZE)).detach();
 }
 
 int usb_write(usb_handle* h, const void* data, int len) {
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 94b2e37..602970c 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -122,7 +122,7 @@
 // On Android devices, we rely on the kernel to provide buffered read.
 // So we can recover automatically from EOVERFLOW.
 static int remote_read(apacket* p, usb_handle* usb) {
-    if (usb_read(usb, &p->msg, sizeof(amessage))) {
+    if (usb_read(usb, &p->msg, sizeof(amessage)) != sizeof(amessage)) {
         PLOG(ERROR) << "remote usb: read terminated (message)";
         return -1;
     }
@@ -134,7 +134,8 @@
         }
 
         p->payload.resize(p->msg.data_length);
-        if (usb_read(usb, &p->payload[0], p->payload.size())) {
+        if (usb_read(usb, &p->payload[0], p->payload.size())
+                != static_cast<int>(p->payload.size())) {
             PLOG(ERROR) << "remote usb: terminated (data)";
             return -1;
         }
@@ -154,14 +155,14 @@
 }
 
 bool UsbConnection::Write(apacket* packet) {
-    unsigned size = packet->msg.data_length;
+    int size = packet->msg.data_length;
 
-    if (usb_write(handle_, &packet->msg, sizeof(packet->msg)) != 0) {
+    if (usb_write(handle_, &packet->msg, sizeof(packet->msg)) != sizeof(packet->msg)) {
         PLOG(ERROR) << "remote usb: 1 - write terminated";
         return false;
     }
 
-    if (packet->msg.data_length != 0 && usb_write(handle_, packet->payload.data(), size) != 0) {
+    if (packet->msg.data_length != 0 && usb_write(handle_, packet->payload.data(), size) != size) {
         PLOG(ERROR) << "remote usb: 2 - write terminated";
         return false;
     }
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index 15ace0e..0cc4fc0 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -90,7 +90,7 @@
     dev_t rdev;
     struct stat st;
 
-    if (TEMP_FAILURE_RETRY(fstat(fd, &st)) < 0) {
+    if (fstat(fd, &st) < 0) {
         return -1;
     }
 
@@ -135,6 +135,12 @@
     return -1;
 }
 
+static int __ashmem_check_failure(int fd, int result)
+{
+    if (result == -1 && errno == ENOTTY) __ashmem_is_ashmem(fd, 1);
+    return result;
+}
+
 int ashmem_valid(int fd)
 {
     return __ashmem_is_ashmem(fd, 0) >= 0;
@@ -182,12 +188,7 @@
 
 int ashmem_set_prot_region(int fd, int prot)
 {
-    int ret = __ashmem_is_ashmem(fd, 1);
-    if (ret < 0) {
-        return ret;
-    }
-
-    return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot));
+    return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)));
 }
 
 int ashmem_pin_region(int fd, size_t offset, size_t len)
@@ -195,12 +196,7 @@
     // TODO: should LP64 reject too-large offset/len?
     ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
 
-    int ret = __ashmem_is_ashmem(fd, 1);
-    if (ret < 0) {
-        return ret;
-    }
-
-    return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin));
+    return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)));
 }
 
 int ashmem_unpin_region(int fd, size_t offset, size_t len)
@@ -208,20 +204,10 @@
     // TODO: should LP64 reject too-large offset/len?
     ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
 
-    int ret = __ashmem_is_ashmem(fd, 1);
-    if (ret < 0) {
-        return ret;
-    }
-
-    return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin));
+    return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)));
 }
 
 int ashmem_get_size_region(int fd)
 {
-    int ret = __ashmem_is_ashmem(fd, 1);
-    if (ret < 0) {
-        return ret;
-    }
-
-    return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL));
+    return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
 }