Loading src/com/android/documentsui/sorting/SortModel.java +10 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,11 @@ public class SortModel implements Parcelable { ContentResolver.QUERY_ARG_SORT_COLUMNS, new String[]{ Document.COLUMN_SIZE }); break; case SortModel.SORT_DIMENSION_ID_FILE_TYPE: // Unfortunately sorting by mime type is pretty much guaranteed different from // sorting by user-friendly type, so there is no point to guide the provider to sort // in a particular order. return; default: throw new IllegalStateException( "Unexpected sort dimension id: " + id); Loading Loading @@ -302,6 +307,11 @@ public class SortModel implements Parcelable { case SortModel.SORT_DIMENSION_ID_SIZE: columnName = Document.COLUMN_SIZE; break; case SortModel.SORT_DIMENSION_ID_FILE_TYPE: // Unfortunately sorting by mime type is pretty much guaranteed different from // sorting by user-friendly type, so there is no point to guide the provider to sort // in a particular order. return null; default: throw new IllegalStateException( "Unexpected sort dimension id: " + id); Loading src/com/android/documentsui/sorting/SortingCursorWrapper.java +10 −5 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ class SortingCursorWrapper extends AbstractCursor { boolean[] isDirs = new boolean[count]; String[] stringValues = null; long[] longValues = null; String[] ids = null; String[] ids = new String[count]; final @SortDimensionId int id = dimension.getId(); switch (id) { Loading @@ -57,7 +57,6 @@ class SortingCursorWrapper extends AbstractCursor { case SortModel.SORT_DIMENSION_ID_DATE: case SortModel.SORT_DIMENSION_ID_SIZE: longValues = new long[count]; ids = new String[count]; break; } Loading @@ -68,6 +67,7 @@ class SortingCursorWrapper extends AbstractCursor { final String mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE); isDirs[i] = Document.MIME_TYPE_DIR.equals(mimeType); ids[i] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID); switch(id) { case SortModel.SORT_DIMENSION_ID_TITLE: Loading @@ -80,11 +80,9 @@ class SortingCursorWrapper extends AbstractCursor { break; case SortModel.SORT_DIMENSION_ID_DATE: longValues[i] = getLastModified(mCursor); ids[i] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID); break; case SortModel.SORT_DIMENSION_ID_SIZE: longValues[i] = getCursorLong(mCursor, Document.COLUMN_SIZE); ids[i] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID); break; } Loading @@ -93,7 +91,7 @@ class SortingCursorWrapper extends AbstractCursor { switch (id) { case SortModel.SORT_DIMENSION_ID_TITLE: case SortModel.SORT_DIMENSION_ID_FILE_TYPE: binarySort(stringValues, isDirs, mPosition, dimension.getSortDirection()); binarySort(stringValues, isDirs, mPosition, ids, dimension.getSortDirection()); break; case SortModel.SORT_DIMENSION_ID_DATE: case SortModel.SORT_DIMENSION_ID_SIZE: Loading Loading @@ -187,12 +185,14 @@ class SortingCursorWrapper extends AbstractCursor { String[] sortKey, boolean[] isDirs, int[] positions, String[] ids, @SortDimension.SortDirection int direction) { final int count = positions.length; for (int start = 1; start < count; start++) { final int pivotPosition = positions[start]; final String pivotValue = sortKey[start]; final boolean pivotIsDir = isDirs[start]; final String pivotId = ids[start]; int left = 0; int right = start; Loading Loading @@ -223,6 +223,11 @@ class SortingCursorWrapper extends AbstractCursor { } } // Use document ID as a tie breaker to achieve stable sort result. if (compare == 0) { compare = pivotId.compareTo(ids[mid]); } if (compare < 0) { right = mid; } else { Loading tests/functional/com/android/documentsui/SortDocumentUiTest.java +51 −3 Original line number Diff line number Diff line Loading @@ -33,7 +33,12 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { private static final String FILE_2 = "doc_2"; private static final String FILE_3 = "image_3"; private static final String MIME_1 = "text/plain"; // Plain text private static final String MIME_2 = "text/html"; // HTML document private static final String MIME_3 = "image/jpeg"; // JPG image private static final String[] FILES = { FILE_1, FILE_3, FILE_2 }; private static final String[] MIMES = { MIME_1, MIME_3, MIME_2 }; private static final String[] DIRS = { DIR_1, DIR_2 }; private static final String[] DIRS_IN_NAME_ASC = { DIR_2, DIR_1 }; Loading @@ -47,6 +52,9 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { private static final String[] DIRS_IN_MODIFIED_DESC = reverse(DIRS); private static final String[] FILES_IN_MODIFIED_DESC = reverse(FILES); private static final String[] FILES_IN_TYPE_ASC = { FILE_2, FILE_3, FILE_1 }; private static final String[] FILES_IN_TYPE_DESC = reverse(FILES_IN_TYPE_ASC); public SortDocumentUiTest() { super(FilesActivity.class); } Loading @@ -67,9 +75,9 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { * @param sleep time to sleep in ms */ private void initFiles(long sleep) throws Exception { for (String file : FILES) { Uri uri = mDocsHelper.createDocument(rootDir0, "text/plain", file); mDocsHelper.writeDocument(uri, file.getBytes()); for (int i = 0; i < FILES.length; ++i) { Uri uri = mDocsHelper.createDocument(rootDir0, MIMES[i], FILES[i]); mDocsHelper.writeDocument(uri, FILES[i].getBytes()); Thread.sleep(sleep); } Loading Loading @@ -136,6 +144,26 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { bots.directory.assertOrder(DIRS_IN_MODIFIED_DESC, FILES_IN_MODIFIED_DESC); } public void testSortByType_Ascending_listMode() throws Exception { initFiles(); bots.main.switchToListMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_ASCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_ASC); } public void testSortByType_Descending_listMode() throws Exception { initFiles(); bots.main.switchToListMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_DESCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_DESC); } public void testSortByName_Descending_gridMode() throws Exception { initFiles(); Loading Loading @@ -186,6 +214,26 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { bots.directory.assertOrder(DIRS_IN_MODIFIED_DESC, FILES_IN_MODIFIED_DESC); } public void testSortByType_Ascending_gridMode() throws Exception { initFiles(); bots.main.switchToGridMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_ASCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_ASC); } public void testSortByType_Descending_gridMode() throws Exception { initFiles(); bots.main.switchToGridMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_DESCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_DESC); } private static String[] reverse(String[] array) { String[] ret = new String[array.length]; Loading Loading
src/com/android/documentsui/sorting/SortModel.java +10 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,11 @@ public class SortModel implements Parcelable { ContentResolver.QUERY_ARG_SORT_COLUMNS, new String[]{ Document.COLUMN_SIZE }); break; case SortModel.SORT_DIMENSION_ID_FILE_TYPE: // Unfortunately sorting by mime type is pretty much guaranteed different from // sorting by user-friendly type, so there is no point to guide the provider to sort // in a particular order. return; default: throw new IllegalStateException( "Unexpected sort dimension id: " + id); Loading Loading @@ -302,6 +307,11 @@ public class SortModel implements Parcelable { case SortModel.SORT_DIMENSION_ID_SIZE: columnName = Document.COLUMN_SIZE; break; case SortModel.SORT_DIMENSION_ID_FILE_TYPE: // Unfortunately sorting by mime type is pretty much guaranteed different from // sorting by user-friendly type, so there is no point to guide the provider to sort // in a particular order. return null; default: throw new IllegalStateException( "Unexpected sort dimension id: " + id); Loading
src/com/android/documentsui/sorting/SortingCursorWrapper.java +10 −5 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ class SortingCursorWrapper extends AbstractCursor { boolean[] isDirs = new boolean[count]; String[] stringValues = null; long[] longValues = null; String[] ids = null; String[] ids = new String[count]; final @SortDimensionId int id = dimension.getId(); switch (id) { Loading @@ -57,7 +57,6 @@ class SortingCursorWrapper extends AbstractCursor { case SortModel.SORT_DIMENSION_ID_DATE: case SortModel.SORT_DIMENSION_ID_SIZE: longValues = new long[count]; ids = new String[count]; break; } Loading @@ -68,6 +67,7 @@ class SortingCursorWrapper extends AbstractCursor { final String mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE); isDirs[i] = Document.MIME_TYPE_DIR.equals(mimeType); ids[i] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID); switch(id) { case SortModel.SORT_DIMENSION_ID_TITLE: Loading @@ -80,11 +80,9 @@ class SortingCursorWrapper extends AbstractCursor { break; case SortModel.SORT_DIMENSION_ID_DATE: longValues[i] = getLastModified(mCursor); ids[i] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID); break; case SortModel.SORT_DIMENSION_ID_SIZE: longValues[i] = getCursorLong(mCursor, Document.COLUMN_SIZE); ids[i] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID); break; } Loading @@ -93,7 +91,7 @@ class SortingCursorWrapper extends AbstractCursor { switch (id) { case SortModel.SORT_DIMENSION_ID_TITLE: case SortModel.SORT_DIMENSION_ID_FILE_TYPE: binarySort(stringValues, isDirs, mPosition, dimension.getSortDirection()); binarySort(stringValues, isDirs, mPosition, ids, dimension.getSortDirection()); break; case SortModel.SORT_DIMENSION_ID_DATE: case SortModel.SORT_DIMENSION_ID_SIZE: Loading Loading @@ -187,12 +185,14 @@ class SortingCursorWrapper extends AbstractCursor { String[] sortKey, boolean[] isDirs, int[] positions, String[] ids, @SortDimension.SortDirection int direction) { final int count = positions.length; for (int start = 1; start < count; start++) { final int pivotPosition = positions[start]; final String pivotValue = sortKey[start]; final boolean pivotIsDir = isDirs[start]; final String pivotId = ids[start]; int left = 0; int right = start; Loading Loading @@ -223,6 +223,11 @@ class SortingCursorWrapper extends AbstractCursor { } } // Use document ID as a tie breaker to achieve stable sort result. if (compare == 0) { compare = pivotId.compareTo(ids[mid]); } if (compare < 0) { right = mid; } else { Loading
tests/functional/com/android/documentsui/SortDocumentUiTest.java +51 −3 Original line number Diff line number Diff line Loading @@ -33,7 +33,12 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { private static final String FILE_2 = "doc_2"; private static final String FILE_3 = "image_3"; private static final String MIME_1 = "text/plain"; // Plain text private static final String MIME_2 = "text/html"; // HTML document private static final String MIME_3 = "image/jpeg"; // JPG image private static final String[] FILES = { FILE_1, FILE_3, FILE_2 }; private static final String[] MIMES = { MIME_1, MIME_3, MIME_2 }; private static final String[] DIRS = { DIR_1, DIR_2 }; private static final String[] DIRS_IN_NAME_ASC = { DIR_2, DIR_1 }; Loading @@ -47,6 +52,9 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { private static final String[] DIRS_IN_MODIFIED_DESC = reverse(DIRS); private static final String[] FILES_IN_MODIFIED_DESC = reverse(FILES); private static final String[] FILES_IN_TYPE_ASC = { FILE_2, FILE_3, FILE_1 }; private static final String[] FILES_IN_TYPE_DESC = reverse(FILES_IN_TYPE_ASC); public SortDocumentUiTest() { super(FilesActivity.class); } Loading @@ -67,9 +75,9 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { * @param sleep time to sleep in ms */ private void initFiles(long sleep) throws Exception { for (String file : FILES) { Uri uri = mDocsHelper.createDocument(rootDir0, "text/plain", file); mDocsHelper.writeDocument(uri, file.getBytes()); for (int i = 0; i < FILES.length; ++i) { Uri uri = mDocsHelper.createDocument(rootDir0, MIMES[i], FILES[i]); mDocsHelper.writeDocument(uri, FILES[i].getBytes()); Thread.sleep(sleep); } Loading Loading @@ -136,6 +144,26 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { bots.directory.assertOrder(DIRS_IN_MODIFIED_DESC, FILES_IN_MODIFIED_DESC); } public void testSortByType_Ascending_listMode() throws Exception { initFiles(); bots.main.switchToListMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_ASCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_ASC); } public void testSortByType_Descending_listMode() throws Exception { initFiles(); bots.main.switchToListMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_DESCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_DESC); } public void testSortByName_Descending_gridMode() throws Exception { initFiles(); Loading Loading @@ -186,6 +214,26 @@ public class SortDocumentUiTest extends ActivityTest<FilesActivity> { bots.directory.assertOrder(DIRS_IN_MODIFIED_DESC, FILES_IN_MODIFIED_DESC); } public void testSortByType_Ascending_gridMode() throws Exception { initFiles(); bots.main.switchToGridMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_ASCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_ASC); } public void testSortByType_Descending_gridMode() throws Exception { initFiles(); bots.main.switchToGridMode(); bots.sortHeader.sortBy( SortModel.SORT_DIMENSION_ID_FILE_TYPE, SortDimension.SORT_DIRECTION_DESCENDING); bots.directory.assertOrder(DIRS_IN_NAME_ASC, FILES_IN_TYPE_DESC); } private static String[] reverse(String[] array) { String[] ret = new String[array.length]; Loading