blob: 3f016b50143fb709385e4aae06883d9032c8c8a4 [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);
80 final Cursor withRoot = new RootCursorWrapper(mUri.getAuthority(), mRootId, cursor, -1);
81 final Cursor sorted = new SortingCursorWrapper(withRoot, mSortOrder);
82
83 result.cursor = sorted;
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070084 result.cursor.registerContentObserver(mObserver);
Jeff Sharkey1d890e02013-08-15 11:24:03 -070085 } catch (Exception e) {
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070086 result.exception = e;
87 ContentProviderClient.closeQuietly(result.client);
88 } finally {
89 synchronized (this) {
90 mSignal = null;
91 }
Jeff Sharkey1d890e02013-08-15 11:24:03 -070092 }
Jeff Sharkey46899c82013-08-18 22:26:48 -070093 return result;
Jeff Sharkey1d890e02013-08-15 11:24:03 -070094 }
95
Jeff Sharkeyac9e6272013-08-31 21:27:44 -070096 @Override
97 public void cancelLoadInBackground() {
98 super.cancelLoadInBackground();
Jeff Sharkeya5defe32013-08-05 17:56:48 -070099
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700100 synchronized (this) {
101 if (mSignal != null) {
102 mSignal.cancel();
Jeff Sharkey46899c82013-08-18 22:26:48 -0700103 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700104 }
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700105 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700106
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700107 @Override
108 public void deliverResult(DirectoryResult result) {
109 if (isReset()) {
110 IoUtils.closeQuietly(result);
111 return;
112 }
113 DirectoryResult oldResult = mResult;
114 mResult = result;
115
116 if (isStarted()) {
117 super.deliverResult(result);
118 }
119
120 if (oldResult != null && oldResult != result) {
121 IoUtils.closeQuietly(oldResult);
122 }
123 }
124
125 @Override
126 protected void onStartLoading() {
127 if (mResult != null) {
128 deliverResult(mResult);
129 }
130 if (takeContentChanged() || mResult == null) {
131 forceLoad();
132 }
133 }
134
135 @Override
136 protected void onStopLoading() {
137 cancelLoad();
138 }
139
140 @Override
141 public void onCanceled(DirectoryResult result) {
142 IoUtils.closeQuietly(result);
143 }
144
145 @Override
146 protected void onReset() {
147 super.onReset();
148
149 // Ensure the loader is stopped
150 onStopLoading();
151
152 IoUtils.closeQuietly(mResult);
153 mResult = null;
154
155 getContext().getContentResolver().unregisterContentObserver(mObserver);
156 }
157
Jeff Sharkeyd82b26b2013-09-02 15:07:28 -0700158 public static String getQuerySortOrder(int sortOrder) {
159 switch (sortOrder) {
Jeff Sharkeyb3620442013-09-01 18:41:04 -0700160 case SORT_ORDER_DISPLAY_NAME:
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700161 return Document.COLUMN_DISPLAY_NAME + " ASC";
Jeff Sharkeyb3620442013-09-01 18:41:04 -0700162 case SORT_ORDER_LAST_MODIFIED:
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700163 return Document.COLUMN_LAST_MODIFIED + " DESC";
Jeff Sharkeyb3620442013-09-01 18:41:04 -0700164 case SORT_ORDER_SIZE:
Jeff Sharkeyac9e6272013-08-31 21:27:44 -0700165 return Document.COLUMN_SIZE + " DESC";
166 default:
167 return null;
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700168 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700169 }
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700170}