Add API for streamed reading on MTP devices.
The existing APIs required to copy all bytes to memory, which will fail in
case of very large files, like movies.
Bug: 22908937
Change-Id: I23bdcbdbf08b7c1b1017591799bbb94e53249a57
diff --git a/api/current.txt b/api/current.txt
index d468831..ea7963c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18088,6 +18088,7 @@
method public android.mtp.MtpStorageInfo getStorageInfo(int);
method public byte[] getThumbnail(int);
method public boolean importFile(int, java.lang.String);
+ method public boolean importFile(int, android.os.ParcelFileDescriptor);
method public boolean open(android.hardware.usb.UsbDeviceConnection);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 4dd85e6..b8cd453 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19602,6 +19602,7 @@
method public android.mtp.MtpStorageInfo getStorageInfo(int);
method public byte[] getThumbnail(int);
method public boolean importFile(int, java.lang.String);
+ method public boolean importFile(int, android.os.ParcelFileDescriptor);
method public boolean open(android.hardware.usb.UsbDeviceConnection);
}
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index a68361b..a9611c5 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -18,6 +18,7 @@
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
+import android.os.ParcelFileDescriptor;
/**
* This class represents an MTP or PTP device connected on the USB host bus. An application can
@@ -235,6 +236,20 @@
return native_import_file(objectHandle, destPath);
}
+ /**
+ * Copies the data for an object to a file descriptor.
+ * This call may block for an arbitrary amount of time depending on the size
+ * of the data and speed of the devices. The file descriptor is not closed
+ * on completion, and must be done by the caller.
+ *
+ * @param objectHandle handle of the object to read
+ * @param descriptor file descriptor to write the data to for the file transfer.
+ * @return true if the file transfer succeeds
+ */
+ public boolean importFile(int objectHandle, ParcelFileDescriptor descriptor) {
+ return native_import_file(objectHandle, descriptor.getFd());
+ }
+
// used by the JNI code
private long mNativeContext;
@@ -251,4 +266,5 @@
private native long native_get_parent(int objectHandle);
private native long native_get_storage_id(int objectHandle);
private native boolean native_import_file(int objectHandle, String destPath);
+ private native boolean native_import_file(int objectHandle, int fd);
}
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 2dbd7dc..6652a54 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -393,6 +393,16 @@
return JNI_FALSE;
}
+static jboolean
+android_mtp_MtpDevice_import_file_to_fd(JNIEnv *env, jobject thiz, jint object_id, jint fd)
+{
+ MtpDevice* device = get_device_from_object(env, thiz);
+ if (device)
+ return device->readObject(object_id, fd);
+ else
+ return JNI_FALSE;
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -413,8 +423,9 @@
{"native_delete_object", "(I)Z", (void *)android_mtp_MtpDevice_delete_object},
{"native_get_parent", "(I)J", (void *)android_mtp_MtpDevice_get_parent},
{"native_get_storage_id", "(I)J", (void *)android_mtp_MtpDevice_get_storage_id},
- {"native_import_file", "(ILjava/lang/String;)Z",
+ {"native_import_file", "(ILjava/lang/String;)Z",
(void *)android_mtp_MtpDevice_import_file},
+ {"native_import_file", "(II)Z", (void *)android_mtp_MtpDevice_import_file_to_fd}
};
int register_android_mtp_MtpDevice(JNIEnv *env)