diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java b/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java deleted file mode 100644 index 844b21685fa1a..0000000000000 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/CursorHelper.java +++ /dev/null @@ -1,91 +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.content.res.Resources; -import android.database.MatrixCursor; -import android.media.MediaFile; -import android.mtp.MtpConstants; -import android.mtp.MtpObjectInfo; -import android.provider.DocumentsContract; -import android.provider.DocumentsContract.Document; - -/** - * TODO Remove this class after we switch to use MtpDatabase. - */ -final class CursorHelper { - static final int DUMMY_HANDLE_FOR_ROOT = 0; - - private CursorHelper() { - } - - static void addToCursor(Resources resources, 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.getRootName(resources)); - 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) { - if (format == MtpConstants.FORMAT_ASSOCIATION) { - return DocumentsContract.Document.MIME_TYPE_DIR; - } else { - return MediaFile.getMimeTypeForFormatCode(format); - } - } - - static int mimeTypeToFormatType(String fileName, String mimeType) { - if (Document.MIME_TYPE_DIR.equals(mimeType)) { - return MtpConstants.FORMAT_ASSOCIATION; - } else { - return MediaFile.getFormatCode(fileName, mimeType); - } - } -} diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java index d4018e120f6bf..e4630ec4c081b 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java @@ -24,7 +24,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.Process; import android.provider.DocumentsContract; -import android.util.Log; import java.io.FileNotFoundException; import java.io.IOException; @@ -75,7 +74,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 == CursorHelper.DUMMY_HANDLE_FOR_ROOT) { + if (parentHandle == Identifier.DUMMY_HANDLE_FOR_ROOT) { parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN; } // TODO: Handle nit race around here. @@ -221,8 +220,8 @@ class DocumentLoader { throw new IOException(mError); } - final Cursor cursor = mDatabase.queryChildDocuments( - columnNames, mIdentifier.mDocumentId, /* use old ID format */ true); + final Cursor cursor = + mDatabase.queryChildDocuments(columnNames, mIdentifier.mDocumentId); cursor.setNotificationUri(resolver, createUri()); cursor.respond(extras); @@ -282,7 +281,7 @@ class DocumentLoader { private Uri createUri() { return DocumentsContract.buildChildDocumentsUri( - MtpDocumentsProvider.AUTHORITY, mIdentifier.toDocumentId()); + MtpDocumentsProvider.AUTHORITY, mIdentifier.mDocumentId); } } } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java index 4238721e12384..20b3bf5db3b7c 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/Identifier.java @@ -16,39 +16,19 @@ package com.android.mtp; +import java.util.Objects; + /** * Static utilities for ID. */ class Identifier { + final static int DUMMY_HANDLE_FOR_ROOT = 0; + final int mDeviceId; final int mStorageId; final int mObjectHandle; final String mDocumentId; - static Identifier createFromRootId(String rootId) { - final String[] components = rootId.split("_"); - return new Identifier( - Integer.parseInt(components[0]), - Integer.parseInt(components[1])); - } - - static Identifier createFromDocumentId(String documentId) { - final String[] components = documentId.split("_"); - return new Identifier( - Integer.parseInt(components[0]), - Integer.parseInt(components[1]), - Integer.parseInt(components[2])); - } - - - Identifier(int deviceId, int storageId) { - this(deviceId, storageId, CursorHelper.DUMMY_HANDLE_FOR_ROOT); - } - - Identifier(int deviceId, int storageId, int objectHandle) { - this(deviceId, storageId, objectHandle, null); - } - Identifier(int deviceId, int storageId, int objectHandle, String documentId) { mDeviceId = deviceId; mStorageId = storageId; @@ -56,16 +36,6 @@ class Identifier { mDocumentId = documentId; } - // TODO: Make the ID persistent. - String toRootId() { - return String.format("%d_%d", mDeviceId, mStorageId); - } - - // TODO: Make the ID persistent. - String toDocumentId() { - return String.format("%d_%d_%d", mDeviceId, mStorageId, mObjectHandle); - } - @Override public boolean equals(Object obj) { if (!(obj instanceof Identifier)) @@ -77,6 +47,6 @@ class Identifier { @Override public int hashCode() { - return (mDeviceId << 16) ^ (mStorageId << 8) ^ mObjectHandle; + return Objects.hash(mDeviceId, mStorageId, mObjectHandle, mDocumentId); } } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java index d535adc456a09..0272255f106a9 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java @@ -22,6 +22,8 @@ import android.content.ContentValues; import android.content.Context; import android.content.res.Resources; import android.database.Cursor; +import android.media.MediaFile; +import android.mtp.MtpConstants; import android.mtp.MtpObjectInfo; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; @@ -67,10 +69,8 @@ import java.util.Map; * the database tries to find corresponding rows by using document's name instead of MTP identifier * at the next update cycle. * - * TODO: Remove @VisibleForTesting annotation when we start to use this class. * TODO: Improve performance by SQL optimization. */ -@VisibleForTesting class MtpDatabase { private final MtpDatabaseInternal mDatabase; @@ -111,38 +111,21 @@ class MtpDatabase { /** * {@link MtpDatabaseInternal#queryChildDocuments} */ - @VisibleForTesting Cursor queryChildDocuments(String[] columnNames, String parentDocumentId) { - return queryChildDocuments(columnNames, parentDocumentId, false); - } - - @VisibleForTesting - Cursor queryChildDocuments(String[] columnNames, String parentDocumentId, boolean useOldId) { - final String[] newColumnNames = new String[columnNames.length]; - - // TODO: Temporary replace document ID with old format. - for (int i = 0; i < columnNames.length; i++) { - if (useOldId && DocumentsContract.Document.COLUMN_DOCUMENT_ID.equals(columnNames[i])) { - newColumnNames[i] = COLUMN_DEVICE_ID + " || '_' || " + COLUMN_STORAGE_ID + - " || '_' || IFNULL(" + COLUMN_OBJECT_HANDLE + ",0) AS " + - DocumentsContract.Document.COLUMN_DOCUMENT_ID; - } else { - newColumnNames[i] = columnNames[i]; - } - } - - return mDatabase.queryChildDocuments(newColumnNames, parentDocumentId); + return mDatabase.queryChildDocuments(columnNames, parentDocumentId); } /** * {@link MtpDatabaseInternal#queryDocument} */ - @VisibleForTesting Cursor queryDocument(String documentId, String[] projection) { return mDatabase.queryDocument(documentId, projection); } - Identifier createIdentifier(String parentDocumentId) { + /** + * {@link MtpDatabaseInternal#createIdentifier} + */ + Identifier createIdentifier(String parentDocumentId) throws FileNotFoundException { return mDatabase.createIdentifier(parentDocumentId); } @@ -157,7 +140,6 @@ class MtpDatabase { * {@link MtpDatabaseInternal#getParentId} * @throws FileNotFoundException */ - @VisibleForTesting String getParentId(String documentId) throws FileNotFoundException { return mDatabase.getParentId(documentId); } @@ -165,7 +147,6 @@ class MtpDatabase { /** * {@link MtpDatabaseInternal#deleteDocument} */ - @VisibleForTesting void deleteDocument(String documentId) { mDatabase.deleteDocument(documentId); } @@ -174,7 +155,6 @@ class MtpDatabase { * {@link MtpDatabaseInternal#putNewDocument} * @throws FileNotFoundException */ - @VisibleForTesting String putNewDocument(int deviceId, String parentDocumentId, MtpObjectInfo info) throws FileNotFoundException { final ContentValues values = new ContentValues(); @@ -405,7 +385,9 @@ class MtpDatabase { private void getChildDocumentValues( ContentValues values, int deviceId, String parentId, MtpObjectInfo info) { values.clear(); - final String mimeType = CursorHelper.formatTypeToMimeType(info.getFormat()); + final String mimeType = info.getFormat() == MtpConstants.FORMAT_ASSOCIATION ? + DocumentsContract.Document.MIME_TYPE_DIR : + MediaFile.getMimeTypeForFormatCode(info.getFormat()); int flag = 0; if (info.getProtectionStatus() == 0) { flag |= Document.FLAG_SUPPORTS_DELETE | diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java index 97c1d293172c7..b0286aa7fce88 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseConstants.java @@ -129,11 +129,7 @@ class MtpDatabaseConstants { Root.COLUMN_TITLE + "," + TABLE_DOCUMENTS + "." + Document.COLUMN_SUMMARY + " AS " + Root.COLUMN_SUMMARY + "," + - // Temporary replace COLUMN_DOCUMENT_ID with old format. TABLE_DOCUMENTS + "." + Document.COLUMN_DOCUMENT_ID + " AS " + - Root.COLUMN_DOCUMENT_ID + "_," + - TABLE_DOCUMENTS + "." + COLUMN_DEVICE_ID + "|| '_' ||" + - TABLE_DOCUMENTS + "." + COLUMN_STORAGE_ID + "||'_0' AS " + Root.COLUMN_DOCUMENT_ID + "," + TABLE_ROOT_EXTRA + "." + Root.COLUMN_AVAILABLE_BYTES + "," + TABLE_ROOT_EXTRA + "." + Root.COLUMN_CAPACITY_BYTES + "," + diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseInternal.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseInternal.java index 580c45e17c745..eba3aaf0eb317 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseInternal.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabaseInternal.java @@ -191,6 +191,7 @@ class MtpDatabaseInternal { String putNewDocument(String parentDocumentId, ContentValues values) { mDatabase.beginTransaction(); try { + final long id = mDatabase.insert(TABLE_DOCUMENTS, null, values); mDatabase.setTransactionSuccessful(); return Long.toString(id); @@ -203,54 +204,28 @@ class MtpDatabaseInternal { * Gets identifier from document ID. * @param documentId Document ID. * @return Identifier. + * @throws FileNotFoundException */ - Identifier createIdentifier(String documentId) { - // Currently documentId is old format. - final Identifier oldIdentifier = Identifier.createFromDocumentId(documentId); - final String selection; - final String[] args; - if (oldIdentifier.mObjectHandle == CursorHelper.DUMMY_HANDLE_FOR_ROOT) { - selection = COLUMN_DEVICE_ID + "= ? AND " + - COLUMN_ROW_STATE + " IN (?, ?) AND " + - COLUMN_STORAGE_ID + "= ? AND " + - COLUMN_PARENT_DOCUMENT_ID + " IS NULL"; - args = strings( - oldIdentifier.mDeviceId, - ROW_STATE_VALID, - ROW_STATE_INVALIDATED, - oldIdentifier.mStorageId); - } else { - selection = COLUMN_DEVICE_ID + "= ? AND " + - COLUMN_ROW_STATE + " IN (?, ?) AND " + - COLUMN_STORAGE_ID + "= ? AND " + - COLUMN_OBJECT_HANDLE + " = ?"; - args = strings( - oldIdentifier.mDeviceId, - ROW_STATE_VALID, - ROW_STATE_INVALIDATED, - oldIdentifier.mStorageId, - oldIdentifier.mObjectHandle); - } - + Identifier createIdentifier(String documentId) throws FileNotFoundException { final Cursor cursor = mDatabase.query( TABLE_DOCUMENTS, - strings(Document.COLUMN_DOCUMENT_ID), - selection, - args, + strings(COLUMN_DEVICE_ID, COLUMN_STORAGE_ID, COLUMN_OBJECT_HANDLE), + SELECTION_DOCUMENT_ID, + strings(documentId), null, null, null, "1"); try { if (cursor.getCount() == 0) { - return oldIdentifier; + throw new FileNotFoundException("ID is not found."); } else { cursor.moveToNext(); return new Identifier( - oldIdentifier.mDeviceId, - oldIdentifier.mStorageId, - oldIdentifier.mObjectHandle, - cursor.getString(0)); + cursor.getInt(0), + cursor.getInt(1), + cursor.isNull(2) ? Identifier.DUMMY_HANDLE_FOR_ROOT : cursor.getInt(2), + documentId); } } finally { cursor.close(); @@ -481,7 +456,8 @@ class MtpDatabaseInternal { void clearMapping() { mDatabase.beginTransaction(); try { - deleteDocumentsAndRootsRecursively(COLUMN_ROW_STATE + " = ?", strings(ROW_STATE_PENDING)); + deleteDocumentsAndRootsRecursively( + COLUMN_ROW_STATE + " = ?", strings(ROW_STATE_PENDING)); final ContentValues values = new ContentValues(); values.putNull(COLUMN_OBJECT_HANDLE); values.putNull(COLUMN_STORAGE_ID); @@ -571,7 +547,6 @@ class MtpDatabaseInternal { args); deleted += mDatabase.delete(TABLE_DOCUMENTS, selection, args); mDatabase.setTransactionSuccessful(); - // TODO Remove child. // TODO Remove mappingState. return deleted != 0; } finally { diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index 7c0676f23a945..743f5837cc710 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -22,6 +22,8 @@ import android.content.res.Resources; import android.database.Cursor; import android.database.MatrixCursor; import android.graphics.Point; +import android.media.MediaFile; +import android.mtp.MtpConstants; import android.mtp.MtpObjectInfo; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; @@ -116,39 +118,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { if (projection == null) { projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION; } - final Identifier identifier = Identifier.createFromDocumentId(documentId); - - if (identifier.mObjectHandle != CursorHelper.DUMMY_HANDLE_FOR_ROOT) { - MtpObjectInfo objectInfo; - try { - 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); - } 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(mResources, root, cursor.newRow()); - return cursor; - } - } - - throw new FileNotFoundException(); + return mDatabase.queryDocument(documentId, projection); } @Override @@ -170,7 +140,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { public ParcelFileDescriptor openDocument( String documentId, String mode, CancellationSignal signal) throws FileNotFoundException { - final Identifier identifier = Identifier.createFromDocumentId(documentId); + final Identifier identifier = mDatabase.createIdentifier(documentId); try { switch (mode) { case "r": @@ -195,7 +165,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { String documentId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException { - final Identifier identifier = Identifier.createFromDocumentId(documentId); + final Identifier identifier = mDatabase.createIdentifier(documentId); try { return new AssetFileDescriptor( getPipeManager(identifier).readThumbnail(mMtpManager, identifier), @@ -209,15 +179,17 @@ public class MtpDocumentsProvider extends DocumentsProvider { @Override public void deleteDocument(String documentId) throws FileNotFoundException { try { - final Identifier identifier = Identifier.createFromDocumentId(documentId); - final int parentHandle = - mMtpManager.getParent(identifier.mDeviceId, identifier.mObjectHandle); + final Identifier identifier = mDatabase.createIdentifier(documentId); + final Identifier parentIdentifier = + mDatabase.createIdentifier(mDatabase.getParentId(documentId)); mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle); - final Identifier parentIdentifier = new Identifier( - identifier.mDeviceId, identifier.mStorageId, parentHandle); + mDatabase.deleteDocument(documentId); getDocumentLoader(parentIdentifier).clearTask(parentIdentifier); - notifyChildDocumentsChange(parentIdentifier.toDocumentId()); + notifyChildDocumentsChange(parentIdentifier.mDocumentId); } catch (IOException error) { + for (final StackTraceElement element : error.getStackTrace()) { + Log.e("hirono", element.toString()); + } throw new FileNotFoundException(error.getMessage()); } } @@ -235,19 +207,23 @@ public class MtpDocumentsProvider extends DocumentsProvider { public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException { try { - final Identifier parentId = Identifier.createFromDocumentId(parentDocumentId); + final Identifier parentId = mDatabase.createIdentifier(parentDocumentId); final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe(); pipe[0].close(); // 0 bytes for a new document. - final int objectHandle = mMtpManager.createDocument( - parentId.mDeviceId, - new MtpObjectInfo.Builder() - .setStorageId(parentId.mStorageId) - .setParent(parentId.mObjectHandle) - .setFormat(CursorHelper.mimeTypeToFormatType(displayName, mimeType)) - .setName(displayName) - .build(), pipe[1]); - final String documentId = new Identifier(parentId.mDeviceId, parentId.mStorageId, - objectHandle).toDocumentId(); + final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ? + MtpConstants.FORMAT_ASSOCIATION : + MediaFile.getFormatCode(displayName, mimeType); + final MtpObjectInfo info = new MtpObjectInfo.Builder() + .setStorageId(parentId.mStorageId) + .setParent(parentId.mObjectHandle) + .setFormat(formatCode) + .setName(displayName) + .build(); + final int objectHandle = mMtpManager.createDocument(parentId.mDeviceId, info, pipe[1]); + final MtpObjectInfo infoWithHandle = + new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build(); + final String documentId = mDatabase.putNewDocument( + parentId.mDeviceId, parentDocumentId, infoWithHandle); getDocumentLoader(parentId).clearTask(parentId); notifyChildDocumentsChange(parentDocumentId); return documentId; diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java index a80eb51b43a08..394a27efec5e5 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java @@ -57,7 +57,7 @@ public class DocumentLoaderTest extends AndroidTestCase { public void testBasic() throws Exception { final Uri uri = DocumentsContract.buildChildDocumentsUri( - MtpDocumentsProvider.AUTHORITY, mParentIdentifier.toDocumentId()); + MtpDocumentsProvider.AUTHORITY, mParentIdentifier.mDocumentId); setUpDocument(mManager, 40); mManager.blockDocument(0, 15); mManager.blockDocument(0, 35); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java index e568f2bb6ccc2..08415a0214d23 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java @@ -104,7 +104,7 @@ public class MtpDatabaseTest extends AndroidTestCase { Root.COLUMN_ICON, Root.COLUMN_TITLE, Root.COLUMN_SUMMARY, - Root.COLUMN_DOCUMENT_ID + "_", + Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES, Root.COLUMN_CAPACITY_BYTES }); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java index cabb08de9a042..459496c5b1c0b 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java @@ -27,6 +27,9 @@ import android.test.suitebuilder.annotation.SmallTest; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.concurrent.TimeoutException; + +import static com.android.mtp.MtpDatabaseInternal.strings; @SmallTest public class MtpDocumentsProviderTest extends AndroidTestCase { @@ -138,7 +141,7 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { // TODO: Add storage icon for MTP devices. assertTrue(cursor.isNull(2) /* icon */); assertEquals("Device A Storage A", cursor.getString(3)); - assertEquals("0_1_0", cursor.getString(4)); + assertEquals("1", cursor.getString(4)); assertEquals(1024, cursor.getInt(5)); } @@ -154,7 +157,7 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { // TODO: Add storage icon for MTP devices. assertTrue(cursor.isNull(2) /* icon */); assertEquals("Device B Storage B", cursor.getString(3)); - assertEquals("1_1_0", cursor.getString(4)); + assertEquals("2", cursor.getString(4)); assertEquals(2048, cursor.getInt(5)); } } @@ -186,29 +189,38 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { // TODO: Add storage icon for MTP devices. assertTrue(cursor.isNull(2) /* icon */); assertEquals("Device B Storage B", cursor.getString(3)); - assertEquals("1_1_0", cursor.getString(4)); + assertEquals("1", cursor.getString(4)); assertEquals(2048, cursor.getInt(5)); } } - public void testQueryDocument() throws IOException { + public void testQueryDocument() throws IOException, InterruptedException, TimeoutException { mMtpManager.addValidDevice(0); mProvider.openDevice(0); - mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder() - .setObjectHandle(2) - .setStorageId(1) - .setFormat(MtpConstants.FORMAT_EXIF_JPEG) - .setName("image.jpg") - .setDateModified(1422716400000L) - .setCompressedSize(1024 * 1024 * 5) - .setThumbCompressedSize(1024 * 50) - .build()); - final Cursor cursor = mProvider.queryDocument("0_1_2", null); + + setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") }); + setupDocuments( + 0, + 0, + MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, + "1", + new MtpObjectInfo[] { + new MtpObjectInfo.Builder() + .setObjectHandle(100) + .setFormat(MtpConstants.FORMAT_EXIF_JPEG) + .setName("image.jpg") + .setDateModified(1422716400000L) + .setCompressedSize(1024 * 1024 * 5) + .setThumbCompressedSize(50 * 1024) + .build() + }); + + final Cursor cursor = mProvider.queryDocument("2", null); assertEquals(1, cursor.getCount()); cursor.moveToNext(); - assertEquals("0_1_2", cursor.getString(0)); + assertEquals("2", cursor.getString(0)); assertEquals("image/jpeg", cursor.getString(1)); assertEquals("image.jpg", cursor.getString(2)); assertEquals(1422716400000L, cursor.getLong(3)); @@ -220,21 +232,32 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { assertEquals(1024 * 1024 * 5, cursor.getInt(5)); } - public void testQueryDocument_directory() throws IOException { + public void testQueryDocument_directory() + throws IOException, InterruptedException, TimeoutException { mMtpManager.addValidDevice(0); mProvider.openDevice(0); - mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder() - .setObjectHandle(2) - .setStorageId(1) - .setFormat(MtpConstants.FORMAT_ASSOCIATION) - .setName("directory") - .setDateModified(1422716400000L) - .build()); - final Cursor cursor = mProvider.queryDocument("0_1_2", null); + + setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") }); + setupDocuments( + 0, + 0, + MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, + "1", + new MtpObjectInfo[] { + new MtpObjectInfo.Builder() + .setObjectHandle(2) + .setStorageId(1) + .setFormat(MtpConstants.FORMAT_ASSOCIATION) + .setName("directory") + .setDateModified(1422716400000L) + .build() + }); + + final Cursor cursor = mProvider.queryDocument("2", null); assertEquals(1, cursor.getCount()); cursor.moveToNext(); - assertEquals("0_1_2", cursor.getString(0)); + assertEquals("2", cursor.getString(0)); assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1)); assertEquals("directory", cursor.getString(2)); assertEquals(1422716400000L, cursor.getLong(3)); @@ -246,10 +269,12 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { assertEquals(0, cursor.getInt(5)); } - public void testQueryDocument_forRoot() throws IOException { + public void testQueryDocument_forRoot() + throws IOException, InterruptedException, TimeoutException { mMtpManager.addValidDevice(0); mProvider.openDevice(0); - mMtpManager.setRoots(0, new MtpRoot[] { + + setupRoots(0, new MtpRoot[] { new MtpRoot( 0 /* deviceId */, 1 /* storageId */, @@ -259,11 +284,11 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { 4096 /* total space */, "" /* no volume identifier */) }); - final Cursor cursor = mProvider.queryDocument("0_1_0", null); + final Cursor cursor = mProvider.queryDocument("1", null); assertEquals(1, cursor.getCount()); cursor.moveToNext(); - assertEquals("0_1_0", cursor.getString(0)); + assertEquals("1", cursor.getString(0)); assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1)); assertEquals("Device A Storage A", cursor.getString(2)); assertTrue(cursor.isNull(3)); @@ -274,42 +299,43 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { public void testQueryChildDocuments() throws Exception { mMtpManager.addValidDevice(0); mProvider.openDevice(0); - mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 }); - mDatabase.startAddingRootDocuments(0); - mDatabase.putRootDocuments(0, mResources, new MtpRoot[] { - new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") - }); - mDatabase.stopAddingRootDocuments(0); + setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") }); + 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(1024 * 1024 * 5) + .setThumbCompressedSize(5 * 1024) + .setProtectionStatus(MtpConstants.PROTECTION_STATUS_READ_ONLY) + .build() + }); - mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder() - .setObjectHandle(1) - .setFormat(MtpConstants.FORMAT_EXIF_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); + final Cursor cursor = mProvider.queryChildDocuments("1", null, null); assertEquals(1, cursor.getCount()); assertTrue(cursor.moveToNext()); - assertEquals("0_0_1", cursor.getString(0)); + assertEquals("2", cursor.getString(0)); assertEquals("image/jpeg", cursor.getString(1)); assertEquals("image.jpg", cursor.getString(2)); assertEquals(0, cursor.getLong(3)); assertEquals(DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4)); assertEquals(1024 * 1024 * 5, cursor.getInt(5)); - assertFalse(cursor.moveToNext()); + cursor.close(); } public void testQueryChildDocuments_cursorError() throws Exception { mMtpManager.addValidDevice(0); mProvider.openDevice(0); try { - mProvider.queryChildDocuments("0_0_0", null, null); + mProvider.queryChildDocuments("1", null, null); fail(); } catch (Throwable error) { assertTrue(error instanceof FileNotFoundException); @@ -319,42 +345,95 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { public void testQueryChildDocuments_documentError() throws Exception { mMtpManager.addValidDevice(0); mProvider.openDevice(0); + setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Device", "Storage", 1000, 1000, "") }); mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 }); try { - mProvider.queryChildDocuments("0_0_0", null, null); + mProvider.queryChildDocuments("1", null, null); fail(); } catch (Throwable error) { assertTrue(error instanceof FileNotFoundException); } } - public void testDeleteDocument() throws IOException { + public void testDeleteDocument() throws IOException, InterruptedException, TimeoutException { mMtpManager.addValidDevice(0); mProvider.openDevice(0); - mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder() - .setObjectHandle(1) - .setParent(2) - .build()); - mProvider.deleteDocument("0_0_1"); + setupRoots(0, new MtpRoot[] { + new MtpRoot(0, 0, "Device", "Storage", 0, 0, "") + }); + setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] { + new MtpObjectInfo.Builder() + .setName("test.txt") + .setObjectHandle(1) + .setParent(-1) + .build() + }); + + mProvider.deleteDocument("2"); assertEquals(1, mResolver.getChangeCount( DocumentsContract.buildChildDocumentsUri( - MtpDocumentsProvider.AUTHORITY, "0_0_2"))); + MtpDocumentsProvider.AUTHORITY, "1"))); } - public void testDeleteDocument_error() throws IOException { + public void testDeleteDocument_error() + throws IOException, InterruptedException, TimeoutException { mMtpManager.addValidDevice(0); mProvider.openDevice(0); - mMtpManager.setObjectInfo(0, new MtpObjectInfo.Builder() - .setObjectHandle(2) - .build()); + setupRoots(0, new MtpRoot[] { + new MtpRoot(0, 0, "Device", "Storage", 0, 0, "") + }); + setupDocuments(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, "1", new MtpObjectInfo[] { + new MtpObjectInfo.Builder() + .setName("test.txt") + .setObjectHandle(1) + .setParent(-1) + .build() + }); try { - mProvider.deleteDocument("0_0_1"); + mProvider.deleteDocument("3"); fail(); } catch (Throwable e) { assertTrue(e instanceof IOException); } assertEquals(0, mResolver.getChangeCount( DocumentsContract.buildChildDocumentsUri( - MtpDocumentsProvider.AUTHORITY, "0_0_2"))); + MtpDocumentsProvider.AUTHORITY, "1"))); + } + + private String[] getStrings(Cursor cursor) { + try { + final String[] results = new String[cursor.getCount()]; + for (int i = 0; cursor.moveToNext(); i++) { + results[i] = cursor.getString(0); + } + return results; + } finally { + cursor.close(); + } + } + + private String[] setupRoots(int deviceId, MtpRoot[] roots) + throws FileNotFoundException, InterruptedException, TimeoutException { + final int changeCount = mResolver.getChangeCount(ROOTS_URI); + mMtpManager.setRoots(deviceId, roots); + mResolver.waitForNotification(ROOTS_URI, changeCount + 1); + return getStrings(mProvider.queryRoots(strings(DocumentsContract.Root.COLUMN_ROOT_ID))); + } + + private String[] setupDocuments( + int deviceId, + int storageId, + int parentHandle, + String parentDocumentId, + MtpObjectInfo[] objects) throws FileNotFoundException { + final int[] handles = new int[objects.length]; + int i = 0; + for (final MtpObjectInfo info : objects) { + handles[i] = info.getObjectHandle(); + mMtpManager.setObjectInfo(deviceId, info); + } + mMtpManager.setObjectHandles(deviceId, storageId, parentHandle, handles); + return getStrings(mProvider.queryChildDocuments( + parentDocumentId, strings(DocumentsContract.Document.COLUMN_DOCUMENT_ID), null)); } } diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java index 7c947f5be1477..ccdea033ab6c3 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java @@ -44,13 +44,13 @@ public class PipeManagerTest extends AndroidTestCase { public void testReadDocument_basic() throws Exception { mtpManager.setImportFileBytes(0, 1, HELLO_BYTES); final ParcelFileDescriptor descriptor = mPipeManager.readDocument( - mtpManager, new Identifier(0, 0, 1)); + mtpManager, new Identifier(0, 0, 1, null)); assertDescriptor(descriptor, HELLO_BYTES); } public void testReadDocument_error() throws Exception { final ParcelFileDescriptor descriptor = - mPipeManager.readDocument(mtpManager, new Identifier(0, 0, 1)); + mPipeManager.readDocument(mtpManager, new Identifier(0, 0, 1, null)); assertDescriptorError(descriptor); } @@ -62,7 +62,7 @@ public class PipeManagerTest extends AndroidTestCase { // Upload testing bytes. final ParcelFileDescriptor descriptor = mPipeManager.writeDocument( - getContext(), mtpManager, new Identifier(0, 0, 1)); + getContext(), mtpManager, new Identifier(0, 0, 1, null)); final ParcelFileDescriptor.AutoCloseOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(descriptor); outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length); @@ -94,13 +94,13 @@ public class PipeManagerTest extends AndroidTestCase { public void testReadThumbnail_basic() throws Exception { mtpManager.setThumbnail(0, 1, HELLO_BYTES); final ParcelFileDescriptor descriptor = mPipeManager.readThumbnail( - mtpManager, new Identifier(0, 0, 1)); + mtpManager, new Identifier(0, 0, 1, null)); assertDescriptor(descriptor, HELLO_BYTES); } public void testReadThumbnail_error() throws Exception { final ParcelFileDescriptor descriptor = - mPipeManager.readThumbnail(mtpManager, new Identifier(0, 0, 1)); + mPipeManager.readThumbnail(mtpManager, new Identifier(0, 0, 1, null)); assertDescriptorError(descriptor); }