Merge "Fix roots filtering for move operations." into nyc-dev

am: de5ec832b1

* commit 'de5ec832b10b155d1d61de4eedb5171da3a76a9c':
  Fix roots filtering for move operations.
This commit is contained in:
Steve McKay
2016-03-02 02:31:41 +00:00
committed by android-build-merger
2 changed files with 114 additions and 60 deletions

View File

@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.Shared.TAG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -62,6 +61,8 @@ public class RootsCache {
public static final Uri sNotificationUri = Uri.parse(
"content://com.android.documentsui.roots/");
private static final String TAG = "RootsCache";
private final Context mContext;
private final ContentObserver mObserver;
private OnCacheUpdateListener mCacheUpdateListener;
@@ -417,25 +418,56 @@ public class RootsCache {
static List<RootInfo> getMatchingRoots(Collection<RootInfo> roots, State state) {
final List<RootInfo> matching = new ArrayList<>();
for (RootInfo root : roots) {
// Exclude read-only devices when creating
if (state.action == State.ACTION_CREATE && !root.supportsCreate()) continue;
if (DEBUG) Log.d(TAG, "Evaluating " + root);
if (state.action == State.ACTION_CREATE && !root.supportsCreate()) {
if (DEBUG) Log.d(TAG, "Excluding read-only root because: ACTION_CREATE.");
continue;
}
if (state.action == State.ACTION_PICK_COPY_DESTINATION
&& !root.supportsCreate()) continue;
// Exclude roots that don't support directory picking
if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) continue;
// Exclude advanced devices when not requested
if (!state.showAdvanced && root.isAdvanced()) continue;
&& !root.supportsCreate()) {
if (DEBUG) Log.d(
TAG, "Excluding read-only root because: ACTION_PICK_COPY_DESTINATION.");
continue;
}
if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) {
if (DEBUG) Log.d(
TAG, "Excluding root !supportsChildren because: ACTION_OPEN_TREE.");
continue;
}
if (!state.showAdvanced && root.isAdvanced()) {
if (DEBUG) Log.d(TAG, "Excluding root because: unwanted advanced device.");
continue;
}
// Exclude non-local devices when local only
if (state.localOnly && !root.isLocalOnly()) continue;
if (state.localOnly && !root.isLocalOnly()) {
if (DEBUG) Log.d(TAG, "Excluding root because: unwanted non-local device.");
continue;
}
// Exclude downloads roots as it doesn't support directory creation (actually
// we just don't show them).
// TODO: Add flag to check the root supports directory creation.
if (state.directoryCopy && !root.isDownloads()) continue;
if (state.directoryCopy && root.isDownloads()) {
if (DEBUG) Log.d(
TAG, "Excluding downloads root because: unsupported directory copy.");
continue;
}
// Only show empty roots when creating, or in browse mode.
if (root.isEmpty() && (state.action == State.ACTION_OPEN
|| state.action == State.ACTION_GET_CONTENT)) {
if (DEBUG) Log.i(TAG, "Skipping empty root: " + root);
if (state.action == State.ACTION_OPEN && root.isEmpty()) {
if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_OPEN.");
continue;
}
// Only show empty roots when creating, or in browse mode.
if (state.action == State.ACTION_GET_CONTENT && root.isEmpty()) {
if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_GET_CONTENT.");
continue;
}
@@ -444,18 +476,19 @@ public class RootsCache {
MimePredicate.mimeMatches(root.derivedMimeTypes, state.acceptMimes) ||
MimePredicate.mimeMatches(state.acceptMimes, root.derivedMimeTypes);
if (!overlap) {
if (DEBUG) Log.d(
TAG, "Excluding root because: unsupported content types > "
+ state.acceptMimes);
continue;
}
// Exclude roots from the calling package.
if (state.excludedAuthorities.contains(root.authority)) {
if (DEBUG) Log.d(
TAG, "Excluding root " + root.authority + " from calling package.");
if (DEBUG) Log.d(TAG, "Excluding root because: calling package.");
continue;
}
if (DEBUG) Log.d(
TAG, "Including root " + root + " in roots list.");
if (DEBUG) Log.d(TAG, "Including " + root);
matching.add(root);
}
return matching;

View File

@@ -16,6 +16,9 @@
package com.android.documentsui;
import static com.android.documentsui.RootsCache.getMatchingRoots;
import static com.google.common.collect.Lists.newArrayList;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -28,23 +31,18 @@ import java.util.List;
@SmallTest
public class RootsCacheTest extends AndroidTestCase {
private static RootInfo buildForMimeTypes(String... mimeTypes) {
final RootInfo root = new RootInfo();
root.derivedMimeTypes = mimeTypes;
return root;
}
private static RootInfo mNull = new RootInfo();
private static RootInfo mEmpty = buildForMimeTypes();
private static RootInfo mWild = buildForMimeTypes("*/*");
private static RootInfo mImages = buildForMimeTypes("image/*");
private static RootInfo mAudio = buildForMimeTypes(
"audio/*", "application/ogg", "application/x-flac");
private static RootInfo mDocs = buildForMimeTypes(
"application/msword", "application/vnd.ms-excel");
private static RootInfo mMalformed1 = buildForMimeTypes("meow");
private static RootInfo mMalformed2 = buildForMimeTypes("*/meow");
private RootInfo mNull = new RootInfo();
private RootInfo mEmpty = buildForMimeTypes();
private RootInfo mWild = buildForMimeTypes("*/*");
private RootInfo mImages = buildForMimeTypes("image/*");
private RootInfo mAudio = buildForMimeTypes("audio/*", "application/ogg", "application/x-flac");
private RootInfo mDocs = buildForMimeTypes("application/msword", "application/vnd.ms-excel");
private RootInfo mMalformed1 = buildForMimeTypes("meow");
private RootInfo mMalformed2 = buildForMimeTypes("*/meow");
private List<RootInfo> mRoots = Lists.newArrayList(
mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
private List<RootInfo> mRoots;
private State mState;
@@ -52,70 +50,87 @@ public class RootsCacheTest extends AndroidTestCase {
protected void setUp() throws Exception {
super.setUp();
mRoots = Lists.newArrayList(
mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
mState = new State();
mState.action = State.ACTION_OPEN;
mState.showAdvanced = true;
mState.localOnly = false;
}
public void testMatchingRootsEverything() throws Exception {
public void testMatchingRoots_Everything() throws Exception {
mState.acceptMimes = new String[] { "*/*" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRootsPngOrWild() throws Exception {
public void testMatchingRoots_DirectoryCopy() throws Exception {
RootInfo downloads = buildForMimeTypes("*/*");
downloads.authority = "com.android.providers.downloads.documents";
mRoots.add(downloads);
mState.acceptMimes = new String[] { "*/*" };
mState.directoryCopy = true;
// basically we're asserting that the results don't contain downloads
assertContainsExactly(
newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRoots_PngOrWild() throws Exception {
mState.acceptMimes = new String[] { "image/png", "*/*" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRootsAudioWild() throws Exception {
public void testMatchingRoots_AudioWild() throws Exception {
mState.acceptMimes = new String[] { "audio/*" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mAudio),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mAudio),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRootsAudioWildOrImageWild() throws Exception {
public void testMatchingRoots_AudioWildOrImageWild() throws Exception {
mState.acceptMimes = new String[] { "audio/*", "image/*" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mAudio, mImages),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mAudio, mImages),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRootsAudioSpecific() throws Exception {
public void testMatchingRoots_AudioSpecific() throws Exception {
mState.acceptMimes = new String[] { "audio/mpeg" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mAudio),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mAudio),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRootsDocument() throws Exception {
public void testMatchingRoots_Document() throws Exception {
mState.acceptMimes = new String[] { "application/msword" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mDocs),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mDocs),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRootsApplication() throws Exception {
public void testMatchingRoots_Application() throws Exception {
mState.acceptMimes = new String[] { "application/*" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mAudio, mDocs),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mAudio, mDocs),
getMatchingRoots(mRoots, mState));
}
public void testMatchingRootsFlacOrPng() throws Exception {
public void testMatchingRoots_FlacOrPng() throws Exception {
mState.acceptMimes = new String[] { "application/x-flac", "image/png" };
assertContainsExactly(
Lists.newArrayList(mNull, mWild, mAudio, mImages),
RootsCache.getMatchingRoots(mRoots, mState));
newArrayList(mNull, mWild, mAudio, mImages),
getMatchingRoots(mRoots, mState));
}
public void testExcludedAuthorities() throws Exception {
final List<RootInfo> roots = Lists.newArrayList();
final List<RootInfo> roots = newArrayList();
// Set up some roots
for (int i = 0; i < 5; ++i) {
@@ -124,7 +139,7 @@ public class RootsCacheTest extends AndroidTestCase {
roots.add(root);
}
// Make some allowed authorities
List<RootInfo> allowedRoots = Lists.newArrayList(
List<RootInfo> allowedRoots = newArrayList(
roots.get(0), roots.get(2), roots.get(4));
// Set up the excluded authority list
for (RootInfo root: roots) {
@@ -136,7 +151,7 @@ public class RootsCacheTest extends AndroidTestCase {
assertContainsExactly(
allowedRoots,
RootsCache.getMatchingRoots(roots, mState));
getMatchingRoots(roots, mState));
}
private static void assertContainsExactly(List<?> expected, List<?> actual) {
@@ -145,4 +160,10 @@ public class RootsCacheTest extends AndroidTestCase {
assertTrue(actual.contains(o));
}
}
private static RootInfo buildForMimeTypes(String... mimeTypes) {
final RootInfo root = new RootInfo();
root.derivedMimeTypes = mimeTypes;
return root;
}
}