blob: 6ea57d77cfa659a00162a0ad9d4784291533178a [file] [log] [blame]
Jeff Sharkeya5defe32013-08-05 17:56:48 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.documentsui;
18
Jeff Sharkeyb3620442013-09-01 18:41:04 -070019import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_DISPLAY_NAME;
20import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED;
21import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE;
22
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070023import android.content.AsyncTaskLoader;
24import android.content.ContentProviderClient;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070025import android.content.Context;
26import android.database.Cursor;
27import android.net.Uri;
28import android.os.CancellationSignal;
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070029import android.os.OperationCanceledException;
30import android.provider.DocumentsContract.Document;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070031
Jeff Sharkeya5defe32013-08-05 17:56:48 -070032import libcore.io.IoUtils;
33
Jeff Sharkey46899c82013-08-18 22:26:48 -070034class DirectoryResult implements AutoCloseable {
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070035 ContentProviderClient client;
Jeff Sharkey46899c82013-08-18 22:26:48 -070036 Cursor cursor;
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070037 Exception exception;
Jeff Sharkey46899c82013-08-18 22:26:48 -070038
39 @Override
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070040 public void close() {
Jeff Sharkey46899c82013-08-18 22:26:48 -070041 IoUtils.closeQuietly(cursor);
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070042 ContentProviderClient.closeQuietly(client);
43 cursor = null;
44 client = null;
Jeff Sharkey46899c82013-08-18 22:26:48 -070045 }
46}
47
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070048public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
49 private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
Jeff Sharkeya5defe32013-08-05 17:56:48 -070050
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -070051 private final String mRootId;
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070052 private final Uri mUri;
53 private final int mSortOrder;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070054
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070055 private CancellationSignal mSignal;
56 private DirectoryResult mResult;
57
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -070058 public DirectoryLoader(Context context, String rootId, Uri uri, int sortOrder) {
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070059 super(context);
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -070060 mRootId = rootId;
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070061 mUri = uri;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070062 mSortOrder = sortOrder;
63 }
64
65 @Override
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070066 public final DirectoryResult loadInBackground() {
67 synchronized (this) {
68 if (isLoadInBackgroundCanceled()) {
69 throw new OperationCanceledException();
70 }
71 mSignal = new CancellationSignal();
72 }
Jeff Sharkey46899c82013-08-18 22:26:48 -070073 final DirectoryResult result = new DirectoryResult();
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -070074 final String authority = mUri.getAuthority();
Jeff Sharkey1d890e02013-08-15 11:24:03 -070075 try {
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070076 result.client = getContext()
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -070077 .getContentResolver().acquireUnstableContentProviderClient(authority);
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070078 final Cursor cursor = result.client.query(
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -070079 mUri, null, null, null, getQuerySortOrder(mSortOrder), mSignal);
Jeff Sharkey20b32272013-09-03 15:25:52 -070080 cursor.registerContentObserver(mObserver);
81
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -070082 final Cursor withRoot = new RootCursorWrapper(mUri.getAuthority(), mRootId, cursor, -1);
83 final Cursor sorted = new SortingCursorWrapper(withRoot, mSortOrder);
84
85 result.cursor = sorted;
Jeff Sharkey1d890e02013-08-15 11:24:03 -070086 } catch (Exception e) {
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070087 result.exception = e;
88 ContentProviderClient.closeQuietly(result.client);
89 } finally {
90 synchronized (this) {
91 mSignal = null;
92 }
Jeff Sharkey1d890e02013-08-15 11:24:03 -070093 }
Jeff Sharkey46899c82013-08-18 22:26:48 -070094 return result;
Jeff Sharkey1d890e02013-08-15 11:24:03 -070095 }
96
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070097 @Override
98 public void cancelLoadInBackground() {
99 super.cancelLoadInBackground();
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700100
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700101 synchronized (this) {
102 if (mSignal != null) {
103 mSignal.cancel();
Jeff Sharkey46899c82013-08-18 22:26:48 -0700104 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700105 }
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700106 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700107
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700108 @Override
109 public void deliverResult(DirectoryResult result) {
110 if (isReset()) {
111 IoUtils.closeQuietly(result);
112 return;
113 }
114 DirectoryResult oldResult = mResult;
115 mResult = result;
116
117 if (isStarted()) {
118 super.deliverResult(result);
119 }
120
121 if (oldResult != null && oldResult != result) {
122 IoUtils.closeQuietly(oldResult);
123 }
124 }
125
126 @Override
127 protected void onStartLoading() {
128 if (mResult != null) {
129 deliverResult(mResult);
130 }
131 if (takeContentChanged() || mResult == null) {
132 forceLoad();
133 }
134 }
135
136 @Override
137 protected void onStopLoading() {
138 cancelLoad();
139 }
140
141 @Override
142 public void onCanceled(DirectoryResult result) {
143 IoUtils.closeQuietly(result);
144 }
145
146 @Override
147 protected void onReset() {
148 super.onReset();
149
150 // Ensure the loader is stopped
151 onStopLoading();
152
153 IoUtils.closeQuietly(mResult);
154 mResult = null;
155
156 getContext().getContentResolver().unregisterContentObserver(mObserver);
157 }
158
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -0700159 public static String getQuerySortOrder(int sortOrder) {
160 switch (sortOrder) {
Jeff Sharkeyb3620442013-09-01 18:41:04 -0700161 case SORT_ORDER_DISPLAY_NAME:
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700162 return Document.COLUMN_DISPLAY_NAME + " ASC";
Jeff Sharkeyb3620442013-09-01 18:41:04 -0700163 case SORT_ORDER_LAST_MODIFIED:
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700164 return Document.COLUMN_LAST_MODIFIED + " DESC";
Jeff Sharkeyb3620442013-09-01 18:41:04 -0700165 case SORT_ORDER_SIZE:
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700166 return Document.COLUMN_SIZE + " DESC";
167 default:
168 return null;
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700169 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700170 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700171}