Not create document under the device.
The structure of files in MtpDocumentsProvider looks like
/device/storage/files. But MtpDocumentsProvider shows files
just under the device if the device has only single storage.
It causes a problem that MtpDocumentsProvider tries to create a file
under the device. Previously it tries to create a file with storageId =
0, which means MTP device choose a storage to store the file.
Because it only happens when the device has a single storage, the file
is properly written to the device. But the database in
MtpDocumentsProvider goes into the illegal state where the file is
placed just under the device.
Bug: 32561572
Test: adb shell am instrument -w -e class com.android.mtp.MtpDocumentsProviderTest com.android.mtp.tests/com.android.mtp.TestResultInstrumentation
Change-Id: I47a373ceee8a64ba9995934317693e79d2497ee0
(cherry picked from commit 35b2ec551f)
This commit is contained in:
@@ -349,6 +349,34 @@ public class MtpDocumentsProvider extends DocumentsProvider {
|
|||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
"Writing operation is not supported by the device.");
|
"Writing operation is not supported by the device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int parentObjectHandle;
|
||||||
|
final int storageId;
|
||||||
|
switch (parentId.mDocumentType) {
|
||||||
|
case MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE:
|
||||||
|
final String[] storageDocumentIds =
|
||||||
|
mDatabase.getStorageDocumentIds(parentId.mDocumentId);
|
||||||
|
if (storageDocumentIds.length == 1) {
|
||||||
|
final String newDocumentId =
|
||||||
|
createDocument(storageDocumentIds[0], mimeType, displayName);
|
||||||
|
notifyChildDocumentsChange(parentDocumentId);
|
||||||
|
return newDocumentId;
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Cannot create a file under the device.");
|
||||||
|
}
|
||||||
|
case MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE:
|
||||||
|
storageId = parentId.mStorageId;
|
||||||
|
parentObjectHandle = -1;
|
||||||
|
break;
|
||||||
|
case MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT:
|
||||||
|
storageId = parentId.mStorageId;
|
||||||
|
parentObjectHandle = parentId.mObjectHandle;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected document type.");
|
||||||
|
}
|
||||||
|
|
||||||
pipe = ParcelFileDescriptor.createReliablePipe();
|
pipe = ParcelFileDescriptor.createReliablePipe();
|
||||||
int objectHandle = -1;
|
int objectHandle = -1;
|
||||||
MtpObjectInfo info = null;
|
MtpObjectInfo info = null;
|
||||||
@@ -359,8 +387,8 @@ public class MtpDocumentsProvider extends DocumentsProvider {
|
|||||||
MtpConstants.FORMAT_ASSOCIATION :
|
MtpConstants.FORMAT_ASSOCIATION :
|
||||||
MediaFile.getFormatCode(displayName, mimeType);
|
MediaFile.getFormatCode(displayName, mimeType);
|
||||||
info = new MtpObjectInfo.Builder()
|
info = new MtpObjectInfo.Builder()
|
||||||
.setStorageId(parentId.mStorageId)
|
.setStorageId(storageId)
|
||||||
.setParent(parentId.mObjectHandle)
|
.setParent(parentObjectHandle)
|
||||||
.setFormat(formatCode)
|
.setFormat(formatCode)
|
||||||
.setName(displayName)
|
.setName(displayName)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
|
|||||||
public void testOpenDocument_writing() throws Exception {
|
public void testOpenDocument_writing() throws Exception {
|
||||||
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
|
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
|
||||||
setupRoots(0, new MtpRoot[] {
|
setupRoots(0, new MtpRoot[] {
|
||||||
new MtpRoot(0, 0, "Storage", 0, 0, "")
|
new MtpRoot(0, 100, "Storage", 0, 0, "")
|
||||||
});
|
});
|
||||||
final String documentId = mProvider.createDocument("2", "text/plain", "test.txt");
|
final String documentId = mProvider.createDocument("2", "text/plain", "test.txt");
|
||||||
{
|
{
|
||||||
@@ -688,6 +688,29 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCreateDocument() throws Exception {
|
||||||
|
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
|
||||||
|
setupRoots(0, new MtpRoot[] {
|
||||||
|
new MtpRoot(0, 100, "Storage A", 100, 100, null)
|
||||||
|
});
|
||||||
|
final String documentId = mProvider.createDocument("1", "text/plain", "note.txt");
|
||||||
|
final Uri deviceUri = DocumentsContract.buildChildDocumentsUri(
|
||||||
|
MtpDocumentsProvider.AUTHORITY, "1");
|
||||||
|
final Uri storageUri = DocumentsContract.buildChildDocumentsUri(
|
||||||
|
MtpDocumentsProvider.AUTHORITY, "2");
|
||||||
|
mResolver.waitForNotification(storageUri, 1);
|
||||||
|
mResolver.waitForNotification(deviceUri, 1);
|
||||||
|
try (final Cursor cursor = mProvider.queryDocument(documentId, null)) {
|
||||||
|
assertTrue(cursor.moveToNext());
|
||||||
|
assertEquals(
|
||||||
|
"note.txt",
|
||||||
|
cursor.getString(cursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME)));
|
||||||
|
assertEquals(
|
||||||
|
"text/plain",
|
||||||
|
cursor.getString(cursor.getColumnIndex(Document.COLUMN_MIME_TYPE)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testCreateDocument_noWritingSupport() throws Exception {
|
public void testCreateDocument_noWritingSupport() throws Exception {
|
||||||
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
|
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
|
||||||
mMtpManager.addValidDevice(new MtpDeviceRecord(
|
mMtpManager.addValidDevice(new MtpDeviceRecord(
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
public class TestMtpManager extends MtpManager {
|
public class TestMtpManager extends MtpManager {
|
||||||
public static final int CREATED_DOCUMENT_HANDLE = 1000;
|
public static final int CREATED_DOCUMENT_HANDLE = 1000;
|
||||||
@@ -151,6 +152,9 @@ public class TestMtpManager extends MtpManager {
|
|||||||
@Override
|
@Override
|
||||||
int createDocument(int deviceId, MtpObjectInfo objectInfo, ParcelFileDescriptor source)
|
int createDocument(int deviceId, MtpObjectInfo objectInfo, ParcelFileDescriptor source)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
Assert.assertNotSame(0, objectInfo.getStorageId());
|
||||||
|
Assert.assertNotSame(-1, objectInfo.getStorageId());
|
||||||
|
Assert.assertNotSame(0, objectInfo.getParent());
|
||||||
final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
|
final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
|
||||||
if (mObjectInfos.containsKey(key)) {
|
if (mObjectInfos.containsKey(key)) {
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
|
|||||||
Reference in New Issue
Block a user