summaryrefslogtreecommitdiffstats
path: root/packages/DocumentsUI
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2013-09-03 00:07:17 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-09-03 00:07:17 +0000
commitcd6d7deec8742e257a670db8e027f628afdf337e (patch)
tree5745aabc61c5ed61d0877082c0e5ebd5eafecbab /packages/DocumentsUI
parent61dda198598e95971ca224e3bcb7393f30e45657 (diff)
parentae9b51bfa313c51a31af30875a71255d7b6d2e61 (diff)
downloadframeworks_base-cd6d7deec8742e257a670db8e027f628afdf337e.zip
frameworks_base-cd6d7deec8742e257a670db8e027f628afdf337e.tar.gz
frameworks_base-cd6d7deec8742e257a670db8e027f628afdf337e.tar.bz2
Merge "Refactoring of DocumentsContract." into klp-dev
Diffstat (limited to 'packages/DocumentsUI')
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java20
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java48
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java18
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java38
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java6
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsCache.java46
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java42
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java6
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java (renamed from packages/DocumentsUI/src/com/android/documentsui/model/Document.java)93
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java11
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java72
13 files changed, 235 insertions, 172 deletions
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 6bc554f..e0b8d19 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -20,7 +20,6 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
-import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
@@ -28,13 +27,13 @@ import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Documents;
+import android.provider.DocumentsContract.Document;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
-import com.android.documentsui.model.Document;
+import com.android.documentsui.model.DocumentInfo;
/**
* Dialog to create a new directory.
@@ -67,24 +66,17 @@ public class CreateDirectoryFragment extends DialogFragment {
final String displayName = text1.getText().toString();
final DocumentsActivity activity = (DocumentsActivity) getActivity();
- final Document cwd = activity.getCurrentDirectory();
+ final DocumentInfo cwd = activity.getCurrentDirectory();
- final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
- cwd.uri.getAuthority());
try {
- final String docId = DocumentsContract.createDocument(client,
- DocumentsContract.getDocId(cwd.uri), Documents.MIME_TYPE_DIR,
- displayName);
+ final Uri childUri = DocumentsContract.createDocument(
+ resolver, cwd.uri, Document.MIME_TYPE_DIR, displayName);
// Navigate into newly created child
- final Uri childUri = DocumentsContract.buildDocumentUri(
- cwd.uri.getAuthority(), docId);
- final Document childDoc = Document.fromUri(resolver, childUri);
+ final DocumentInfo childDoc = DocumentInfo.fromUri(resolver, childUri);
activity.onDocumentPicked(childDoc);
} catch (Exception e) {
Toast.makeText(context, R.string.save_error, Toast.LENGTH_SHORT).show();
- } finally {
- ContentProviderClient.closeQuietly(client);
}
}
});
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 783b6ff..79d20a4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -61,7 +61,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.documentsui.DocumentsActivity.DisplayState;
-import com.android.documentsui.model.Document;
+import com.android.documentsui.model.DocumentInfo;
import com.android.internal.util.Predicate;
import com.google.android.collect.Lists;
@@ -81,7 +81,7 @@ public class DirectoryFragment extends Fragment {
private AbsListView mCurrentView;
- private Predicate<Document> mFilter;
+ private Predicate<DocumentInfo> mFilter;
public static final int TYPE_NORMAL = 1;
public static final int TYPE_SEARCH = 2;
@@ -106,8 +106,8 @@ public class DirectoryFragment extends Fragment {
}
public static void showSearch(FragmentManager fm, Uri uri, String query) {
- final Uri searchUri = DocumentsContract.buildSearchUri(
- uri.getAuthority(), DocumentsContract.getDocId(uri), query);
+ final Uri searchUri = DocumentsContract.buildSearchDocumentsUri(
+ uri.getAuthority(), DocumentsContract.getDocumentId(uri), query);
show(fm, TYPE_SEARCH, searchUri);
}
@@ -163,21 +163,21 @@ public class DirectoryFragment extends Fragment {
Uri contentsUri;
if (mType == TYPE_NORMAL) {
- contentsUri = DocumentsContract.buildChildrenUri(
- uri.getAuthority(), DocumentsContract.getDocId(uri));
+ contentsUri = DocumentsContract.buildChildDocumentsUri(
+ uri.getAuthority(), DocumentsContract.getDocumentId(uri));
} else if (mType == TYPE_RECENT_OPEN) {
contentsUri = RecentsProvider.buildRecentOpen();
} else {
contentsUri = uri;
}
- final Comparator<Document> sortOrder;
+ final Comparator<DocumentInfo> sortOrder;
if (state.sortOrder == SORT_ORDER_LAST_MODIFIED || mType == TYPE_RECENT_OPEN) {
- sortOrder = new Document.LastModifiedComparator();
+ sortOrder = new DocumentInfo.LastModifiedComparator();
} else if (state.sortOrder == SORT_ORDER_DISPLAY_NAME) {
- sortOrder = new Document.DisplayNameComparator();
+ sortOrder = new DocumentInfo.DisplayNameComparator();
} else if (state.sortOrder == SORT_ORDER_SIZE) {
- sortOrder = new Document.SizeComparator();
+ sortOrder = new DocumentInfo.SizeComparator();
} else {
throw new IllegalArgumentException("Unknown sort order " + state.sortOrder);
}
@@ -258,7 +258,7 @@ public class DirectoryFragment extends Fragment {
private OnItemClickListener mItemListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final Document doc = mAdapter.getItem(position);
+ final DocumentInfo doc = mAdapter.getItem(position);
if (mFilter.apply(doc)) {
((DocumentsActivity) getActivity()).onDocumentPicked(doc);
}
@@ -291,11 +291,11 @@ public class DirectoryFragment extends Fragment {
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions();
- final ArrayList<Document> docs = Lists.newArrayList();
+ final ArrayList<DocumentInfo> docs = Lists.newArrayList();
final int size = checked.size();
for (int i = 0; i < size; i++) {
if (checked.valueAt(i)) {
- final Document doc = mAdapter.getItem(checked.keyAt(i));
+ final DocumentInfo doc = mAdapter.getItem(checked.keyAt(i));
docs.add(doc);
}
}
@@ -328,7 +328,7 @@ public class DirectoryFragment extends Fragment {
ActionMode mode, int position, long id, boolean checked) {
if (checked) {
// Directories cannot be checked
- final Document doc = mAdapter.getItem(position);
+ final DocumentInfo doc = mAdapter.getItem(position);
if (doc.isDirectory()) {
mCurrentView.setItemChecked(position, false);
}
@@ -339,9 +339,9 @@ public class DirectoryFragment extends Fragment {
}
};
- private void onShareDocuments(List<Document> docs) {
+ private void onShareDocuments(List<DocumentInfo> docs) {
final ArrayList<Uri> uris = Lists.newArrayList();
- for (Document doc : docs) {
+ for (DocumentInfo doc : docs) {
uris.add(doc.uri);
}
@@ -363,12 +363,12 @@ public class DirectoryFragment extends Fragment {
startActivity(intent);
}
- private void onDeleteDocuments(List<Document> docs) {
+ private void onDeleteDocuments(List<DocumentInfo> docs) {
final Context context = getActivity();
final ContentResolver resolver = context.getContentResolver();
boolean hadTrouble = false;
- for (Document doc : docs) {
+ for (DocumentInfo doc : docs) {
if (!doc.isDeleteSupported()) {
Log.w(TAG, "Skipping " + doc);
hadTrouble = true;
@@ -396,12 +396,12 @@ public class DirectoryFragment extends Fragment {
}
private class DocumentsAdapter extends BaseAdapter {
- private List<Document> mDocuments;
+ private List<DocumentInfo> mDocuments;
public DocumentsAdapter() {
}
- public void swapDocuments(List<Document> documents) {
+ public void swapDocuments(List<DocumentInfo> documents) {
mDocuments = documents;
if (mDocuments != null && mDocuments.isEmpty()) {
@@ -433,7 +433,7 @@ public class DirectoryFragment extends Fragment {
}
}
- final Document doc = getItem(position);
+ final DocumentInfo doc = getItem(position);
final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
@@ -507,7 +507,7 @@ public class DirectoryFragment extends Fragment {
}
@Override
- public Document getItem(int position) {
+ public DocumentInfo getItem(int position) {
return mDocuments.get(position);
}
@@ -538,8 +538,8 @@ public class DirectoryFragment extends Fragment {
Bitmap result = null;
try {
- result = DocumentsContract.getThumbnail(
- context.getContentResolver(), uri, mThumbSize);
+ result = DocumentsContract.getDocumentThumbnail(
+ context.getContentResolver(), uri, mThumbSize, null);
if (result != null) {
final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
context, mThumbSize);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 4ce5ef8..cb92d76 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -28,7 +28,7 @@ import android.net.Uri;
import android.os.CancellationSignal;
import android.util.Log;
-import com.android.documentsui.model.Document;
+import com.android.documentsui.model.DocumentInfo;
import com.android.internal.util.Predicate;
import com.google.android.collect.Lists;
@@ -41,7 +41,7 @@ import java.util.List;
class DirectoryResult implements AutoCloseable {
Cursor cursor;
- List<Document> contents = Lists.newArrayList();
+ List<DocumentInfo> contents = Lists.newArrayList();
Exception e;
@Override
@@ -53,11 +53,11 @@ class DirectoryResult implements AutoCloseable {
public class DirectoryLoader extends UriDerivativeLoader<Uri, DirectoryResult> {
private final int mType;
- private Predicate<Document> mFilter;
- private Comparator<Document> mSortOrder;
+ private Predicate<DocumentInfo> mFilter;
+ private Comparator<DocumentInfo> mSortOrder;
- public DirectoryLoader(Context context, Uri uri, int type, Predicate<Document> filter,
- Comparator<Document> sortOrder) {
+ public DirectoryLoader(Context context, Uri uri, int type, Predicate<DocumentInfo> filter,
+ Comparator<DocumentInfo> sortOrder) {
super(context, uri);
mType = type;
mFilter = filter;
@@ -84,15 +84,15 @@ public class DirectoryLoader extends UriDerivativeLoader<Uri, DirectoryResult> {
result.cursor.registerContentObserver(mObserver);
while (cursor.moveToNext()) {
- Document doc = null;
+ DocumentInfo doc = null;
switch (mType) {
case TYPE_NORMAL:
case TYPE_SEARCH:
- doc = Document.fromDirectoryCursor(uri, cursor);
+ doc = DocumentInfo.fromDirectoryCursor(uri, cursor);
break;
case TYPE_RECENT_OPEN:
try {
- doc = Document.fromRecentOpenCursor(resolver, cursor);
+ doc = DocumentInfo.fromRecentOpenCursor(resolver, cursor);
} catch (FileNotFoundException e) {
Log.w(TAG, "Failed to find recent: " + e);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java
index 0ce5968..54f62ef 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java
@@ -21,11 +21,10 @@ import static com.android.documentsui.DocumentsActivity.TAG;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.provider.DocumentsContract.DocumentRoot;
import android.util.Log;
/**
- * Handles {@link DocumentRoot} changes which invalidate cached data.
+ * Handles changes which invalidate cached data.
*/
public class DocumentChangedReceiver extends BroadcastReceiver {
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 73ca8fa..912d6dc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -42,7 +42,6 @@ import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.DocumentRoot;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
@@ -60,8 +59,9 @@ import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.documentsui.model.Document;
+import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.model.RootInfo;
import java.io.FileNotFoundException;
import java.util.Arrays;
@@ -160,7 +160,7 @@ public class DocumentsActivity extends Activity {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
final Uri rootUri = intent.getData();
- final DocumentRoot root = mRoots.findRoot(rootUri);
+ final RootInfo root = mRoots.findRoot(rootUri);
if (root != null) {
onRootPicked(root, true);
} else {
@@ -252,7 +252,7 @@ public class DocumentsActivity extends Activity {
mDrawerToggle.setDrawerIndicatorEnabled(true);
} else {
- final DocumentRoot root = getCurrentRoot();
+ final RootInfo root = getCurrentRoot();
actionBar.setIcon(root != null ? root.loadIcon(this) : null);
if (mRoots.isRecentsRoot(root)) {
@@ -317,7 +317,7 @@ public class DocumentsActivity extends Activity {
super.onPrepareOptionsMenu(menu);
final FragmentManager fm = getFragmentManager();
- final Document cwd = getCurrentDirectory();
+ final DocumentInfo cwd = getCurrentDirectory();
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
final MenuItem search = menu.findItem(R.id.menu_search);
@@ -473,7 +473,7 @@ public class DocumentsActivity extends Activity {
}
};
- public DocumentRoot getCurrentRoot() {
+ public RootInfo getCurrentRoot() {
if (mStack.size() > 0) {
return mStack.getRoot(mRoots);
} else {
@@ -481,7 +481,7 @@ public class DocumentsActivity extends Activity {
}
}
- public Document getCurrentDirectory() {
+ public DocumentInfo getCurrentDirectory() {
return mStack.peek();
}
@@ -491,7 +491,7 @@ public class DocumentsActivity extends Activity {
private void onCurrentDirectoryChanged() {
final FragmentManager fm = getFragmentManager();
- final Document cwd = getCurrentDirectory();
+ final DocumentInfo cwd = getCurrentDirectory();
if (cwd == null) {
// No directory means recents
@@ -533,14 +533,14 @@ public class DocumentsActivity extends Activity {
onCurrentDirectoryChanged();
}
- public void onRootPicked(DocumentRoot root, boolean closeDrawer) {
+ public void onRootPicked(RootInfo root, boolean closeDrawer) {
// Clear entire backstack and start in new root
mStack.clear();
if (!mRoots.isRecentsRoot(root)) {
try {
- final Uri uri = DocumentsContract.buildDocumentUri(root.authority, root.docId);
- onDocumentPicked(Document.fromUri(getContentResolver(), uri));
+ final Uri uri = DocumentsContract.buildDocumentUri(root.authority, root.documentId);
+ onDocumentPicked(DocumentInfo.fromUri(getContentResolver(), uri));
} catch (FileNotFoundException e) {
}
} else {
@@ -561,7 +561,7 @@ public class DocumentsActivity extends Activity {
finish();
}
- public void onDocumentPicked(Document doc) {
+ public void onDocumentPicked(DocumentInfo doc) {
final FragmentManager fm = getFragmentManager();
if (doc.isDirectory()) {
// TODO: query display mode user preference for this dir
@@ -591,7 +591,7 @@ public class DocumentsActivity extends Activity {
}
}
- public void onDocumentsPicked(List<Document> docs) {
+ public void onDocumentsPicked(List<DocumentInfo> docs) {
if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
final int size = docs.size();
final Uri[] uris = new Uri[size];
@@ -602,21 +602,19 @@ public class DocumentsActivity extends Activity {
}
}
- public void onSaveRequested(Document replaceTarget) {
+ public void onSaveRequested(DocumentInfo replaceTarget) {
onFinished(replaceTarget.uri);
}
public void onSaveRequested(String mimeType, String displayName) {
- final Document cwd = getCurrentDirectory();
+ final DocumentInfo cwd = getCurrentDirectory();
final String authority = cwd.uri.getAuthority();
final ContentProviderClient client = getContentResolver()
.acquireUnstableContentProviderClient(authority);
try {
- final String docId = DocumentsContract.createDocument(client,
- DocumentsContract.getDocId(cwd.uri), mimeType, displayName);
-
- final Uri childUri = DocumentsContract.buildDocumentUri(authority, docId);
+ final Uri childUri = DocumentsContract.createDocument(
+ getContentResolver(), cwd.uri, mimeType, displayName);
onFinished(childUri);
} catch (Exception e) {
Toast.makeText(this, R.string.save_error, Toast.LENGTH_SHORT).show();
@@ -701,7 +699,7 @@ public class DocumentsActivity extends Activity {
private void dumpStack() {
Log.d(TAG, "Current stack:");
- for (Document doc : mStack) {
+ for (DocumentInfo doc : mStack) {
Log.d(TAG, "--> " + doc);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
index a9929de..15ad061 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
@@ -16,10 +16,10 @@
package com.android.documentsui;
-import com.android.documentsui.model.Document;
+import com.android.documentsui.model.DocumentInfo;
import com.android.internal.util.Predicate;
-public class MimePredicate implements Predicate<Document> {
+public class MimePredicate implements Predicate<DocumentInfo> {
private final String[] mFilters;
public MimePredicate(String[] filters) {
@@ -27,7 +27,7 @@ public class MimePredicate implements Predicate<Document> {
}
@Override
- public boolean apply(Document doc) {
+ public boolean apply(DocumentInfo doc) {
if (doc.isDirectory()) {
return true;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 3447a51..f5d87a7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -29,7 +29,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
-import android.provider.DocumentsContract.DocumentRoot;
import android.text.TextUtils.TruncateAt;
import android.util.Log;
import android.view.LayoutInflater;
@@ -43,6 +42,7 @@ import android.widget.ListView;
import android.widget.TextView;
import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.model.RootInfo;
import com.google.android.collect.Lists;
import libcore.io.IoUtils;
@@ -181,7 +181,7 @@ public class RecentsCreateFragment extends Fragment {
final View summaryList = convertView.findViewById(R.id.summary_list);
final DocumentStack stack = getItem(position);
- final DocumentRoot root = stack.getRoot(roots);
+ final RootInfo root = stack.getRoot(roots);
icon.setImageDrawable(root.loadIcon(context));
final StringBuilder builder = new StringBuilder();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index aa21457..880a92b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -25,17 +25,21 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
+import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.DocumentRoot;
-import android.provider.DocumentsContract.Documents;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
import android.util.Log;
+import com.android.documentsui.model.RootInfo;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Objects;
import com.google.android.collect.Lists;
+import libcore.io.IoUtils;
+
import java.util.List;
/**
@@ -48,9 +52,9 @@ public class RootsCache {
private final Context mContext;
- public List<DocumentRoot> mRoots = Lists.newArrayList();
+ public List<RootInfo> mRoots = Lists.newArrayList();
- private DocumentRoot mRecentsRoot;
+ private RootInfo mRecentsRoot;
public RootsCache(Context context) {
mContext = context;
@@ -66,12 +70,10 @@ public class RootsCache {
{
// Create special root for recents
- final DocumentRoot root = new DocumentRoot();
- root.rootType = DocumentRoot.ROOT_TYPE_SHORTCUT;
- root.docId = null;
+ final RootInfo root = new RootInfo();
+ root.rootType = Root.ROOT_TYPE_SHORTCUT;
root.icon = R.drawable.ic_dir;
root.title = mContext.getString(R.string.root_recent);
- root.summary = null;
root.availableBytes = -1;
mRoots.add(root);
@@ -89,28 +91,32 @@ public class RootsCache {
// TODO: remove deprecated customRoots flag
// TODO: populate roots on background thread, and cache results
+ final Uri rootsUri = DocumentsContract.buildRootsUri(info.authority);
final ContentProviderClient client = resolver
.acquireUnstableContentProviderClient(info.authority);
+ Cursor cursor = null;
try {
- final List<DocumentRoot> roots = DocumentsContract.getDocumentRoots(client);
- for (DocumentRoot root : roots) {
- root.authority = info.authority;
+ cursor = client.query(rootsUri, null, null, null, null);
+ while (cursor.moveToNext()) {
+ final RootInfo root = RootInfo.fromRootsCursor(info.authority, cursor);
+ mRoots.add(root);
}
- mRoots.addAll(roots);
} catch (Exception e) {
Log.w(TAG, "Failed to load some roots from " + info.authority + ": " + e);
} finally {
+ IoUtils.closeQuietly(cursor);
ContentProviderClient.closeQuietly(client);
}
}
}
}
- public DocumentRoot findRoot(Uri uri) {
+ @Deprecated
+ public RootInfo findRoot(Uri uri) {
final String authority = uri.getAuthority();
- final String docId = DocumentsContract.getDocId(uri);
- for (DocumentRoot root : mRoots) {
- if (Objects.equal(root.authority, authority) && Objects.equal(root.docId, docId)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ for (RootInfo root : mRoots) {
+ if (Objects.equal(root.authority, authority) && Objects.equal(root.documentId, docId)) {
return root;
}
}
@@ -118,23 +124,23 @@ public class RootsCache {
}
@GuardedBy("ActivityThread")
- public DocumentRoot getRecentsRoot() {
+ public RootInfo getRecentsRoot() {
return mRecentsRoot;
}
@GuardedBy("ActivityThread")
- public boolean isRecentsRoot(DocumentRoot root) {
+ public boolean isRecentsRoot(RootInfo root) {
return mRecentsRoot == root;
}
@GuardedBy("ActivityThread")
- public List<DocumentRoot> getRoots() {
+ public List<RootInfo> getRoots() {
return mRoots;
}
@GuardedBy("ActivityThread")
public static Drawable resolveDocumentIcon(Context context, String mimeType) {
- if (Documents.MIME_TYPE_DIR.equals(mimeType)) {
+ if (Document.MIME_TYPE_DIR.equals(mimeType)) {
return context.getResources().getDrawable(R.drawable.ic_dir);
} else {
final PackageManager pm = context.getPackageManager();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 2cfa841..3102b88 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -26,7 +26,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
-import android.provider.DocumentsContract.DocumentRoot;
+import android.provider.DocumentsContract.Root;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
@@ -40,7 +40,8 @@ import android.widget.ListView;
import android.widget.TextView;
import com.android.documentsui.SectionedListAdapter.SectionAdapter;
-import com.android.documentsui.model.Document;
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.RootInfo;
import java.util.Comparator;
import java.util.List;
@@ -101,8 +102,8 @@ public class RootsFragment extends Fragment {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
final Object item = mAdapter.getItem(position);
- if (item instanceof DocumentRoot) {
- activity.onRootPicked((DocumentRoot) item, true);
+ if (item instanceof RootInfo) {
+ activity.onRootPicked((RootInfo) item, true);
} else if (item instanceof ResolveInfo) {
activity.onAppPicked((ResolveInfo) item);
} else {
@@ -111,7 +112,7 @@ public class RootsFragment extends Fragment {
}
};
- private static class RootsAdapter extends ArrayAdapter<DocumentRoot> implements SectionAdapter {
+ private static class RootsAdapter extends ArrayAdapter<RootInfo> implements SectionAdapter {
private int mHeaderId;
public RootsAdapter(Context context, int headerId) {
@@ -131,15 +132,13 @@ public class RootsFragment extends Fragment {
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
- final DocumentRoot root = getItem(position);
+ final RootInfo root = getItem(position);
icon.setImageDrawable(root.loadIcon(context));
title.setText(root.title);
// Device summary is always available space
final String summaryText;
- if ((root.rootType == DocumentRoot.ROOT_TYPE_DEVICE
- || root.rootType == DocumentRoot.ROOT_TYPE_DEVICE_ADVANCED)
- && root.availableBytes >= 0) {
+ if (root.rootType == Root.ROOT_TYPE_DEVICE && root.availableBytes >= 0) {
summaryText = context.getString(R.string.root_available_bytes,
Formatter.formatFileSize(context, root.availableBytes));
} else {
@@ -215,28 +214,27 @@ public class RootsFragment extends Fragment {
private final RootsAdapter mDevicesAdvanced;
private final AppsAdapter mApps;
- public SectionedRootsAdapter(Context context, List<DocumentRoot> roots, Intent includeApps) {
+ public SectionedRootsAdapter(Context context, List<RootInfo> roots, Intent includeApps) {
mServices = new RootsAdapter(context, R.string.root_type_service);
mShortcuts = new RootsAdapter(context, R.string.root_type_shortcut);
mDevices = new RootsAdapter(context, R.string.root_type_device);
mDevicesAdvanced = new RootsAdapter(context, R.string.root_type_device);
mApps = new AppsAdapter(context);
- for (DocumentRoot root : roots) {
+ for (RootInfo root : roots) {
Log.d(TAG, "Found rootType=" + root.rootType);
switch (root.rootType) {
- case DocumentRoot.ROOT_TYPE_SERVICE:
+ case Root.ROOT_TYPE_SERVICE:
mServices.add(root);
break;
- case DocumentRoot.ROOT_TYPE_SHORTCUT:
+ case Root.ROOT_TYPE_SHORTCUT:
mShortcuts.add(root);
break;
- case DocumentRoot.ROOT_TYPE_DEVICE:
- mDevices.add(root);
- mDevicesAdvanced.add(root);
- break;
- case DocumentRoot.ROOT_TYPE_DEVICE_ADVANCED:
+ case Root.ROOT_TYPE_DEVICE:
mDevicesAdvanced.add(root);
+ if ((root.flags & Root.FLAG_ADVANCED) == 0) {
+ mDevices.add(root);
+ }
break;
}
}
@@ -281,14 +279,14 @@ public class RootsFragment extends Fragment {
}
}
- public static class RootComparator implements Comparator<DocumentRoot> {
+ public static class RootComparator implements Comparator<RootInfo> {
@Override
- public int compare(DocumentRoot lhs, DocumentRoot rhs) {
- final int score = Document.compareToIgnoreCaseNullable(lhs.title, rhs.title);
+ public int compare(RootInfo lhs, RootInfo rhs) {
+ final int score = DocumentInfo.compareToIgnoreCaseNullable(lhs.title, rhs.title);
if (score != 0) {
return score;
} else {
- return Document.compareToIgnoreCaseNullable(lhs.summary, rhs.summary);
+ return DocumentInfo.compareToIgnoreCaseNullable(lhs.summary, rhs.summary);
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index 7e1a297..8b0a974 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -31,7 +31,7 @@ import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
-import com.android.documentsui.model.Document;
+import com.android.documentsui.model.DocumentInfo;
/**
* Display document title editor and save button.
@@ -39,7 +39,7 @@ import com.android.documentsui.model.Document;
public class SaveFragment extends Fragment {
public static final String TAG = "SaveFragment";
- private Document mReplaceTarget;
+ private DocumentInfo mReplaceTarget;
private EditText mDisplayName;
private Button mSave;
private boolean mIgnoreNextEdit;
@@ -128,7 +128,7 @@ public class SaveFragment extends Fragment {
* without changing the filename. Can be set to {@code null} if user
* navigates outside the target directory.
*/
- public void setReplaceTarget(Document replaceTarget) {
+ public void setReplaceTarget(DocumentInfo replaceTarget) {
mReplaceTarget = replaceTarget;
if (mReplaceTarget != null) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index 692d171..f6e46a8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -20,8 +20,7 @@ import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.DocumentColumns;
-import android.provider.DocumentsContract.Documents;
+import android.provider.DocumentsContract.Document;
import com.android.documentsui.RecentsProvider;
@@ -31,9 +30,9 @@ import java.io.FileNotFoundException;
import java.util.Comparator;
/**
- * Representation of a single document.
+ * Representation of a {@link Document}.
*/
-public class Document {
+public class DocumentInfo {
public final Uri uri;
public final String mimeType;
public final String displayName;
@@ -42,7 +41,7 @@ public class Document {
public final String summary;
public final long size;
- private Document(Uri uri, String mimeType, String displayName, long lastModified, int flags,
+ private DocumentInfo(Uri uri, String mimeType, String displayName, long lastModified, int flags,
String summary, long size) {
this.uri = uri;
this.mimeType = mimeType;
@@ -53,23 +52,23 @@ public class Document {
this.size = size;
}
- public static Document fromDirectoryCursor(Uri parent, Cursor cursor) {
+ public static DocumentInfo fromDirectoryCursor(Uri parent, Cursor cursor) {
final String authority = parent.getAuthority();
- final String docId = getCursorString(cursor, DocumentColumns.DOC_ID);
+ final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
final Uri uri = DocumentsContract.buildDocumentUri(authority, docId);
- final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE);
- final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME);
- final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED);
- final int flags = getCursorInt(cursor, DocumentColumns.FLAGS);
- final String summary = getCursorString(cursor, DocumentColumns.SUMMARY);
- final long size = getCursorLong(cursor, DocumentColumns.SIZE);
+ final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+ final String displayName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
+ final long lastModified = getCursorLong(cursor, Document.COLUMN_LAST_MODIFIED);
+ final int flags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+ final String summary = getCursorString(cursor, Document.COLUMN_SUMMARY);
+ final long size = getCursorLong(cursor, Document.COLUMN_SIZE);
- return new Document(uri, mimeType, displayName, lastModified, flags, summary, size);
+ return new DocumentInfo(uri, mimeType, displayName, lastModified, flags, summary, size);
}
@Deprecated
- public static Document fromRecentOpenCursor(ContentResolver resolver, Cursor recentCursor)
+ public static DocumentInfo fromRecentOpenCursor(ContentResolver resolver, Cursor recentCursor)
throws FileNotFoundException {
final Uri uri = Uri.parse(getCursorString(recentCursor, RecentsProvider.COL_URI));
final long lastModified = getCursorLong(recentCursor, RecentsProvider.COL_TIMESTAMP);
@@ -80,14 +79,14 @@ public class Document {
if (!cursor.moveToFirst()) {
throw new FileNotFoundException("Missing details for " + uri);
}
- final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE);
- final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME);
- final int flags = getCursorInt(cursor, DocumentColumns.FLAGS)
- & Documents.FLAG_SUPPORTS_THUMBNAIL;
- final String summary = getCursorString(cursor, DocumentColumns.SUMMARY);
- final long size = getCursorLong(cursor, DocumentColumns.SIZE);
-
- return new Document(uri, mimeType, displayName, lastModified, flags, summary, size);
+ final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+ final String displayName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
+ final int flags = getCursorInt(cursor, Document.COLUMN_FLAGS)
+ & Document.FLAG_SUPPORTS_THUMBNAIL;
+ final String summary = getCursorString(cursor, Document.COLUMN_SUMMARY);
+ final long size = getCursorLong(cursor, Document.COLUMN_SIZE);
+
+ return new DocumentInfo(uri, mimeType, displayName, lastModified, flags, summary, size);
} catch (Throwable t) {
throw asFileNotFoundException(t);
} finally {
@@ -95,21 +94,21 @@ public class Document {
}
}
- public static Document fromUri(ContentResolver resolver, Uri uri) throws FileNotFoundException {
+ public static DocumentInfo fromUri(ContentResolver resolver, Uri uri) throws FileNotFoundException {
Cursor cursor = null;
try {
cursor = resolver.query(uri, null, null, null, null);
if (!cursor.moveToFirst()) {
throw new FileNotFoundException("Missing details for " + uri);
}
- final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE);
- final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME);
- final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED);
- final int flags = getCursorInt(cursor, DocumentColumns.FLAGS);
- final String summary = getCursorString(cursor, DocumentColumns.SUMMARY);
- final long size = getCursorLong(cursor, DocumentColumns.SIZE);
-
- return new Document(uri, mimeType, displayName, lastModified, flags, summary, size);
+ final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+ final String displayName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
+ final long lastModified = getCursorLong(cursor, Document.COLUMN_LAST_MODIFIED);
+ final int flags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+ final String summary = getCursorString(cursor, Document.COLUMN_SUMMARY);
+ final long size = getCursorLong(cursor, Document.COLUMN_SIZE);
+
+ return new DocumentInfo(uri, mimeType, displayName, lastModified, flags, summary, size);
} catch (Throwable t) {
throw asFileNotFoundException(t);
} finally {
@@ -123,30 +122,30 @@ public class Document {
}
public boolean isCreateSupported() {
- return (flags & Documents.FLAG_SUPPORTS_CREATE) != 0;
+ return (flags & Document.FLAG_DIR_SUPPORTS_CREATE) != 0;
}
public boolean isSearchSupported() {
- return (flags & Documents.FLAG_SUPPORTS_SEARCH) != 0;
+ return (flags & Document.FLAG_DIR_SUPPORTS_SEARCH) != 0;
}
public boolean isThumbnailSupported() {
- return (flags & Documents.FLAG_SUPPORTS_THUMBNAIL) != 0;
+ return (flags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
}
public boolean isDirectory() {
- return Documents.MIME_TYPE_DIR.equals(mimeType);
+ return Document.MIME_TYPE_DIR.equals(mimeType);
}
public boolean isGridPreferred() {
- return (flags & Documents.FLAG_PREFERS_GRID) != 0;
+ return (flags & Document.FLAG_DIR_PREFERS_GRID) != 0;
}
public boolean isDeleteSupported() {
- return (flags & Documents.FLAG_SUPPORTS_DELETE) != 0;
+ return (flags & Document.FLAG_SUPPORTS_DELETE) != 0;
}
- private static String getCursorString(Cursor cursor, String columnName) {
+ public static String getCursorString(Cursor cursor, String columnName) {
final int index = cursor.getColumnIndex(columnName);
return (index != -1) ? cursor.getString(index) : null;
}
@@ -154,7 +153,7 @@ public class Document {
/**
* Missing or null values are returned as -1.
*/
- private static long getCursorLong(Cursor cursor, String columnName) {
+ public static long getCursorLong(Cursor cursor, String columnName) {
final int index = cursor.getColumnIndex(columnName);
if (index == -1) return -1;
final String value = cursor.getString(index);
@@ -166,14 +165,14 @@ public class Document {
}
}
- private static int getCursorInt(Cursor cursor, String columnName) {
+ public static int getCursorInt(Cursor cursor, String columnName) {
final int index = cursor.getColumnIndex(columnName);
return (index != -1) ? cursor.getInt(index) : 0;
}
- public static class DisplayNameComparator implements Comparator<Document> {
+ public static class DisplayNameComparator implements Comparator<DocumentInfo> {
@Override
- public int compare(Document lhs, Document rhs) {
+ public int compare(DocumentInfo lhs, DocumentInfo rhs) {
final boolean leftDir = lhs.isDirectory();
final boolean rightDir = rhs.isDirectory();
@@ -185,16 +184,16 @@ public class Document {
}
}
- public static class LastModifiedComparator implements Comparator<Document> {
+ public static class LastModifiedComparator implements Comparator<DocumentInfo> {
@Override
- public int compare(Document lhs, Document rhs) {
+ public int compare(DocumentInfo lhs, DocumentInfo rhs) {
return Long.compare(rhs.lastModified, lhs.lastModified);
}
}
- public static class SizeComparator implements Comparator<Document> {
+ public static class SizeComparator implements Comparator<DocumentInfo> {
@Override
- public int compare(Document lhs, Document rhs) {
+ public int compare(DocumentInfo lhs, DocumentInfo rhs) {
return Long.compare(rhs.size, lhs.size);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java
index 81f75d2..b123a46 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java
@@ -17,11 +17,10 @@
package com.android.documentsui.model;
import static com.android.documentsui.DocumentsActivity.TAG;
-import static com.android.documentsui.model.Document.asFileNotFoundException;
+import static com.android.documentsui.model.DocumentInfo.asFileNotFoundException;
import android.content.ContentResolver;
import android.net.Uri;
-import android.provider.DocumentsContract.DocumentRoot;
import android.util.Log;
import com.android.documentsui.RootsCache;
@@ -33,10 +32,10 @@ import java.io.FileNotFoundException;
import java.util.LinkedList;
/**
- * Representation of a stack of {@link Document}, usually the result of a
+ * Representation of a stack of {@link DocumentInfo}, usually the result of a
* user-driven traversal.
*/
-public class DocumentStack extends LinkedList<Document> {
+public class DocumentStack extends LinkedList<DocumentInfo> {
public static String serialize(DocumentStack stack) {
final JSONArray json = new JSONArray();
@@ -55,7 +54,7 @@ public class DocumentStack extends LinkedList<Document> {
final JSONArray json = new JSONArray(raw);
for (int i = 0; i < json.length(); i++) {
final Uri uri = Uri.parse(json.getString(i));
- final Document doc = Document.fromUri(resolver, uri);
+ final DocumentInfo doc = DocumentInfo.fromUri(resolver, uri);
stack.add(doc);
}
} catch (JSONException e) {
@@ -66,7 +65,7 @@ public class DocumentStack extends LinkedList<Document> {
return stack;
}
- public DocumentRoot getRoot(RootsCache roots) {
+ public RootInfo getRoot(RootsCache roots) {
return roots.findRoot(getLast().uri);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
new file mode 100644
index 0000000..f7027f3
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.model;
+
+import static com.android.documentsui.model.DocumentInfo.getCursorInt;
+import static com.android.documentsui.model.DocumentInfo.getCursorLong;
+import static com.android.documentsui.model.DocumentInfo.getCursorString;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.provider.DocumentsContract.Root;
+
+/**
+ * Representation of a {@link Root}.
+ */
+public class RootInfo {
+ public String authority;
+ public String rootId;
+ public int rootType;
+ public int flags;
+ public int icon;
+ public String title;
+ public String summary;
+ public String documentId;
+ public long availableBytes;
+
+ public static RootInfo fromRootsCursor(String authority, Cursor cursor) {
+ final RootInfo root = new RootInfo();
+ root.authority = authority;
+ root.rootId = getCursorString(cursor, Root.COLUMN_ROOT_ID);
+ root.rootType = getCursorInt(cursor, Root.COLUMN_ROOT_TYPE);
+ root.flags = getCursorInt(cursor, Root.COLUMN_FLAGS);
+ root.icon = getCursorInt(cursor, Root.COLUMN_ICON);
+ root.title = getCursorString(cursor, Root.COLUMN_TITLE);
+ root.summary = getCursorString(cursor, Root.COLUMN_SUMMARY);
+ root.documentId = getCursorString(cursor, Root.COLUMN_DOCUMENT_ID);
+ root.availableBytes = getCursorLong(cursor, Root.COLUMN_AVAILABLE_BYTES);
+ return root;
+ }
+
+ public Drawable loadIcon(Context context) {
+ if (icon != 0) {
+ if (authority != null) {
+ final PackageManager pm = context.getPackageManager();
+ final ProviderInfo info = pm.resolveContentProvider(authority, 0);
+ if (info != null) {
+ return pm.getDrawable(info.packageName, icon, info.applicationInfo);
+ }
+ } else {
+ return context.getResources().getDrawable(icon);
+ }
+ }
+ return null;
+ }
+}