TestDocumentsProviderpublic class TestDocumentsProvider extends android.provider.DocumentsProvider
Fields Summary |
---|
private static final String | TAG | private static final boolean | LAG | private static final boolean | ROOT_LAME_PROJECTION | private static final boolean | DOCUMENT_LAME_PROJECTION | private static final boolean | ROOTS_WEDGE | private static final boolean | ROOTS_CRASH | private static final boolean | ROOTS_REFRESH | private static final boolean | DOCUMENT_CRASH | private static final boolean | RECENT_WEDGE | private static final boolean | CHILD_WEDGE | private static final boolean | CHILD_CRASH | private static final boolean | THUMB_HUNDREDS | private static final boolean | THUMB_WEDGE | private static final boolean | THUMB_CRASH | private static final String | MY_ROOT_ID | private static final String | MY_DOC_ID | private static final String | MY_DOC_NULL | private static final String[] | DEFAULT_ROOT_PROJECTION | private static final String[] | DEFAULT_DOCUMENT_PROJECTION | private String | mAuthority | private WeakReference | mTaskHolds any outstanding or finished "network" fetching. |
Methods Summary |
---|
public void | attachInfo(android.content.Context context, android.content.pm.ProviderInfo info)
mAuthority = info.authority;
super.attachInfo(context, info);
| public java.lang.String | createDocument(java.lang.String parentDocumentId, java.lang.String mimeType, java.lang.String displayName)
if (LAG) lagUntilCanceled(null);
return super.createDocument(parentDocumentId, mimeType, displayName);
| private static void | includeFile(android.database.MatrixCursor result, java.lang.String docId, int flags)
final RowBuilder row = result.newRow();
row.add(Document.COLUMN_DOCUMENT_ID, docId);
row.add(Document.COLUMN_DISPLAY_NAME, docId);
row.add(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
row.add(Document.COLUMN_FLAGS, flags);
if (MY_DOC_ID.equals(docId)) {
row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
row.add(Document.COLUMN_FLAGS, Document.FLAG_DIR_SUPPORTS_CREATE);
} else if (MY_DOC_NULL.equals(docId)) {
// No MIME type
} else {
row.add(Document.COLUMN_MIME_TYPE, "application/octet-stream");
}
| private static void | lagUntilCanceled(android.os.CancellationSignal signal)
waitForCancelOrTimeout(signal, 1500);
| public boolean | onCreate()
return true;
| public android.os.ParcelFileDescriptor | openDocument(java.lang.String docId, java.lang.String mode, android.os.CancellationSignal signal)
if (LAG) lagUntilCanceled(null);
throw new FileNotFoundException();
| public android.content.res.AssetFileDescriptor | openDocumentThumbnail(java.lang.String docId, android.graphics.Point sizeHint, android.os.CancellationSignal signal)
if (LAG) lagUntilCanceled(signal);
if (THUMB_WEDGE) wedgeUntilCanceled(signal);
if (THUMB_CRASH) System.exit(12);
final Bitmap bitmap = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
final Paint paint = new Paint();
paint.setColor(Color.BLUE);
canvas.drawColor(Color.RED);
canvas.drawLine(0, 0, 32, 32, paint);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 50, bos);
final ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
try {
final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createReliablePipe();
new AsyncTask<Object, Object, Object>() {
@Override
protected Object doInBackground(Object... params) {
final FileOutputStream fos = new FileOutputStream(fds[1].getFileDescriptor());
try {
Streams.copy(bis, fos);
} catch (IOException e) {
throw new RuntimeException(e);
}
IoUtils.closeQuietly(fds[1]);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
return new AssetFileDescriptor(fds[0], 0, AssetFileDescriptor.UNKNOWN_LENGTH);
} catch (IOException e) {
throw new FileNotFoundException(e.getMessage());
}
| public android.database.Cursor | queryChildDocuments(java.lang.String parentDocumentId, java.lang.String[] projection, java.lang.String sortOrder)
if (LAG) lagUntilCanceled(null);
if (CHILD_WEDGE) SystemClock.sleep(Integer.MAX_VALUE);
if (CHILD_CRASH) System.exit(12);
final ContentResolver resolver = getContext().getContentResolver();
final Uri notifyUri = DocumentsContract.buildDocumentUri(
"com.example.documents", parentDocumentId);
CloudCursor result = new CloudCursor(resolveDocumentProjection(projection));
result.setNotificationUri(resolver, notifyUri);
// Always include local results
includeFile(result, MY_DOC_NULL, 0);
includeFile(result, "localfile1", 0);
includeFile(result, "localfile2", Document.FLAG_SUPPORTS_THUMBNAIL);
includeFile(result, "localfile3", 0);
includeFile(result, "localfile4", 0);
if (THUMB_HUNDREDS) {
for (int i = 0; i < 256; i++) {
includeFile(result, "i maded u an picshure" + i, Document.FLAG_SUPPORTS_THUMBNAIL);
}
}
synchronized (this) {
// Try picking up an existing network fetch
CloudTask task = mTask != null ? mTask.get() : null;
if (task == null) {
Log.d(TAG, "No network task found; starting!");
task = new CloudTask(resolver, notifyUri);
mTask = new WeakReference<CloudTask>(task);
new Thread(task).start();
// Aggressively try freeing weak reference above
new Thread() {
@Override
public void run() {
while (mTask.get() != null) {
SystemClock.sleep(200);
System.gc();
System.runFinalization();
}
Log.d(TAG, "AHA! THE CLOUD TASK WAS GC'ED!");
}
}.start();
}
// Blend in cloud results if ready
if (task.includeIfFinished(result)) {
result.extras.putString(DocumentsContract.EXTRA_INFO,
"Everything Went Better Than Expected and this message is quite "
+ "long and verbose and maybe even too long");
result.extras.putString(DocumentsContract.EXTRA_ERROR,
"But then again, maybe our server ran into an error, which means "
+ "we're going to have a bad time");
} else {
result.extras.putBoolean(DocumentsContract.EXTRA_LOADING, true);
}
// Tie the network fetch to the cursor GC lifetime
result.keepAlive = task;
return result;
}
| public android.database.Cursor | queryDocument(java.lang.String documentId, java.lang.String[] projection)
if (LAG) lagUntilCanceled(null);
if (DOCUMENT_CRASH) System.exit(12);
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
includeFile(result, documentId, 0);
return result;
| public android.database.Cursor | queryRecentDocuments(java.lang.String rootId, java.lang.String[] projection)
if (LAG) lagUntilCanceled(null);
if (RECENT_WEDGE) wedgeUntilCanceled(null);
// Pretend to take a super long time to respond
SystemClock.sleep(3000);
final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
includeFile(
result, "It was /worth/ the_wait for?the file:with the&incredibly long name", 0);
return result;
| public android.database.Cursor | queryRoots(java.lang.String[] projection)
Log.d(TAG, "Someone asked for our roots!");
if (LAG) lagUntilCanceled(null);
if (ROOTS_WEDGE) wedgeUntilCanceled(null);
if (ROOTS_CRASH) System.exit(12);
if (ROOTS_REFRESH) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(3000);
Log.d(TAG, "Notifying that something changed!!");
final Uri uri = DocumentsContract.buildRootsUri(mAuthority);
getContext().getContentResolver().notifyChange(uri, null, false);
return null;
}
}.execute();
}
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
final RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS | Root.FLAG_SUPPORTS_CREATE);
row.add(Root.COLUMN_TITLE, "_Test title which is really long");
row.add(Root.COLUMN_SUMMARY,
SystemClock.elapsedRealtime() + " summary which is also super long text");
row.add(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
row.add(Root.COLUMN_AVAILABLE_BYTES, 1024);
return result;
| private static java.lang.String[] | resolveDocumentProjection(java.lang.String[] projection)
if (DOCUMENT_LAME_PROJECTION) return new String[0];
return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
| private static java.lang.String[] | resolveRootProjection(java.lang.String[] projection)
if (ROOT_LAME_PROJECTION) return new String[0];
return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
| private static void | waitForCancelOrTimeout(android.os.CancellationSignal signal, long timeoutMillis)
if (signal != null) {
final Thread blocked = Thread.currentThread();
signal.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel() {
blocked.interrupt();
}
});
signal.throwIfCanceled();
}
try {
Thread.sleep(timeoutMillis);
} catch (InterruptedException e) {
}
if (signal != null) {
signal.throwIfCanceled();
}
| private static void | wedgeUntilCanceled(android.os.CancellationSignal signal)
waitForCancelOrTimeout(signal, Integer.MAX_VALUE);
|
|