MTP: Add extended operations to support in-place editing of files

MTP does not support partial writes of files (the entire file must be transferred at once).
This makes it impossible to implement a FUSE file system for MTP
with acceptable performance.
To fix this problem, this change adds extended MTP operations to allow
partial writes to files:

SendPartialObject - allows writing a subset of a file, or appending to the end of a file

TruncateObject - allows changing the size of a file

BeginEditObject - must be called before using SendPartialObject and TruncateObject

EndEditObject - commits changes to a file after it has been edited with SendPartialObject or TruncateObject

We also add GetPartialObject64, which is the same as GetPartialObject
but has a 64 bit offset rather than 32.

Change-Id: I4b110748b97ae05cdc8aab02ecdbbbeb263f7840
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index fa729a8..35a38e7 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -65,6 +65,17 @@
 
     Mutex               mMutex;
 
+    // represents an MTP object that is being edited using the android extensions
+    // for direct editing (BeginEditObject, SendPartialObject, TruncateObject and EndEditObject)
+    struct ObjectEdit {
+        MtpObjectHandle     handle;
+        MtpString           path;
+        uint64_t            size;
+        MtpObjectFormat     format;
+        int                 fd;
+    };
+    Vector<ObjectEdit*>  mObjectEditList;
+
 public:
                         MtpServer(int fd, MtpDatabase* database,
                                     int fileGroup, int filePerm, int directoryPerm);
@@ -86,6 +97,12 @@
     void                sendStoreRemoved(MtpStorageID id);
     void                sendEvent(MtpEventCode code, uint32_t param1);
 
+    void                addEditObject(MtpObjectHandle handle, MtpString& path,
+                                uint64_t size, MtpObjectFormat format, int fd);
+    ObjectEdit*         getEditObject(MtpObjectHandle handle);
+    void                removeEditObject(MtpObjectHandle handle);
+    void                commitEdit(ObjectEdit* edit);
+
     bool                handleRequest();
 
     MtpResponseCode     doGetDeviceInfo();
@@ -106,12 +123,16 @@
     MtpResponseCode     doGetObjectPropList();
     MtpResponseCode     doGetObjectInfo();
     MtpResponseCode     doGetObject();
-    MtpResponseCode     doGetPartialObject();
+    MtpResponseCode     doGetPartialObject(MtpOperationCode operation);
     MtpResponseCode     doSendObjectInfo();
     MtpResponseCode     doSendObject();
     MtpResponseCode     doDeleteObject();
     MtpResponseCode     doGetObjectPropDesc();
     MtpResponseCode     doGetDevicePropDesc();
+    MtpResponseCode     doSendPartialObject();
+    MtpResponseCode     doTruncateObject();
+    MtpResponseCode     doBeginEditObject();
+    MtpResponseCode     doEndEditObject();
 };
 
 }; // namespace android