DirectoryLoader.java revision 954be0232655d316bc5decbbd35579af902c75c2
1ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey/* 2ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project 3ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * 4ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * you may not use this file except in compliance with the License. 6ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * You may obtain a copy of the License at 7ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * 8ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * 10ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * See the License for the specific language governing permissions and 14ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey * limitations under the License. 15ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey */ 16ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 17ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeypackage com.android.documentsui; 18ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 19b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_DISPLAY_NAME; 20b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED; 21b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE; 22b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 235dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.content.AsyncTaskLoader; 245dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.content.ContentProviderClient; 25ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.content.Context; 26ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.database.Cursor; 27ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.net.Uri; 28ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.os.CancellationSignal; 295dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.os.OperationCanceledException; 305dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.provider.DocumentsContract.Document; 31ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 32ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport libcore.io.IoUtils; 33ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 34b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkeyclass DirectoryResult implements AutoCloseable { 355dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey ContentProviderClient client; 36b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey Cursor cursor; 375dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey Exception exception; 38b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey 39b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey @Override 405dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public void close() { 41b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey IoUtils.closeQuietly(cursor); 425dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey ContentProviderClient.closeQuietly(client); 435dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey cursor = null; 445dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey client = null; 45b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey } 46b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey} 47b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey 485dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeypublic class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> { 495dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver(); 505dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 51251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey private final String mRootId; 525dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey private final Uri mUri; 535dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey private final int mSortOrder; 54ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 555dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey private CancellationSignal mSignal; 565dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey private DirectoryResult mResult; 57ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 58251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey public DirectoryLoader(Context context, String rootId, Uri uri, int sortOrder) { 595dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey super(context); 60251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey mRootId = rootId; 615dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mUri = uri; 62ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey mSortOrder = sortOrder; 63ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 64ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 65ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey @Override 665dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public final DirectoryResult loadInBackground() { 675dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey synchronized (this) { 685dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (isLoadInBackgroundCanceled()) { 695dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey throw new OperationCanceledException(); 705dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 715dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mSignal = new CancellationSignal(); 725dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 73b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey final DirectoryResult result = new DirectoryResult(); 74251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final String authority = mUri.getAuthority(); 7554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey try { 765dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey result.client = getContext() 77251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey .getContentResolver().acquireUnstableContentProviderClient(authority); 785dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final Cursor cursor = result.client.query( 79251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey mUri, null, null, null, getQuerySortOrder(mSortOrder), mSignal); 80954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey cursor.registerContentObserver(mObserver); 81954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 82251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final Cursor withRoot = new RootCursorWrapper(mUri.getAuthority(), mRootId, cursor, -1); 83251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final Cursor sorted = new SortingCursorWrapper(withRoot, mSortOrder); 84251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey 85251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey result.cursor = sorted; 8654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } catch (Exception e) { 875dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey result.exception = e; 885dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey ContentProviderClient.closeQuietly(result.client); 895dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } finally { 905dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey synchronized (this) { 915dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mSignal = null; 925dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 9354ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } 94b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey return result; 9554ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey } 9654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey 975dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey @Override 985dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public void cancelLoadInBackground() { 995dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey super.cancelLoadInBackground(); 100b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey 1015dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey synchronized (this) { 1025dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (mSignal != null) { 1035dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mSignal.cancel(); 104ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 105ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 1065dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1075dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1085dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey @Override 1095dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public void deliverResult(DirectoryResult result) { 1105dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (isReset()) { 1115dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey IoUtils.closeQuietly(result); 1125dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey return; 1135dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1145dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey DirectoryResult oldResult = mResult; 1155dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mResult = result; 1165dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1175dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (isStarted()) { 1185dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey super.deliverResult(result); 1195dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1205dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1215dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (oldResult != null && oldResult != result) { 1225dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey IoUtils.closeQuietly(oldResult); 1235dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1245dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1255dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1265dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey @Override 1275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey protected void onStartLoading() { 1285dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (mResult != null) { 1295dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey deliverResult(mResult); 1305dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1315dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (takeContentChanged() || mResult == null) { 1325dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey forceLoad(); 1335dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1345dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1355dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1365dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey @Override 1375dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey protected void onStopLoading() { 1385dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey cancelLoad(); 1395dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1405dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1415dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey @Override 1425dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public void onCanceled(DirectoryResult result) { 1435dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey IoUtils.closeQuietly(result); 1445dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 1455dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1465dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey @Override 1475dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey protected void onReset() { 1485dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey super.onReset(); 1495dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1505dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey // Ensure the loader is stopped 1515dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey onStopLoading(); 1525dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1535dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey IoUtils.closeQuietly(mResult); 1545dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mResult = null; 1555dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 1565dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey getContext().getContentResolver().unregisterContentObserver(mObserver); 1575dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 158ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 159251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey public static String getQuerySortOrder(int sortOrder) { 160251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey switch (sortOrder) { 161b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey case SORT_ORDER_DISPLAY_NAME: 1625dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey return Document.COLUMN_DISPLAY_NAME + " ASC"; 163b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey case SORT_ORDER_LAST_MODIFIED: 1645dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey return Document.COLUMN_LAST_MODIFIED + " DESC"; 165b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey case SORT_ORDER_SIZE: 1665dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey return Document.COLUMN_SIZE + " DESC"; 1675dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey default: 1685dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey return null; 169ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 170ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 171ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey} 172