Loading src/com/android/documentsui/archives/ArchivesProvider.java +43 −8 Original line number Diff line number Diff line Loading @@ -21,10 +21,11 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.database.ContentObserver; import android.database.Cursor; import android.database.MatrixCursor; import android.database.MatrixCursor.RowBuilder; import android.database.MatrixCursor; import android.graphics.Point; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract.Document; Loading @@ -44,6 +45,8 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; Loading Loading @@ -95,9 +98,23 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { public Cursor queryChildDocuments(String documentId, @Nullable String[] projection, @Nullable String sortOrder) throws FileNotFoundException { final ArchiveId archiveId = ArchiveId.fromDocumentId(documentId); Loader loader = null; try { loader = obtainInstance(documentId); if (loader.mArchive == null) { final MatrixCursor cursor = new MatrixCursor( projection != null ? projection : Archive.DEFAULT_PROJECTION); // Return an empty cursor with EXTRA_LOADING, which shows spinner // in DocumentsUI. Once the archive is loaded, the notification will // be sent, and the directory reloaded. final Bundle bundle = new Bundle(); bundle.putBoolean(DocumentsContract.EXTRA_LOADING, true); cursor.setExtras(bundle); cursor.setNotificationUri(getContext().getContentResolver(), buildUriForArchive(archiveId.mArchiveUri)); return cursor; } return loader.get().queryChildDocuments(documentId, projection, sortOrder); } finally { releaseInstance(loader); Loading Loading @@ -138,16 +155,11 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { throws FileNotFoundException { final ArchiveId archiveId = ArchiveId.fromDocumentId(documentId); if (archiveId.mPath.equals("/")) { // For the archive's root directory return hard-coded cursor, so clients know that // it's actually a directory and queryChildDocuments() can be called on it. // // TODO: Move this code to the Archive class, once opening archives is moved to // background. final MatrixCursor cursor = new MatrixCursor( projection != null ? projection : Archive.DEFAULT_PROJECTION); final RowBuilder row = cursor.newRow(); row.add(Document.COLUMN_DOCUMENT_ID, documentId); row.add(Document.COLUMN_DISPLAY_NAME, "Archive"); // TODO: Fix. row.add(Document.COLUMN_DISPLAY_NAME, "Archive"); // TODO: Translate. row.add(Document.COLUMN_SIZE, 0); row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR); return cursor; Loading Loading @@ -278,12 +290,17 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { private final Uri mArchiveUri; private final Uri mNotificationUri; private final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock(); private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); private Archive mArchive = null; private Exception mFailureException = null; Loader(Context context, Uri archiveUri, Uri notificationUri) { this.mContext = context; this.mArchiveUri = archiveUri; this.mNotificationUri = notificationUri; // Start loading the archive immediately in the background. mExecutor.submit(this::get); } synchronized Archive get() throws FileNotFoundException { Loading @@ -291,6 +308,15 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { return mArchive; } // Once loading the archive failed, do not to retry opening it until the // archive file has changed (the loader is deleted once we receive // a notification about the archive file being changed). if (mFailureException != null) { throw new IllegalStateException( "Trying to perform an operation on an archive which failed to load.", mFailureException); } try { mArchive = Archive.createForParcelFileDescriptor( mContext, Loading @@ -298,9 +324,18 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { mArchiveUri, "r", null /* signal */), mArchiveUri, mNotificationUri); } catch (IOException e) { mFailureException = e; throw new IllegalStateException(e); } catch (RuntimeException e) { mFailureException = e; throw e; } finally { // Notify observers that the root directory is loaded (or failed) // so clients reload it. mContext.getContentResolver().notifyChange( buildUriForArchive(mArchiveUri), null /* observer */, false /* syncToNetwork */); } return mArchive; } Loading Loading
src/com/android/documentsui/archives/ArchivesProvider.java +43 −8 Original line number Diff line number Diff line Loading @@ -21,10 +21,11 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; import android.database.ContentObserver; import android.database.Cursor; import android.database.MatrixCursor; import android.database.MatrixCursor.RowBuilder; import android.database.MatrixCursor; import android.graphics.Point; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract.Document; Loading @@ -44,6 +45,8 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; Loading Loading @@ -95,9 +98,23 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { public Cursor queryChildDocuments(String documentId, @Nullable String[] projection, @Nullable String sortOrder) throws FileNotFoundException { final ArchiveId archiveId = ArchiveId.fromDocumentId(documentId); Loader loader = null; try { loader = obtainInstance(documentId); if (loader.mArchive == null) { final MatrixCursor cursor = new MatrixCursor( projection != null ? projection : Archive.DEFAULT_PROJECTION); // Return an empty cursor with EXTRA_LOADING, which shows spinner // in DocumentsUI. Once the archive is loaded, the notification will // be sent, and the directory reloaded. final Bundle bundle = new Bundle(); bundle.putBoolean(DocumentsContract.EXTRA_LOADING, true); cursor.setExtras(bundle); cursor.setNotificationUri(getContext().getContentResolver(), buildUriForArchive(archiveId.mArchiveUri)); return cursor; } return loader.get().queryChildDocuments(documentId, projection, sortOrder); } finally { releaseInstance(loader); Loading Loading @@ -138,16 +155,11 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { throws FileNotFoundException { final ArchiveId archiveId = ArchiveId.fromDocumentId(documentId); if (archiveId.mPath.equals("/")) { // For the archive's root directory return hard-coded cursor, so clients know that // it's actually a directory and queryChildDocuments() can be called on it. // // TODO: Move this code to the Archive class, once opening archives is moved to // background. final MatrixCursor cursor = new MatrixCursor( projection != null ? projection : Archive.DEFAULT_PROJECTION); final RowBuilder row = cursor.newRow(); row.add(Document.COLUMN_DOCUMENT_ID, documentId); row.add(Document.COLUMN_DISPLAY_NAME, "Archive"); // TODO: Fix. row.add(Document.COLUMN_DISPLAY_NAME, "Archive"); // TODO: Translate. row.add(Document.COLUMN_SIZE, 0); row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR); return cursor; Loading Loading @@ -278,12 +290,17 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { private final Uri mArchiveUri; private final Uri mNotificationUri; private final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock(); private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); private Archive mArchive = null; private Exception mFailureException = null; Loader(Context context, Uri archiveUri, Uri notificationUri) { this.mContext = context; this.mArchiveUri = archiveUri; this.mNotificationUri = notificationUri; // Start loading the archive immediately in the background. mExecutor.submit(this::get); } synchronized Archive get() throws FileNotFoundException { Loading @@ -291,6 +308,15 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { return mArchive; } // Once loading the archive failed, do not to retry opening it until the // archive file has changed (the loader is deleted once we receive // a notification about the archive file being changed). if (mFailureException != null) { throw new IllegalStateException( "Trying to perform an operation on an archive which failed to load.", mFailureException); } try { mArchive = Archive.createForParcelFileDescriptor( mContext, Loading @@ -298,9 +324,18 @@ public class ArchivesProvider extends DocumentsProvider implements Closeable { mArchiveUri, "r", null /* signal */), mArchiveUri, mNotificationUri); } catch (IOException e) { mFailureException = e; throw new IllegalStateException(e); } catch (RuntimeException e) { mFailureException = e; throw e; } finally { // Notify observers that the root directory is loaded (or failed) // so clients reload it. mContext.getContentResolver().notifyChange( buildUriForArchive(mArchiveUri), null /* observer */, false /* syncToNetwork */); } return mArchive; } Loading