diff options
| author | 2016-11-02 05:18:26 +0000 | |
|---|---|---|
| committer | 2016-11-02 05:18:29 +0000 | |
| commit | c4e678e7df54688cdcdc5fee7b58b61fd4aa2b36 (patch) | |
| tree | ded6061ccbd28f829ec3bf7e797fb5c85a11955f | |
| parent | 5974b4df49eb3c861d87962ea47580eee4beae31 (diff) | |
| parent | b9ffa2a1d2cfd0b182629c849a22f2efa832892e (diff) | |
Merge "Add findPath method to MtpDocumentsProvider."
| -rw-r--r-- | packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java | 51 | ||||
| -rw-r--r-- | packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java | 124 |
2 files changed, 169 insertions, 6 deletions
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index 1823711acd59..96f91d980b12 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -35,23 +35,21 @@ import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.os.storage.StorageManager; import android.provider.DocumentsContract.Document; +import android.provider.DocumentsContract.Path; import android.provider.DocumentsContract.Root; import android.provider.DocumentsContract; import android.provider.DocumentsProvider; import android.provider.Settings; import android.system.ErrnoException; -import android.system.Os; -import android.system.OsConstants; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import java.io.File; -import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; @@ -414,6 +412,51 @@ public class MtpDocumentsProvider extends DocumentsProvider { } } + @Override + public Path findPath(String childDocumentId, String parentDocumentId) + throws FileNotFoundException { + final LinkedList<String> ids = new LinkedList<>(); + final Identifier childIdentifier = mDatabase.createIdentifier(childDocumentId); + + Identifier i = childIdentifier; + outer: while (true) { + if (i.mDocumentId.equals(parentDocumentId)) { + ids.addFirst(i.mDocumentId); + break; + } + switch (i.mDocumentType) { + case MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT: + ids.addFirst(i.mDocumentId); + i = mDatabase.getParentIdentifier(i.mDocumentId); + break; + case MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE: { + // Check if there is the multiple storage. + final Identifier deviceIdentifier = + mDatabase.getParentIdentifier(i.mDocumentId); + final String[] storageIds = + mDatabase.getStorageDocumentIds(deviceIdentifier.mDocumentId); + // Add storage's document ID to the path only when the device has multiple + // storages. + if (storageIds.length > 1) { + ids.addFirst(i.mDocumentId); + break outer; + } + i = deviceIdentifier; + break; + } + case MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE: + ids.addFirst(i.mDocumentId); + break outer; + } + } + + if (parentDocumentId != null) { + return new Path(null, ids); + } else { + return new Path(/* Should be same with root ID */ i.mDocumentId, ids); + } + } + void openDevice(int deviceId) throws IOException { synchronized (mDeviceListLock) { if (mDeviceToolkits.containsKey(deviceId)) { diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java index 3f7e8b6d7192..a29e27d0e110 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java @@ -21,9 +21,9 @@ import android.mtp.MtpConstants; import android.mtp.MtpObjectInfo; import android.net.Uri; import android.os.ParcelFileDescriptor; -import android.os.ParcelFileDescriptor.AutoCloseOutputStream; import android.os.storage.StorageManager; import android.provider.DocumentsContract.Document; +import android.provider.DocumentsContract.Path; import android.provider.DocumentsContract.Root; import android.system.Os; import android.system.OsConstants; @@ -34,6 +34,9 @@ import android.test.suitebuilder.annotation.MediumTest; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; +import java.util.LinkedList; +import java.util.Objects; +import java.util.Queue; import java.util.concurrent.TimeoutException; import static com.android.mtp.MtpDatabase.strings; @@ -770,6 +773,64 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { assertEquals(0x400000000L, cursor.getLong(0)); } + public void testFindPath_singleStorage_toRoot() throws Exception { + setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); + setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") }); + setupHierarchyDocuments("1"); + + final Path path = mProvider.findPath("15", null); + assertEquals("1", path.getRootId()); + assertEquals(4, path.getPath().size()); + assertEquals("1", path.getPath().get(0)); + assertEquals("3", path.getPath().get(1)); + assertEquals("6", path.getPath().get(2)); + assertEquals("15", path.getPath().get(3)); + } + + public void testFindPath_singleStorage_toDoc() throws Exception { + setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); + setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") }); + setupHierarchyDocuments("1"); + + final Path path = mProvider.findPath("18", "3"); + assertNull(path.getRootId()); + assertEquals(3, path.getPath().size()); + assertEquals("3", path.getPath().get(0)); + assertEquals("7", path.getPath().get(1)); + assertEquals("18", path.getPath().get(2)); + } + + public void testFindPath_multiStorage_toRoot() throws Exception { + setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); + setupRoots(0, new MtpRoot[] { + new MtpRoot(0, 0, "Storage A", 1000, 1000, ""), + new MtpRoot(0, 1, "Storage B", 1000, 1000, "") }); + setupHierarchyDocuments("2"); + + final Path path = mProvider.findPath("16", null); + assertEquals("2", path.getRootId()); + assertEquals(4, path.getPath().size()); + assertEquals("2", path.getPath().get(0)); + assertEquals("4", path.getPath().get(1)); + assertEquals("7", path.getPath().get(2)); + assertEquals("16", path.getPath().get(3)); + } + + public void testFindPath_multiStorage_toDoc() throws Exception { + setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); + setupRoots(0, new MtpRoot[] { + new MtpRoot(0, 0, "Storage A", 1000, 1000, ""), + new MtpRoot(0, 1, "Storage B", 1000, 1000, "") }); + setupHierarchyDocuments("2"); + + final Path path = mProvider.findPath("19", "4"); + assertNull(path.getRootId()); + assertEquals(3, path.getPath().size()); + assertEquals("4", path.getPath().get(0)); + assertEquals("8", path.getPath().get(1)); + assertEquals("19", path.getPath().get(2)); + } + private void setupProvider(int flag) { mDatabase = new MtpDatabase(getContext(), flag); mProvider = new MtpDocumentsProvider(); @@ -816,11 +877,70 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { final int[] handles = new int[objects.length]; int i = 0; for (final MtpObjectInfo info : objects) { - handles[i] = info.getObjectHandle(); + 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)); } + + static class HierarchyDocument { + int depth; + String documentId; + int objectHandle; + int parentHandle; + + HierarchyDocument createChildDocument(int newHandle) { + final HierarchyDocument doc = new HierarchyDocument(); + doc.depth = depth - 1; + doc.objectHandle = newHandle; + doc.parentHandle = objectHandle; + return doc; + } + + MtpObjectInfo toObjectInfo() { + return new MtpObjectInfo.Builder() + .setName("doc_" + documentId) + .setFormat(depth > 0 ? + MtpConstants.FORMAT_ASSOCIATION : MtpConstants.FORMAT_TEXT) + .setObjectHandle(objectHandle) + .setParent(parentHandle) + .build(); + } + } + + private void setupHierarchyDocuments(String documentId) throws Exception { + final Queue<HierarchyDocument> ids = new LinkedList<>(); + final HierarchyDocument firstDocument = new HierarchyDocument(); + firstDocument.depth = 3; + firstDocument.documentId = documentId; + firstDocument.objectHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN; + ids.add(firstDocument); + + int objectHandle = 100; + while (!ids.isEmpty()) { + final HierarchyDocument document = ids.remove(); + final HierarchyDocument[] children = new HierarchyDocument[] { + document.createChildDocument(objectHandle++), + document.createChildDocument(objectHandle++), + document.createChildDocument(objectHandle++), + }; + final String[] childDocIds = setupDocuments( + 0, 0, document.objectHandle, document.documentId, new MtpObjectInfo[] { + children[0].toObjectInfo(), + children[1].toObjectInfo(), + children[2].toObjectInfo(), + }); + children[0].documentId = childDocIds[0]; + children[1].documentId = childDocIds[1]; + children[2].documentId = childDocIds[2]; + + if (children[0].depth > 0) { + ids.add(children[0]); + ids.add(children[1]); + ids.add(children[2]); + } + } + } } |