MTP: Fixes to allow file transfers > 4 gigabytes

BUG: 3198248

Change-Id: I6f11c79a19d7bdd63718a7370939124b1262d221
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index ab31cd4..e48e9e8 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -164,7 +164,7 @@
         }
     }
 
-    private void endSendObject(String path, int handle, int format, boolean succeeded) {
+    private void endSendObject(String path, int handle, int format, long actualSize, boolean succeeded) {
         if (succeeded) {
             // handle abstract playlists separately
             // they do not exist in the file system so don't use the media scanner here
@@ -192,6 +192,18 @@
                     Log.e(TAG, "RemoteException in endSendObject", e);
                 }
             } else {
+                if (actualSize >= 0) {
+                    // update size if necessary
+                    ContentValues values = new ContentValues();
+                    values.put(Files.FileColumns.SIZE, actualSize);
+                    try {
+                        String[] whereArgs = new String[] {  Integer.toString(handle) };
+                        mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "RemoteException in mMediaProvider.update", e);
+                    }
+                }
+
                 mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
             }
         } else {
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 5377af6..4525d1f 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -99,6 +99,7 @@
     virtual void                    endSendObject(const char* path,
                                             MtpObjectHandle handle,
                                             MtpObjectFormat format,
+                                            int64_t actualSize,
                                             bool succeeded);
 
     virtual MtpObjectHandleList*    getObjectList(MtpStorageID storageID,
@@ -235,11 +236,11 @@
 }
 
 void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
-                                MtpObjectFormat format, bool succeeded) {
+                                MtpObjectFormat format, int64_t actualSize, bool succeeded) {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jstring pathStr = env->NewStringUTF(path);
     env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
-                        (jint)handle, (jint)format, (jboolean)succeeded);
+                        (jint)handle, (jint)format, (jlong)actualSize, (jboolean)succeeded);
 
     if (pathStr)
         env->DeleteLocalRef(pathStr);
@@ -1076,7 +1077,7 @@
         LOGE("Can't find beginSendObject");
         return -1;
     }
-    method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
+    method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIJZ)V");
     if (method_endSendObject == NULL) {
         LOGE("Can't find endSendObject");
         return -1;
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index fafd221..900b517 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -42,6 +42,7 @@
     virtual void                    endSendObject(const char* path,
                                             MtpObjectHandle handle,
                                             MtpObjectFormat format,
+                                            int64_t size,
                                             bool succeeded) = 0;
 
     virtual MtpObjectHandleList*    getObjectList(MtpStorageID storageID,
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 7edbeb4..ca13636 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -664,6 +664,7 @@
     MtpResponseCode result = MTP_RESPONSE_OK;
     mode_t mask;
     int ret;
+    uint64_t actualSize = -1;
 
     if (mSendObjectHandle == kInvalidObjectHandle) {
         LOGE("Expected SendObjectInfo before SendObject");
@@ -706,11 +707,18 @@
             result = MTP_RESPONSE_TRANSACTION_CANCELLED;
         else
             result = MTP_RESPONSE_GENERAL_ERROR;
+    } else if (mSendObjectFileSize == 0xFFFFFFFF) {
+        // actual size is likely > 4 gig so stat the file to compute actual length
+        struct stat s;
+        if (lstat(mSendObjectFilePath, &s) == 0) {
+            actualSize = s.st_size;
+            LOGD("actualSize: %lld\n", actualSize);
+        }
     }
 
 done:
     mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
-            result == MTP_RESPONSE_OK);
+            actualSize, result == MTP_RESPONSE_OK);
     mSendObjectHandle = kInvalidObjectHandle;
     mSendObjectFormat = 0;
     return result;