Integrate host to device file transfer with the media provider.

MTP file transfers happen in two stages.  The SendObjectInfo command sends
some information about the file and reserves an ObjectHandle for the new file.
The file transfer is then performed using the SendObject command.

To support this in the media provider, MtpDatabase.beginSendObject receives
the information from SendObjectInfo and creates an row for it in the MTP objects
table for the new file.  After the file transfer has completed, then
MtpDatabase.endSendObject is called.  In endSendObject, we run the media scanner
on the new file, which will add a row to the images, audio, video
or audio playlist table.

To avoid the media scanner creating a second row for the file in the MTP objects
table, we pass the ObjectHandle created in beginSendObject to the media scanner,
which then passes it to the media provider via the content values when it
performs its insert.

Change-Id: I1ebcc63d6bd4404b0d3a93c703a9d3c097381d3a
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 5a16a03..e8f09fa 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -123,6 +123,7 @@
         mSessionID(0),
         mSessionOpen(false),
         mSendObjectHandle(kInvalidObjectHandle),
+        mSendObjectFormat(0),
         mSendObjectFileSize(0)
 {
     initObjectProperties();
@@ -519,8 +520,8 @@
     path += (const char *)name;
 
     mDatabase->beginTransaction();
-    MtpObjectHandle handle = mDatabase->addFile((const char*)path, format, parent, storageID, 
-                                    mSendObjectFileSize, modifiedTime);
+    MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
+            format, parent, storageID, mSendObjectFileSize, modifiedTime);
     if (handle == kInvalidObjectHandle) {
         mDatabase->rollbackTransaction();
         return MTP_RESPONSE_GENERAL_ERROR;
@@ -538,6 +539,7 @@
         mSendObjectFilePath = path;
         // save the handle for the SendObject call, which should follow
         mSendObjectHandle = handle;
+        mSendObjectFormat = format;
     }
 
     mResponse.setParameter(1, storageID);
@@ -548,13 +550,18 @@
 }
 
 MtpResponseCode MtpServer::doSendObject() {
+    MtpResponseCode result = MTP_RESPONSE_OK;
+    mode_t mask;
+    int ret;
+
     if (mSendObjectHandle == kInvalidObjectHandle) {
         LOGE("Expected SendObjectInfo before SendObject");
-        return MTP_RESPONSE_NO_VALID_OBJECT_INFO;
+        result = MTP_RESPONSE_NO_VALID_OBJECT_INFO;
+        goto done;
     }
 
     // read the header
-    int ret = mData.readDataHeader(mFD);
+    ret = mData.readDataHeader(mFD);
     // FIXME - check for errors here.
 
     // reset so we don't attempt to send this back
@@ -563,11 +570,12 @@
     mtp_file_range  mfr;
     mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC);
     if (mfr.fd < 0) {
-        return MTP_RESPONSE_GENERAL_ERROR;
+        result = MTP_RESPONSE_GENERAL_ERROR;
+        goto done;
     }
     fchown(mfr.fd, getuid(), mFileGroup);
     // set permissions
-    mode_t mask = umask(0);
+    mask = umask(0);
     fchmod(mfr.fd, mFilePermission);
     umask(mask);
 
@@ -578,18 +586,22 @@
     ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
     close(mfr.fd);
 
-    // FIXME - we need to delete mSendObjectHandle from the database if this fails.
     LOGV("MTP_RECEIVE_FILE returned %d", ret);
-    mSendObjectHandle = kInvalidObjectHandle;
 
     if (ret < 0) {
         unlink(mSendObjectFilePath);
         if (errno == ECANCELED)
-            return MTP_RESPONSE_TRANSACTION_CANCELLED;
+            result = MTP_RESPONSE_TRANSACTION_CANCELLED;
         else
-            return MTP_RESPONSE_GENERAL_ERROR;
+            result = MTP_RESPONSE_GENERAL_ERROR;
     }
-    return MTP_RESPONSE_OK;
+
+done:
+    mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
+            result == MTP_RESPONSE_OK);
+    mSendObjectHandle = kInvalidObjectHandle;
+    mSendObjectFormat = 0;
+    return result;
 }
 
 MtpResponseCode MtpServer::doDeleteObject() {