Merge "Use FUNCTIONFS_ENDPOINT_ALLOC_BUFFER ioctl to improve performance."
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 10314e9..d11a10d 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -38,6 +38,8 @@
 #define cpu_to_le16(x)  htole16(x)
 #define cpu_to_le32(x)  htole32(x)
 
+#define FUNCTIONFS_ENDPOINT_ALLOC       _IOR('g', 131, __u32)
+
 namespace {
 
 constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
@@ -467,6 +469,24 @@
     mLock.unlock();
 }
 
+class ScopedEndpointBufferAlloc {
+private:
+    const int mFd;
+    const unsigned int mAllocSize;
+public:
+    ScopedEndpointBufferAlloc(int fd, unsigned alloc_size) :
+        mFd(fd),
+        mAllocSize(alloc_size) {
+        if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mAllocSize)))
+            PLOG(DEBUG) << "FFS endpoint alloc failed!";
+    }
+
+    ~ScopedEndpointBufferAlloc() {
+        if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(0)))
+            PLOG(DEBUG) << "FFS endpoint alloc reset failed!";
+    }
+};
+
 /* Read from USB and write to a local file. */
 int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
     // When receiving files, the incoming length is given in 32 bits.
@@ -494,6 +514,7 @@
     bool write = false;
 
     posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
+    ScopedEndpointBufferAlloc(mBulkOut, mMaxRead);
 
     // Break down the file into pieces that fit in buffers
     while (file_length > 0 || write) {
@@ -609,6 +630,8 @@
     if (writeHandle(mBulkIn, data, packet_size) == -1) return -1;
     if (file_length == 0) return 0;
 
+    ScopedEndpointBufferAlloc(mBulkIn, mMaxWrite);
+
     // Break down the file into pieces that fit in buffers
     while(file_length > 0) {
         if (read) {