Fix file transfer corner cases.
Fix zero packet read/write in corner cases
with initial read/writes. This affects transfers
of 16372 bytes to the device and transfers of
1012 bytes (or packet size - 12) from the device.
Test: Transfer various length files
Bug: 37175601
Change-Id: Ic1281e8757d1a33d78c66d2c57319b5ee38d6a46
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index c78002c..c50af2f 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -516,7 +516,7 @@
}
/* Read from USB and write to a local file. */
-int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
+int MtpFfsHandle::receiveFile(mtp_file_range mfr, bool zero_packet) {
// When receiving files, the incoming length is given in 32 bits.
// A >4G file is given as 0xFFFFFFFF
uint32_t file_length = mfr.length;
@@ -538,7 +538,7 @@
aio.aio_fildes = mfr.fd;
aio.aio_buf = nullptr;
struct aiocb *aiol[] = {&aio};
- int ret;
+ int ret = -1;
size_t length;
bool read = false;
bool write = false;
@@ -590,11 +590,6 @@
} 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;
@@ -610,6 +605,11 @@
read = false;
}
}
+ if (ret % packet_size == 0 || zero_packet) {
+ if (TEMP_FAILURE_RETRY(::read(mBulkOut, data, packet_size)) != 0) {
+ return -1;
+ }
+ }
return 0;
}
@@ -660,10 +660,9 @@
sizeof(mtp_data_header), init_read_len, offset))
!= init_read_len) return -1;
if (writeHandle(mBulkIn, data, sizeof(mtp_data_header) + init_read_len) == -1) return -1;
- if (file_length == static_cast<unsigned>(init_read_len)) return 0;
file_length -= init_read_len;
offset += init_read_len;
- ret = 0;
+ ret = init_read_len + sizeof(mtp_data_header);
// Break down the file into pieces that fit in buffers
while(file_length > 0) {