diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java index b539421068751..c44890c66d9c9 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java @@ -133,8 +133,7 @@ public final class Shared { /** * 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. + * case-insensitive mode. */ public static int compareToIgnoreCaseNullable(String lhs, String rhs) { final boolean leftEmpty = TextUtils.isEmpty(lhs); @@ -147,6 +146,14 @@ public final class Shared { return sCollator.compare(lhs, rhs); } + /** + * Compare two strings against each other using system default collator in a + * case-insensitive mode. + */ + public static int compareToIgnoreCase(String lhs, String rhs) { + return sCollator.compare(lhs, rhs); + } + public static boolean isHardwareKeyboardAvailable(Context context) { return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java index c5ee59237fb08..179cb9bd46e32 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java @@ -20,8 +20,6 @@ import static com.android.documentsui.Shared.DEBUG; import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME; import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED; import static com.android.documentsui.State.SORT_ORDER_SIZE; -import static com.android.documentsui.model.DocumentInfo.getCursorLong; -import static com.android.documentsui.model.DocumentInfo.getCursorString; import android.database.Cursor; import android.os.Bundle; @@ -48,6 +46,7 @@ import java.util.Map; @VisibleForTesting public class Model { private static final String TAG = "Model"; + private static final String EMPTY = ""; private boolean mIsLoading; private List mUpdateListeners = new ArrayList<>(); @@ -62,24 +61,17 @@ public class Model { private String mIds[] = new String[0]; private int mSortOrder = SORT_ORDER_DISPLAY_NAME; + private int mAuthorityIndex = -1; + private int mDocIdIndex = -1; + private int mMimeTypeIndex = -1; + private int mDisplayNameIndex = -1; + private int mSizeIndex = -1; + private int mLastModifiedIndex = -1; + @Nullable String info; @Nullable String error; @Nullable DocumentInfo doc; - /** - * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique - * string that can be used to identify the document referred to by the cursor. - * - * @param c A cursor that refers to a document. - */ - private static String createModelId(Cursor c) { - // TODO: Maybe more efficient to use just the document ID, in cases where there is only one - // authority (which should be the majority of cases). - return createModelId( - getCursorString(c, RootCursorWrapper.COLUMN_AUTHORITY), - getCursorString(c, Document.COLUMN_DOCUMENT_ID)); - } - /** * Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique * string that can be used to identify the document referred to by the cursor. @@ -127,6 +119,14 @@ public class Model { mCursor = result.cursor; mCursorCount = mCursor.getCount(); mSortOrder = result.sortOrder; + mAuthorityIndex = mCursor.getColumnIndex(RootCursorWrapper.COLUMN_AUTHORITY); + assert(mAuthorityIndex != -1); + mDocIdIndex = mCursor.getColumnIndex(Document.COLUMN_DOCUMENT_ID); + mMimeTypeIndex = mCursor.getColumnIndex(Document.COLUMN_MIME_TYPE); + mDisplayNameIndex = mCursor.getColumnIndex(Document.COLUMN_DISPLAY_NAME); + mLastModifiedIndex = mCursor.getColumnIndex(Document.COLUMN_LAST_MODIFIED); + mSizeIndex = mCursor.getColumnIndex(Document.COLUMN_SIZE); + doc = result.doc; updateModelData(); @@ -173,22 +173,24 @@ public class Model { for (int pos = 0; pos < mCursorCount; ++pos) { mCursor.moveToNext(); positions[pos] = pos; - mIds[pos] = createModelId(mCursor); - mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE); + // Generates a Model ID for a cursor entry that refers to a document. The Model ID is a + // unique string that can be used to identify the document referred to by the cursor. + mIds[pos] = createModelId( + getStringOrEmpty(mAuthorityIndex), getStringOrEmpty(mDocIdIndex)); + + mimeType = getStringOrEmpty(mMimeTypeIndex); isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType); - switch(mSortOrder) { + switch (mSortOrder) { case SORT_ORDER_DISPLAY_NAME: - final String displayName = getCursorString( - mCursor, Document.COLUMN_DISPLAY_NAME); - displayNames[pos] = displayName; + displayNames[pos] = getStringOrEmpty(mDisplayNameIndex); break; case SORT_ORDER_LAST_MODIFIED: - longValues[pos] = getLastModified(mCursor); + longValues[pos] = getLastModified(); break; case SORT_ORDER_SIZE: - longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE); + longValues[pos] = getDocSize(); break; } } @@ -244,7 +246,7 @@ public class Model { } else { final String lhs = pivotValue; final String rhs = sortKey[mid]; - compare = Shared.compareToIgnoreCaseNullable(lhs, rhs); + compare = Shared.compareToIgnoreCase(lhs, rhs); } if (compare < 0) { @@ -365,13 +367,42 @@ public class Model { } /** - * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null - * timestamp - these will be replaced with MAX_LONG so that such files get sorted to the top - * when sorting by date. + * @return Value of the string column, or an empty string if no value, or empty value. */ - long getLastModified(Cursor cursor) { - long l = getCursorLong(mCursor, Document.COLUMN_LAST_MODIFIED); - return (l == -1) ? Long.MAX_VALUE : l; + private String getStringOrEmpty(int columnIndex) { + if (columnIndex == -1) + return EMPTY; + final String result = mCursor.getString(columnIndex); + return result != null ? result : EMPTY; + } + + /** + * @return Timestamp for the given document. Some docs (e.g. active downloads) have a null + * or missing timestamp - these will be replaced with MAX_LONG so that such files get sorted to + * the top when sorting by date. + */ + private long getLastModified() { + if (mLastModifiedIndex == -1) + return Long.MAX_VALUE; + try { + final long result = mCursor.getLong(mLastModifiedIndex); + return result > 0 ? result : Long.MAX_VALUE; + } catch (NumberFormatException e) { + return Long.MAX_VALUE; + } + } + + /** + * @return Size for the given document. If the size is unknown or invalid, returns 0. + */ + private long getDocSize() { + if (mSizeIndex == -1) + return 0; + try { + return mCursor.getLong(mSizeIndex); + } catch (NumberFormatException e) { + return 0; + } } public @Nullable Cursor getItem(String modelId) {