Add tests for copying virtual typed files.
Bug: 26147488
Change-Id: I44cfae518f4b6dfceed5b9f50b132e2acf161b3f
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index c6c1961..6a5911b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -501,16 +501,23 @@
// If the file is virtual, but can be converted to another format, then try to copy it
// as such format. Also, append an extension for the target mime type (if known).
- if (srcInfo.isVirtualDocument() && srcInfo.isTypedDocument()) {
+ if (srcInfo.isVirtualDocument()) {
+ if (!srcInfo.isTypedDocument()) {
+ // Impossible to copy a file which is virtual, but not typed.
+ mFailedFiles.add(srcInfo);
+ return false;
+ }
final String[] streamTypes = getContentResolver().getStreamTypes(
srcInfo.derivedUri, "*/*");
- if (streamTypes.length > 0) {
+ if (streamTypes != null && streamTypes.length > 0) {
dstMimeType = streamTypes[0];
final String extension = MimeTypeMap.getSingleton().
getExtensionFromMimeType(dstMimeType);
dstDisplayName = srcInfo.displayName +
(extension != null ? "." + extension : srcInfo.displayName);
} else {
+ // The provider says that it supports typed documents, but doesn't say
+ // anything about available formats.
// TODO: Log failures. b/26192412
mFailedFiles.add(srcInfo);
return false;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyServiceTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyServiceTest.java
index 079d599..24a8113 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyServiceTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyServiceTest.java
@@ -97,7 +97,7 @@
public void testCopyFile() throws Exception {
String srcPath = "/test0.txt";
- Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
+ Uri testFile = mStorage.createRegularFile(SRC_ROOT, srcPath, "text/plain",
"The five boxing wizards jump quickly".getBytes());
startService(createCopyIntent(Lists.newArrayList(testFile)));
@@ -110,10 +110,33 @@
assertCopied(srcPath);
}
+ public void testCopyVirtualTypedFile() throws Exception {
+ String srcPath = "/virtual.sth";
+ String expectedDstPath = "/virtual.sth.pdf";
+ ArrayList<String> streamTypes = new ArrayList<>();
+ streamTypes.add("application/pdf");
+ streamTypes.add("text/html");
+ String testContent = "I love fruit cakes!";
+ Uri testFile = mStorage.createVirtualFile(SRC_ROOT, srcPath, "virtual/mime-type",
+ streamTypes, testContent.getBytes());
+
+ startService(createCopyIntent(Lists.newArrayList(testFile)));
+
+ // 2 operations: file creation, then writing data.
+ mResolver.waitForChanges(2);
+
+ // Verify that one file was copied.
+ assertDestFileCount(1);
+
+ byte[] dstContent = readFile(DST_ROOT, expectedDstPath);
+ MoreAsserts.assertEquals("Moved file contents differ", testContent.getBytes(), dstContent);
+ }
+
public void testMoveFile() throws Exception {
String srcPath = "/test0.txt";
String testContent = "The five boxing wizards jump quickly";
- Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain", testContent.getBytes());
+ Uri testFile = mStorage.createRegularFile(SRC_ROOT, srcPath, "text/plain",
+ testContent.getBytes());
Intent moveIntent = createCopyIntent(Lists.newArrayList(testFile));
moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
@@ -142,9 +165,12 @@
"/test2.txt"
};
List<Uri> testFiles = Lists.newArrayList(
- mStorage.createFile(SRC_ROOT, srcPaths[0], "text/plain", testContent[0].getBytes()),
- mStorage.createFile(SRC_ROOT, srcPaths[1], "text/plain", testContent[1].getBytes()),
- mStorage.createFile(SRC_ROOT, srcPaths[2], "text/plain", testContent[2].getBytes()));
+ mStorage.createRegularFile(SRC_ROOT, srcPaths[0], "text/plain",
+ testContent[0].getBytes()),
+ mStorage.createRegularFile(SRC_ROOT, srcPaths[1], "text/plain",
+ testContent[1].getBytes()),
+ mStorage.createRegularFile(SRC_ROOT, srcPaths[2], "text/plain",
+ testContent[2].getBytes()));
// Copy all the test files.
startService(createCopyIntent(testFiles));
@@ -195,7 +221,6 @@
Intent intent = createCopyIntent(Lists.newArrayList(testDir), descDir);
startService(intent);
-
getService().addFinishedListener(mListener);
mListener.waitForFinished();
@@ -240,9 +265,9 @@
};
// Create test dir; put some files in it.
Uri testDir = createTestDirectory(srcDir);
- mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
- mStorage.createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
- mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
+ mStorage.createRegularFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
+ mStorage.createRegularFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
+ mStorage.createRegularFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
@@ -270,7 +295,7 @@
public void testCopyFileWithReadErrors() throws Exception {
String srcPath = "/test0.txt";
- Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
+ Uri testFile = mStorage.createRegularFile(SRC_ROOT, srcPath, "text/plain",
"The five boxing wizards jump quickly".getBytes());
mStorage.simulateReadErrorsForFile(testFile);
@@ -284,9 +309,26 @@
assertDestFileCount(0);
}
+ public void testCopyVirtualNonTypedFile() throws Exception {
+ String srcPath = "/non-typed.sth";
+ // Empty stream types causes the FLAG_SUPPORTS_TYPED_DOCUMENT to be not set.
+ ArrayList<String> streamTypes = new ArrayList<>();
+ Uri testFile = mStorage.createVirtualFile(SRC_ROOT, srcPath, "virtual/mime-type",
+ streamTypes, "I love Tokyo!".getBytes());
+
+ Intent intent = createCopyIntent(Lists.newArrayList(testFile));
+ startService(intent);
+ getService().addFinishedListener(mListener);
+
+ mListener.waitForFinished();
+ mListener.assertFailedCount(1);
+ mListener.assertFileFailed("non-typed.sth");
+ assertDestFileCount(0);
+ }
+
public void testMoveFileWithReadErrors() throws Exception {
String srcPath = "/test0.txt";
- Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
+ Uri testFile = mStorage.createRegularFile(SRC_ROOT, srcPath, "text/plain",
"The five boxing wizards jump quickly".getBytes());
mStorage.simulateReadErrorsForFile(testFile);
@@ -326,10 +368,10 @@
};
// Create test dir; put some files in it.
Uri testDir = createTestDirectory(srcDir);
- mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
+ mStorage.createRegularFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
Uri errFile = mStorage
- .createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
- mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
+ .createRegularFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
+ mStorage.createRegularFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
mStorage.simulateReadErrorsForFile(errFile);
@@ -363,7 +405,7 @@
}
private Uri createTestDirectory(String dir) throws IOException {
- return mStorage.createFile(
+ return mStorage.createRegularFile(
SRC_ROOT, dir, DocumentsContract.Document.MIME_TYPE_DIR, null);
}
@@ -473,6 +515,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final List<DocumentInfo> failedDocs = new ArrayList<>();
+
@Override
public void onFinished(List<DocumentInfo> failed) {
failedDocs.addAll(failed);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index bcf946e..63a519f 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -324,11 +324,11 @@
}
for (final String mimeType : document.streamTypes) {
// Strict compare won't accept wildcards, but that's OK for tests, as DocumentsUI
- // doesn't use them for openTypedDocument.
+ // doesn't use them for getStreamTypes nor openTypedDocument.
if (mimeType.equals(mimeTypeFilter)) {
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
document.file, ParcelFileDescriptor.MODE_READ_ONLY);
- if (!documentId.equals(mSimulateReadErrors)) {
+ if (documentId.equals(mSimulateReadErrors)) {
pfd = new ParcelFileDescriptor(pfd) {
@Override
public void checkError() throws IOException {
@@ -342,6 +342,23 @@
throw new IllegalArgumentException("Invalid MIME type filter for openTypedDocument().");
}
+ @Override
+ public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
+ final StubDocument document = mStorage.get(DocumentsContract.getDocumentId(uri));
+ if (document == null) {
+ throw new IllegalArgumentException(
+ "The provided Uri is incorrect, or the file is gone.");
+ }
+ if ((document.flags & Document.FLAG_SUPPORTS_TYPED_DOCUMENT) == 0) {
+ return null;
+ }
+ if (!"*/*".equals(mimeTypeFilter)) {
+ // Not used by DocumentsUI, so don't bother implementing it.
+ throw new UnsupportedOperationException();
+ }
+ return document.streamTypes.toArray(new String[document.streamTypes.size()]);
+ }
+
private ParcelFileDescriptor startWrite(final StubDocument document)
throws FileNotFoundException {
ParcelFileDescriptor[] pipe;
@@ -476,23 +493,14 @@
}
@VisibleForTesting
- public Uri createFile(String rootId, String path, String mimeType, byte[] content)
+ public File createFile(String rootId, String path, String mimeType, byte[] content)
throws FileNotFoundException, IOException {
Log.d(TAG, "Creating test file " + rootId + ":" + path);
StubDocument root = mRoots.get(rootId).document;
if (root == null) {
throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
}
- File file = new File(root.file, path.substring(1));
- StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
- if (parent == null) {
- parent = mStorage.get(createFile(rootId, file.getParentFile().getPath(),
- DocumentsContract.Document.MIME_TYPE_DIR, null));
- Log.d(TAG, "Created parent " + parent.documentId);
- } else {
- Log.d(TAG, "Found parent " + parent.documentId);
- }
-
+ final File file = new File(root.file, path.substring(1));
if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
if (!file.mkdirs()) {
throw new FileNotFoundException("Couldn't create directory " + file.getPath());
@@ -501,10 +509,20 @@
if (!file.createNewFile()) {
throw new FileNotFoundException("Couldn't create file " + file.getPath());
}
- // Add content to the file.
- FileOutputStream fout = new FileOutputStream(file);
- fout.write(content);
- fout.close();
+ try (final FileOutputStream fout = new FileOutputStream(file)) {
+ fout.write(content);
+ }
+ }
+ return file;
+ }
+
+ @VisibleForTesting
+ public Uri createRegularFile(String rootId, String path, String mimeType, byte[] content)
+ throws FileNotFoundException, IOException {
+ final File file = createFile(rootId, path, mimeType, content);
+ final StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
+ if (parent == null) {
+ throw new FileNotFoundException("Parent not found.");
}
final StubDocument document = StubDocument.createRegularDocument(file, mimeType, parent);
mStorage.put(document.documentId, document);
@@ -512,6 +530,21 @@
}
@VisibleForTesting
+ public Uri createVirtualFile(
+ String rootId, String path, String mimeType, List<String> streamTypes, byte[] content)
+ throws FileNotFoundException, IOException {
+ final File file = createFile(rootId, path, mimeType, content);
+ final StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
+ if (parent == null) {
+ throw new FileNotFoundException("Parent not found.");
+ }
+ final StubDocument document = StubDocument.createVirtualDocument(
+ file, mimeType, streamTypes, parent);
+ mStorage.put(document.documentId, document);
+ return DocumentsContract.buildDocumentUri(mAuthority, document.documentId);
+ }
+
+ @VisibleForTesting
public File getFile(String rootId, String path) throws FileNotFoundException {
StubDocument root = mRoots.get(rootId).document;
if (root == null) {