Loading api/current.txt +27 −0 Original line number Diff line number Diff line Loading @@ -18102,6 +18102,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 { Loading Loading @@ -18134,6 +18136,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(); api/system-current.txt +27 −0 Original line number Diff line number Diff line Loading @@ -19614,6 +19614,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 { Loading Loading @@ -19646,6 +19648,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(); media/java/android/mtp/MtpDevice.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); } media/java/android/mtp/MtpObjectInfo.java +151 −1 Original line number Diff line number Diff line Loading @@ -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() { } Loading Loading @@ -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; } } } media/jni/android_mtp_MtpDevice.cpp +130 −43 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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[] = { Loading @@ -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) Loading Loading
api/current.txt +27 −0 Original line number Diff line number Diff line Loading @@ -18102,6 +18102,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 { Loading Loading @@ -18134,6 +18136,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();
api/system-current.txt +27 −0 Original line number Diff line number Diff line Loading @@ -19614,6 +19614,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 { Loading Loading @@ -19646,6 +19648,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();
media/java/android/mtp/MtpDevice.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); }
media/java/android/mtp/MtpObjectInfo.java +151 −1 Original line number Diff line number Diff line Loading @@ -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() { } Loading Loading @@ -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; } } }
media/jni/android_mtp_MtpDevice.cpp +130 −43 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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[] = { Loading @@ -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) Loading