diff options
| author | 2015-08-10 10:10:22 +0900 | |
|---|---|---|
| committer | 2015-08-20 11:34:44 +0900 | |
| commit | 87763e6a91a54e7995cfda9b7e80162f02ac4cbc (patch) | |
| tree | edf0cd1f57a31a5d36ae7df61af2cad4477d3c67 | |
| parent | fc58dff0dd838d71661bb26f09b949a246ba5434 (diff) | |
Wire uploading to MtpDocumentsProvider.
This patch does not yet allow to upload files, but uploading (creating)
directories already works.
Bug: 22545670
Change-Id: If4d5a53aa26f791475bb1a783e0ac9540d6760c1
9 files changed, 90 insertions, 24 deletions
diff --git a/api/current.txt b/api/current.txt index 3e1f5a521db6..9f020474bebf 100644 --- a/api/current.txt +++ b/api/current.txt @@ -18136,7 +18136,7 @@ package android.mtp { method public final int getThumbPixWidth(); } - public class MtpObjectInfo.Builder { + public static class MtpObjectInfo.Builder { ctor public MtpObjectInfo.Builder(); ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo); method public android.mtp.MtpObjectInfo build(); diff --git a/api/system-current.txt b/api/system-current.txt index 984d3953ef86..7c4c81e434ed 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -19649,7 +19649,7 @@ package android.mtp { method public final int getThumbPixWidth(); } - public class MtpObjectInfo.Builder { + public static class MtpObjectInfo.Builder { ctor public MtpObjectInfo.Builder(); ctor public MtpObjectInfo.Builder(android.mtp.MtpObjectInfo); method public android.mtp.MtpObjectInfo build(); diff --git a/media/java/android/mtp/MtpObjectInfo.java b/media/java/android/mtp/MtpObjectInfo.java index d2824b556315..f79d52ee8c56 100644 --- a/media/java/android/mtp/MtpObjectInfo.java +++ b/media/java/android/mtp/MtpObjectInfo.java @@ -256,7 +256,7 @@ public final class MtpObjectInfo { /** * Builds a new object info instance. */ - public class Builder { + public static class Builder { private MtpObjectInfo mObjectInfo; public Builder() { diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp index ad804f32fd9f..9dd3861177e9 100644 --- a/media/jni/android_mtp_MtpDevice.cpp +++ b/media/jni/android_mtp_MtpDevice.cpp @@ -430,12 +430,14 @@ static jobject android_mtp_MtpDevice_send_object_info(JNIEnv *env, jobject thiz, jobject info) { MtpDevice* device = get_device_from_object(env, thiz); - if (!device) + if (!device) { return JNI_FALSE; + } // Updating existing objects is not supported. - if (env->GetIntField(info, field_objectInfo_handle) != -1) + 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); @@ -456,17 +458,21 @@ android_mtp_MtpDevice_send_object_info(JNIEnv *env, jobject thiz, jobject info) 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); + if (name_jstring != NULL) { + 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); + if (keywords_jstring != NULL) { + 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) { diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java index 98775b36f796..7126694bc4a5 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java @@ -32,6 +32,7 @@ class MtpDocument { private final Date mDateModified; private final int mSize; private final int mThumbSize; + private final boolean mReadOnly; /** * Constructor for root document. @@ -40,9 +41,10 @@ class MtpDocument { this(DUMMY_HANDLE_FOR_ROOT, 0x3001, // Directory. root.mDescription, - null, // Unknown, + null, // Unknown name. (int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE), - 0); + 0, // Total size. + true); // Writable. } MtpDocument(MtpObjectInfo objectInfo) { @@ -51,7 +53,8 @@ class MtpDocument { objectInfo.getName(), objectInfo.getDateModified() != 0 ? new Date(objectInfo.getDateModified()) : null, objectInfo.getCompressedSize(), - objectInfo.getThumbCompressedSize()); + objectInfo.getThumbCompressedSize(), + objectInfo.getProtectionStatus() != 0); } MtpDocument(int objectHandle, @@ -59,13 +62,15 @@ class MtpDocument { String name, Date dateModified, int size, - int thumbSize) { + int thumbSize, + boolean readOnly) { this.mObjectHandle = objectHandle; this.mFormat = format; this.mName = name; this.mDateModified = dateModified; this.mSize = size; this.mThumbSize = thumbSize; + this.mReadOnly = readOnly; } void addToCursor(Identifier rootIdentifier, MatrixCursor.RowBuilder builder) { @@ -82,7 +87,7 @@ class MtpDocument { builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId()); builder.add(Document.COLUMN_DISPLAY_NAME, mName); - builder.add(Document.COLUMN_MIME_TYPE, getMimeType()); + builder.add(Document.COLUMN_MIME_TYPE, formatTypeToMimeType(mFormat)); builder.add( Document.COLUMN_LAST_MODIFIED, mDateModified != null ? mDateModified.getTime() : null); @@ -90,9 +95,9 @@ class MtpDocument { builder.add(Document.COLUMN_SIZE, mSize); } - private String getMimeType() { + static String formatTypeToMimeType(int format) { // TODO: Add complete list of mime types. - switch (mFormat) { + switch (format) { case 0x3001: return DocumentsContract.Document.MIME_TYPE_DIR; case 0x3009: @@ -100,7 +105,21 @@ class MtpDocument { case 0x3801: return "image/jpeg"; default: - return ""; + return "application/octet-stream"; + } + } + + static int mimeTypeToFormatType(String mimeType) { + // TODO: Add complete list of mime types. + switch (mimeType.toLowerCase()) { + case Document.MIME_TYPE_DIR: + return 0x3001; + case "audio/mp3": + return 0x3009; + case "image/jpeg": + return 0x3801; + default: + return 0x3000; // Undefined object. } } } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index 3a98a588c548..753641545481 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -96,7 +96,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { final Identifier rootIdentifier = new Identifier(root.mDeviceId, root.mStorageId); final MatrixCursor.RowBuilder builder = cursor.newRow(); builder.add(Root.COLUMN_ROOT_ID, rootIdentifier.toRootId()); - builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD); + builder.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE); builder.add(Root.COLUMN_TITLE, root.mDescription); builder.add( Root.COLUMN_DOCUMENT_ID, @@ -214,6 +214,24 @@ public class MtpDocumentsProvider extends DocumentsProvider { mDocumentLoader.clearCache(); } + @Override + public String createDocument(String parentDocumentId, String mimeType, String displayName) + throws FileNotFoundException { + try { + final Identifier parentId = Identifier.createFromDocumentId(parentDocumentId); + final int objectHandle = mMtpManager.createDocument( + parentId.mDeviceId, parentId.mStorageId, parentId.mObjectHandle, mimeType, + displayName); + final String documentId = new Identifier(parentId.mDeviceId, parentId.mStorageId, + objectHandle).toDocumentId(); + notifyChildDocumentsChange(parentDocumentId); + return documentId; + } catch (IOException error) { + Log.e(TAG, error.getMessage()); + throw new FileNotFoundException(error.getMessage()); + } + } + void openDevice(int deviceId) throws IOException { mMtpManager.openDevice(deviceId); mRootScanner.scanNow(); diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java index 3afc173fcc52..27ba794d3883 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java @@ -21,7 +21,10 @@ import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbManager; import android.mtp.MtpDevice; +import android.mtp.MtpObjectInfo; import android.os.ParcelFileDescriptor; +import android.provider.DocumentsContract.Document; +import android.provider.DocumentsContract; import android.util.SparseArray; import java.io.FileNotFoundException; @@ -134,6 +137,22 @@ class MtpManager { } } + synchronized int createDocument(int deviceId, int storageId, int parentObjectHandle, + String mimeType, String name) throws IOException { + final MtpDevice device = getDevice(deviceId); + final MtpObjectInfo objectInfo = new MtpObjectInfo.Builder() + .setName(name) + .setStorageId(storageId) + .setParent(parentObjectHandle) + .setFormat(MtpDocument.mimeTypeToFormatType(mimeType)) + .build(); + final MtpObjectInfo result = device.sendObjectInfo(objectInfo); + if (result == null) { + throw new IOException("Failed to create a document"); + } + return result.getObjectHandle(); + } + synchronized int getParent(int deviceId, int objectHandle) throws IOException { final MtpDevice device = getDevice(deviceId); final int result = (int) device.getParent(objectHandle); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java index 55041478f105..1e015bdc78d5 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java @@ -91,7 +91,8 @@ public class DocumentLoaderTest extends AndroidTestCase { "file" + objectHandle, new Date(), 1024, - 0 /* thumbnail size */)); + 0 /* thumbnail size */, + false /* not read only */)); } manager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, childDocuments); } diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java index c1da59f5cb43..f06e2ffacf9a 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java @@ -210,7 +210,8 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { "image.jpg" /* display name */, new Date(1422716400000L) /* modified date */, 1024 * 1024 * 5 /* file size */, - 1024 * 50 /* thumbnail size */)); + 1024 * 50 /* thumbnail size */, + true /* read only */)); final Cursor cursor = mProvider.queryDocument("0_1_2", null); assertEquals(1, cursor.getCount()); @@ -257,7 +258,8 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { "image.jpg" /* display name */, new Date(0) /* modified date */, 1024 * 1024 * 5 /* file size */, - 1024 * 50 /* thumbnail size */)); + 1024 * 50 /* thumbnail size */, + true /* read only */)); final Cursor cursor = mProvider.queryChildDocuments("0_0_0", null, null); assertEquals(1, cursor.getCount()); @@ -302,7 +304,8 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { "image.jpg" /* display name */, new Date(1422716400000L) /* modified date */, 1024 * 1024 * 5 /* file size */, - 1024 * 50 /* thumbnail size */)); + 1024 * 50 /* thumbnail size */, + false /* not read only */)); mMtpManager.setParent(0, 1, 2); mProvider.deleteDocument("0_0_1"); assertEquals(1, mResolver.getChangeCount( |