Merge "Remove MtpDocument."
diff --git a/api/current.txt b/api/current.txt
index e9c5727..923808d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18164,6 +18164,7 @@
     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);
diff --git a/api/system-current.txt b/api/system-current.txt
index e234970..5cd8697 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19676,6 +19676,7 @@
     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);
diff --git a/media/java/android/mtp/MtpObjectInfo.java b/media/java/android/mtp/MtpObjectInfo.java
index a080c73..64aa997 100644
--- a/media/java/android/mtp/MtpObjectInfo.java
+++ b/media/java/android/mtp/MtpObjectInfo.java
@@ -294,6 +294,11 @@
             mObjectInfo.mThumbPixWidth = objectInfo.mThumbPixWidth;
         }
 
+        public Builder setObjectHandle(int value) {
+            mObjectInfo.mHandle = value;
+            return this;
+        }
+
         public Builder setAssociationDesc(int value) {
             mObjectInfo.mAssociationDesc = value;
             return this;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
new file mode 100644
index 0000000..48d5dcf
--- /dev/null
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java
@@ -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.
+        }
+    }
+}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index c430def..eef173c 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -19,6 +19,7 @@
 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 @@
  * 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 @@
         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 @@
             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 @@
                     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 @@
     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 @@
             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 @@
         }
 
         boolean completed() {
-            return mNumLoaded == mDocuments.length;
+            return mNumLoaded == mObjectInfos.length;
         }
 
         int[] getUnloadedObjectHandles(int count) {
@@ -224,9 +226,9 @@
             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];
             }
         }
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
index bd0c837..ae29f52 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java
@@ -41,7 +41,7 @@
 
 
     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) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
deleted file mode 100644
index c1d9609..0000000
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
+++ /dev/null
@@ -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.
-        }
-    }
-}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index a3cf3e2..4ba0c1f 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -21,11 +21,12 @@
 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 @@
         }
         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 @@
         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);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 6647009..7cfc679 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -108,16 +108,12 @@
         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 @@
         }
     }
 
-    // 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);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index 1e015bd..a012d7f 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -18,6 +18,7 @@
 
 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 @@
 
 @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 @@
         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 @@
         }
 
         @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 @@
                     fail();
                 }
             }
-            return super.getDocument(deviceId, objectHandle);
+            return super.getObjectInfo(deviceId, objectHandle);
         }
     }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 1826bd0..47ced7a 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -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 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 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 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 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(
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index cfb8b04..53018cc 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -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 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 @@
 
         // 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);
 
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 94b5ba0..fc16fc7 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -40,7 +40,7 @@
     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 @@
         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 @@
         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);
     }
@@ -108,22 +110,13 @@
     }
 
     @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 @@
 
     @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 @@
     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 @@
     @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();
         }