summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tomasz Mikolajewski <mtomasz@google.com> 2015-08-06 19:13:09 +0900
committer Tomasz Mikolajewski <mtomasz@google.com> 2015-08-14 13:09:52 +0900
commitb04990599a1a05cc922b0fe9dd98128440efb56a (patch)
tree3fa2cac3ca093e3249a9b6b7cf629f4a05a16f48
parent0ca8da52f76c1996a9ea6df866324855fd4d145f (diff)
Add API for uploading files to MTP devices.
Bug: 22545670 Change-Id: I038c54db06b7cf780bd027d76693e98c685d57a7
-rw-r--r--api/current.txt27
-rw-r--r--api/system-current.txt27
-rw-r--r--media/java/android/mtp/MtpDevice.java29
-rw-r--r--media/java/android/mtp/MtpObjectInfo.java152
-rw-r--r--media/jni/android_mtp_MtpDevice.cpp173
5 files changed, 364 insertions, 44 deletions
diff --git a/api/current.txt b/api/current.txt
index 47b8aeb0a59a..4ffd52c1a286 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18091,6 +18091,8 @@ package android.mtp {
method public boolean importFile(int, java.lang.String);
method public boolean importFile(int, android.os.ParcelFileDescriptor);
method public boolean open(android.hardware.usb.UsbDeviceConnection);
+ method public boolean sendObject(int, android.os.ParcelFileDescriptor);
+ method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
}
public class MtpDeviceInfo {
@@ -18123,6 +18125,31 @@ package android.mtp {
method public final int getThumbPixWidth();
}
+ public class MtpObjectInfo.Builder {
+ ctor public MtpObjectInfo.Builder();
+ ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo);
+ method public android.mtp.MtpObjectInfo build();
+ method public android.mtp.MtpObjectInfo.Builder setAssociationDesc(int);
+ method public android.mtp.MtpObjectInfo.Builder setAssociationType(int);
+ method public android.mtp.MtpObjectInfo.Builder setCompressedSize(int);
+ method public android.mtp.MtpObjectInfo.Builder setDateCreated(long);
+ method public android.mtp.MtpObjectInfo.Builder setDateModified(long);
+ method public android.mtp.MtpObjectInfo.Builder setFormat(int);
+ method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(int);
+ method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(int);
+ method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(int);
+ method public android.mtp.MtpObjectInfo.Builder setKeywords(java.lang.String);
+ method public android.mtp.MtpObjectInfo.Builder setName(java.lang.String);
+ method public android.mtp.MtpObjectInfo.Builder setParent(int);
+ method public android.mtp.MtpObjectInfo.Builder setProtectionStatus(int);
+ method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(int);
+ method public android.mtp.MtpObjectInfo.Builder setStorageId(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbFormat(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(int);
+ }
+
public final class MtpStorageInfo {
method public final java.lang.String getDescription();
method public final long getFreeSpace();
diff --git a/api/system-current.txt b/api/system-current.txt
index 45a90e0bfde7..30086e666ffb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19603,6 +19603,8 @@ package android.mtp {
method public boolean importFile(int, java.lang.String);
method public boolean importFile(int, android.os.ParcelFileDescriptor);
method public boolean open(android.hardware.usb.UsbDeviceConnection);
+ method public boolean sendObject(int, android.os.ParcelFileDescriptor);
+ method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
}
public class MtpDeviceInfo {
@@ -19635,6 +19637,31 @@ package android.mtp {
method public final int getThumbPixWidth();
}
+ public class MtpObjectInfo.Builder {
+ ctor public MtpObjectInfo.Builder();
+ ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo);
+ method public android.mtp.MtpObjectInfo build();
+ method public android.mtp.MtpObjectInfo.Builder setAssociationDesc(int);
+ method public android.mtp.MtpObjectInfo.Builder setAssociationType(int);
+ method public android.mtp.MtpObjectInfo.Builder setCompressedSize(int);
+ method public android.mtp.MtpObjectInfo.Builder setDateCreated(long);
+ method public android.mtp.MtpObjectInfo.Builder setDateModified(long);
+ method public android.mtp.MtpObjectInfo.Builder setFormat(int);
+ method public android.mtp.MtpObjectInfo.Builder setImagePixDepth(int);
+ method public android.mtp.MtpObjectInfo.Builder setImagePixHeight(int);
+ method public android.mtp.MtpObjectInfo.Builder setImagePixWidth(int);
+ method public android.mtp.MtpObjectInfo.Builder setKeywords(java.lang.String);
+ method public android.mtp.MtpObjectInfo.Builder setName(java.lang.String);
+ method public android.mtp.MtpObjectInfo.Builder setParent(int);
+ method public android.mtp.MtpObjectInfo.Builder setProtectionStatus(int);
+ method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(int);
+ method public android.mtp.MtpObjectInfo.Builder setStorageId(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbCompressedSize(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbFormat(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbPixHeight(int);
+ method public android.mtp.MtpObjectInfo.Builder setThumbPixWidth(int);
+ }
+
public final class MtpStorageInfo {
method public final java.lang.String getDescription();
method public final long getFreeSpace();
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index a9611c52f75e..fbe047dea1d7 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -250,6 +250,33 @@ public final class MtpDevice {
return native_import_file(objectHandle, descriptor.getFd());
}
+ /**
+ * Copies the data for an object from 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 target file
+ * @param descriptor file descriptor to read the data from.
+ * @return true if the file transfer succeeds
+ */
+ public boolean sendObject(int objectHandle, ParcelFileDescriptor descriptor) {
+ return native_send_object(objectHandle, descriptor.getFd());
+ }
+
+ /**
+ * Uploads an object metadata for a new entry. The {@link MtpObjectInfo} can be
+ * created with the {@link MtpObjectInfo.Builder} class.
+ *
+ * The returned {@link MtpObjectInfo} has the new object handle field filled in.
+ *
+ * @param info metadata of the entry
+ * @return object info of the created entry
+ */
+ public MtpObjectInfo sendObjectInfo(MtpObjectInfo info) {
+ return native_send_object_info(info);
+ }
+
// used by the JNI code
private long mNativeContext;
@@ -267,4 +294,6 @@ public final class MtpDevice {
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);
+ private native boolean native_send_object(int objectHandle, int fd);
+ private native MtpObjectInfo native_send_object_info(MtpObjectInfo info);
}
diff --git a/media/java/android/mtp/MtpObjectInfo.java b/media/java/android/mtp/MtpObjectInfo.java
index 5bbfe9a6888f..d2824b556315 100644
--- a/media/java/android/mtp/MtpObjectInfo.java
+++ b/media/java/android/mtp/MtpObjectInfo.java
@@ -43,7 +43,7 @@ public final class MtpObjectInfo {
private long mDateModified;
private String mKeywords;
- // only instantiated via JNI
+ // only instantiated via JNI or via a builder
private MtpObjectInfo() {
}
@@ -252,4 +252,154 @@ public final class MtpObjectInfo {
public final String getKeywords() {
return mKeywords;
}
+
+ /**
+ * Builds a new object info instance.
+ */
+ public class Builder {
+ private MtpObjectInfo mObjectInfo;
+
+ public Builder() {
+ mObjectInfo = new MtpObjectInfo();
+ mObjectInfo.mHandle = -1;
+ }
+
+ /**
+ * Creates a builder on a copy of an existing object info.
+ * All fields, except the object handle will be copied.
+ *
+ * @param objectInfo object info of an existing entry
+ */
+ public Builder(MtpObjectInfo objectInfo) {
+ mObjectInfo = new MtpObjectInfo();
+ mObjectInfo.mHandle = -1;
+ mObjectInfo.mAssociationDesc = mObjectInfo.mAssociationDesc;
+ mObjectInfo.mAssociationType = mObjectInfo.mAssociationType;
+ mObjectInfo.mCompressedSize = mObjectInfo.mCompressedSize;
+ mObjectInfo.mDateCreated = mObjectInfo.mDateCreated;
+ mObjectInfo.mDateModified = mObjectInfo.mDateModified;
+ mObjectInfo.mFormat = mObjectInfo.mFormat;
+ mObjectInfo.mImagePixDepth = mObjectInfo.mImagePixDepth;
+ mObjectInfo.mImagePixHeight = mObjectInfo.mImagePixHeight;
+ mObjectInfo.mImagePixWidth = mObjectInfo.mImagePixWidth;
+ mObjectInfo.mKeywords = mObjectInfo.mKeywords;
+ mObjectInfo.mName = mObjectInfo.mName;
+ mObjectInfo.mParent = mObjectInfo.mParent;
+ mObjectInfo.mProtectionStatus = mObjectInfo.mProtectionStatus;
+ mObjectInfo.mSequenceNumber = mObjectInfo.mSequenceNumber;
+ mObjectInfo.mStorageId = mObjectInfo.mStorageId;
+ mObjectInfo.mThumbCompressedSize = mObjectInfo.mThumbCompressedSize;
+ mObjectInfo.mThumbFormat = mObjectInfo.mThumbFormat;
+ mObjectInfo.mThumbPixHeight = mObjectInfo.mThumbPixHeight;
+ mObjectInfo.mThumbPixWidth = mObjectInfo.mThumbPixWidth;
+ }
+
+ public Builder setAssociationDesc(int value) {
+ mObjectInfo.mAssociationDesc = value;
+ return this;
+ }
+
+ public Builder setAssociationType(int value) {
+ mObjectInfo.mAssociationType = value;
+ return this;
+ }
+
+ public Builder setCompressedSize(int value) {
+ mObjectInfo.mCompressedSize = value;
+ return this;
+ }
+
+ public Builder setDateCreated(long value) {
+ mObjectInfo.mDateCreated = value;
+ return this;
+ }
+
+ public Builder setDateModified(long value) {
+ mObjectInfo.mDateModified = value;
+ return this;
+ }
+
+ public Builder setFormat(int value) {
+ mObjectInfo.mFormat = value;
+ return this;
+ }
+
+ public Builder setImagePixDepth(int value) {
+ mObjectInfo.mImagePixDepth = value;
+ return this;
+ }
+
+ public Builder setImagePixHeight(int value) {
+ mObjectInfo.mImagePixHeight = value;
+ return this;
+ }
+
+ public Builder setImagePixWidth(int value) {
+ mObjectInfo.mImagePixWidth = value;
+ return this;
+ }
+
+ public Builder setKeywords(String value) {
+ mObjectInfo.mKeywords = value;
+ return this;
+ }
+
+ public Builder setName(String value) {
+ mObjectInfo.mName = value;
+ return this;
+ }
+
+ public Builder setParent(int value) {
+ mObjectInfo.mParent = value;
+ return this;
+ }
+
+ public Builder setProtectionStatus(int value) {
+ mObjectInfo.mProtectionStatus = value;
+ return this;
+ }
+
+ public Builder setSequenceNumber(int value) {
+ mObjectInfo.mSequenceNumber = value;
+ return this;
+ }
+
+ public Builder setStorageId(int value) {
+ mObjectInfo.mStorageId = value;
+ return this;
+ }
+
+ public Builder setThumbCompressedSize(int value) {
+ mObjectInfo.mThumbCompressedSize = value;
+ return this;
+ }
+
+ public Builder setThumbFormat(int value) {
+ mObjectInfo.mThumbFormat = value;
+ return this;
+ }
+
+ public Builder setThumbPixHeight(int value) {
+ mObjectInfo.mThumbPixHeight = value;
+ return this;
+ }
+
+ public Builder setThumbPixWidth(int value) {
+ mObjectInfo.mThumbPixWidth = value;
+ return this;
+ }
+
+ /**
+ * Builds the object info instance. Once called, methods of the builder
+ * must not be called anymore.
+ *
+ * @return the object info of the newly created file, or NULL in case
+ * of an error.
+ */
+ public MtpObjectInfo build() {
+ MtpObjectInfo result = mObjectInfo;
+ mObjectInfo = null;
+ return result;
+ }
+ }
}
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 6652a54506e0..ad804f32fd9f 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -91,6 +91,55 @@ MtpDevice* get_device_from_object(JNIEnv* env, jobject javaDevice)
return (MtpDevice*)env->GetLongField(javaDevice, field_context);
}
+void fill_jobject_from_object_info(JNIEnv* env, jobject object, MtpObjectInfo* objectInfo) {
+ if (objectInfo->mHandle)
+ env->SetIntField(object, field_objectInfo_handle, objectInfo->mHandle);
+ if (objectInfo->mStorageID)
+ env->SetIntField(object, field_objectInfo_storageId, objectInfo->mStorageID);
+ if (objectInfo->mFormat)
+ env->SetIntField(object, field_objectInfo_format, objectInfo->mFormat);
+ if (objectInfo->mProtectionStatus)
+ env->SetIntField(object, field_objectInfo_protectionStatus, objectInfo->mProtectionStatus);
+ if (objectInfo->mCompressedSize)
+ env->SetIntField(object, field_objectInfo_compressedSize, objectInfo->mCompressedSize);
+ if (objectInfo->mThumbFormat)
+ env->SetIntField(object, field_objectInfo_thumbFormat, objectInfo->mThumbFormat);
+ if (objectInfo->mThumbCompressedSize) {
+ env->SetIntField(object, field_objectInfo_thumbCompressedSize,
+ objectInfo->mThumbCompressedSize);
+ }
+ if (objectInfo->mThumbPixWidth)
+ env->SetIntField(object, field_objectInfo_thumbPixWidth, objectInfo->mThumbPixWidth);
+ if (objectInfo->mThumbPixHeight)
+ env->SetIntField(object, field_objectInfo_thumbPixHeight, objectInfo->mThumbPixHeight);
+ if (objectInfo->mImagePixWidth)
+ env->SetIntField(object, field_objectInfo_imagePixWidth, objectInfo->mImagePixWidth);
+ if (objectInfo->mImagePixHeight)
+ env->SetIntField(object, field_objectInfo_imagePixHeight, objectInfo->mImagePixHeight);
+ if (objectInfo->mImagePixDepth)
+ env->SetIntField(object, field_objectInfo_imagePixDepth, objectInfo->mImagePixDepth);
+ if (objectInfo->mParent)
+ env->SetIntField(object, field_objectInfo_parent, objectInfo->mParent);
+ if (objectInfo->mAssociationType)
+ env->SetIntField(object, field_objectInfo_associationType, objectInfo->mAssociationType);
+ if (objectInfo->mAssociationDesc)
+ env->SetIntField(object, field_objectInfo_associationDesc, objectInfo->mAssociationDesc);
+ if (objectInfo->mSequenceNumber)
+ env->SetIntField(object, field_objectInfo_sequenceNumber, objectInfo->mSequenceNumber);
+ if (objectInfo->mName)
+ env->SetObjectField(object, field_objectInfo_name, env->NewStringUTF(objectInfo->mName));
+ if (objectInfo->mDateCreated)
+ env->SetLongField(object, field_objectInfo_dateCreated, objectInfo->mDateCreated * 1000LL);
+ if (objectInfo->mDateModified) {
+ env->SetLongField(object, field_objectInfo_dateModified,
+ objectInfo->mDateModified * 1000LL);
+ }
+ if (objectInfo->mKeywords) {
+ env->SetObjectField(object, field_objectInfo_keywords,
+ env->NewStringUTF(objectInfo->mKeywords));
+ }
+}
+
// ----------------------------------------------------------------------------
static jboolean
@@ -246,48 +295,7 @@ android_mtp_MtpDevice_get_object_info(JNIEnv *env, jobject thiz, jint objectID)
return NULL;
}
- if (objectInfo->mHandle)
- env->SetIntField(info, field_objectInfo_handle, objectInfo->mHandle);
- if (objectInfo->mStorageID)
- env->SetIntField(info, field_objectInfo_storageId, objectInfo->mStorageID);
- if (objectInfo->mFormat)
- env->SetIntField(info, field_objectInfo_format, objectInfo->mFormat);
- if (objectInfo->mProtectionStatus)
- env->SetIntField(info, field_objectInfo_protectionStatus, objectInfo->mProtectionStatus);
- if (objectInfo->mCompressedSize)
- env->SetIntField(info, field_objectInfo_compressedSize, objectInfo->mCompressedSize);
- if (objectInfo->mThumbFormat)
- env->SetIntField(info, field_objectInfo_thumbFormat, objectInfo->mThumbFormat);
- if (objectInfo->mThumbCompressedSize)
- env->SetIntField(info, field_objectInfo_thumbCompressedSize, objectInfo->mThumbCompressedSize);
- if (objectInfo->mThumbPixWidth)
- env->SetIntField(info, field_objectInfo_thumbPixWidth, objectInfo->mThumbPixWidth);
- if (objectInfo->mThumbPixHeight)
- env->SetIntField(info, field_objectInfo_thumbPixHeight, objectInfo->mThumbPixHeight);
- if (objectInfo->mImagePixWidth)
- env->SetIntField(info, field_objectInfo_imagePixWidth, objectInfo->mImagePixWidth);
- if (objectInfo->mImagePixHeight)
- env->SetIntField(info, field_objectInfo_imagePixHeight, objectInfo->mImagePixHeight);
- if (objectInfo->mImagePixDepth)
- env->SetIntField(info, field_objectInfo_imagePixDepth, objectInfo->mImagePixDepth);
- if (objectInfo->mParent)
- env->SetIntField(info, field_objectInfo_parent, objectInfo->mParent);
- if (objectInfo->mAssociationType)
- env->SetIntField(info, field_objectInfo_associationType, objectInfo->mAssociationType);
- if (objectInfo->mAssociationDesc)
- env->SetIntField(info, field_objectInfo_associationDesc, objectInfo->mAssociationDesc);
- if (objectInfo->mSequenceNumber)
- env->SetIntField(info, field_objectInfo_sequenceNumber, objectInfo->mSequenceNumber);
- if (objectInfo->mName)
- env->SetObjectField(info, field_objectInfo_name, env->NewStringUTF(objectInfo->mName));
- if (objectInfo->mDateCreated)
- env->SetLongField(info, field_objectInfo_dateCreated, objectInfo->mDateCreated * 1000LL);
- if (objectInfo->mDateModified)
- env->SetLongField(info, field_objectInfo_dateModified, objectInfo->mDateModified * 1000LL);
- if (objectInfo->mKeywords)
- env->SetObjectField(info, field_objectInfo_keywords,
- env->NewStringUTF(objectInfo->mKeywords));
-
+ fill_jobject_from_object_info(env, info, objectInfo);
delete objectInfo;
return info;
}
@@ -403,6 +411,82 @@ android_mtp_MtpDevice_import_file_to_fd(JNIEnv *env, jobject thiz, jint object_i
return JNI_FALSE;
}
+static jboolean
+android_mtp_MtpDevice_send_object(JNIEnv *env, jobject thiz, jint object_id, jint fd)
+{
+ MtpDevice* device = get_device_from_object(env, thiz);
+ if (!device)
+ return JNI_FALSE;
+ MtpObjectInfo* object_info = device->getObjectInfo(object_id);
+ if (!object_info)
+ return JNI_FALSE;
+
+ bool result = device->sendObject(object_info, fd);
+ delete object_info;
+ return result;
+}
+
+static jobject
+android_mtp_MtpDevice_send_object_info(JNIEnv *env, jobject thiz, jobject info)
+{
+ MtpDevice* device = get_device_from_object(env, thiz);
+ if (!device)
+ return JNI_FALSE;
+
+ // Updating existing objects is not supported.
+ if (env->GetIntField(info, field_objectInfo_handle) != -1)
+ return JNI_FALSE;
+
+ MtpObjectInfo* object_info = new MtpObjectInfo(-1);
+ object_info->mStorageID = env->GetIntField(info, field_objectInfo_storageId);
+ object_info->mFormat = env->GetIntField(info, field_objectInfo_format);
+ object_info->mProtectionStatus = env->GetIntField(info, field_objectInfo_protectionStatus);
+ object_info->mCompressedSize = env->GetIntField(info, field_objectInfo_compressedSize);
+ object_info->mThumbFormat = env->GetIntField(info, field_objectInfo_thumbFormat);
+ object_info->mThumbCompressedSize =
+ env->GetIntField(info, field_objectInfo_thumbCompressedSize);
+ object_info->mThumbPixWidth = env->GetIntField(info, field_objectInfo_thumbPixWidth);
+ object_info->mThumbPixHeight = env->GetIntField(info, field_objectInfo_thumbPixHeight);
+ object_info->mImagePixWidth = env->GetIntField(info, field_objectInfo_imagePixWidth);
+ object_info->mImagePixHeight = env->GetIntField(info, field_objectInfo_imagePixHeight);
+ object_info->mImagePixDepth = env->GetIntField(info, field_objectInfo_imagePixDepth);
+ object_info->mParent = env->GetIntField(info, field_objectInfo_parent);
+ object_info->mAssociationType = env->GetIntField(info, field_objectInfo_associationType);
+ object_info->mAssociationDesc = env->GetIntField(info, field_objectInfo_associationDesc);
+ object_info->mSequenceNumber = env->GetIntField(info, field_objectInfo_sequenceNumber);
+
+ jstring name_jstring = (jstring) env->GetObjectField(info, field_objectInfo_name);
+ const char* name_string = env->GetStringUTFChars(name_jstring, NULL);
+ object_info->mName = strdup(name_string);
+ env->ReleaseStringUTFChars(name_jstring, name_string);
+
+ object_info->mDateCreated = env->GetLongField(info, field_objectInfo_dateCreated) / 1000LL;
+ object_info->mDateModified = env->GetLongField(info, field_objectInfo_dateModified) / 1000LL;
+
+ jstring keywords_jstring = (jstring) env->GetObjectField(info, field_objectInfo_keywords);
+ const char* keywords_string = env->GetStringUTFChars(keywords_jstring, NULL);
+ object_info->mKeywords = strdup(keywords_string);
+ env->ReleaseStringUTFChars(keywords_jstring, keywords_string);
+
+ int object_handle = device->sendObjectInfo(object_info);
+ if (object_handle == -1) {
+ delete object_info;
+ return NULL;
+ }
+
+ object_info->mHandle = object_handle;
+ jobject result = env->NewObject(clazz_objectInfo, constructor_objectInfo);
+ if (result == NULL) {
+ ALOGE("Could not create a MtpObjectInfo object");
+ delete object_info;
+ return NULL;
+ }
+
+ fill_jobject_from_object_info(env, result, object_info);
+ delete object_info;
+ return result;
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -425,7 +509,10 @@ static JNINativeMethod gMethods[] = {
{"native_get_storage_id", "(I)J", (void *)android_mtp_MtpDevice_get_storage_id},
{"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}
+ {"native_import_file", "(II)Z",(void *)android_mtp_MtpDevice_import_file_to_fd},
+ {"native_send_object", "(II)Z",(void *)android_mtp_MtpDevice_send_object},
+ {"native_send_object_info", "(Landroid/mtp/MtpObjectInfo;)Landroid/mtp/MtpObjectInfo;",
+ (void *)android_mtp_MtpDevice_send_object_info}
};
int register_android_mtp_MtpDevice(JNIEnv *env)