Merge "Undo generalization isDownloads > supportsChildren." into nyc-dev
am: fdfd5b60fc
* commit 'fdfd5b60fc7b62d2a3af97af39abde8c5067eada':
Undo generalization isDownloads > supportsChildren.
This commit is contained in:
@@ -18,6 +18,7 @@ package com.android.documentsui;
|
||||
|
||||
import static com.android.documentsui.Shared.DEBUG;
|
||||
import static com.android.documentsui.Shared.TAG;
|
||||
import static com.android.internal.util.Preconditions.checkState;
|
||||
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentResolver;
|
||||
@@ -40,6 +41,7 @@ import android.util.Log;
|
||||
|
||||
import com.android.documentsui.model.RootInfo;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
@@ -85,15 +87,13 @@ public class RootsCache {
|
||||
|
||||
// Create a new anonymous "Recents" RootInfo. It's a faker.
|
||||
mRecentsRoot = new RootInfo() {{
|
||||
// Special root for recents
|
||||
authority = null;
|
||||
rootId = null;
|
||||
derivedIcon = R.drawable.ic_root_recent;
|
||||
derivedType = RootInfo.TYPE_RECENTS;
|
||||
flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD;
|
||||
title = mContext.getString(R.string.root_recent);
|
||||
availableBytes = -1;
|
||||
}};
|
||||
// Special root for recents
|
||||
derivedIcon = R.drawable.ic_root_recent;
|
||||
derivedType = RootInfo.TYPE_RECENTS;
|
||||
flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD;
|
||||
title = mContext.getString(R.string.root_recent);
|
||||
availableBytes = -1;
|
||||
}};
|
||||
}
|
||||
|
||||
private class RootsChangedObserver extends ContentObserver {
|
||||
@@ -116,6 +116,16 @@ public class RootsCache {
|
||||
* Gather roots from all known storage providers.
|
||||
*/
|
||||
public void updateAsync() {
|
||||
// Verifying an assumption about the recents root being immutable.
|
||||
if (DEBUG) {
|
||||
checkState(mRecentsRoot.authority == null);
|
||||
checkState(mRecentsRoot.rootId == null);
|
||||
checkState(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent);
|
||||
checkState(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS);
|
||||
checkState(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_IS_CHILD));
|
||||
checkState(mRecentsRoot.title == mContext.getString(R.string.root_recent));
|
||||
checkState(mRecentsRoot.availableBytes == -1);
|
||||
}
|
||||
new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
@@ -412,9 +422,10 @@ public class RootsCache {
|
||||
if (!state.showAdvanced && root.isAdvanced()) continue;
|
||||
// Exclude non-local devices when local only
|
||||
if (state.localOnly && !root.isLocalOnly()) continue;
|
||||
// Exclude downloads roots that don't support directory creation
|
||||
// TODO: Add flag to check the root supports directory creation or not.
|
||||
if (state.directoryCopy && !root.supportsChildren()) 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;
|
||||
|
||||
// Only show empty roots when creating, or in browse mode.
|
||||
if (root.isEmpty() && (state.action == State.ACTION_OPEN
|
||||
|
||||
@@ -45,7 +45,6 @@ import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.documentsui.model.DocumentInfo;
|
||||
import com.android.documentsui.model.RootInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -403,17 +402,7 @@ public class RootsFragment extends Fragment {
|
||||
public static class RootComparator implements Comparator<RootItem> {
|
||||
@Override
|
||||
public int compare(RootItem lhs, RootItem rhs) {
|
||||
// Sort by root type, then title, then summary.
|
||||
int score = lhs.root.derivedType - rhs.root.derivedType;
|
||||
if (score != 0) {
|
||||
return score;
|
||||
}
|
||||
score = DocumentInfo.compareToIgnoreCaseNullable(lhs.root.title, rhs.root.title);
|
||||
if (score != 0) {
|
||||
return score;
|
||||
}
|
||||
|
||||
return DocumentInfo.compareToIgnoreCaseNullable(lhs.root.summary, rhs.root.summary);
|
||||
return lhs.root.compareTo(rhs.root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,17 @@
|
||||
package com.android.documentsui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.text.format.Time;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** @hide */
|
||||
public final class Shared {
|
||||
|
||||
/** Intent action name to pick a copy destination. */
|
||||
public static final String ACTION_PICK_COPY_DESTINATION =
|
||||
"com.android.documentsui.PICK_COPY_DESTINATION";
|
||||
@@ -39,6 +42,19 @@ public final class Shared {
|
||||
public static final String TAG = "Documents";
|
||||
public static final String EXTRA_STACK = "com.android.documentsui.STACK";
|
||||
|
||||
|
||||
/**
|
||||
* String prefix used to indicate the document is a directory.
|
||||
*/
|
||||
public static final char DIR_PREFIX = '\001';
|
||||
|
||||
private static final Collator sCollator;
|
||||
|
||||
static {
|
||||
sCollator = Collator.getInstance();
|
||||
sCollator.setStrength(Collator.SECONDARY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a formatted quantity string.
|
||||
*/
|
||||
@@ -76,4 +92,26 @@ public final class Shared {
|
||||
? (ArrayList<T>) list
|
||||
: new ArrayList<T>(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two strings against each other using system default collator in a
|
||||
* case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX}
|
||||
* before other items.
|
||||
*/
|
||||
public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
|
||||
final boolean leftEmpty = TextUtils.isEmpty(lhs);
|
||||
final boolean rightEmpty = TextUtils.isEmpty(rhs);
|
||||
|
||||
if (leftEmpty && rightEmpty) return 0;
|
||||
if (leftEmpty) return -1;
|
||||
if (rightEmpty) return 1;
|
||||
|
||||
final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX);
|
||||
final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX);
|
||||
|
||||
if (leftDir && !rightDir) return -1;
|
||||
if (rightDir && !leftDir) return 1;
|
||||
|
||||
return sCollator.compare(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1071,8 +1071,8 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't copy folders to roots that don't support children.
|
||||
if (!root.supportsChildren()) {
|
||||
// Can't copy folders to downloads, because we don't show folders there.
|
||||
if (!root.isDownloads()) {
|
||||
for (DocumentInfo docs : files) {
|
||||
if (docs.isDirectory()) {
|
||||
return false;
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.util.Log;
|
||||
|
||||
import com.android.documentsui.DirectoryResult;
|
||||
import com.android.documentsui.RootCursorWrapper;
|
||||
import com.android.documentsui.Shared;
|
||||
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
|
||||
import com.android.documentsui.model.DocumentInfo;
|
||||
|
||||
@@ -170,7 +171,7 @@ public class Model {
|
||||
final String displayName = getCursorString(
|
||||
mCursor, Document.COLUMN_DISPLAY_NAME);
|
||||
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
|
||||
stringValues[pos] = DocumentInfo.DIR_PREFIX + displayName;
|
||||
stringValues[pos] = Shared.DIR_PREFIX + displayName;
|
||||
} else {
|
||||
stringValues[pos] = displayName;
|
||||
}
|
||||
@@ -227,7 +228,7 @@ public class Model {
|
||||
|
||||
final String lhs = pivotValue;
|
||||
final String rhs = sortKey[mid];
|
||||
final int compare = DocumentInfo.compareToIgnoreCaseNullable(lhs, rhs);
|
||||
final int compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
|
||||
|
||||
if (compare < 0) {
|
||||
right = mid;
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.provider.DocumentsContract;
|
||||
import android.provider.DocumentsContract.Document;
|
||||
import android.provider.DocumentsProvider;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.documentsui.DocumentsApplication;
|
||||
import com.android.documentsui.RootCursorWrapper;
|
||||
@@ -38,7 +37,6 @@ import java.io.DataOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import java.text.Collator;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -48,13 +46,6 @@ public class DocumentInfo implements Durable, Parcelable {
|
||||
private static final int VERSION_INIT = 1;
|
||||
private static final int VERSION_SPLIT_URI = 2;
|
||||
|
||||
private static final Collator sCollator;
|
||||
|
||||
static {
|
||||
sCollator = Collator.getInstance();
|
||||
sCollator.setStrength(Collator.SECONDARY);
|
||||
}
|
||||
|
||||
public String authority;
|
||||
public String documentId;
|
||||
public String mimeType;
|
||||
@@ -320,31 +311,4 @@ public class DocumentInfo implements Durable, Parcelable {
|
||||
fnfe.initCause(t);
|
||||
throw fnfe;
|
||||
}
|
||||
|
||||
/**
|
||||
* String prefix used to indicate the document is a directory.
|
||||
*/
|
||||
public static final char DIR_PREFIX = '\001';
|
||||
|
||||
/**
|
||||
* Compare two strings against each other using system default collator in a
|
||||
* case-insensitive mode. Clusters strings prefixed with {@link #DIR_PREFIX}
|
||||
* before other items.
|
||||
*/
|
||||
public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
|
||||
final boolean leftEmpty = TextUtils.isEmpty(lhs);
|
||||
final boolean rightEmpty = TextUtils.isEmpty(rhs);
|
||||
|
||||
if (leftEmpty && rightEmpty) return 0;
|
||||
if (leftEmpty) return -1;
|
||||
if (rightEmpty) return 1;
|
||||
|
||||
final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX);
|
||||
final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX);
|
||||
|
||||
if (leftDir && !rightDir) return -1;
|
||||
if (rightDir && !leftDir) return 1;
|
||||
|
||||
return sCollator.compare(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package com.android.documentsui.model;
|
||||
|
||||
import static com.android.documentsui.Shared.compareToIgnoreCaseNullable;
|
||||
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.annotation.IntDef;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -36,17 +38,31 @@ import com.android.documentsui.R;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.net.ProtocolException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Representation of a {@link Root}.
|
||||
*/
|
||||
public class RootInfo implements Durable, Parcelable {
|
||||
public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
|
||||
private static final int VERSION_INIT = 1;
|
||||
private static final int VERSION_DROP_TYPE = 2;
|
||||
|
||||
// The values of these constants determine the sort order of various roots in the RootsFragment.
|
||||
@IntDef(flag = true, value = {
|
||||
TYPE_IMAGES,
|
||||
TYPE_VIDEO,
|
||||
TYPE_AUDIO,
|
||||
TYPE_RECENTS,
|
||||
TYPE_DOWNLOADS,
|
||||
TYPE_LOCAL,
|
||||
TYPE_MTP,
|
||||
TYPE_OTHER
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface RootType {}
|
||||
public static final int TYPE_IMAGES = 1;
|
||||
public static final int TYPE_VIDEO = 2;
|
||||
public static final int TYPE_AUDIO = 3;
|
||||
@@ -69,7 +85,7 @@ public class RootInfo implements Durable, Parcelable {
|
||||
/** Derived fields that aren't persisted */
|
||||
public String[] derivedMimeTypes;
|
||||
public int derivedIcon;
|
||||
public int derivedType;
|
||||
public @RootType int derivedType;
|
||||
|
||||
public RootInfo() {
|
||||
reset();
|
||||
@@ -328,6 +344,22 @@ public class RootInfo implements Durable, Parcelable {
|
||||
return Objects.hash(authority, rootId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(RootInfo other) {
|
||||
// Sort by root type, then title, then summary.
|
||||
int score = derivedType - other.derivedType;
|
||||
if (score != 0) {
|
||||
return score;
|
||||
}
|
||||
|
||||
score = compareToIgnoreCaseNullable(title, other.title);
|
||||
if (score != 0) {
|
||||
return score;
|
||||
}
|
||||
|
||||
return compareToIgnoreCaseNullable(summary, other.summary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.test.suitebuilder.annotation.SmallTest;
|
||||
|
||||
import com.android.documentsui.DirectoryResult;
|
||||
import com.android.documentsui.RootCursorWrapper;
|
||||
import com.android.documentsui.Shared;
|
||||
import com.android.documentsui.State;
|
||||
import com.android.documentsui.dirlist.MultiSelectManager.Selection;
|
||||
import com.android.documentsui.model.DocumentInfo;
|
||||
@@ -190,7 +191,7 @@ public class ModelTest extends AndroidTestCase {
|
||||
|
||||
assertEquals(ITEM_COUNT, seen.cardinality());
|
||||
for (int i = 0; i < names.size()-1; ++i) {
|
||||
assertTrue(DocumentInfo.compareToIgnoreCaseNullable(names.get(i), names.get(i+1)) <= 0);
|
||||
assertTrue(Shared.compareToIgnoreCaseNullable(names.get(i), names.get(i+1)) <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user