am 118cb035: Merge "Filter roots based on incoming request." into klp-dev
* commit '118cb0353f6dabce1a1d6b550f7fc9eb78c7de87':
Filter roots based on incoming request.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index c24341e..5b23ca5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -191,7 +191,9 @@
authority, docId, query);
return new DirectoryLoader(context, rootId, contentsUri, state.sortOrder);
case TYPE_RECENT_OPEN:
- return new RecentLoader(context);
+ final RootsCache roots = DocumentsApplication.getRootsCache(context);
+ final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
+ return new RecentLoader(context, matchingRoots);
default:
throw new IllegalStateException("Unknown type " + mType);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index da790cc..f569f5a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -161,6 +161,7 @@
}
mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
+ mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);
if (mState.action == ACTION_MANAGE) {
mState.sortOrder = SORT_ORDER_LAST_MODIFIED;
@@ -701,6 +702,7 @@
public boolean allowMultiple = false;
public boolean showSize = false;
public boolean localOnly = false;
+ public boolean showAdvanced = false;
/** Current user navigation stack; empty implies recents. */
public DocumentStack stack = new DocumentStack();
@@ -733,6 +735,7 @@
out.writeInt(allowMultiple ? 1 : 0);
out.writeInt(showSize ? 1 : 0);
out.writeInt(localOnly ? 1 : 0);
+ out.writeInt(showAdvanced ? 1 : 0);
DurableUtils.writeToParcel(out, stack);
out.writeString(currentSearch);
}
@@ -748,6 +751,7 @@
state.allowMultiple = in.readInt() != 0;
state.showSize = in.readInt() != 0;
state.localOnly = in.readInt() != 0;
+ state.showAdvanced = in.readInt() != 0;
DurableUtils.readFromParcel(in, state.stack);
state.currentSearch = in.readString();
return state;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index 5f6fd13..756a297 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -78,6 +78,8 @@
return executor;
}
+ private final List<RootInfo> mRoots;
+
private final HashMap<RootInfo, RecentTask> mTasks = Maps.newHashMap();
private final int mSortOrder = State.SORT_ORDER_LAST_MODIFIED;
@@ -133,8 +135,9 @@
}
}
- public RecentLoader(Context context) {
+ public RecentLoader(Context context, List<RootInfo> roots) {
super(context);
+ mRoots = roots;
}
@Override
@@ -143,8 +146,7 @@
// First time through we kick off all the recent tasks, and wait
// around to see if everyone finishes quickly.
- final RootsCache roots = DocumentsApplication.getRootsCache(getContext());
- for (RootInfo root : roots.getRoots()) {
+ for (RootInfo root : mRoots) {
if ((root.flags & Root.FLAG_SUPPORTS_RECENTS) != 0) {
final RecentTask task = new RecentTask(root.authority, root.rootId);
mTasks.put(root, task);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index ac3b740..0b10f19 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -33,6 +33,7 @@
import android.provider.DocumentsContract.Root;
import android.util.Log;
+import com.android.documentsui.DocumentsActivity.State;
import com.android.documentsui.model.RootInfo;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Objects;
@@ -40,6 +41,7 @@
import libcore.io.IoUtils;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -75,6 +77,7 @@
final RootInfo root = new RootInfo();
root.rootType = Root.ROOT_TYPE_SHORTCUT;
root.icon = R.drawable.ic_dir;
+ root.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE;
root.title = mContext.getString(R.string.root_recent);
root.availableBytes = -1;
@@ -150,6 +153,60 @@
return mRoots;
}
+ /**
+ * Flags that declare explicit content types.
+ */
+ private static final int FLAGS_CONTENT_MASK = Root.FLAG_PROVIDES_IMAGES
+ | Root.FLAG_PROVIDES_AUDIO | Root.FLAG_PROVIDES_VIDEO;
+
+ @GuardedBy("ActivityThread")
+ public List<RootInfo> getMatchingRoots(State state) {
+
+ // Determine acceptable content flags
+ int includeFlags = 0;
+ for (String acceptMime : state.acceptMimes) {
+ final String[] type = acceptMime.split("/");
+ if (type.length != 2) continue;
+
+ if ("image".equals(type[0])) {
+ includeFlags |= Root.FLAG_PROVIDES_IMAGES;
+ } else if ("audio".equals(type[0])) {
+ includeFlags |= Root.FLAG_PROVIDES_AUDIO;
+ } else if ("video".equals(type[0])) {
+ includeFlags |= Root.FLAG_PROVIDES_VIDEO;
+ } else if ("*".equals(type[0])) {
+ includeFlags |= Root.FLAG_PROVIDES_IMAGES | Root.FLAG_PROVIDES_AUDIO
+ | Root.FLAG_PROVIDES_VIDEO;
+ }
+ }
+
+ ArrayList<RootInfo> matching = Lists.newArrayList();
+ for (RootInfo root : mRoots) {
+ final boolean supportsCreate = (root.flags & Root.FLAG_SUPPORTS_CREATE) != 0;
+ final boolean advanced = (root.flags & Root.FLAG_ADVANCED) != 0;
+ final boolean localOnly = (root.flags & Root.FLAG_LOCAL_ONLY) != 0;
+
+ // Exclude read-only devices when creating
+ if (state.action == State.ACTION_CREATE && !supportsCreate) continue;
+ // Exclude advanced devices when not requested
+ if (!state.showAdvanced && advanced) continue;
+ // Exclude non-local devices when local only
+ if (state.localOnly && !localOnly) continue;
+
+ if ((root.flags & FLAGS_CONTENT_MASK) != 0) {
+ // This root offers specific content, so only include if the
+ // caller asked for that content type.
+ if ((root.flags & includeFlags) == 0) {
+ // Sorry, no overlap.
+ continue;
+ }
+ }
+
+ matching.add(root);
+ }
+ return matching;
+ }
+
@GuardedBy("ActivityThread")
public static Drawable resolveDocumentIcon(Context context, String mimeType) {
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 3102b88..ef3a31d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -16,8 +16,6 @@
package com.android.documentsui;
-import static com.android.documentsui.DocumentsActivity.TAG;
-
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
@@ -28,7 +26,6 @@
import android.os.Bundle;
import android.provider.DocumentsContract.Root;
import android.text.format.Formatter;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -39,6 +36,7 @@
import android.widget.ListView;
import android.widget.TextView;
+import com.android.documentsui.DocumentsActivity.State;
import com.android.documentsui.SectionedListAdapter.SectionAdapter;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
@@ -76,24 +74,31 @@
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final Context context = inflater.getContext();
- final RootsCache roots = DocumentsApplication.getRootsCache(context);
final View view = inflater.inflate(R.layout.fragment_roots, container, false);
mList = (ListView) view.findViewById(android.R.id.list);
mList.setOnItemClickListener(mItemListener);
- final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
- mAdapter = new SectionedRootsAdapter(context, roots.getRoots(), includeApps);
-
return view;
}
@Override
public void onStart() {
super.onStart();
+ updateRootsAdapter();
+ }
+ private void updateRootsAdapter() {
final Context context = getActivity();
- mAdapter.updateVisible(SettingsActivity.getDisplayAdvancedDevices(context));
+
+ final State state = ((DocumentsActivity) context).getDisplayState();
+ state.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(context);
+
+ final RootsCache roots = DocumentsApplication.getRootsCache(context);
+ final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
+ final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
+
+ mAdapter = new SectionedRootsAdapter(context, matchingRoots, includeApps);
mList.setAdapter(mAdapter);
}
@@ -211,18 +216,15 @@
private final RootsAdapter mServices;
private final RootsAdapter mShortcuts;
private final RootsAdapter mDevices;
- private final RootsAdapter mDevicesAdvanced;
private final AppsAdapter mApps;
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 (RootInfo root : roots) {
- Log.d(TAG, "Found rootType=" + root.rootType);
switch (root.rootType) {
case Root.ROOT_TYPE_SERVICE:
mServices.add(root);
@@ -231,10 +233,7 @@
mShortcuts.add(root);
break;
case Root.ROOT_TYPE_DEVICE:
- mDevicesAdvanced.add(root);
- if ((root.flags & Root.FLAG_ADVANCED) == 0) {
- mDevices.add(root);
- }
+ mDevices.add(root);
break;
}
}
@@ -256,23 +255,16 @@
mServices.sort(comp);
mShortcuts.sort(comp);
mDevices.sort(comp);
- mDevicesAdvanced.sort(comp);
- }
- public void updateVisible(boolean showAdvanced) {
- clearSections();
if (mServices.getCount() > 0) {
addSection(mServices);
}
if (mShortcuts.getCount() > 0) {
addSection(mShortcuts);
}
-
- final RootsAdapter devices = showAdvanced ? mDevicesAdvanced : mDevices;
- if (devices.getCount() > 0) {
- addSection(devices);
+ if (mDevices.getCount() > 0) {
+ addSection(mDevices);
}
-
if (mApps.getCount() > 0) {
addSection(mApps);
}
@@ -282,6 +274,12 @@
public static class RootComparator implements Comparator<RootInfo> {
@Override
public int compare(RootInfo lhs, RootInfo rhs) {
+ if (lhs.authority == null) {
+ return -1;
+ } else if (rhs.authority == null) {
+ return 1;
+ }
+
final int score = DocumentInfo.compareToIgnoreCaseNullable(lhs.title, rhs.title);
if (score != 0) {
return score;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
index f6548e8..2405cb5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
@@ -32,7 +32,6 @@
import libcore.io.IoUtils;
import libcore.io.Streams;
-import java.io.IOException;
import java.io.InputStream;
public class TestActivity extends Activity {
@@ -50,8 +49,11 @@
view.setOrientation(LinearLayout.VERTICAL);
final CheckBox multiple = new CheckBox(context);
- multiple.setText("ALLOW_MULTIPLE");
+ multiple.setText("\nALLOW_MULTIPLE\n");
view.addView(multiple);
+ final CheckBox localOnly = new CheckBox(context);
+ localOnly.setText("\nLOCAL_ONLY\n");
+ view.addView(localOnly);
Button button;
button = new Button(context);
@@ -65,6 +67,9 @@
if (multiple.isChecked()) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
+ if (localOnly.isChecked()) {
+ intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+ }
startActivityForResult(intent, 42);
}
});
@@ -81,6 +86,28 @@
if (multiple.isChecked()) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
+ if (localOnly.isChecked()) {
+ intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+ }
+ startActivityForResult(intent, 42);
+ }
+ });
+ view.addView(button);
+
+ button = new Button(context);
+ button.setText("OPEN_DOC audio/ogg");
+ button.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("audio/ogg");
+ if (multiple.isChecked()) {
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ }
+ if (localOnly.isChecked()) {
+ intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+ }
startActivityForResult(intent, 42);
}
});
@@ -99,6 +126,9 @@
if (multiple.isChecked()) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
+ if (localOnly.isChecked()) {
+ intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+ }
startActivityForResult(intent, 42);
}
});
@@ -113,6 +143,9 @@
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TITLE, "foobar.txt");
+ if (localOnly.isChecked()) {
+ intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+ }
startActivityForResult(intent, 42);
}
});
@@ -129,6 +162,9 @@
if (multiple.isChecked()) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
+ if (localOnly.isChecked()) {
+ intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+ }
startActivityForResult(Intent.createChooser(intent, "Kittens!"), 42);
}
});
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index de8c29a..bbe3b45 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -87,9 +87,7 @@
final RootInfo root = new RootInfo();
root.rootId = "primary";
root.rootType = Root.ROOT_TYPE_DEVICE;
- root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
- | Root.FLAG_PROVIDES_AUDIO | Root.FLAG_PROVIDES_VIDEO
- | Root.FLAG_PROVIDES_IMAGES;
+ root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED;
root.icon = R.drawable.ic_pdf;
root.title = getContext().getString(R.string.root_internal_storage);
root.docId = getDocIdForFile(path);