summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2013-09-10 17:05:07 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2013-09-10 17:05:07 -0700
commitd7ae1474465357e40d2c4c1141258dc06308beb5 (patch)
tree5ac6e36b7bd9c99d339b1c59d616acbf4adb3bee
parent279f3cdf70652a211c54f7b70fb08722a50e6cec (diff)
parentbd56a17df26a3c7f4e32ca3be08fbf28f625dffa (diff)
downloadframeworks_base-d7ae1474465357e40d2c4c1141258dc06308beb5.zip
frameworks_base-d7ae1474465357e40d2c4c1141258dc06308beb5.tar.gz
frameworks_base-d7ae1474465357e40d2c4c1141258dc06308beb5.tar.bz2
am bd56a17d: am af4d039f: Merge "More UX work for thumbnails, search, management." into klp-dev
* commit 'bd56a17df26a3c7f4e32ca3be08fbf28f625dffa': More UX work for thumbnails, search, management.
-rw-r--r--core/java/android/provider/DocumentsContract.java11
-rw-r--r--core/java/android/provider/DocumentsProvider.java15
-rw-r--r--packages/DocumentsUI/res/layout/item_doc_grid.xml22
-rw-r--r--packages/DocumentsUI/res/layout/item_doc_list.xml22
-rw-r--r--packages/DocumentsUI/res/layout/item_root_header.xml13
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java127
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java26
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java44
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java8
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java7
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java6
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsCache.java17
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java3
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java9
16 files changed, 270 insertions, 67 deletions
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 91b3b48..43120c4 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -459,6 +459,7 @@ public final class DocumentsContract {
private static final String PATH_SEARCH = "search";
private static final String PARAM_QUERY = "query";
+ private static final String PARAM_MANAGE = "manage";
/**
* Build Uri representing the roots of a document provider. When queried, a
@@ -583,6 +584,16 @@ public final class DocumentsContract {
return searchDocumentsUri.getQueryParameter(PARAM_QUERY);
}
+ /** {@hide} */
+ public static Uri setManageMode(Uri uri) {
+ return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
+ }
+
+ /** {@hide} */
+ public static boolean isManageMode(Uri uri) {
+ return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
+ }
+
/**
* Return list of all documents that the calling package has "open." These
* are Uris matching {@link DocumentsContract} to which persistent
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 1b0fc4d..d801827 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -167,6 +167,14 @@ public abstract class DocumentsProvider extends ContentProvider {
String parentDocumentId, String[] projection, String sortOrder)
throws FileNotFoundException;
+ /** {@hide} */
+ @SuppressWarnings("unused")
+ public Cursor queryChildDocumentsForManage(
+ String parentDocumentId, String[] projection, String sortOrder)
+ throws FileNotFoundException {
+ throw new UnsupportedOperationException("Manage not supported");
+ }
+
/**
* Return documents that that match the given query, starting the search at
* the given directory.
@@ -262,7 +270,12 @@ public abstract class DocumentsProvider extends ContentProvider {
case MATCH_DOCUMENT:
return queryDocument(getDocumentId(uri), projection);
case MATCH_CHILDREN:
- return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
+ if (DocumentsContract.isManageMode(uri)) {
+ return queryChildDocumentsForManage(
+ getDocumentId(uri), projection, sortOrder);
+ } else {
+ return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
+ }
case MATCH_SEARCH:
return querySearchDocuments(
getDocumentId(uri), getSearchDocumentsQuery(uri), projection);
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index 8d1fc9a..8b37d21 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -32,12 +32,26 @@
android:layout_weight="1"
android:background="#fff">
- <ImageView
+ <FrameLayout
android:id="@android:id/icon"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerInside"
- android:contentDescription="@null" />
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:id="@+id/icon_mime"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:contentDescription="@null" />
+
+ <ImageView
+ android:id="@+id/icon_thumb"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:contentDescription="@null" />
+
+ </FrameLayout>
<ImageView
android:layout_width="match_parent"
diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml
index 8372eed..9958e44 100644
--- a/packages/DocumentsUI/res/layout/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_list.xml
@@ -25,15 +25,29 @@
android:paddingBottom="8dip"
android:orientation="horizontal">
- <ImageView
+ <FrameLayout
android:id="@android:id/icon"
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:layout_marginStart="12dp"
android:layout_marginEnd="20dp"
- android:layout_gravity="center_vertical"
- android:scaleType="centerInside"
- android:contentDescription="@null" />
+ android:layout_gravity="center_vertical">
+
+ <ImageView
+ android:id="@+id/icon_mime"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:contentDescription="@null" />
+
+ <ImageView
+ android:id="@+id/icon_thumb"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:contentDescription="@null" />
+
+ </FrameLayout>
<LinearLayout
android:layout_width="0dip"
diff --git a/packages/DocumentsUI/res/layout/item_root_header.xml b/packages/DocumentsUI/res/layout/item_root_header.xml
index 127b254..7b6cd76 100644
--- a/packages/DocumentsUI/res/layout/item_root_header.xml
+++ b/packages/DocumentsUI/res/layout/item_root_header.xml
@@ -14,6 +14,13 @@
limitations under the License.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/title"
- style="?android:attr/listSeparatorTextViewStyle" />
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="12dp">
+
+ <TextView
+ android:id="@android:id/title"
+ style="?android:attr/listSeparatorTextViewStyle" />
+
+</FrameLayout>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 45f028d..13a84f4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -38,9 +38,11 @@ import android.content.Loader;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Point;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.text.format.DateUtils;
@@ -56,6 +58,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.MultiChoiceModeListener;
+import android.widget.AbsListView.RecyclerListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
@@ -162,10 +165,12 @@ public class DirectoryFragment extends Fragment {
mListView = (ListView) view.findViewById(R.id.list);
mListView.setOnItemClickListener(mItemListener);
mListView.setMultiChoiceModeListener(mMultiListener);
+ mListView.setRecyclerListener(mRecycleListener);
mGridView = (GridView) view.findViewById(R.id.grid);
mGridView.setOnItemClickListener(mItemListener);
mGridView.setMultiChoiceModeListener(mMultiListener);
+ mGridView.setRecyclerListener(mRecycleListener);
return view;
}
@@ -192,13 +197,19 @@ public class DirectoryFragment extends Fragment {
case TYPE_NORMAL:
contentsUri = DocumentsContract.buildChildDocumentsUri(
doc.authority, doc.documentId);
+ if (state.action == ACTION_MANAGE) {
+ contentsUri = DocumentsContract.setManageMode(contentsUri);
+ }
return new DirectoryLoader(
- context, root, doc, contentsUri, state.userSortOrder);
+ context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_SEARCH:
contentsUri = DocumentsContract.buildSearchDocumentsUri(
doc.authority, doc.documentId, query);
+ if (state.action == ACTION_MANAGE) {
+ contentsUri = DocumentsContract.setManageMode(contentsUri);
+ }
return new DirectoryLoader(
- context, root, doc, contentsUri, state.userSortOrder);
+ context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_RECENT_OPEN:
final RootsCache roots = DocumentsApplication.getRootsCache(context);
final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
@@ -425,6 +436,20 @@ public class DirectoryFragment extends Fragment {
}
};
+ private RecyclerListener mRecycleListener = new RecyclerListener() {
+ @Override
+ public void onMovedToScrapHeap(View view) {
+ final ImageView iconThumb = (ImageView) view.findViewById(R.id.icon_thumb);
+ if (iconThumb != null) {
+ final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
+ if (oldTask != null) {
+ oldTask.reallyCancel();
+ iconThumb.setTag(null);
+ }
+ }
+ }
+ };
+
private void onShareDocuments(List<DocumentInfo> docs) {
Intent intent;
if (docs.size() == 1) {
@@ -632,7 +657,9 @@ public class DirectoryFragment extends Fragment {
final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY);
final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
- final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+ final View icon = convertView.findViewById(android.R.id.icon);
+ final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
+ final ImageView iconThumb = (ImageView) convertView.findViewById(R.id.icon_thumb);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
final View line2 = convertView.findViewById(R.id.line2);
final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1);
@@ -640,30 +667,49 @@ public class DirectoryFragment extends Fragment {
final TextView date = (TextView) convertView.findViewById(R.id.date);
final TextView size = (TextView) convertView.findViewById(R.id.size);
- final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) icon.getTag();
+ final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
if (oldTask != null) {
- oldTask.cancel(false);
+ oldTask.reallyCancel();
+ iconThumb.setTag(null);
}
+ iconMime.animate().cancel();
+ iconThumb.animate().cancel();
+
final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
|| MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);
+ boolean cacheHit = false;
if (supportsThumbnail && allowThumbnail) {
final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId);
final Bitmap cachedResult = thumbs.get(uri);
if (cachedResult != null) {
- icon.setImageBitmap(cachedResult);
+ iconThumb.setImageBitmap(cachedResult);
+ cacheHit = true;
} else {
- final ThumbnailAsyncTask task = new ThumbnailAsyncTask(icon, mThumbSize);
- icon.setImageBitmap(null);
- icon.setTag(task);
- task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, uri);
+ iconThumb.setImageDrawable(null);
+ final ThumbnailAsyncTask task = new ThumbnailAsyncTask(
+ uri, iconMime, iconThumb, mThumbSize);
+ iconThumb.setTag(task);
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
- } else if (docIcon != 0) {
- icon.setImageDrawable(IconUtils.loadPackageIcon(context, docAuthority, docIcon));
+ }
+
+ // Always throw MIME icon into place, even when a thumbnail is being
+ // loaded in background.
+ if (cacheHit) {
+ iconMime.setAlpha(0f);
+ iconThumb.setAlpha(1f);
} else {
- icon.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType));
+ iconMime.setAlpha(1f);
+ iconThumb.setAlpha(0f);
+ if (docIcon != 0) {
+ iconMime.setImageDrawable(
+ IconUtils.loadPackageIcon(context, docAuthority, docIcon));
+ } else {
+ iconMime.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType));
+ }
}
title.setText(docDisplayName);
@@ -672,12 +718,19 @@ public class DirectoryFragment extends Fragment {
if (mType == TYPE_RECENT_OPEN) {
final RootInfo root = roots.getRoot(docAuthority, docRootId);
+ final Drawable iconDrawable = root.loadIcon(context);
icon1.setVisibility(View.VISIBLE);
- icon1.setImageDrawable(root.loadIcon(context));
- summary.setText(root.getDirectoryString());
- summary.setVisibility(View.VISIBLE);
- summary.setTextAlignment(TextView.TEXT_ALIGNMENT_TEXT_END);
- hasLine2 = true;
+ icon1.setImageDrawable(iconDrawable);
+
+ if (iconDrawable != null && roots.isIconUnique(root)) {
+ // No summary needed if icon speaks for itself
+ summary.setVisibility(View.INVISIBLE);
+ } else {
+ summary.setText(root.getDirectoryString());
+ summary.setVisibility(View.VISIBLE);
+ summary.setTextAlignment(TextView.TEXT_ALIGNMENT_TEXT_END);
+ hasLine2 = true;
+ }
} else {
icon1.setVisibility(View.GONE);
if (docSummary != null) {
@@ -762,32 +815,39 @@ public class DirectoryFragment extends Fragment {
}
private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> {
- private final ImageView mTarget;
+ private final Uri mUri;
+ private final ImageView mIconMime;
+ private final ImageView mIconThumb;
private final Point mThumbSize;
+ private final CancellationSignal mSignal;
- public ThumbnailAsyncTask(ImageView target, Point thumbSize) {
- mTarget = target;
+ public ThumbnailAsyncTask(
+ Uri uri, ImageView iconMime, ImageView iconThumb, Point thumbSize) {
+ mUri = uri;
+ mIconMime = iconMime;
+ mIconThumb = iconThumb;
mThumbSize = thumbSize;
+ mSignal = new CancellationSignal();
}
- @Override
- protected void onPreExecute() {
- mTarget.setTag(this);
+ public void reallyCancel() {
+ cancel(false);
+ mSignal.cancel();
}
@Override
protected Bitmap doInBackground(Uri... params) {
- final Context context = mTarget.getContext();
- final Uri uri = params[0];
+ final Context context = mIconThumb.getContext();
Bitmap result = null;
try {
+ // TODO: switch to using unstable provider
result = DocumentsContract.getDocumentThumbnail(
- context.getContentResolver(), uri, mThumbSize, null);
+ context.getContentResolver(), mUri, mThumbSize, mSignal);
if (result != null) {
final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
context, mThumbSize);
- thumbs.put(uri, result);
+ thumbs.put(mUri, result);
}
} catch (Exception e) {
Log.w(TAG, "Failed to load thumbnail: " + e);
@@ -797,9 +857,14 @@ public class DirectoryFragment extends Fragment {
@Override
protected void onPostExecute(Bitmap result) {
- if (mTarget.getTag() == this) {
- mTarget.setImageBitmap(result);
- mTarget.setTag(null);
+ if (mIconThumb.getTag() == this && result != null) {
+ mIconThumb.setTag(null);
+ mIconThumb.setImageBitmap(result);
+
+ mIconMime.setAlpha(1f);
+ mIconMime.animate().alpha(0f).start();
+ mIconThumb.setAlpha(0f);
+ mIconThumb.animate().alpha(1f).start();
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 1471836..334e262 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -62,6 +62,7 @@ class DirectoryResult implements AutoCloseable {
public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
+ private final int mType;
private final RootInfo mRoot;
private final DocumentInfo mDoc;
private final Uri mUri;
@@ -70,9 +71,10 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
private CancellationSignal mSignal;
private DirectoryResult mResult;
- public DirectoryLoader(
- Context context, RootInfo root, DocumentInfo doc, Uri uri, int userSortOrder) {
+ public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
+ int userSortOrder) {
super(context);
+ mType = type;
mRoot = root;
mDoc = doc;
mUri = uri;
@@ -128,6 +130,11 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
}
}
+ // Search always uses ranking from provider
+ if (mType == DirectoryFragment.TYPE_SEARCH) {
+ result.sortOrder = State.SORT_ORDER_UNKNOWN;
+ }
+
Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
+ result.mode + ", sortOrder=" + result.sortOrder);
@@ -137,11 +144,18 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
mUri, null, null, null, getQuerySortOrder(result.sortOrder), mSignal);
cursor.registerContentObserver(mObserver);
- final Cursor withRoot = new RootCursorWrapper(
- mUri.getAuthority(), mRoot.rootId, cursor, -1);
- final Cursor sorted = new SortingCursorWrapper(withRoot, result.sortOrder);
+ cursor = new RootCursorWrapper(mUri.getAuthority(), mRoot.rootId, cursor, -1);
+
+ if (mType == DirectoryFragment.TYPE_SEARCH) {
+ // Filter directories out of search results, for now
+ cursor = new FilteringCursorWrapper(cursor, null, new String[] {
+ Document.MIME_TYPE_DIR });
+ } else {
+ // Normal directories should have sorting applied
+ cursor = new SortingCursorWrapper(cursor, result.sortOrder);
+ }
- result.cursor = sorted;
+ result.cursor = cursor;
} catch (Exception e) {
Log.d(TAG, "Failed to query", e);
result.exception = e;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 79d2443..e89d388 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -50,6 +50,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.MenuItem.OnActionExpandListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
@@ -87,6 +88,7 @@ public class DocumentsActivity extends Activity {
private static final String EXTRA_STATE = "state";
private boolean mIgnoreNextNavigation;
+ private boolean mIgnoreNextCollapse;
private RootsCache mRoots;
private State mState;
@@ -234,12 +236,14 @@ public class DocumentsActivity extends Activity {
public void onDrawerOpened(View drawerView) {
mDrawerToggle.onDrawerOpened(drawerView);
updateActionBar();
+ invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View drawerView) {
mDrawerToggle.onDrawerClosed(drawerView);
updateActionBar();
+ invalidateOptionsMenu();
}
@Override
@@ -305,7 +309,6 @@ public class DocumentsActivity extends Activity {
public boolean onQueryTextSubmit(String query) {
mState.currentSearch = query;
onCurrentDirectoryChanged();
- mSearchView.setIconified(true);
return true;
}
@@ -315,12 +318,22 @@ public class DocumentsActivity extends Activity {
}
});
- mSearchView.setOnCloseListener(new OnCloseListener() {
+ searchMenu.setOnActionExpandListener(new OnActionExpandListener() {
@Override
- public boolean onClose() {
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return true;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ if (mIgnoreNextCollapse) {
+ mIgnoreNextCollapse = false;
+ return true;
+ }
+
mState.currentSearch = null;
onCurrentDirectoryChanged();
- return false;
+ return true;
}
});
@@ -342,6 +355,18 @@ public class DocumentsActivity extends Activity {
final MenuItem list = menu.findItem(R.id.menu_list);
final MenuItem settings = menu.findItem(R.id.menu_settings);
+ // Open drawer means we hide most actions
+ if (mDrawerLayout.isDrawerOpen(mRootsContainer)) {
+ createDir.setVisible(false);
+ search.setVisible(false);
+ sort.setVisible(false);
+ grid.setVisible(false);
+ list.setVisible(false);
+ mIgnoreNextCollapse = true;
+ search.collapseActionView();
+ return true;
+ }
+
if (cwd != null) {
sort.setVisible(true);
grid.setVisible(mState.derivedMode != MODE_GRID);
@@ -352,6 +377,17 @@ public class DocumentsActivity extends Activity {
list.setVisible(false);
}
+ if (mState.currentSearch != null) {
+ // Search uses backend ranking; no sorting
+ sort.setVisible(false);
+
+ search.expandActionView();
+ mSearchView.setQuery(mState.currentSearch, false);
+ } else {
+ mIgnoreNextCollapse = true;
+ search.collapseActionView();
+ }
+
// Only sort by size when visible
sortSize.setVisible(mState.showSize);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
index 0a6cbc0..180ddef 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -56,7 +56,11 @@ public class DocumentsApplication extends Application {
packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilter.addDataScheme("package");
- registerReceiver(mPackageReceiver, packageFilter);
+ registerReceiver(mCacheReceiver, packageFilter);
+
+ final IntentFilter localeFilter = new IntentFilter();
+ localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
+ registerReceiver(mCacheReceiver, localeFilter);
}
@Override
@@ -70,7 +74,7 @@ public class DocumentsApplication extends Application {
}
}
- private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: narrow changed/removed to only packages that have backends
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
index 60f0103..5f56963 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
@@ -34,6 +34,10 @@ public class FilteringCursorWrapper extends AbstractCursor {
private int mCount;
public FilteringCursorWrapper(Cursor cursor, String[] acceptMimes) {
+ this(cursor, acceptMimes, null);
+ }
+
+ public FilteringCursorWrapper(Cursor cursor, String[] acceptMimes, String[] rejectMimes) {
mCursor = cursor;
final int count = cursor.getCount();
@@ -43,6 +47,9 @@ public class FilteringCursorWrapper extends AbstractCursor {
while (cursor.moveToNext()) {
final String mimeType = cursor.getString(
cursor.getColumnIndex(Document.COLUMN_MIME_TYPE));
+ if (rejectMimes != null && MimePredicate.mimeMatches(rejectMimes, mimeType)) {
+ continue;
+ }
if (MimePredicate.mimeMatches(acceptMimes, mimeType)) {
mPosition[mCount++] = cursor.getPosition();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 3642478..140373b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -183,12 +183,12 @@ public class RecentsCreateFragment extends Fragment {
convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
}
- final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+ final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
final View line2 = convertView.findViewById(R.id.line2);
final DocumentStack stack = getItem(position);
- icon.setImageDrawable(stack.root.loadIcon(context));
+ iconMime.setImageDrawable(stack.root.loadIcon(context));
final Drawable crumb = context.getResources()
.getDrawable(R.drawable.ic_breadcrumb_arrow);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index 1fe5d54..af79c93 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -151,18 +151,18 @@ public class RecentsProvider extends ContentProvider {
case URI_RECENT:
final long cutoff = System.currentTimeMillis() - MAX_HISTORY_IN_MILLIS;
return db.query(TABLE_RECENT, projection, RecentColumns.TIMESTAMP + ">" + cutoff,
- null, null, null, null);
+ null, null, null, sortOrder);
case URI_STATE:
final String authority = uri.getPathSegments().get(1);
final String rootId = uri.getPathSegments().get(2);
final String documentId = uri.getPathSegments().get(3);
return db.query(TABLE_STATE, projection, StateColumns.AUTHORITY + "=? AND "
+ StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
- new String[] { authority, rootId, documentId }, null, null, null);
+ new String[] { authority, rootId, documentId }, null, null, sortOrder);
case URI_RESUME:
final String packageName = uri.getPathSegments().get(1);
return db.query(TABLE_RESUME, projection, ResumeColumns.PACKAGE_NAME + "=?",
- new String[] { packageName }, null, null, null);
+ new String[] { packageName }, null, null, sortOrder);
default:
throw new UnsupportedOperationException("Unsupported Uri " + uri);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index adf4701..b48674cf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -109,6 +109,8 @@ public class RootsCache {
}
}
}
+
+ Log.d(TAG, "Update found " + mRoots.size() + " roots");
}
@Deprecated
@@ -134,6 +136,21 @@ public class RootsCache {
}
@GuardedBy("ActivityThread")
+ public boolean isIconUnique(RootInfo root) {
+ for (RootInfo test : mRoots) {
+ if (Objects.equal(test.authority, root.authority)) {
+ if (Objects.equal(test.rootId, root.rootId)) {
+ continue;
+ }
+ if (test.icon == root.icon) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ @GuardedBy("ActivityThread")
public RootInfo getRecentsRoot() {
return mRecentsRoot;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index efb972d..f3a21c6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.provider.DocumentsContract.Root;
+import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
@@ -168,7 +169,7 @@ public class RootsFragment extends Fragment {
}
summary.setText(summaryText);
- summary.setVisibility(summaryText != null ? View.VISIBLE : View.GONE);
+ summary.setVisibility(TextUtils.isEmpty(summaryText) ? View.GONE : View.VISIBLE);
return convertView;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index e0e8acf..b5a198c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.DocumentsContract.Root;
+import android.text.TextUtils;
import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
@@ -203,6 +204,6 @@ public class RootInfo implements Durable, Parcelable {
}
public String getDirectoryString() {
- return (summary != null) ? summary : title;
+ return !TextUtils.isEmpty(summary) ? summary : title;
}
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 2326ec2..ada3ad7 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -267,16 +267,15 @@ public class ExternalStorageProvider extends DocumentsProvider {
final LinkedList<File> pending = new LinkedList<File>();
pending.add(parent);
- while (!pending.isEmpty() && result.getCount() < 20) {
+ while (!pending.isEmpty() && result.getCount() < 24) {
final File file = pending.removeFirst();
if (file.isDirectory()) {
for (File child : file.listFiles()) {
pending.add(child);
}
- } else {
- if (file.getName().toLowerCase().contains(query)) {
- includeFile(result, null, file);
- }
+ }
+ if (file.getName().toLowerCase().contains(query)) {
+ includeFile(result, null, file);
}
}
return result;