Remove MtpDocument.

Change-Id: Ie4b0e55f6ff2c7b323cf767a5ed3d3c61c12734d
This commit is contained in:
Tomasz Mikolajewski
2015-08-25 18:34:30 +09:00
parent b7a97fc271
commit bb430fa930
13 changed files with 223 additions and 273 deletions

View File

@@ -18164,6 +18164,7 @@ package android.mtp {
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 setObjectHandle(int);
method public android.mtp.MtpObjectInfo.Builder setParent(int);
method public android.mtp.MtpObjectInfo.Builder setProtectionStatus(int);
method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(int);

View File

@@ -19676,6 +19676,7 @@ package android.mtp {
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 setObjectHandle(int);
method public android.mtp.MtpObjectInfo.Builder setParent(int);
method public android.mtp.MtpObjectInfo.Builder setProtectionStatus(int);
method public android.mtp.MtpObjectInfo.Builder setSequenceNumber(int);

View File

@@ -294,6 +294,11 @@ public final class MtpObjectInfo {
mObjectInfo.mThumbPixWidth = objectInfo.mThumbPixWidth;
}
public Builder setObjectHandle(int value) {
mObjectInfo.mHandle = value;
return this;
}
public Builder setAssociationDesc(int value) {
mObjectInfo.mAssociationDesc = value;
return this;

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mtp;
import android.database.MatrixCursor;
import android.mtp.MtpObjectInfo;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import java.util.Date;
final class CursorHelper {
static final int DUMMY_HANDLE_FOR_ROOT = 0;
private CursorHelper() {
}
static void addToCursor(MtpRoot root, MatrixCursor.RowBuilder builder) {
final Identifier identifier = new Identifier(
root.mDeviceId, root.mStorageId, DUMMY_HANDLE_FOR_ROOT);
builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
builder.add(Document.COLUMN_DISPLAY_NAME, root.mDescription);
builder.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
builder.add(Document.COLUMN_LAST_MODIFIED, null);
builder.add(Document.COLUMN_FLAGS, 0);
builder.add(Document.COLUMN_SIZE,
(int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE));
}
static void addToCursor(MtpObjectInfo objectInfo, Identifier rootIdentifier,
MatrixCursor.RowBuilder builder) {
final Identifier identifier = new Identifier(
rootIdentifier.mDeviceId, rootIdentifier.mStorageId, objectInfo.getObjectHandle());
final String mimeType = formatTypeToMimeType(objectInfo.getFormat());
int flag = 0;
if (objectInfo.getProtectionStatus() == 0) {
flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
DocumentsContract.Document.FLAG_SUPPORTS_WRITE;
if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR) {
flag |= DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE;
}
}
if (objectInfo.getThumbCompressedSize() > 0) {
flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
}
builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
builder.add(Document.COLUMN_DISPLAY_NAME, objectInfo.getName());
builder.add(Document.COLUMN_MIME_TYPE, mimeType);
builder.add(
Document.COLUMN_LAST_MODIFIED,
objectInfo.getDateModified() != 0 ? objectInfo.getDateModified() : null);
builder.add(Document.COLUMN_FLAGS, flag);
builder.add(Document.COLUMN_SIZE, objectInfo.getCompressedSize());
}
static String formatTypeToMimeType(int format) {
// TODO: Add complete list of mime types.
switch (format) {
case 0x3001:
return DocumentsContract.Document.MIME_TYPE_DIR;
case 0x3009:
return "audio/mp3";
case 0x3801:
return "image/jpeg";
default:
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.
}
}
}

View File

@@ -19,6 +19,7 @@ package com.android.mtp;
import android.content.ContentResolver;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
@@ -34,6 +35,7 @@ import java.util.LinkedList;
* Loader for MTP document.
* At the first request, the loader returns only first NUM_INITIAL_ENTRIES. Then it launches
* background thread to load the rest documents and caches its result for next requests.
* TODO: Rename this class to ObjectInfoLoader
*/
class DocumentLoader {
static final int NUM_INITIAL_ENTRIES = 10;
@@ -50,13 +52,13 @@ class DocumentLoader {
mResolver = resolver;
}
private static MtpDocument[] loadDocuments(MtpManager manager, int deviceId, int[] handles)
private static MtpObjectInfo[] loadDocuments(MtpManager manager, int deviceId, int[] handles)
throws IOException {
final MtpDocument[] documents = new MtpDocument[handles.length];
final MtpObjectInfo[] objectInfos = new MtpObjectInfo[handles.length];
for (int i = 0; i < handles.length; i++) {
documents[i] = manager.getDocument(deviceId, handles[i]);
objectInfos[i] = manager.getObjectInfo(deviceId, handles[i]);
}
return documents;
return objectInfos;
}
synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
@@ -66,7 +68,7 @@ class DocumentLoader {
int parentHandle = parent.mObjectHandle;
// Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
// getObjectHandles if we would like to obtain children under the root.
if (parentHandle == MtpDocument.DUMMY_HANDLE_FOR_ROOT) {
if (parentHandle == CursorHelper.DUMMY_HANDLE_FOR_ROOT) {
parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
}
task = new LoaderTask(parent, mMtpManager.getObjectHandles(
@@ -114,16 +116,16 @@ class DocumentLoader {
deviceId = task.mIdentifier.mDeviceId;
handles = task.getUnloadedObjectHandles(NUM_LOADING_ENTRIES);
}
MtpDocument[] documents;
MtpObjectInfo[] objectInfos;
try {
documents = loadDocuments(mMtpManager, deviceId, handles);
objectInfos = loadDocuments(mMtpManager, deviceId, handles);
} catch (IOException exception) {
documents = null;
objectInfos = null;
Log.d(MtpDocumentsProvider.TAG, exception.getMessage());
}
synchronized (DocumentLoader.this) {
if (documents != null) {
task.fillDocuments(documents);
if (objectInfos != null) {
task.fillDocuments(objectInfos);
final boolean shouldNotify =
task.mLastNotified.getTime() <
new Date().getTime() - NOTIFY_PERIOD_MS ||
@@ -182,14 +184,14 @@ class DocumentLoader {
private static class LoaderTask {
final Identifier mIdentifier;
final int[] mObjectHandles;
final MtpDocument[] mDocuments;
final MtpObjectInfo[] mObjectInfos;
Date mLastNotified;
int mNumLoaded;
LoaderTask(Identifier identifier, int[] objectHandles) {
mIdentifier = identifier;
mObjectHandles = objectHandles;
mDocuments = new MtpDocument[mObjectHandles.length];
mObjectInfos = new MtpObjectInfo[mObjectHandles.length];
mNumLoaded = 0;
mLastNotified = new Date();
}
@@ -199,7 +201,7 @@ class DocumentLoader {
final Identifier rootIdentifier = new Identifier(
mIdentifier.mDeviceId, mIdentifier.mStorageId);
for (int i = 0; i < mNumLoaded; i++) {
mDocuments[i].addToCursor(rootIdentifier, cursor.newRow());
CursorHelper.addToCursor(mObjectInfos[i], rootIdentifier, cursor.newRow());
}
final Bundle extras = new Bundle();
extras.putBoolean(DocumentsContract.EXTRA_LOADING, !completed());
@@ -209,7 +211,7 @@ class DocumentLoader {
}
boolean completed() {
return mNumLoaded == mDocuments.length;
return mNumLoaded == mObjectInfos.length;
}
int[] getUnloadedObjectHandles(int count) {
@@ -224,9 +226,9 @@ class DocumentLoader {
mLastNotified = new Date();
}
void fillDocuments(MtpDocument[] documents) {
for (int i = 0; i < documents.length; i++) {
mDocuments[mNumLoaded++] = documents[i];
void fillDocuments(MtpObjectInfo[] objectInfos) {
for (int i = 0; i < objectInfos.length; i++) {
mObjectInfos[mNumLoaded++] = objectInfos[i];
}
}

View File

@@ -41,7 +41,7 @@ class Identifier {
Identifier(int deviceId, int storageId) {
this(deviceId, storageId, MtpDocument.DUMMY_HANDLE_FOR_ROOT);
this(deviceId, storageId, CursorHelper.DUMMY_HANDLE_FOR_ROOT);
}
Identifier(int deviceId, int storageId, int objectHandle) {

View File

@@ -1,132 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mtp;
import android.database.MatrixCursor;
import android.mtp.MtpObjectInfo;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import java.util.Date;
class MtpDocument {
static final int DUMMY_HANDLE_FOR_ROOT = 0;
private final int mObjectHandle;
private final int mFormat;
private final String mName;
private final Date mDateModified;
private final int mSize;
private final int mThumbSize;
private final boolean mReadOnly;
/**
* Constructor for root document.
*/
MtpDocument(MtpRoot root) {
this(DUMMY_HANDLE_FOR_ROOT,
0x3001, // Directory.
root.mDescription,
null, // Unknown name.
(int) Math.min(root.mMaxCapacity - root.mFreeSpace, Integer.MAX_VALUE),
0, // Total size.
true); // Writable.
}
MtpDocument(MtpObjectInfo objectInfo) {
this(objectInfo.getObjectHandle(),
objectInfo.getFormat(),
objectInfo.getName(),
objectInfo.getDateModified() != 0 ? new Date(objectInfo.getDateModified()) : null,
objectInfo.getCompressedSize(),
objectInfo.getThumbCompressedSize(),
objectInfo.getProtectionStatus() != 0);
}
MtpDocument(int objectHandle,
int format,
String name,
Date dateModified,
int size,
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) {
final Identifier identifier = new Identifier(
rootIdentifier.mDeviceId, rootIdentifier.mStorageId, mObjectHandle);
final String mimeType = formatTypeToMimeType(mFormat);
int flag = 0;
if (mObjectHandle != DUMMY_HANDLE_FOR_ROOT) {
if (mThumbSize > 0) {
flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
}
if (!mReadOnly) {
flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
DocumentsContract.Document.FLAG_SUPPORTS_WRITE;
}
}
if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR && !mReadOnly) {
flag |= DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE;
}
builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
builder.add(Document.COLUMN_DISPLAY_NAME, mName);
builder.add(Document.COLUMN_MIME_TYPE, mimeType);
builder.add(
Document.COLUMN_LAST_MODIFIED,
mDateModified != null ? mDateModified.getTime() : null);
builder.add(Document.COLUMN_FLAGS, flag);
builder.add(Document.COLUMN_SIZE, mSize);
}
static String formatTypeToMimeType(int format) {
// TODO: Add complete list of mime types.
switch (format) {
case 0x3001:
return DocumentsContract.Document.MIME_TYPE_DIR;
case 0x3009:
return "audio/mp3";
case 0x3801:
return "image/jpeg";
default:
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.
}
}
}

View File

@@ -21,11 +21,12 @@ import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.Point;
import android.mtp.MtpObjectInfo;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
import android.util.Log;
@@ -116,37 +117,37 @@ public class MtpDocumentsProvider extends DocumentsProvider {
}
final Identifier identifier = Identifier.createFromDocumentId(documentId);
MtpDocument document = null;
if (identifier.mObjectHandle != MtpDocument.DUMMY_HANDLE_FOR_ROOT) {
if (identifier.mObjectHandle != CursorHelper.DUMMY_HANDLE_FOR_ROOT) {
MtpObjectInfo objectInfo;
try {
document = mMtpManager.getDocument(identifier.mDeviceId, identifier.mObjectHandle);
objectInfo = mMtpManager.getObjectInfo(
identifier.mDeviceId, identifier.mObjectHandle);
} catch (IOException e) {
throw new FileNotFoundException(e.getMessage());
}
final MatrixCursor cursor = new MatrixCursor(projection);
CursorHelper.addToCursor(
objectInfo,
new Identifier(identifier.mDeviceId, identifier.mStorageId),
cursor.newRow());
return cursor;
} else {
MtpRoot[] roots;
try {
roots = mMtpManager.getRoots(identifier.mDeviceId);
if (roots != null) {
for (final MtpRoot root : roots) {
if (identifier.mStorageId == root.mStorageId) {
document = new MtpDocument(root);
break;
}
}
}
if (document == null) {
throw new FileNotFoundException();
}
} catch (IOException e) {
throw new FileNotFoundException(e.getMessage());
}
for (final MtpRoot root : roots) {
if (identifier.mStorageId != root.mStorageId)
continue;
final MatrixCursor cursor = new MatrixCursor(projection);
CursorHelper.addToCursor(root, cursor.newRow());
return cursor;
}
}
final MatrixCursor cursor = new MatrixCursor(projection);
document.addToCursor(
new Identifier(identifier.mDeviceId, identifier.mStorageId), cursor.newRow());
return cursor;
throw new FileNotFoundException();
}
@Override
@@ -225,8 +226,13 @@ public class MtpDocumentsProvider extends DocumentsProvider {
try {
final Identifier parentId = Identifier.createFromDocumentId(parentDocumentId);
final int objectHandle = mMtpManager.createDocument(
parentId.mDeviceId, parentId.mStorageId, parentId.mObjectHandle, mimeType,
displayName);
parentId.mDeviceId,
new MtpObjectInfo.Builder()
.setStorageId(parentId.mStorageId)
.setParent(parentId.mObjectHandle)
.setFormat(CursorHelper.mimeTypeToFormatType(mimeType))
.setName(displayName)
.build());
final String documentId = new Identifier(parentId.mDeviceId, parentId.mStorageId,
objectHandle).toDocumentId();
notifyChildDocumentsChange(parentDocumentId);

View File

@@ -108,16 +108,12 @@ class MtpManager {
return results;
}
synchronized MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
synchronized MtpObjectInfo getObjectInfo(int deviceId, int objectHandle)
throws IOException {
final MtpDevice device = getDevice(deviceId);
return device.getObjectInfo(objectHandle);
}
synchronized MtpDocument getDocument(int deviceId, int objectHandle) throws IOException {
final MtpDevice device = getDevice(deviceId);
return new MtpDocument(device.getObjectInfo(objectHandle));
}
synchronized int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle)
throws IOException {
final MtpDevice device = getDevice(deviceId);
@@ -142,18 +138,6 @@ class MtpManager {
}
}
// TODO: Remove this method.
synchronized int createDocument(int deviceId, int storageId, int parentObjectHandle,
String mimeType, String name) throws IOException {
final MtpObjectInfo objectInfo = new MtpObjectInfo.Builder()
.setName(name)
.setStorageId(storageId)
.setParent(parentObjectHandle)
.setFormat(MtpDocument.mimeTypeToFormatType(mimeType))
.build();
return createDocument(deviceId, objectInfo);
}
synchronized int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
final MtpDevice device = getDevice(deviceId);
final MtpObjectInfo result = device.sendObjectInfo(objectInfo);

View File

@@ -18,6 +18,7 @@ package com.android.mtp;
import android.content.Context;
import android.database.Cursor;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.test.AndroidTestCase;
@@ -31,14 +32,14 @@ import java.util.concurrent.CountDownLatch;
@SmallTest
public class DocumentLoaderTest extends AndroidTestCase {
private BlockableTestMtpMaanger mManager;
private BlockableTestMtpManager mManager;
private TestContentResolver mResolver;
private DocumentLoader mLoader;
final private Identifier mParentIdentifier = new Identifier(0, 0, 0);
@Override
public void setUp() {
mManager = new BlockableTestMtpMaanger(getContext());
mManager = new BlockableTestMtpManager(getContext());
mResolver = new TestContentResolver();
mLoader = new DocumentLoader(mManager, mResolver);
}
@@ -85,22 +86,17 @@ public class DocumentLoaderTest extends AndroidTestCase {
for (int i = 0; i < childDocuments.length; i++) {
final int objectHandle = i + 1;
childDocuments[i] = objectHandle;
manager.setDocument(0, objectHandle, new MtpDocument(
objectHandle,
0 /* format */,
"file" + objectHandle,
new Date(),
1024,
0 /* thumbnail size */,
false /* not read only */));
manager.setObjectInfo(0, new MtpObjectInfo.Builder()
.setObjectHandle(objectHandle)
.build());
}
manager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, childDocuments);
}
private static class BlockableTestMtpMaanger extends TestMtpManager {
private static class BlockableTestMtpManager extends TestMtpManager {
final private Map<String, CountDownLatch> blockedDocuments = new HashMap<>();
BlockableTestMtpMaanger(Context context) {
BlockableTestMtpManager(Context context) {
super(context);
}
@@ -113,7 +109,7 @@ public class DocumentLoaderTest extends AndroidTestCase {
}
@Override
MtpDocument getDocument(int deviceId, int objectHandle) throws IOException {
MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
final CountDownLatch latch = blockedDocuments.get(pack(deviceId, objectHandle));
if (latch != null) {
try {
@@ -122,7 +118,7 @@ public class DocumentLoaderTest extends AndroidTestCase {
fail();
}
}
return super.getDocument(deviceId, objectHandle);
return super.getObjectInfo(deviceId, objectHandle);
}
}
}

View File

@@ -17,9 +17,12 @@
package com.android.mtp;
import android.database.Cursor;
import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo.Builder;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsContract;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -204,14 +207,14 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
}
public void testQueryDocument() throws IOException {
mMtpManager.setDocument(0, 2, new MtpDocument(
2 /* object handle */,
0x3801 /* JPEG */,
"image.jpg" /* display name */,
new Date(1422716400000L) /* modified date */,
1024 * 1024 * 5 /* file size */,
1024 * 50 /* thumbnail size */,
false /* read only */));
mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
.setObjectHandle(2)
.setFormat(0x3801)
.setName("image.jpg")
.setDateModified(1422716400000L)
.setCompressedSize(1024 * 1024 * 5)
.setThumbCompressedSize(1024 * 50)
.build());
final Cursor cursor = mProvider.queryDocument("0_1_2", null);
assertEquals(1, cursor.getCount());
@@ -229,14 +232,12 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
}
public void testQueryDocument_directory() throws IOException {
mMtpManager.setDocument(0, 2, new MtpDocument(
2 /* object handle */,
0x3001 /* directory */,
"directory" /* display name */,
new Date(1422716400000L) /* modified date */,
0 /* file size */,
0 /* thumbnail size */,
false /* read only */));
mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
.setObjectHandle(2)
.setFormat(0x3001 /* directory format */)
.setName("directory")
.setDateModified(1422716400000L)
.build());
final Cursor cursor = mProvider.queryDocument("0_1_2", null);
assertEquals(1, cursor.getCount());
@@ -278,14 +279,14 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
public void testQueryChildDocuments() throws Exception {
mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
mMtpManager.setDocument(0, 1, new MtpDocument(
1 /* object handle */,
0x3801 /* JPEG */,
"image.jpg" /* display name */,
new Date(0) /* modified date */,
1024 * 1024 * 5 /* file size */,
1024 * 50 /* thumbnail size */,
true /* read only */));
mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
.setObjectHandle(1)
.setFormat(0x3801 /* JPEG */)
.setName("image.jpg")
.setCompressedSize(1024 * 1024 * 5)
.setThumbCompressedSize(5 * 1024)
.setProtectionStatus(MtpConstants.PROTECTION_STATUS_READ_ONLY)
.build());
final Cursor cursor = mProvider.queryChildDocuments("0_0_0", null, null);
assertEquals(1, cursor.getCount());
@@ -321,14 +322,14 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
}
public void testDeleteDocument() throws FileNotFoundException {
mMtpManager.setDocument(0, 1, new MtpDocument(
1 /* object handle */,
0x3801 /* JPEG */,
"image.jpg" /* display name */,
new Date(1422716400000L) /* modified date */,
1024 * 1024 * 5 /* file size */,
1024 * 50 /* thumbnail size */,
false /* not read only */));
mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
.setObjectHandle(1)
.setFormat(0x3801)
.setName("image.jpg")
.setDateModified(1422716400000L)
.setCompressedSize(1024 * 1024 * 5)
.setThumbCompressedSize(1024 * 50)
.build());
mMtpManager.setParent(0, 1, 2);
mProvider.deleteDocument("0_0_1");
assertEquals(1, mResolver.getChangeCount(

View File

@@ -16,6 +16,7 @@
package com.android.mtp;
import android.mtp.MtpObjectInfo;
import android.os.ParcelFileDescriptor;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -56,7 +57,9 @@ public class PipeManagerTest extends AndroidTestCase {
public void testWriteDocument_basic() throws Exception {
// Create a placeholder file which should be replaced by a real file later.
mtpManager.setDocument(0, 1, new MtpDocument(1, 0, "", new Date(), 0, 0, false));
mtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
.setObjectHandle(1)
.build());
// Upload testing bytes.
final ParcelFileDescriptor descriptor = mPipeManager.writeDocument(
@@ -69,14 +72,14 @@ public class PipeManagerTest extends AndroidTestCase {
// Check if the placeholder file is removed.
try {
final MtpDocument placeholderDocument = mtpManager.getDocument(0, 1);
final MtpObjectInfo placeholderDocument = mtpManager.getObjectInfo(0, 1);
fail(); // The placeholder file has not been deleted.
} catch (IOException e) {
// Expected error, as the file is gone.
}
// Confirm that the target file is created.
final MtpDocument targetDocument = mtpManager.getDocument(
final MtpObjectInfo targetDocument = mtpManager.getObjectInfo(
0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
assertTrue(targetDocument != null);

View File

@@ -40,7 +40,7 @@ public class TestMtpManager extends MtpManager {
private final Set<Integer> mValidDevices = new HashSet<>();
private final Set<Integer> mOpenedDevices = new TreeSet<>();
private final Map<Integer, MtpRoot[]> mRoots = new HashMap<>();
private final Map<String, MtpDocument> mDocuments = new HashMap<>();
private final Map<String, MtpObjectInfo> mObjectInfos = new HashMap<>();
private final Map<String, int[]> mObjectHandles = new HashMap<>();
private final Map<String, byte[]> mThumbnailBytes = new HashMap<>();
private final Map<String, Integer> mParents = new HashMap<>();
@@ -54,16 +54,16 @@ public class TestMtpManager extends MtpManager {
mValidDevices.add(deviceId);
}
void setObjectHandles(int deviceId, int storageId, int objectHandle, int[] documents) {
mObjectHandles.put(pack(deviceId, storageId, objectHandle), documents);
void setObjectHandles(int deviceId, int storageId, int parentHandle, int[] objectHandles) {
mObjectHandles.put(pack(deviceId, storageId, parentHandle), objectHandles);
}
void setRoots(int deviceId, MtpRoot[] roots) {
mRoots.put(deviceId, roots);
}
void setDocument(int deviceId, int objectHandle, MtpDocument document) {
mDocuments.put(pack(deviceId, objectHandle), document);
void setObjectInfo(int deviceId, MtpObjectInfo objectInfo) {
mObjectInfos.put(pack(deviceId, objectInfo.getObjectHandle()), objectInfo);
}
void setImportFileBytes(int deviceId, int objectHandle, byte[] bytes) {
@@ -78,6 +78,8 @@ public class TestMtpManager extends MtpManager {
mThumbnailBytes.put(pack(deviceId, objectHandle), bytes);
}
// TODO: Remove this method, as MtpObjectInfo contains information about
// parents.
void setParent(int deviceId, int objectHandle, int parentObjectHandle) {
mParents.put(pack(deviceId, objectHandle), parentObjectHandle);
}
@@ -107,23 +109,14 @@ public class TestMtpManager extends MtpManager {
}
}
@Override
MtpDocument getDocument(int deviceId, int objectHandle) throws IOException {
final String key = pack(deviceId, objectHandle);
if (mDocuments.containsKey(key)) {
return mDocuments.get(key);
} else {
throw new IOException("getDocument error: " + key);
}
}
@Override
MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
final MtpDocument document = getDocument(deviceId, objectHandle);
// It's impossible to set an object id of MtpObjectInfo at this stage. Also,
// it's hard to get any information from MtpDocument, as it's designed to return them
// only via cursors. Rework these.
return new MtpObjectInfo.Builder().build();
final String key = pack(deviceId, objectHandle);
if (mObjectInfos.containsKey(key)) {
return mObjectInfos.get(key);
} else {
throw new IOException("getObjectInfo error: " + key);
}
}
@Override
@@ -152,18 +145,9 @@ public class TestMtpManager extends MtpManager {
@Override
int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
// For simplicity, it allows to create only one document, and it always has the hardcoded
// CREATED_DOCUMENT_HANDLE document handle.
final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
if (!mDocuments.containsKey(key)) {
mDocuments.put(key, new MtpDocument(
CREATED_DOCUMENT_HANDLE,
objectInfo.getFormat(),
objectInfo.getName(),
new Date(objectInfo.getDateModified()),
objectInfo.getCompressedSize(),
objectInfo.getThumbCompressedSize(),
false /* Always writable for testing. */));
if (!mObjectInfos.containsKey(key)) {
mObjectInfos.put(key, objectInfo);
} else {
throw new IOException();
}
@@ -174,7 +158,7 @@ public class TestMtpManager extends MtpManager {
void sendObject(int deviceId, int objectHandle, int size, ParcelFileDescriptor source)
throws IOException {
final String key = pack(deviceId, objectHandle);
if (!mDocuments.containsKey(key)) {
if (!mObjectInfos.containsKey(key)) {
throw new IOException();
}
@@ -201,8 +185,8 @@ public class TestMtpManager extends MtpManager {
@Override
void deleteDocument(int deviceId, int objectHandle) throws IOException {
final String key = pack(deviceId, objectHandle);
if (mDocuments.containsKey(key)) {
mDocuments.remove(key);
if (mObjectInfos.containsKey(key)) {
mObjectInfos.remove(key);
} else {
throw new IOException();
}