Fix zero length packet handling

Ensure that a zero length packet is properly sent
/ received when handling data that is a multiple of the
endpoint size.

This fixes an issue where files whose size is a multiple
of the endpoint size would hang during transfer.

Bug: 37175601
Test: check successful file transfer.
Change-Id: Iaf3cea18422234d65b59f5961ef9fb3f3ee2049a
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 565a2fe..c78002c 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -520,7 +520,16 @@
     // When receiving files, the incoming length is given in 32 bits.
     // A >4G file is given as 0xFFFFFFFF
     uint32_t file_length = mfr.length;
-    uint64_t offset = lseek(mfr.fd, 0, SEEK_CUR);
+    uint64_t offset = mfr.offset;
+    struct usb_endpoint_descriptor mBulkOut_desc;
+    int packet_size;
+
+    if (ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&mBulkOut_desc))) {
+        PLOG(ERROR) << "Could not get FFS bulk-out descriptor";
+        packet_size = MAX_PACKET_SIZE_HS;
+    } else {
+        packet_size = mBulkOut_desc.wMaxPacketSize;
+    }
 
     char *data = mBuffer1.data();
     char *data2 = mBuffer2.data();
@@ -573,21 +582,26 @@
         }
 
         if (read) {
-            // Enqueue a new write request
-            aio.aio_buf = data;
-            aio.aio_sink = mfr.fd;
-            aio.aio_offset = offset;
-            aio.aio_nbytes = ret;
-            aio_write(&aio);
-
             if (file_length == MAX_MTP_FILE_SIZE) {
                 // For larger files, receive until a short packet is received.
                 if (static_cast<size_t>(ret) < length) {
                     file_length = 0;
                 }
             } else {
+                // Receive an empty packet if size is a multiple of the endpoint size.
                 file_length -= ret;
+                if (file_length == 0 && ret % packet_size == 0) {
+                    if (TEMP_FAILURE_RETRY(::read(mBulkOut, data, packet_size)) != 0) {
+                        return -1;
+                    }
+                }
             }
+            // Enqueue a new write request
+            aio.aio_buf = data;
+            aio.aio_sink = mfr.fd;
+            aio.aio_offset = offset;
+            aio.aio_nbytes = ret;
+            aio_write(&aio);
 
             offset += ret;
             std::swap(data, data2);
@@ -695,9 +709,11 @@
         }
     }
 
-    if (given_length == MAX_MTP_FILE_SIZE && ret % packet_size == 0) {
+    if (ret % packet_size == 0) {
         // If the last packet wasn't short, send a final empty packet
-        if (writeHandle(mBulkIn, data, 0) == -1) return -1;
+        if (TEMP_FAILURE_RETRY(::write(mBulkIn, data, 0)) != 0) {
+            return -1;
+        }
     }
 
     return 0;