diff options
Diffstat (limited to 'packages/MtpDocumentsProvider')
4 files changed, 120 insertions, 9 deletions
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml index 843b313db6b1..8d79f62f21d7 100644 --- a/packages/MtpDocumentsProvider/AndroidManifest.xml +++ b/packages/MtpDocumentsProvider/AndroidManifest.xml @@ -22,7 +22,6 @@ android:label="@string/downloads_app_label" android:icon="@mipmap/ic_launcher_download" android:theme="@android:style/Theme.NoDisplay" - android:screenOrientation="locked" android:excludeFromRecents="true"> <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java index 4950af3e14e0..9b5982b96e31 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java @@ -200,10 +200,7 @@ class MtpDatabase { storageCursor.close(); } - final RowBuilder row = result.newRow(); - for (final String key : values.keySet()) { - row.add(key, values.get(key)); - } + putValuesToCursor(values, result); } return result; @@ -760,7 +757,9 @@ class MtpDatabase { Document.MIME_TYPE_DIR, 0, MtpConstants.PROTECTION_STATUS_NONE, - DOCUMENT_TYPE_DEVICE)); + // Storages are placed under device so we cannot create a document just under + // device. + DOCUMENT_TYPE_DEVICE) & ~Document.FLAG_DIR_SUPPORTS_CREATE); values.putNull(Document.COLUMN_SIZE); extraValues.clear(); @@ -915,6 +914,13 @@ class MtpDatabase { return results; } + static void putValuesToCursor(ContentValues values, MatrixCursor cursor) { + final RowBuilder row = cursor.newRow(); + for (final String name : cursor.getColumnNames()) { + row.add(values.get(name)); + } + } + private static String getIdList(Set<String> ids) { String result = "("; for (final String id : ids) { diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index db88f2c038ec..eb2d8aa71955 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -17,11 +17,13 @@ package com.android.mtp; import android.content.ContentResolver; +import android.content.ContentValues; import android.content.Context; import android.content.UriPermission; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.database.Cursor; +import android.database.DatabaseUtils; import android.database.MatrixCursor; import android.database.sqlite.SQLiteDiskIOException; import android.graphics.Point; @@ -55,7 +57,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; - import libcore.io.IoUtils; /** @@ -177,7 +178,57 @@ public class MtpDocumentsProvider extends DocumentsProvider { if (projection == null) { projection = MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION; } - return mDatabase.queryDocument(documentId, projection); + final Cursor cursor = mDatabase.queryDocument(documentId, projection); + final int cursorCount = cursor.getCount(); + if (cursorCount == 0) { + cursor.close(); + throw new FileNotFoundException(); + } else if (cursorCount != 1) { + cursor.close(); + Log.wtf(TAG, "Unexpected cursor size: " + cursorCount); + return null; + } + + final Identifier identifier = mDatabase.createIdentifier(documentId); + if (identifier.mDocumentType != MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE) { + return cursor; + } + final String[] storageDocIds = mDatabase.getStorageDocumentIds(documentId); + if (storageDocIds.length != 1) { + return mDatabase.queryDocument(documentId, projection); + } + + // If the documentId specifies a device having exact one storage, we repalce some device + // attributes with the storage attributes. + try { + final String storageName; + final int storageFlags; + try (final Cursor storageCursor = mDatabase.queryDocument( + storageDocIds[0], + MtpDatabase.strings(Document.COLUMN_DISPLAY_NAME, Document.COLUMN_FLAGS))) { + if (!storageCursor.moveToNext()) { + throw new FileNotFoundException(); + } + storageName = storageCursor.getString(0); + storageFlags = storageCursor.getInt(1); + } + + cursor.moveToNext(); + final ContentValues values = new ContentValues(); + DatabaseUtils.cursorRowToContentValues(cursor, values); + if (values.containsKey(Document.COLUMN_DISPLAY_NAME)) { + values.put(Document.COLUMN_DISPLAY_NAME, mResources.getString( + R.string.root_name, + values.getAsString(Document.COLUMN_DISPLAY_NAME), + storageName)); + } + values.put(Document.COLUMN_FLAGS, storageFlags); + final MatrixCursor output = new MatrixCursor(projection, 1); + MtpDatabase.putValuesToCursor(values, output); + return output; + } finally { + cursor.close(); + } } @Override diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java index c9420d13a6e5..3fa5eb581ef7 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java @@ -368,7 +368,7 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { assertEquals(0, cursor.getInt(5)); } - public void testQueryDocument_forRoot() + public void testQueryDocument_forStorage() throws IOException, InterruptedException, TimeoutException { setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); setupRoots(0, new MtpRoot[] { @@ -392,6 +392,61 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { assertEquals(3072, cursor.getInt(5)); } + public void testQueryDocument_forDeviceWithSingleStorage() + throws IOException, InterruptedException, TimeoutException { + setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); + setupRoots(0, new MtpRoot[] { + new MtpRoot( + 0 /* deviceId */, + 1 /* storageId */, + "Storage A" /* volume description */, + 1024 /* free space */, + 4096 /* total space */, + "" /* no volume identifier */) + }); + final Cursor cursor = mProvider.queryDocument("1", null); + assertEquals(1, cursor.getCount()); + + cursor.moveToNext(); + assertEquals("1", cursor.getString(0)); + assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1)); + assertEquals("Device Storage A", cursor.getString(2)); + assertTrue(cursor.isNull(3)); + assertEquals(DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE, cursor.getInt(4)); + assertTrue(cursor.isNull(5)); + } + + public void testQueryDocument_forDeviceWithTwoStorages() + throws IOException, InterruptedException, TimeoutException { + setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); + setupRoots(0, new MtpRoot[] { + new MtpRoot( + 0 /* deviceId */, + 1 /* storageId */, + "Storage A" /* volume description */, + 1024 /* free space */, + 4096 /* total space */, + "" /* no volume identifier */), + new MtpRoot( + 0 /* deviceId */, + 2 /* storageId */, + "Storage B" /* volume description */, + 1024 /* free space */, + 4096 /* total space */, + "" /* no volume identifier */) + }); + final Cursor cursor = mProvider.queryDocument("1", null); + assertEquals(1, cursor.getCount()); + + cursor.moveToNext(); + assertEquals("1", cursor.getString(0)); + assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1)); + assertEquals("Device", cursor.getString(2)); + assertTrue(cursor.isNull(3)); + assertEquals(0, cursor.getInt(4)); + assertTrue(cursor.isNull(5)); + } + public void testQueryChildDocuments() throws Exception { setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") }); |