Don't send short URB packet when sending MtpDataPacket.

When sending a MtpDataPacket to a MTP device, the kernel driver splits
it into multiple URB packets so that the URB packet size does not exceed
the buffer size at the MTP device.

Previously MtpDataPacket sends its header first, then sends the
payload. It means the first URB packet only contains the header of
MtpDataPacket and the URB packet size is smaller than the maximum URB
packet size (short packet). Some MTP devices regard the short packet as
the end of the sequencail URB packets, thus the devices do not accept
the following URB packets that contain the payload.

The MTP spec says if the responder (MTP device) sends the data in a way
where the first pacekt contains only the header, the initiator (MTP
host) must send data in the same way. Otherwise the initiator must not
send a short packet in the sequencial URB packets.

The CL fixes the MTP host implementation so that it remembers how the
MTP device sends data, and uses the same way when sending data
from the host.

Bug: 31165557
Test: Manually invokes MtpDevice#sendObject
Change-Id: Ic76eb4241ed74957414aef2990be08cd77a9f5a9
(cherry picked from commit d4b4296b401162a7a42f757c96e3652b82255b13)
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 7301193..e3d2ec6 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -222,7 +222,8 @@
         mProcessingEvent(false),
         mCurrentEventHandle(0),
         mLastSendObjectInfoTransactionID(0),
-        mLastSendObjectInfoObjectHandle(0)
+        mLastSendObjectInfoObjectHandle(0),
+        mPacketDivisionMode(FIRST_PACKET_HAS_PAYLOAD)
 {
     mRequestIn1 = usb_request_new(device, ep_in);
     mRequestIn2 = usb_request_new(device, ep_in);
@@ -512,30 +513,15 @@
         return false;
     }
 
-    int remaining = size;
     mRequest.reset();
-    bool error = false;
     if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
-        // send data header
-        writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
-
-        // USB writes greater than 16K don't work
-        char buffer[MTP_BUFFER_SIZE];
-        while (remaining > 0) {
-            int count = read(srcFD, buffer, sizeof(buffer));
-            if (count > 0) {
-                if (mData.write(mRequestOut, buffer, count) < 0) {
-                    error = true;
-                }
-                // FIXME check error
-                remaining -= count;
-            } else {
-                break;
-            }
-        }
+        mData.setOperationCode(mRequest.getOperationCode());
+        mData.setTransactionID(mRequest.getTransactionID());
+        const int writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size);
+        const MtpResponseCode ret = readResponse();
+        return ret == MTP_RESPONSE_OK && writeResult > 0;
     }
-    MtpResponseCode ret = readResponse();
-    return (remaining == 0 && ret == MTP_RESPONSE_OK && !error);
+    return false;
 }
 
 bool MtpDevice::deleteObject(MtpObjectHandle handle) {
@@ -707,8 +693,8 @@
         return false;
     }
 
-    // If object size 0 byte, the remote device can reply response packet
-    // without sending any data packets.
+    // If object size 0 byte, the remote device may reply a response packet without sending any data
+    // packets.
     if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
         mResponse.copyFrom(mData);
         return mResponse.getResponseCode() == MTP_RESPONSE_OK;
@@ -731,6 +717,14 @@
     {
         int initialDataLength = 0;
         void* const initialData = mData.getData(&initialDataLength);
+        if (fullLength > MTP_CONTAINER_HEADER_SIZE && initialDataLength == 0) {
+            // According to the MTP spec, the responder (MTP device) can choose two ways of sending
+            // data. a) The first packet contains the head and as much of the payload as possible
+            // b) The first packet contains only the header. The initiator (MTP host) needs
+            // to remember which way the responder used, and send upcoming data in the same way.
+            ALOGD("Found short packet that contains only a header.");
+            mPacketDivisionMode = FIRST_PACKET_ONLY_HEADER;
+        }
         if (initialData) {
             if (initialDataLength > 0) {
                 if (!callback(initialData, offset, initialDataLength, clientData)) {
@@ -854,7 +848,7 @@
     ALOGV("sendData\n");
     mData.setOperationCode(mRequest.getOperationCode());
     mData.setTransactionID(mRequest.getTransactionID());
-    int ret = mData.write(mRequestOut);
+    int ret = mData.write(mRequestOut, mPacketDivisionMode);
     mData.dump();
     return (ret >= 0);
 }
@@ -881,12 +875,6 @@
     }
 }
 
-bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
-    mData.setOperationCode(operation);
-    mData.setTransactionID(mRequest.getTransactionID());
-    return (!mData.writeDataHeader(mRequestOut, dataLength));
-}
-
 MtpResponseCode MtpDevice::readResponse() {
     ALOGV("readResponse\n");
     if (mReceivedResponse) {