diff options
author | Ben Kwa <kenobi@google.com> | 2015-04-16 18:14:35 -0700 |
---|---|---|
committer | Ben Kwa <kenobi@google.com> | 2015-04-21 15:39:12 -0700 |
commit | 448dbbbf0e66340e262a5c163ee1829121018523 (patch) | |
tree | 60490a0b18df08c398fd8954ff798ba5ea07c98a /packages/DocumentsUI/tests | |
parent | 5c1e306502a77d354def3d426dabdacea8cc4055 (diff) | |
download | frameworks_base-448dbbbf0e66340e262a5c163ee1829121018523.zip frameworks_base-448dbbbf0e66340e262a5c163ee1829121018523.tar.gz frameworks_base-448dbbbf0e66340e262a5c163ee1829121018523.tar.bz2 |
Implement some tests for com.android.documentsui.CopyService.
- Add a unit test for CopyService.
- Make some changes to StubProvider to make it more configurable, for
testing.
Change-Id: I3d726099feaf6b7a3fdd40bf2449f4ee3e848d77
Diffstat (limited to 'packages/DocumentsUI/tests')
3 files changed, 482 insertions, 60 deletions
diff --git a/packages/DocumentsUI/tests/Android.mk b/packages/DocumentsUI/tests/Android.mk index fdf4fab..3f191a9 100644 --- a/packages/DocumentsUI/tests/Android.mk +++ b/packages/DocumentsUI/tests/Android.mk @@ -7,6 +7,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_JAVA_LIBRARIES := android.test.runner +LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target guava LOCAL_PACKAGE_NAME := DocumentsUITests LOCAL_INSTRUMENTATION_FOR := DocumentsUI diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java new file mode 100644 index 0000000..13f7daa --- /dev/null +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java @@ -0,0 +1,281 @@ +/* + * 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.documentsui; + +import static com.android.documentsui.model.DocumentInfo.getCursorString; + +import android.app.NotificationManager; +import android.content.ContentProviderClient; +import android.content.ContentResolver; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; +import android.os.RemoteException; +import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Document; +import android.test.MoreAsserts; +import android.test.ServiceTestCase; +import android.util.Log; + +import com.android.documentsui.model.DocumentInfo; +import com.android.documentsui.model.DocumentStack; +import com.android.documentsui.model.RootInfo; +import com.google.common.collect.Lists; + +import libcore.io.IoUtils; +import libcore.io.Streams; + +import org.mockito.Mockito; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CopyTest extends ServiceTestCase<CopyService> { + + public CopyTest() { + super(CopyService.class); + } + + private static String TAG = "CopyTest"; + // This must match the authority for the StubProvider. + private static String AUTHORITY = "com.android.documentsui.stubprovider"; + private List<RootInfo> mRoots; + private Context mContext; + private ContentResolver mResolver; + private ContentProviderClient mClient; + private NotificationManager mNotificationManager; + + @Override + protected void setUp() throws Exception { + super.setUp(); + setupTestContext(); + + mResolver = mContext.getContentResolver(); + mClient = mResolver.acquireContentProviderClient(AUTHORITY); + + // Reset the stub provider's storage. + mClient.call("clear", "", null); + + mRoots = Lists.newArrayList(); + Uri queryUri = DocumentsContract.buildRootsUri(AUTHORITY); + Cursor cursor = null; + try { + cursor = mClient.query(queryUri, null, null, null, null); + while (cursor.moveToNext()) { + final RootInfo root = RootInfo.fromRootsCursor(AUTHORITY, cursor); + final String id = root.rootId; + mRoots.add(root); + } + } finally { + IoUtils.closeQuietly(cursor); + } + + } + + @Override + protected void tearDown() throws Exception { + mClient.release(); + super.tearDown(); + } + + public List<Uri> setupTestFiles() throws Exception { + Uri rootUri = DocumentsContract.buildDocumentUri(AUTHORITY, mRoots.get(0).documentId); + List<Uri> testFiles = Lists.newArrayList( + DocumentsContract.createDocument(mClient, rootUri, "text/plain", "test0.txt"), + DocumentsContract.createDocument(mClient, rootUri, "text/plain", "test1.txt"), + DocumentsContract.createDocument(mClient, rootUri, "text/plain", "test2.txt") + ); + String testContent[] = { + "The five boxing wizards jump quickly", + "The quick brown fox jumps over the lazy dog", + "Jackdaws love my big sphinx of quartz" + }; + for (int i = 0; i < testFiles.size(); ++i) { + ParcelFileDescriptor pfd = null; + OutputStream out = null; + try { + pfd = mClient.openFile(testFiles.get(i), "w"); + out = new ParcelFileDescriptor.AutoCloseOutputStream(pfd); + out.write(testContent[i].getBytes()); + } finally { + IoUtils.closeQuietly(out); + } + } + return testFiles; + } + + /** + * Test copying a single file. + */ + public void testCopyFile() throws Exception { + Uri testFile = setupTestFiles().get(0); + + // Just copy one file. + copyToDestination(Lists.newArrayList(testFile)); + + // A call to NotificationManager.cancel marks the end of the copy operation. + Mockito.verify(mNotificationManager, Mockito.timeout(1000)).cancel(Mockito.anyString(), + Mockito.anyInt()); + + // Verify that one file was copied; check file contents. + assertDstFileCountEquals(1); + assertCopied(testFile); + } + + /** + * Test copying multiple files. + */ + public void testCopyMultipleFiles() throws Exception { + List<Uri> testFiles = setupTestFiles(); + // Copy all the test files. + copyToDestination(testFiles); + + // A call to NotificationManager.cancel marks the end of the copy operation. + Mockito.verify(mNotificationManager, Mockito.timeout(1000)).cancel(Mockito.anyString(), + Mockito.anyInt()); + + assertDstFileCountEquals(3); + for (Uri testFile : testFiles) { + assertCopied(testFile); + } + } + + /** + * Copies the given files to a pre-determined destination. + * + * @throws FileNotFoundException + */ + private void copyToDestination(List<Uri> srcs) throws FileNotFoundException { + final ArrayList<DocumentInfo> srcDocs = Lists.newArrayList(); + for (Uri src : srcs) { + srcDocs.add(DocumentInfo.fromUri(mResolver, src)); + } + + final Uri dst = DocumentsContract.buildDocumentUri(AUTHORITY, mRoots.get(1).documentId); + DocumentStack stack = new DocumentStack(); + stack.push(DocumentInfo.fromUri(mResolver, dst)); + final Intent copyIntent = new Intent(mContext, CopyService.class); + copyIntent.putParcelableArrayListExtra(CopyService.EXTRA_SRC_LIST, srcDocs); + copyIntent.putExtra(CopyService.EXTRA_STACK, (Parcelable) stack); + + startService(copyIntent); + } + + /** + * Returns a count of the files in the given directory. + */ + private void assertDstFileCountEquals(int expected) throws RemoteException { + final Uri queryUri = DocumentsContract.buildChildDocumentsUri(AUTHORITY, + mRoots.get(1).documentId); + Cursor c = null; + int count = 0; + try { + c = mClient.query(queryUri, null, null, null, null); + count = c.getCount(); + } finally { + IoUtils.closeQuietly(c); + } + assertEquals("Incorrect file count after copy", expected, count); + } + + /** + * Verifies that the file pointed to by the given URI was correctly copied to the destination. + */ + private void assertCopied(Uri src) throws Exception { + Cursor cursor = null; + String srcName = null; + try { + cursor = mClient.query(src, null, null, null, null); + if (cursor.moveToFirst()) { + srcName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME); + } + } finally { + IoUtils.closeQuietly(cursor); + } + Uri dst = getDstFileUri(srcName); + + InputStream in0 = null; + InputStream in1 = null; + try { + in0 = new ParcelFileDescriptor.AutoCloseInputStream(mClient.openFile(src, "r")); + in1 = new ParcelFileDescriptor.AutoCloseInputStream(mClient.openFile(dst, "r")); + + byte[] buffer0 = Streams.readFully(in0); + byte[] buffer1 = Streams.readFully(in1); + + MoreAsserts.assertEquals(buffer0, buffer1); + } finally { + IoUtils.closeQuietly(in0); + IoUtils.closeQuietly(in1); + } + } + + /** + * Generates a file URI from a given filename. This assumes the file already exists in the + * destination root. + */ + private Uri getDstFileUri(String filename) throws RemoteException { + final Uri dstFileQuery = DocumentsContract.buildChildDocumentsUri(AUTHORITY, + mRoots.get(1).documentId); + Cursor cursor = null; + try { + // StubProvider doesn't seem to support query strings; filter the results manually. + cursor = mClient.query(dstFileQuery, null, null, null, null); + while (cursor.moveToNext()) { + if (filename.equals(getCursorString(cursor, Document.COLUMN_DISPLAY_NAME))) { + return DocumentsContract.buildDocumentUri(AUTHORITY, + getCursorString(cursor, Document.COLUMN_DOCUMENT_ID)); + } + } + } finally { + IoUtils.closeQuietly(cursor); + } + return null; + } + + /** + * Sets up a ContextWrapper that substitutes a stub NotificationManager. This allows the test to + * listen for notification events, to gauge copy progress. + */ + private void setupTestContext() { + mContext = getSystemContext(); + System.setProperty("dexmaker.dexcache", mContext.getCacheDir().getPath()); + + mNotificationManager = Mockito.spy((NotificationManager) mContext + .getSystemService(Context.NOTIFICATION_SERVICE)); + + // Insert a stub NotificationManager that enables us to listen for when copying is complete. + setContext(new ContextWrapper(mContext) { + @Override + public Object getSystemService(String name) { + if (Context.NOTIFICATION_SERVICE.equals(name)) { + return mNotificationManager; + } else { + return super.getSystemService(name); + } + } + }); + } +} diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java index 75effa7..438f6cd 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java @@ -17,34 +17,45 @@ package com.android.documentsui; import android.content.Context; +import android.content.SharedPreferences; import android.content.pm.ProviderInfo; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.MatrixCursor.RowBuilder; import android.database.MatrixCursor; import android.graphics.Point; +import android.os.Bundle; import android.os.CancellationSignal; import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; import android.provider.DocumentsContract.Root; -import android.provider.DocumentsContract.Root; import android.provider.DocumentsProvider; +import android.util.Log; + +import com.google.android.collect.Maps; + +import libcore.io.IoUtils; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; -import java.util.List; +import java.util.Map; public class StubProvider extends DocumentsProvider { - private static int STORAGE_SIZE = 1024 * 1024; // 1 MB. + private static final String EXTRA_SIZE = "com.android.documentsui.stubprovider.SIZE"; + private static final String EXTRA_ROOT = "com.android.documentsui.stubprovider.ROOT"; + private static final String STORAGE_SIZE_KEY = "documentsui.stubprovider.size"; + private static int DEFAULT_SIZE = 1024 * 1024; // 1 MB. private static final String TAG = "StubProvider"; - private static final String MY_ROOT_ID = "myRoot"; - + private static final String MY_ROOT_ID = "sd0"; private static final String[] DEFAULT_ROOT_PROJECTION = new String[] { Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES @@ -54,11 +65,11 @@ public class StubProvider extends DocumentsProvider { Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE, }; - private String mRootDocumentId; private HashMap<String, StubDocument> mStorage = new HashMap<String, StubDocument>(); - private int mStorageUsedBytes; private Object mWriteLock = new Object(); private String mAuthority; + private SharedPreferences mPrefs; + private Map<String, RootInfo> mRoots; @Override public void attachInfo(Context context, ProviderInfo info) { @@ -68,29 +79,61 @@ public class StubProvider extends DocumentsProvider { @Override public boolean onCreate() { + clearCacheAndBuildRoots(); + return true; + } + + private void clearCacheAndBuildRoots() { final File cacheDir = getContext().getCacheDir(); removeRecursively(cacheDir); - final StubDocument document = new StubDocument(cacheDir, Document.MIME_TYPE_DIR, null); - mRootDocumentId = document.documentId; - mStorage.put(mRootDocumentId, document); - return true; + mStorage.clear(); + + mPrefs = getContext().getSharedPreferences( + "com.android.documentsui.stubprovider.preferences", Context.MODE_PRIVATE); + Collection<String> rootIds = mPrefs.getStringSet("roots", null); + if (rootIds == null) { + rootIds = Arrays.asList(new String[] { + "sd0", "sd1" + }); + } + // Create new roots. + mRoots = Maps.newHashMap(); + for (String rootId : rootIds) { + final RootInfo rootInfo = new RootInfo(rootId, getSize(rootId)); + mRoots.put(rootId, rootInfo); + } + } + + /** + * @return Storage size, in bytes. + */ + private long getSize(String rootId) { + final String key = STORAGE_SIZE_KEY + "." + rootId; + return mPrefs.getLong(key, DEFAULT_SIZE); } @Override public Cursor queryRoots(String[] projection) throws FileNotFoundException { - final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION); - final RowBuilder row = result.newRow(); - row.add(Root.COLUMN_ROOT_ID, MY_ROOT_ID); - row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD); - row.add(Root.COLUMN_TITLE, "Foobar SD 4GB"); - row.add(Root.COLUMN_DOCUMENT_ID, mRootDocumentId); - row.add(Root.COLUMN_AVAILABLE_BYTES, STORAGE_SIZE - mStorageUsedBytes); + final MatrixCursor result = new MatrixCursor(projection != null ? projection + : DEFAULT_ROOT_PROJECTION); + for (Map.Entry<String, RootInfo> entry : mRoots.entrySet()) { + final String id = entry.getKey(); + final RootInfo info = entry.getValue(); + final RowBuilder row = result.newRow(); + row.add(Root.COLUMN_ROOT_ID, id); + row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD); + row.add(Root.COLUMN_TITLE, id); + row.add(Root.COLUMN_DOCUMENT_ID, info.rootDocument.documentId); + row.add(Root.COLUMN_AVAILABLE_BYTES, info.getRemainingCapacity()); + } return result; } @Override - public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException { - final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION); + public Cursor queryDocument(String documentId, String[] projection) + throws FileNotFoundException { + final MatrixCursor result = new MatrixCursor(projection != null ? projection + : DEFAULT_DOCUMENT_PROJECTION); final StubDocument file = mStorage.get(documentId); if (file == null) { throw new FileNotFoundException(); @@ -123,14 +166,12 @@ public class StubProvider extends DocumentsProvider { if (!file.createNewFile()) { throw new FileNotFoundException(); } - } - catch (IOException e) { + } catch (IOException e) { throw new FileNotFoundException(); } } final StubDocument document = new StubDocument(file, mimeType, parentDocument); - mStorage.put(document.documentId, document); notifyParentChanged(document.parentId); return document.documentId; } @@ -143,7 +184,7 @@ public class StubProvider extends DocumentsProvider { if (document == null || !document.file.delete()) throw new FileNotFoundException(); synchronized (mWriteLock) { - mStorageUsedBytes -= fileSize; + document.rootInfo.size -= fileSize; } notifyParentChanged(document.parentId); } @@ -155,12 +196,13 @@ public class StubProvider extends DocumentsProvider { if (parentDocument == null || parentDocument.file.isFile()) { throw new FileNotFoundException(); } - final MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION); + final MatrixCursor result = new MatrixCursor(projection != null ? projection + : DEFAULT_DOCUMENT_PROJECTION); result.setNotificationUri(getContext().getContentResolver(), DocumentsContract.buildChildDocumentsUri(mAuthority, parentDocumentId)); StubDocument document; for (File file : parentDocument.file.listFiles()) { - document = mStorage.get(StubDocument.getDocumentIdForFile(file)); + document = mStorage.get(getDocumentIdForFile(file)); if (document != null) { includeDocument(result, document); } @@ -171,7 +213,9 @@ public class StubProvider extends DocumentsProvider { @Override public Cursor queryRecentDocuments(String rootId, String[] projection) throws FileNotFoundException { - throw new FileNotFoundException(); + final MatrixCursor result = new MatrixCursor(projection != null ? projection + : DEFAULT_DOCUMENT_PROJECTION); + return result; } @Override @@ -202,8 +246,7 @@ public class StubProvider extends DocumentsProvider { ParcelFileDescriptor[] pipe; try { pipe = ParcelFileDescriptor.createReliablePipe(); - } - catch (IOException exception) { + } catch (IOException exception) { throw new FileNotFoundException(); } final ParcelFileDescriptor readPipe = pipe[0]; @@ -212,15 +255,19 @@ public class StubProvider extends DocumentsProvider { new Thread() { @Override public void run() { + InputStream inputStream = null; + OutputStream outputStream = null; try { - final FileInputStream inputStream = new FileInputStream(readPipe.getFileDescriptor()); - final FileOutputStream outputStream = new FileOutputStream(document.file); + inputStream = new ParcelFileDescriptor.AutoCloseInputStream(readPipe); + outputStream = new FileOutputStream(document.file); byte[] buffer = new byte[32 * 1024]; int bytesToRead; int bytesRead = 0; while (bytesRead != -1) { synchronized (mWriteLock) { - bytesToRead = Math.min(STORAGE_SIZE - mStorageUsedBytes, buffer.length); + // This cast is safe because the max possible value is buffer.length. + bytesToRead = (int) Math.min(document.rootInfo.getRemainingCapacity(), + buffer.length); if (bytesToRead == 0) { closePipeWithErrorSilently(readPipe, "Not enough space."); break; @@ -230,15 +277,14 @@ public class StubProvider extends DocumentsProvider { break; } outputStream.write(buffer, 0, bytesRead); - mStorageUsedBytes += bytesRead; + document.rootInfo.size += bytesRead; } } - } - catch (IOException e) { + } catch (IOException e) { closePipeWithErrorSilently(readPipe, e.getMessage()); - } - finally { - closePipeSilently(readPipe); + } finally { + IoUtils.closeQuietly(inputStream); + IoUtils.closeQuietly(outputStream); notifyParentChanged(document.parentId); } } @@ -250,24 +296,38 @@ public class StubProvider extends DocumentsProvider { private void closePipeWithErrorSilently(ParcelFileDescriptor pipe, String error) { try { pipe.closeWithError(error); - } - catch (IOException ignore) { + } catch (IOException ignore) { } } - private void closePipeSilently(ParcelFileDescriptor pipe) { - try { - pipe.close(); - } - catch (IOException ignore) { + @Override + public Bundle call(String method, String arg, Bundle extras) { + Log.d(TAG, "call: " + method + arg); + switch (method) { + case "clear": + clearCacheAndBuildRoots(); + return null; + case "configure": + configure(arg, extras); + return null; + default: + return super.call(method, arg, extras); } } + private void configure(String arg, Bundle extras) { + Log.d(TAG, "Configure " + arg); + String rootName = extras.getString(EXTRA_ROOT, MY_ROOT_ID); + long rootSize = extras.getLong(EXTRA_SIZE, 1) * 1024 * 1024; + setSize(rootName, rootSize); + } + private void notifyParentChanged(String parentId) { getContext().getContentResolver().notifyChange( DocumentsContract.buildChildDocumentsUri(mAuthority, parentId), null, false); // Notify also about possible change in remaining space on the root. - getContext().getContentResolver().notifyChange(DocumentsContract.buildRootsUri(mAuthority), null, false); + getContext().getContentResolver().notifyChange(DocumentsContract.buildRootsUri(mAuthority), + null, false); } private void includeDocument(MatrixCursor result, StubDocument document) { @@ -295,22 +355,102 @@ public class StubProvider extends DocumentsProvider { childFile.delete(); } } -} -class StubDocument { - public final File file; - public final String mimeType; - public final String documentId; - public final String parentId; - - StubDocument(File file, String mimeType, StubDocument parent) { - this.file = file; - this.mimeType = mimeType; - this.documentId = getDocumentIdForFile(file); - this.parentId = parent != null ? parent.documentId : null; + public void setSize(String rootId, long rootSize) { + RootInfo root = mRoots.get(rootId); + if (root != null) { + final String key = STORAGE_SIZE_KEY + "." + rootId; + Log.d(TAG, "Set size of " + key + " : " + rootSize); + + // Persist the size. + SharedPreferences.Editor editor = mPrefs.edit(); + editor.putLong(key, rootSize); + editor.apply(); + // Apply the size in the current instance of this provider. + root.capacity = rootSize; + getContext().getContentResolver().notifyChange( + DocumentsContract.buildRootsUri(mAuthority), + null, false); + } else { + Log.e(TAG, "Attempt to configure non-existent root: " + rootId); + } + } + + public File createFile(String rootId, File parent, String mimeType, String name) + throws IOException { + StubDocument parentDoc = null; + if (parent == null) { + // Use the root dir as the parent, if one wasn't specified. + parentDoc = mRoots.get(rootId).rootDocument; + } else { + // Verify that the parent exists and is a directory. + parentDoc = mStorage.get(getDocumentIdForFile(parent)); + if (parentDoc == null) { + throw new IllegalArgumentException("Parent file not found."); + } + if (!Document.MIME_TYPE_DIR.equals(parentDoc.mimeType)) { + throw new IllegalArgumentException("Parent file must be a directory."); + } + } + File file = new File(parentDoc.file, name); + if (Document.MIME_TYPE_DIR.equals(mimeType)) { + file.mkdir(); + } else { + file.createNewFile(); + } + new StubDocument(file, mimeType, parentDoc); + return file; + } + + final class RootInfo { + public final String name; + public final StubDocument rootDocument; + public long capacity; + public long size; + + RootInfo(String name, long capacity) { + this.name = name; + this.capacity = 1024 * 1024; + // Make a subdir in the cache dir for each root. + File rootDir = new File(getContext().getCacheDir(), name); + rootDir.mkdir(); + this.rootDocument = new StubDocument(rootDir, Document.MIME_TYPE_DIR, this); + this.capacity = capacity; + this.size = 0; + } + + public long getRemainingCapacity() { + return capacity - size; + } + } + + final class StubDocument { + public final File file; + public final String mimeType; + public final String documentId; + public final String parentId; + public final RootInfo rootInfo; + + StubDocument(File file, String mimeType, StubDocument parent) { + this.file = file; + this.mimeType = mimeType; + this.documentId = getDocumentIdForFile(file); + this.parentId = parent.documentId; + this.rootInfo = parent.rootInfo; + mStorage.put(this.documentId, this); + } + + StubDocument(File file, String mimeType, RootInfo rootInfo) { + this.file = file; + this.mimeType = mimeType; + this.documentId = getDocumentIdForFile(file); + this.parentId = null; + this.rootInfo = rootInfo; + mStorage.put(this.documentId, this); + } } - public static String getDocumentIdForFile(File file) { + private static String getDocumentIdForFile(File file) { return file.getAbsolutePath(); } } |