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
19d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.TAG;
20d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_UNKNOWN;
21b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_DISPLAY_NAME;
22b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED;
23b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE;
24d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_UNKNOWN;
25d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport static com.android.documentsui.model.DocumentInfo.getCursorInt;
26b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey
275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.content.AsyncTaskLoader;
285dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.content.ContentProviderClient;
29d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport android.content.ContentResolver;
30ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.content.Context;
31ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.database.Cursor;
32ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.net.Uri;
33ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.os.CancellationSignal;
345dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.os.OperationCanceledException;
353e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkeyimport android.provider.DocumentsContract;
365dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.provider.DocumentsContract.Document;
37d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport android.util.Log;
38d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
39d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.DocumentsActivity.State;
40d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.RecentsProvider.StateColumns;
41d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo;
42d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.model.RootInfo;
43ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
44ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport libcore.io.IoUtils;
45ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
463e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkeyimport java.io.FileNotFoundException;
473e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey
48b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkeyclass DirectoryResult implements AutoCloseable {
495dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    ContentProviderClient client;
50b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey    Cursor cursor;
515dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    Exception exception;
52b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey
53d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    int mode = MODE_UNKNOWN;
54d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    int sortOrder = SORT_ORDER_UNKNOWN;
55d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
56b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey    @Override
575dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public void close() {
58b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey        IoUtils.closeQuietly(cursor);
597aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey        ContentProviderClient.releaseQuietly(client);
605dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        cursor = null;
615dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        client = null;
62b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey    }
63b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey}
64b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey
655dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeypublic class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
676efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private static final String[] SEARCH_REJECT_MIMES = new String[] { Document.MIME_TYPE_DIR };
686efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
695dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
705dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
714ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey    private final int mType;
72d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey    private final RootInfo mRoot;
733e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey    private DocumentInfo mDoc;
745dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private final Uri mUri;
75fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey    private final int mUserSortOrder;
76ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
775dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private CancellationSignal mSignal;
785dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    private DirectoryResult mResult;
79ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
804ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey    public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
814ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            int userSortOrder) {
82d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        super(context, ProviderExecutor.forAuthority(root.authority));
834ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        mType = type;
84d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        mRoot = root;
85d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        mDoc = doc;
865dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        mUri = uri;
87fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        mUserSortOrder = userSortOrder;
88ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    }
89ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
90ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    @Override
915dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public final DirectoryResult loadInBackground() {
925dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        synchronized (this) {
935dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            if (isLoadInBackgroundCanceled()) {
945dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                throw new OperationCanceledException();
955dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            }
965dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            mSignal = new CancellationSignal();
975dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
98d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
99d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        final ContentResolver resolver = getContext().getContentResolver();
100251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey        final String authority = mUri.getAuthority();
101d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
102d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        final DirectoryResult result = new DirectoryResult();
103d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
104d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        int userMode = State.MODE_UNKNOWN;
105d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
1063e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey        // Use default document when searching
1073e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey        if (mType == DirectoryFragment.TYPE_SEARCH) {
1083e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey            final Uri docUri = DocumentsContract.buildDocumentUri(
1093e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey                    mRoot.authority, mRoot.documentId);
1103e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey            try {
1113e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey                mDoc = DocumentInfo.fromUri(resolver, docUri);
1123e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey            } catch (FileNotFoundException e) {
1133e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey                Log.w(TAG, "Failed to query", e);
1143e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey                result.exception = e;
1153e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey                return result;
1163e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey            }
1173e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey        }
1183e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey
119d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        // Pick up any custom modes requested by user
120d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        Cursor cursor = null;
12154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        try {
122d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            final Uri stateUri = RecentsProvider.buildState(
123d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                    mRoot.authority, mRoot.rootId, mDoc.documentId);
124d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            cursor = resolver.query(stateUri, null, null, null, null);
125d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            if (cursor.moveToFirst()) {
126d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                userMode = getCursorInt(cursor, StateColumns.MODE);
127d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            }
128d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        } finally {
129d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            IoUtils.closeQuietly(cursor);
130d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        }
131d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
132d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        if (userMode != State.MODE_UNKNOWN) {
133d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            result.mode = userMode;
134d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        } else {
135d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            if ((mDoc.flags & Document.FLAG_DIR_PREFERS_GRID) != 0) {
136d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                result.mode = State.MODE_GRID;
137d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            } else {
138d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                result.mode = State.MODE_LIST;
139d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            }
140d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        }
141d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
142fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        if (mUserSortOrder != State.SORT_ORDER_UNKNOWN) {
143fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey            result.sortOrder = mUserSortOrder;
144d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        } else {
145d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            if ((mDoc.flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0) {
146d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                result.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
147d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            } else {
148d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                result.sortOrder = State.SORT_ORDER_DISPLAY_NAME;
149d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey            }
150d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        }
151d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
1524ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        // Search always uses ranking from provider
1534ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        if (mType == DirectoryFragment.TYPE_SEARCH) {
1544ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            result.sortOrder = State.SORT_ORDER_UNKNOWN;
1554ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey        }
1564ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
157fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey        Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
158d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                + result.mode + ", sortOrder=" + result.sortOrder);
159d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
160d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey        ContentProviderClient client = null;
161d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey        try {
162d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            client = DocumentsApplication.acquireUnstableProviderOrThrow(resolver, authority);
1637aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
164d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            cursor = client.query(
165d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey                    mUri, null, null, null, getQuerySortOrder(result.sortOrder), mSignal);
166954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey            cursor.registerContentObserver(mObserver);
167954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey
1684ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            cursor = new RootCursorWrapper(mUri.getAuthority(), mRoot.rootId, cursor, -1);
1694ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey
1704ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            if (mType == DirectoryFragment.TYPE_SEARCH) {
1714ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                // Filter directories out of search results, for now
1726efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                cursor = new FilteringCursorWrapper(cursor, null, SEARCH_REJECT_MIMES);
1734ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            } else {
1744ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                // Normal directories should have sorting applied
1754ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey                cursor = new SortingCursorWrapper(cursor, result.sortOrder);
1764ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            }
177251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey
178d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            result.client = client;
1794ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey            result.cursor = cursor;
18054ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        } catch (Exception e) {
1813e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey            Log.w(TAG, "Failed to query", e);
1825dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            result.exception = e;
183d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey            ContentProviderClient.releaseQuietly(client);
1845dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        } finally {
1855dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            synchronized (this) {
1865dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                mSignal = null;
1875dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            }
18854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey        }
189d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey
190b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey        return result;
19154ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey    }
19254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
1935dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
1945dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public void cancelLoadInBackground() {
1955dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        super.cancelLoadInBackground();
196b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey
1975dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        synchronized (this) {
1985dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            if (mSignal != null) {
1995dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                mSignal.cancel();
200ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            }
201ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        }
2025dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
2035dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2045dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
2055dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public void deliverResult(DirectoryResult result) {
2065dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        if (isReset()) {
2075dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            IoUtils.closeQuietly(result);
2085dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            return;
2095dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
2105dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        DirectoryResult oldResult = mResult;
2115dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        mResult = result;
2125dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2135dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        if (isStarted()) {
2145dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            super.deliverResult(result);
2155dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
2165dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2175dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        if (oldResult != null && oldResult != result) {
2185dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            IoUtils.closeQuietly(oldResult);
2195dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
2205dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
2215dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2225dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
2235dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    protected void onStartLoading() {
2245dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        if (mResult != null) {
2255dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            deliverResult(mResult);
2265dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
2275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        if (takeContentChanged() || mResult == null) {
2285dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            forceLoad();
2295dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        }
2305dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
2315dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2325dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
2335dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    protected void onStopLoading() {
2345dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        cancelLoad();
2355dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
2365dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2375dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
2385dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    public void onCanceled(DirectoryResult result) {
2395dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        IoUtils.closeQuietly(result);
2405dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
2415dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2425dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    @Override
2435dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    protected void onReset() {
2445dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        super.onReset();
2455dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2465dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        // Ensure the loader is stopped
2475dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        onStopLoading();
2485dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2495dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        IoUtils.closeQuietly(mResult);
2505dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        mResult = null;
2515dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey
2525dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey        getContext().getContentResolver().unregisterContentObserver(mObserver);
2535dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey    }
254ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
255251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey    public static String getQuerySortOrder(int sortOrder) {
256251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey        switch (sortOrder) {
257b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            case SORT_ORDER_DISPLAY_NAME:
2585dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                return Document.COLUMN_DISPLAY_NAME + " ASC";
259b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            case SORT_ORDER_LAST_MODIFIED:
2605dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                return Document.COLUMN_LAST_MODIFIED + " DESC";
261b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey            case SORT_ORDER_SIZE:
2625dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                return Document.COLUMN_SIZE + " DESC";
2635dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey            default:
2645dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey                return null;
265ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        }
266ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    }
267ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey}
268