Get object size that is more than 4GB.

MtpObjectInfo contains object size as 32-bit integer and the provider
needs to invoke MtpDevice#getObjectSizeLong hidden API to get 64-bit
object size.

The CL switches to use MtpDevice#getObjectSizeLong hidden API if
MtpObjectInfo#getCompressedSize() returns 0xffffffffL, which means the
object size is more than 4GB.

BUG=27805369

Change-Id: I87ea02c09aa784246cf016def309d1f39ed20e90
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 68f426f..246b95de 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -20,6 +20,7 @@
 import android.annotation.WorkerThread;
 import android.content.ContentResolver;
 import android.database.Cursor;
+import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
 import android.net.Uri;
 import android.os.Bundle;
@@ -340,13 +341,46 @@
                     Log.e(MtpDocumentsProvider.TAG, "Failed to load object info", error);
                 }
             }
+            final long[] objectSizeList = new long[infoList.size()];
+            for (int i = 0; i < infoList.size(); i++) {
+                final MtpObjectInfo info = infoList.get(i);
+                // Compressed size is 32-bit unsigned integer but getCompressedSize returns the
+                // value in Java int (signed 32-bit integer). Use getCompressedSizeLong instead
+                // to get the value in Java long.
+                if (info.getCompressedSizeLong() != 0xffffffffl) {
+                    objectSizeList[i] = info.getCompressedSizeLong();
+                    continue;
+                }
+
+                if (!MtpDeviceRecord.isSupported(
+                        mOperationsSupported,
+                        MtpConstants.OPERATION_GET_OBJECT_PROP_DESC) ||
+                        !MtpDeviceRecord.isSupported(
+                                mOperationsSupported,
+                                MtpConstants.OPERATION_GET_OBJECT_PROP_VALUE)) {
+                    objectSizeList[i] = -1;
+                    continue;
+                }
+
+                // Object size is more than 4GB.
+                try {
+                    objectSizeList[i] = mManager.getObjectSizeLong(
+                            mIdentifier.mDeviceId,
+                            info.getObjectHandle(),
+                            info.getFormat());
+                } catch (IOException error) {
+                    Log.e(MtpDocumentsProvider.TAG, "Failed to get object size property.", error);
+                    objectSizeList[i] = -1;
+                }
+            }
             synchronized (this) {
                 try {
                     mDatabase.getMapper().putChildDocuments(
                             mIdentifier.mDeviceId,
                             mIdentifier.mDocumentId,
                             mOperationsSupported,
-                            infoList.toArray(new MtpObjectInfo[infoList.size()]));
+                            infoList.toArray(new MtpObjectInfo[infoList.size()]),
+                            objectSizeList);
                 } catch (FileNotFoundException error) {
                     // Looks like the parent document information is removed.
                     // Adding documents has already cancelled in Mapper so we don't need to invoke
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
index 8058183..adc71ae 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Mapper.java
@@ -128,16 +128,27 @@
      * @param deviceId Device ID
      * @param parentId Parent document ID.
      * @param documents List of document information.
+     * @param documentSizes 64-bit size of documents. MtpObjectInfo#getComporessedSize will be
+     *     ignored because it does not contain 4GB> object size. Can be -1 if the size is unknown.
      * @throws FileNotFoundException
      */
     synchronized void putChildDocuments(
-            int deviceId, String parentId, int[] operationsSupported, MtpObjectInfo[] documents)
+            int deviceId, String parentId,
+            int[] operationsSupported,
+            MtpObjectInfo[] documents,
+            long[] documentSizes)
             throws FileNotFoundException {
+        assert documents.length == documentSizes.length;
         final ContentValues[] valuesList = new ContentValues[documents.length];
         for (int i = 0; i < documents.length; i++) {
             valuesList[i] = new ContentValues();
             MtpDatabase.getObjectDocumentValues(
-                    valuesList[i], deviceId, parentId, operationsSupported, documents[i]);
+                    valuesList[i],
+                    deviceId,
+                    parentId,
+                    operationsSupported,
+                    documents[i],
+                    documentSizes[i]);
         }
         putDocuments(
                 parentId,
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 4564018..cce619e 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -372,12 +372,16 @@
      * newly added and never mapped with existing ones.
      * @param parentDocumentId
      * @param info
+     * @param size Object size. info#getCompressedSize() will be ignored because it does not contain
+     *     object size more than 4GB.
      * @return Document ID of added document.
      */
     String putNewDocument(
-            int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info) {
+            int deviceId, String parentDocumentId, int[] operationsSupported, MtpObjectInfo info,
+            long size) {
         final ContentValues values = new ContentValues();
-        getObjectDocumentValues(values, deviceId, parentDocumentId, operationsSupported, info);
+        getObjectDocumentValues(
+                values, deviceId, parentDocumentId, operationsSupported, info, size);
         mDatabase.beginTransaction();
         try {
             final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values);
@@ -586,9 +590,9 @@
     }
 
     void updateObject(String documentId, int deviceId, String parentId, int[] operationsSupported,
-                      MtpObjectInfo info) {
+                      MtpObjectInfo info, Long size) {
         final ContentValues values = new ContentValues();
-        getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info);
+        getObjectDocumentValues(values, deviceId, parentId, operationsSupported, info, size);
 
         mDatabase.beginTransaction();
         try {
@@ -811,11 +815,12 @@
      * @param values {@link ContentValues} that receives values.
      * @param deviceId Device ID of the object.
      * @param parentId Parent document ID of the object.
-     * @param info MTP object info.
+     * @param info MTP object info. getCompressedSize will be ignored.
+     * @param size 64-bit size of documents. Negative value is regarded as unknown size.
      */
     static void getObjectDocumentValues(
             ContentValues values, int deviceId, String parentId,
-            int[] operationsSupported, MtpObjectInfo info) {
+            int[] operationsSupported, MtpObjectInfo info, long size) {
         values.clear();
         final String mimeType = getMimeType(info);
         values.put(COLUMN_DEVICE_ID, deviceId);
@@ -834,7 +839,11 @@
         values.put(Document.COLUMN_FLAGS, getDocumentFlags(
                 operationsSupported, mimeType, info.getThumbCompressedSizeLong(),
                 info.getProtectionStatus(), DOCUMENT_TYPE_OBJECT));
-        values.put(Document.COLUMN_SIZE, info.getCompressedSizeLong());
+        if (size >= 0) {
+            values.put(Document.COLUMN_SIZE, size);
+        } else {
+            values.putNull(Document.COLUMN_SIZE);
+        }
     }
 
     private static String getMimeType(MtpObjectInfo info) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index cf5bee5..06ac7d3 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -30,7 +30,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
-import android.os.FileUriExposedException;
 import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
@@ -388,7 +387,7 @@
                     new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
             final String documentId = mDatabase.putNewDocument(
                     parentId.mDeviceId, parentDocumentId, record.operationsSupported,
-                    infoWithHandle);
+                    infoWithHandle, 0l);
             getDocumentLoader(parentId).clearTask(parentId);
             notifyChildDocumentsChange(parentDocumentId);
             return documentId;
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 0599b70..53873fb 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -229,6 +229,11 @@
         return device.readEvent(signal);
     }
 
+    long getObjectSizeLong(int deviceId, int objectHandle, int format) throws IOException {
+        final MtpDevice device = getDevice(deviceId);
+        return device.getObjectSizeLong(objectHandle, format);
+    }
+
     private synchronized MtpDevice getDevice(int deviceId) throws IOException {
         final MtpDevice device = mDevices.get(deviceId);
         if (device == null) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
index c10a65e..1520f3b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
@@ -174,7 +174,8 @@
                         mIdentifier.mDeviceId,
                         parentIdentifier.mDocumentId,
                         mOperationsSupported,
-                        newObjectInfo);
+                        newObjectInfo,
+                        tempFile.length());
             } catch (IOException error) {
                 Log.w(MtpDocumentsProvider.TAG,
                         "Failed to send a file because of: " + error.getMessage());
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 284223b..404047b 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -200,7 +200,7 @@
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
                 createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
-        });
+        }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
 
         final Cursor cursor = mDatabase.queryChildDocuments(COLUMN_NAMES, "2");
         assertEquals(3, cursor.getCount());
@@ -273,7 +273,7 @@
         mDatabase.getMapper().startAddingDocuments("2");
         mDatabase.getMapper().putChildDocuments(0, "2", new int[0], new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         try (final Cursor cursor =
@@ -290,7 +290,7 @@
                 MtpConstants.OPERATION_SEND_OBJECT_INFO,
         }, new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         try (final Cursor cursor =
@@ -306,7 +306,7 @@
                 MtpConstants.OPERATION_DELETE_OBJECT
         }, new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024)
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         try (final Cursor cursor =
@@ -395,7 +395,7 @@
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
                 createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
-        });
+        }, new long[] { 1024L, 2L * 1024L * 1024L, 3L * 1024L * 1024L});
         mDatabase.getMapper().clearMapping();
 
         addTestDevice();
@@ -412,7 +412,7 @@
         mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
-        });
+        }, new long[] { 1024L, 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         {
@@ -545,7 +545,7 @@
         mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
                 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
-        });
+        }, new long[] { 0L, 0L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         // Put note.txt in each directory.
@@ -553,10 +553,10 @@
         mDatabase.getMapper().startAddingDocuments("4");
         mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L });
 
         // Clear mapping.
         mDatabase.getMapper().clearMapping();
@@ -568,7 +568,7 @@
         mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(50, "A", MtpConstants.FORMAT_ASSOCIATION, 0),
                 createDocument(51, "B", MtpConstants.FORMAT_ASSOCIATION, 0),
-        });
+        }, new long[] { 0L, 0L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         // Add note.txt in each directory again.
@@ -576,10 +576,10 @@
         mDatabase.getMapper().startAddingDocuments("4");
         mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().putChildDocuments(0, "4", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().stopAddingDocuments("3");
         mDatabase.getMapper().stopAddingDocuments("4");
 
@@ -860,7 +860,7 @@
         mDatabase.getMapper().startAddingDocuments("2");
         mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         assertEquals("2", mDatabase.getParentIdentifier("3").mDocumentId);
@@ -873,13 +873,13 @@
         mDatabase.getMapper().startAddingDocuments("2");
         mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(200, "dir", MtpConstants.FORMAT_ASSOCIATION, 1024),
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         mDatabase.getMapper().startAddingDocuments("3");
         mDatabase.getMapper().putChildDocuments(0, "3", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L });
         mDatabase.getMapper().stopAddingDocuments("3");
 
         mDatabase.deleteDocument("3");
@@ -909,7 +909,8 @@
                 "3",
                 mDatabase.putNewDocument(
                         0, "2", OPERATIONS_SUPPORTED,
-                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024)));
+                        createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+                        1024L));
 
         {
             final Cursor cursor =
@@ -928,7 +929,8 @@
         mDatabase.getMapper().startAddingDocuments("2");
         mDatabase.putNewDocument(
                 0, "2", OPERATIONS_SUPPORTED,
-                createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024));
+                createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+                1024L);
         mDatabase.getMapper().stopAddingDocuments("2");
 
         {
@@ -1045,7 +1047,7 @@
         mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L, 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         // Disconnect the device.
@@ -1064,7 +1066,7 @@
         mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
                 createDocument(100, "apple.txt", MtpConstants.FORMAT_TEXT, 1024),
                 createDocument(101, "orange.txt", MtpConstants.FORMAT_TEXT, 1024),
-        });
+        }, new long[] { 1024L, 1024L });
         mDatabase.getMapper().stopAddingDocuments("2");
 
         try (final Cursor cursor = mDatabase.queryChildDocuments(
@@ -1093,7 +1095,7 @@
             createDocument(102, "unknown.mp4", MtpConstants.FORMAT_MPEG, 1000),
             createDocument(103, "inconsistent.txt", MtpConstants.FORMAT_MPEG, 1000),
             createDocument(104, "noext", MtpConstants.FORMAT_UNDEFINED, 1000),
-        });
+        }, new long[] { 1000L, 1000L, 1000L, 1000L, 1000L });
         mDatabase.getMapper().stopAddingDocuments("2");
         try (final Cursor cursor = mDatabase.queryChildDocuments(
                 strings(COLUMN_DISPLAY_NAME,  COLUMN_MIME_TYPE),
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index da6af37..0de761cb 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -708,6 +708,33 @@
         } catch (UnsupportedOperationException exception) {}
     }
 
+    public void testObjectSizeLong() throws Exception {
+        setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
+        setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
+        mMtpManager.setObjectSizeLong(0, 100, MtpConstants.FORMAT_EXIF_JPEG, 0x400000000L);
+        setupDocuments(
+                0,
+                0,
+                MtpManager.OBJECT_HANDLE_ROOT_CHILDREN,
+                "1",
+                new MtpObjectInfo[] {
+                        new MtpObjectInfo.Builder()
+                                .setObjectHandle(100)
+                                .setFormat(MtpConstants.FORMAT_EXIF_JPEG)
+                                .setName("image.jpg")
+                                .setCompressedSize(0xffffffffl)
+                                .build()
+                });
+
+        final Cursor cursor = mProvider.queryDocument("3", new String[] {
+                DocumentsContract.Document.COLUMN_SIZE
+        });
+        assertEquals(1, cursor.getCount());
+
+        cursor.moveToNext();
+        assertEquals(0x400000000L, cursor.getLong(0));
+    }
+
     private void setupProvider(int flag) {
         mDatabase = new MtpDatabase(getContext(), flag);
         mProvider = new MtpDocumentsProvider();
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index a08d9ee..8611797 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -75,7 +75,8 @@
         mDatabase.getMapper().startAddingDocuments("2");
         mDatabase.getMapper().putChildDocuments(
                 0, "2", TestUtil.OPERATIONS_SUPPORTED,
-                new MtpObjectInfo[] { info });
+                new MtpObjectInfo[] { info },
+                new long[] { 0L });
         mDatabase.getMapper().stopAddingDocuments("2");
         // Create a placeholder file which should be replaced by a real file later.
         mtpManager.setObjectInfo(0, info);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 5171bd2..9a81489 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -39,6 +39,7 @@
     private final Map<String, int[]> mObjectHandles = new HashMap<>();
     private final Map<String, byte[]> mThumbnailBytes = new HashMap<>();
     private final Map<String, byte[]> mImportFileBytes = new HashMap<>();
+    private final Map<String, Long> mObjectSizeLongs = new HashMap<>();
 
     TestMtpManager(Context context) {
         super(context);
@@ -68,6 +69,10 @@
         mThumbnailBytes.put(pack(deviceId, objectHandle), bytes);
     }
 
+    void setObjectSizeLong(int deviceId, int objectHandle, int format, long value) {
+        mObjectSizeLongs.put(pack(deviceId, objectHandle, format), value);
+    }
+
     @Override
     MtpDeviceRecord[] getDevices() {
         final MtpDeviceRecord[] result = new MtpDeviceRecord[mDevices.size()];
@@ -214,4 +219,14 @@
         }
         return i;
     }
+
+    @Override
+    long getObjectSizeLong(int deviceId, int objectHandle, int format) throws IOException {
+        final String key = pack(deviceId, objectHandle, format);
+        if (mObjectSizeLongs.containsKey(key)) {
+            return mObjectSizeLongs.get(key);
+        } else {
+            throw new IOException();
+        }
+    }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
index 5ceab01..8805d19 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestUtil.java
@@ -38,6 +38,8 @@
             MtpConstants.OPERATION_SEND_OBJECT,
             MtpConstants.OPERATION_SEND_OBJECT_INFO,
             MtpConstants.OPERATION_DELETE_OBJECT,
+            MtpConstants.OPERATION_GET_OBJECT_PROP_DESC,
+            MtpConstants.OPERATION_GET_OBJECT_PROP_VALUE
     };
 
     /**