diff options
| author | Jeff Sharkey <jsharkey@android.com> | 2013-08-16 00:08:05 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-08-16 00:08:05 +0000 |
| commit | 3aa2d9f5530524287dcff84369d8298f12bc3f0d (patch) | |
| tree | ae4e297cc1b6c0f6c3a3f5e3e9157203ccf286a4 | |
| parent | 6bab49deaa96ddb0c427c1e2ab127608e5a8d93b (diff) | |
| parent | a5599ef636e37cb0b6474349936999be1afe6987 (diff) | |
| download | frameworks_base-3aa2d9f5530524287dcff84369d8298f12bc3f0d.zip frameworks_base-3aa2d9f5530524287dcff84369d8298f12bc3f0d.tar.gz frameworks_base-3aa2d9f5530524287dcff84369d8298f12bc3f0d.tar.bz2 | |
Merge "Documents management mode; API adjustment." into klp-dev
13 files changed, 266 insertions, 175 deletions
diff --git a/api/current.txt b/api/current.txt index c0cb9f0..5a3c7db 100644 --- a/api/current.txt +++ b/api/current.txt @@ -20620,19 +20620,6 @@ package android.provider { field public static final java.lang.String EXTRA_HAS_MORE = "has_more"; field public static final java.lang.String EXTRA_REQUEST_MORE = "request_more"; field public static final java.lang.String EXTRA_THUMBNAIL_SIZE = "thumbnail_size"; - field public static final int FLAG_PREFERS_GRID = 64; // 0x40 - field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1 - field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4 - field public static final int FLAG_SUPPORTS_RENAME = 2; // 0x2 - field public static final int FLAG_SUPPORTS_SEARCH = 16; // 0x10 - field public static final int FLAG_SUPPORTS_THUMBNAIL = 8; // 0x8 - field public static final int FLAG_SUPPORTS_WRITE = 32; // 0x20 - field public static final java.lang.String MIME_TYPE_DIRECTORY = "vnd.android.cursor.dir/doc"; - field public static final java.lang.String ROOT_DOC_ID = "0"; - field public static final int ROOT_TYPE_DEVICE = 3; // 0x3 - field public static final int ROOT_TYPE_DEVICE_ADVANCED = 4; // 0x4 - field public static final int ROOT_TYPE_SERVICE = 1; // 0x1 - field public static final int ROOT_TYPE_SHORTCUT = 2; // 0x2 } public static abstract interface DocumentsContract.DocumentColumns implements android.provider.OpenableColumns { @@ -20643,6 +20630,18 @@ package android.provider { field public static final java.lang.String SUMMARY = "summary"; } + public static class DocumentsContract.Documents { + field public static final java.lang.String DOC_ID_ROOT = "0"; + field public static final int FLAG_PREFERS_GRID = 64; // 0x40 + field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1 + field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4 + field public static final int FLAG_SUPPORTS_RENAME = 2; // 0x2 + field public static final int FLAG_SUPPORTS_SEARCH = 16; // 0x10 + field public static final int FLAG_SUPPORTS_THUMBNAIL = 8; // 0x8 + field public static final int FLAG_SUPPORTS_WRITE = 32; // 0x20 + field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.cursor.dir/doc"; + } + public static abstract interface DocumentsContract.RootColumns { field public static final java.lang.String AVAILABLE_BYTES = "available_bytes"; field public static final java.lang.String ICON = "icon"; @@ -20652,6 +20651,15 @@ package android.provider { field public static final java.lang.String TITLE = "title"; } + public static class DocumentsContract.Roots { + field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.cursor.dir/root"; + field public static final java.lang.String MIME_TYPE_ITEM = "vnd.android.cursor.item/root"; + field public static final int ROOT_TYPE_DEVICE = 3; // 0x3 + field public static final int ROOT_TYPE_DEVICE_ADVANCED = 4; // 0x4 + field public static final int ROOT_TYPE_SERVICE = 1; // 0x1 + field public static final int ROOT_TYPE_SHORTCUT = 2; // 0x2 + } + public final deprecated class LiveFolders implements android.provider.BaseColumns { field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER"; field public static final java.lang.String DESCRIPTION = "description"; diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index ff350b9..017ad98 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2678,6 +2678,10 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT"; + /** {@hide} */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_DOCUMENT = "android.intent.action.MANAGE_DOCUMENT"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent categories (see addCategory()). diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 909c4dd..e1810ca 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -53,80 +53,85 @@ public final class DocumentsContract { // content://com.example/roots/sdcard/docs/0/contents/ // content://com.example/roots/sdcard/docs/0/search/?query=pony - /** - * MIME type of a document which is a directory that may contain additional - * documents. - * - * @see #buildContentsUri(String, String, String) - */ - public static final String MIME_TYPE_DIRECTORY = "vnd.android.cursor.dir/doc"; - /** {@hide} */ public static final String META_DATA_DOCUMENT_PROVIDER = "android.content.DOCUMENT_PROVIDER"; /** {@hide} */ public static final String ACTION_DOCUMENT_CHANGED = "android.provider.action.DOCUMENT_CHANGED"; - /** - * {@link DocumentColumns#DOC_ID} value representing the root directory of a - * storage root. - */ - public static final String ROOT_DOC_ID = "0"; + public static class Documents { + private Documents() { + } - /** - * Flag indicating that a document is a directory that supports creation of - * new files within it. - * - * @see DocumentColumns#FLAGS - * @see #createDocument(ContentResolver, Uri, String, String) - */ - public static final int FLAG_SUPPORTS_CREATE = 1; + /** + * MIME type of a document which is a directory that may contain additional + * documents. + * + * @see #buildContentsUri(String, String, String) + */ + public static final String MIME_TYPE_DIR = "vnd.android.cursor.dir/doc"; - /** - * Flag indicating that a document is renamable. - * - * @see DocumentColumns#FLAGS - * @see #renameDocument(ContentResolver, Uri, String) - */ - public static final int FLAG_SUPPORTS_RENAME = 1 << 1; + /** + * {@link DocumentColumns#DOC_ID} value representing the root directory of a + * storage root. + */ + public static final String DOC_ID_ROOT = "0"; - /** - * Flag indicating that a document is deletable. - * - * @see DocumentColumns#FLAGS - */ - public static final int FLAG_SUPPORTS_DELETE = 1 << 2; + /** + * Flag indicating that a document is a directory that supports creation of + * new files within it. + * + * @see DocumentColumns#FLAGS + * @see #createDocument(ContentResolver, Uri, String, String) + */ + public static final int FLAG_SUPPORTS_CREATE = 1; - /** - * Flag indicating that a document can be represented as a thumbnail. - * - * @see DocumentColumns#FLAGS - * @see #getThumbnail(ContentResolver, Uri, Point) - */ - public static final int FLAG_SUPPORTS_THUMBNAIL = 1 << 3; + /** + * Flag indicating that a document is renamable. + * + * @see DocumentColumns#FLAGS + * @see #renameDocument(ContentResolver, Uri, String) + */ + public static final int FLAG_SUPPORTS_RENAME = 1 << 1; - /** - * Flag indicating that a document is a directory that supports search. - * - * @see DocumentColumns#FLAGS - */ - public static final int FLAG_SUPPORTS_SEARCH = 1 << 4; + /** + * Flag indicating that a document is deletable. + * + * @see DocumentColumns#FLAGS + */ + public static final int FLAG_SUPPORTS_DELETE = 1 << 2; - /** - * Flag indicating that a document is writable. - * - * @see DocumentColumns#FLAGS - */ - public static final int FLAG_SUPPORTS_WRITE = 1 << 5; + /** + * Flag indicating that a document can be represented as a thumbnail. + * + * @see DocumentColumns#FLAGS + * @see #getThumbnail(ContentResolver, Uri, Point) + */ + public static final int FLAG_SUPPORTS_THUMBNAIL = 1 << 3; - /** - * Flag indicating that a document is a directory that prefers its contents - * be shown in a larger format grid. Usually suitable when a directory - * contains mostly pictures. - * - * @see DocumentColumns#FLAGS - */ - public static final int FLAG_PREFERS_GRID = 1 << 6; + /** + * Flag indicating that a document is a directory that supports search. + * + * @see DocumentColumns#FLAGS + */ + public static final int FLAG_SUPPORTS_SEARCH = 1 << 4; + + /** + * Flag indicating that a document is writable. + * + * @see DocumentColumns#FLAGS + */ + public static final int FLAG_SUPPORTS_WRITE = 1 << 5; + + /** + * Flag indicating that a document is a directory that prefers its contents + * be shown in a larger format grid. Usually suitable when a directory + * contains mostly pictures. + * + * @see DocumentColumns#FLAGS + */ + public static final int FLAG_PREFERS_GRID = 1 << 6; + } /** * Optimal dimensions for a document thumbnail request, stored as a @@ -189,7 +194,7 @@ public final class DocumentsContract { /** * Build URI representing the contents of the given directory in a storage - * backend. The given document must be {@link #MIME_TYPE_DIRECTORY}. + * backend. The given document must be {@link Documents#MIME_TYPE_DIR}. */ public static Uri buildContentsUri(String authority, String rootId, String docId) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) @@ -296,7 +301,7 @@ public final class DocumentsContract { * <p> * Type: STRING * - * @see DocumentsContract#MIME_TYPE_DIRECTORY + * @see Documents#MIME_TYPE_DIR */ public static final String MIME_TYPE = "mime_type"; @@ -327,35 +332,43 @@ public final class DocumentsContract { public static final String SUMMARY = "summary"; } - /** - * Root that represents a cloud-based storage service. - * - * @see RootColumns#ROOT_TYPE - */ - public static final int ROOT_TYPE_SERVICE = 1; + public static class Roots { + private Roots() { + } - /** - * Root that represents a shortcut to content that may be available - * elsewhere through another storage root. - * - * @see RootColumns#ROOT_TYPE - */ - public static final int ROOT_TYPE_SHORTCUT = 2; + public static final String MIME_TYPE_DIR = "vnd.android.cursor.dir/root"; + public static final String MIME_TYPE_ITEM = "vnd.android.cursor.item/root"; - /** - * Root that represents a physical storage device. - * - * @see RootColumns#ROOT_TYPE - */ - public static final int ROOT_TYPE_DEVICE = 3; + /** + * Root that represents a cloud-based storage service. + * + * @see RootColumns#ROOT_TYPE + */ + public static final int ROOT_TYPE_SERVICE = 1; - /** - * Root that represents a physical storage device that should only be - * displayed to advanced users. - * - * @see RootColumns#ROOT_TYPE - */ - public static final int ROOT_TYPE_DEVICE_ADVANCED = 4; + /** + * Root that represents a shortcut to content that may be available + * elsewhere through another storage root. + * + * @see RootColumns#ROOT_TYPE + */ + public static final int ROOT_TYPE_SHORTCUT = 2; + + /** + * Root that represents a physical storage device. + * + * @see RootColumns#ROOT_TYPE + */ + public static final int ROOT_TYPE_DEVICE = 3; + + /** + * Root that represents a physical storage device that should only be + * displayed to advanced users. + * + * @see RootColumns#ROOT_TYPE + */ + public static final int ROOT_TYPE_DEVICE_ADVANCED = 4; + } /** * These are standard columns for the roots URI. @@ -370,8 +383,8 @@ public final class DocumentsContract { * <p> * Type: INTEGER (int) * - * @see DocumentsContract#ROOT_TYPE_SERVICE - * @see DocumentsContract#ROOT_TYPE_DEVICE + * @see Roots#ROOT_TYPE_SERVICE + * @see Roots#ROOT_TYPE_DEVICE */ public static final String ROOT_TYPE = "root_type"; @@ -440,7 +453,7 @@ public final class DocumentsContract { /** * Return thumbnail representing the document at the given URI. Callers are * responsible for their own caching. Given document must have - * {@link #FLAG_SUPPORTS_THUMBNAIL} set. + * {@link Documents#FLAG_SUPPORTS_THUMBNAIL} set. * * @return decoded thumbnail, or {@code null} if problem was encountered. */ @@ -465,7 +478,8 @@ public final class DocumentsContract { * Create a new document under a specific parent document with the given * display name and MIME type. * - * @param parentDocumentUri document with {@link #FLAG_SUPPORTS_CREATE} + * @param parentDocumentUri document with + * {@link Documents#FLAG_SUPPORTS_CREATE} * @param displayName name for new document * @param mimeType MIME type for new document, which cannot be changed * @return newly created document Uri, or {@code null} if failed @@ -480,7 +494,7 @@ public final class DocumentsContract { /** * Rename the document at the given URI. Given document must have - * {@link #FLAG_SUPPORTS_RENAME} set. + * {@link Documents#FLAG_SUPPORTS_RENAME} set. * * @return if rename was successful. */ diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index 9a1953f..518dcdc 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -32,6 +32,12 @@ <category android:name="android.intent.category.OPENABLE" /> <data android:mimeType="*/*" /> </intent-filter> + <!-- data expected to point at existing root to manage --> + <intent-filter> + <action android:name="android.intent.action.MANAGE_DOCUMENT" /> + <category android:name="android.intent.category.DEFAULT" /> + <data android:mimeType="vnd.android.cursor.item/root" /> + </intent-filter> </activity> <activity diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java index 313774b..575947f 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java @@ -27,8 +27,8 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.net.Uri; import android.os.Bundle; -import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; +import android.provider.DocumentsContract.Documents; import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; @@ -69,7 +69,7 @@ public class CreateDirectoryFragment extends DialogFragment { final String displayName = text1.getText().toString(); final ContentValues values = new ContentValues(); - values.put(DocumentColumns.MIME_TYPE, DocumentsContract.MIME_TYPE_DIRECTORY); + values.put(DocumentColumns.MIME_TYPE, Documents.MIME_TYPE_DIR); values.put(DocumentColumns.DISPLAY_NAME, displayName); final DocumentsActivity activity = (DocumentsActivity) getActivity(); diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index e1b6a91..ac5629e 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -190,10 +190,6 @@ public class DirectoryFragment extends Fragment { @Override public void onStart() { super.onStart(); - - final Context context = getActivity(); - getDisplayState(this).showSize = SettingsActivity.getDisplayFileSize(context); - getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks); } @@ -244,7 +240,9 @@ public class DirectoryFragment extends Fragment { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Document doc = mAdapter.getItem(position); - ((DocumentsActivity) getActivity()).onDocumentPicked(doc); + if (mFilter.apply(doc)) { + ((DocumentsActivity) getActivity()).onDocumentPicked(doc); + } } }; @@ -389,7 +387,7 @@ public class DirectoryFragment extends Fragment { if (state.showSize) { size.setVisibility(View.VISIBLE); - if (doc.isDirectory()) { + if (doc.isDirectory() || doc.size == -1) { size.setText(null); } else { size.setText(Formatter.formatFileSize(context, doc.size)); @@ -415,16 +413,5 @@ public class DirectoryFragment extends Fragment { public long getItemId(int position) { return getItem(position).uri.hashCode(); } - - @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int position) { - final Document doc = getItem(position); - return mFilter.apply(doc); - } } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 89ba66e..11ccc89 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -31,6 +31,7 @@ import android.database.Cursor; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; +import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; @@ -63,6 +64,7 @@ public class DocumentsActivity extends Activity { public static final int ACTION_OPEN = 1; public static final int ACTION_CREATE = 2; public static final int ACTION_GET_CONTENT = 3; + public static final int ACTION_MANAGE = 4; private int mAction; @@ -91,6 +93,8 @@ public class DocumentsActivity extends Activity { mAction = ACTION_CREATE; } else if (Intent.ACTION_GET_CONTENT.equals(action)) { mAction = ACTION_GET_CONTENT; + } else if (Intent.ACTION_MANAGE_DOCUMENT.equals(action)) { + mAction = ACTION_MANAGE; } if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) { @@ -98,7 +102,9 @@ public class DocumentsActivity extends Activity { Intent.EXTRA_ALLOW_MULTIPLE, false); } - if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { + if (mAction == ACTION_MANAGE) { + mDisplayState.acceptMimes = new String[] { "*/*" }; + } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { mDisplayState.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES); } else { mDisplayState.acceptMimes = new String[] { intent.getType() }; @@ -120,10 +126,14 @@ public class DocumentsActivity extends Activity { moreApps.setComponent(null); moreApps.setPackage(null); RootsFragment.show(getFragmentManager(), moreApps); - } else { + } else if (mAction == ACTION_OPEN || mAction == ACTION_CREATE) { RootsFragment.show(getFragmentManager(), null); } + if (mAction == ACTION_MANAGE) { + mDisplayState.sortOrder = DisplayState.SORT_ORDER_DATE; + } + mRootsContainer = findViewById(R.id.container_roots); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); @@ -134,26 +144,54 @@ public class DocumentsActivity extends Activity { mDrawerLayout.setDrawerListener(mDrawerListener); mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); - mDrawerLayout.openDrawer(mRootsContainer); + if (mAction == ACTION_MANAGE) { + mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); - // Restore last stack for calling package - // TODO: move into async loader - final String packageName = getCallingPackage(); - final Cursor cursor = getContentResolver() - .query(RecentsProvider.buildResume(packageName), null, null, null, null); - try { - if (cursor.moveToFirst()) { - final String raw = cursor.getString( - cursor.getColumnIndex(RecentsProvider.COL_PATH)); - mStack = DocumentStack.deserialize(getContentResolver(), raw); + final Uri rootUri = intent.getData(); + final String authority = rootUri.getAuthority(); + final String rootId = DocumentsContract.getRootId(rootUri); + + final Root root = RootsCache.findRoot(this, authority, rootId); + if (root != null) { + onRootPicked(root, true); + } else { + Log.w(TAG, "Failed to find root: " + rootUri); + finish(); + } + + } else { + mDrawerLayout.openDrawer(mRootsContainer); + + // Restore last stack for calling package + // TODO: move into async loader + final String packageName = getCallingPackage(); + final Cursor cursor = getContentResolver() + .query(RecentsProvider.buildResume(packageName), null, null, null, null); + try { + if (cursor.moveToFirst()) { + final String raw = cursor.getString( + cursor.getColumnIndex(RecentsProvider.COL_PATH)); + mStack = DocumentStack.deserialize(getContentResolver(), raw); + } + } catch (FileNotFoundException e) { + Log.w(TAG, "Failed to resume", e); + } finally { + cursor.close(); } - } catch (FileNotFoundException e) { - Log.w(TAG, "Failed to resume", e); - } finally { - cursor.close(); + + onCurrentDirectoryChanged(); } + } - onCurrentDirectoryChanged(); + @Override + public void onStart() { + super.onStart(); + + if (mAction == ACTION_MANAGE) { + mDisplayState.showSize = true; + } else { + mDisplayState.showSize = SettingsActivity.getDisplayFileSize(this); + } } private DrawerListener mDrawerListener = new DrawerListener() { @@ -190,7 +228,6 @@ public class DocumentsActivity extends Activity { final ActionBar actionBar = getActionBar(); actionBar.setDisplayShowHomeEnabled(true); - actionBar.setDisplayHomeAsUpEnabled(true); if (mDrawerLayout.isDrawerOpen(mRootsContainer)) { actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); @@ -202,6 +239,9 @@ public class DocumentsActivity extends Activity { actionBar.setTitle(R.string.title_save); } + actionBar.setDisplayHomeAsUpEnabled(true); + mDrawerToggle.setDrawerIndicatorEnabled(true); + } else { final Root root = getCurrentRoot(); actionBar.setIcon(root != null ? root.icon : null); @@ -217,8 +257,13 @@ public class DocumentsActivity extends Activity { } if (mStack.size() > 1) { + actionBar.setDisplayHomeAsUpEnabled(true); + mDrawerToggle.setDrawerIndicatorEnabled(false); + } else if (mAction == ACTION_MANAGE) { + actionBar.setDisplayHomeAsUpEnabled(false); mDrawerToggle.setDrawerIndicatorEnabled(false); } else { + actionBar.setDisplayHomeAsUpEnabled(true); mDrawerToggle.setDrawerIndicatorEnabled(true); } } @@ -269,6 +314,7 @@ public class DocumentsActivity extends Activity { final MenuItem search = menu.findItem(R.id.menu_search); final MenuItem grid = menu.findItem(R.id.menu_grid); final MenuItem list = menu.findItem(R.id.menu_list); + final MenuItem settings = menu.findItem(R.id.menu_settings); grid.setVisible(mDisplayState.mode != DisplayState.MODE_GRID); list.setVisible(mDisplayState.mode != DisplayState.MODE_LIST); @@ -293,6 +339,8 @@ public class DocumentsActivity extends Activity { // TODO: close any search in-progress when hiding search.setVisible(searchVisible); + settings.setVisible(mAction != ACTION_MANAGE); + return true; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java index f945c6a0..a9929de 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java +++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java @@ -49,7 +49,9 @@ public class MimePredicate implements Predicate<Document> { } public static boolean mimeMatches(String filter, String test) { - if (filter.equals(test)) { + if (test == null) { + return false; + } else if (filter.equals(test)) { return true; } else if ("*/*".equals(filter)) { return true; diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index ceab8fc..acd9396 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -27,6 +27,7 @@ import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Documents; import android.util.Log; import android.util.Pair; @@ -162,7 +163,7 @@ public class RootsCache { } } - if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { + if (Documents.MIME_TYPE_DIR.equals(mimeType)) { return context.getResources().getDrawable(R.drawable.ic_dir); } else { final PackageManager pm = context.getPackageManager(); diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index e32414b..4973e1d 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -26,7 +26,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; -import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Roots; import android.text.format.Formatter; import android.util.Log; import android.view.LayoutInflater; @@ -44,7 +44,6 @@ import com.android.documentsui.model.Root; import com.android.documentsui.model.Root.RootComparator; import java.util.Collection; -import java.util.Iterator; import java.util.List; /** @@ -138,8 +137,8 @@ public class RootsFragment extends Fragment { // Device summary is always available space final String summaryText; - if ((root.rootType == DocumentsContract.ROOT_TYPE_DEVICE - || root.rootType == DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED) + if ((root.rootType == Roots.ROOT_TYPE_DEVICE + || root.rootType == Roots.ROOT_TYPE_DEVICE_ADVANCED) && root.availableBytes >= 0) { summaryText = context.getString(R.string.root_available_bytes, Formatter.formatFileSize(context, root.availableBytes)); @@ -226,17 +225,17 @@ public class RootsFragment extends Fragment { for (Root root : roots) { Log.d(TAG, "Found rootType=" + root.rootType); switch (root.rootType) { - case DocumentsContract.ROOT_TYPE_SERVICE: + case Roots.ROOT_TYPE_SERVICE: mServices.add(root); break; - case DocumentsContract.ROOT_TYPE_SHORTCUT: + case Roots.ROOT_TYPE_SHORTCUT: mShortcuts.add(root); break; - case DocumentsContract.ROOT_TYPE_DEVICE: + case Roots.ROOT_TYPE_DEVICE: mDevices.add(root); mDevicesAdvanced.add(root); break; - case DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED: + case Roots.ROOT_TYPE_DEVICE_ADVANCED: mDevicesAdvanced.add(root); break; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java index 95922b4..cf45394 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java @@ -21,6 +21,7 @@ import android.database.Cursor; import android.net.Uri; import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; +import android.provider.DocumentsContract.Documents; import com.android.documentsui.RecentsProvider; @@ -87,7 +88,7 @@ public class Document { final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS) - & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL; + & Documents.FLAG_SUPPORTS_THUMBNAIL; final String summary = getCursorString(cursor, DocumentColumns.SUMMARY); final long size = getCursorLong(cursor, DocumentColumns.SIZE); @@ -127,19 +128,19 @@ public class Document { } public boolean isCreateSupported() { - return (flags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0; + return (flags & Documents.FLAG_SUPPORTS_CREATE) != 0; } public boolean isSearchSupported() { - return (flags & DocumentsContract.FLAG_SUPPORTS_SEARCH) != 0; + return (flags & Documents.FLAG_SUPPORTS_SEARCH) != 0; } public boolean isThumbnailSupported() { - return (flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0; + return (flags & Documents.FLAG_SUPPORTS_THUMBNAIL) != 0; } public boolean isDirectory() { - return DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType); + return Documents.MIME_TYPE_DIR.equals(mimeType); } private static String getCursorString(Cursor cursor, String columnName) { @@ -147,9 +148,19 @@ public class Document { return (index != -1) ? cursor.getString(index) : null; } + /** + * Missing or null values are returned as -1. + */ private static long getCursorLong(Cursor cursor, String columnName) { final int index = cursor.getColumnIndex(columnName); - return (index != -1) ? cursor.getLong(index) : 0; + if (index == -1) return -1; + final String value = cursor.getString(index); + if (value == null) return -1; + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return -1; + } } private static int getCursorInt(Cursor cursor, String columnName) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java index 0880731..23d16df 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java @@ -24,7 +24,9 @@ import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; import android.provider.DocumentsContract; +import android.provider.DocumentsContract.Documents; import android.provider.DocumentsContract.RootColumns; +import android.provider.DocumentsContract.Roots; import com.android.documentsui.R; @@ -47,7 +49,7 @@ public class Root { final PackageManager pm = context.getPackageManager(); final Root root = new Root(); root.rootId = null; - root.rootType = DocumentsContract.ROOT_TYPE_SHORTCUT; + root.rootType = Roots.ROOT_TYPE_SHORTCUT; root.uri = null; root.icon = context.getResources().getDrawable(R.drawable.ic_dir); root.title = context.getString(R.string.root_recent); @@ -65,7 +67,7 @@ public class Root { root.rootId = cursor.getString(cursor.getColumnIndex(RootColumns.ROOT_ID)); root.rootType = cursor.getInt(cursor.getColumnIndex(RootColumns.ROOT_TYPE)); root.uri = DocumentsContract.buildDocumentUri( - info.providerInfo.authority, root.rootId, DocumentsContract.ROOT_DOC_ID); + info.providerInfo.authority, root.rootId, Documents.DOC_ID_ROOT); root.icon = info.providerInfo.loadIcon(pm); root.title = info.providerInfo.loadLabel(pm).toString(); root.availableBytes = cursor.getLong(cursor.getColumnIndex(RootColumns.AVAILABLE_BYTES)); diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java index 5c12484..659139d 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java @@ -28,7 +28,9 @@ import android.os.ParcelFileDescriptor; import android.provider.BaseColumns; import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; +import android.provider.DocumentsContract.Documents; import android.provider.DocumentsContract.RootColumns; +import android.provider.DocumentsContract.Roots; import android.util.Log; import android.webkit.MimeTypeMap; @@ -79,7 +81,7 @@ public class ExternalStorageProvider extends ContentProvider { mRoots.clear(); final Root root = new Root(); - root.rootType = DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED; + root.rootType = Roots.ROOT_TYPE_DEVICE_ADVANCED; root.name = "primary"; root.title = getContext().getString(R.string.root_internal_storage); root.path = Environment.getExternalStorageDirectory(); @@ -173,7 +175,7 @@ public class ExternalStorageProvider extends ContentProvider { String rootPath = root.path.getAbsolutePath(); final String path = file.getAbsolutePath(); if (path.equals(rootPath)) { - return DocumentsContract.ROOT_DOC_ID; + return Documents.DOC_ID_ROOT; } if (!rootPath.endsWith("/")) { @@ -187,7 +189,7 @@ public class ExternalStorageProvider extends ContentProvider { } private File docIdToFile(Root root, String docId) { - if (DocumentsContract.ROOT_DOC_ID.equals(docId)) { + if (Documents.DOC_ID_ROOT.equals(docId)) { return root.path; } else { return new File(root.path, docId); @@ -204,26 +206,27 @@ public class ExternalStorageProvider extends ContentProvider { int flags = 0; if (file.isDirectory()) { - flags |= DocumentsContract.FLAG_SUPPORTS_SEARCH; + flags |= Documents.FLAG_SUPPORTS_SEARCH; } if (file.isDirectory() && file.canWrite()) { - flags |= DocumentsContract.FLAG_SUPPORTS_CREATE; + flags |= Documents.FLAG_SUPPORTS_CREATE; } if (file.canWrite()) { - flags |= DocumentsContract.FLAG_SUPPORTS_RENAME; - flags |= DocumentsContract.FLAG_SUPPORTS_DELETE; + flags |= Documents.FLAG_SUPPORTS_WRITE; + flags |= Documents.FLAG_SUPPORTS_RENAME; + flags |= Documents.FLAG_SUPPORTS_DELETE; } final String mimeType = getTypeForFile(file); if (mimeType.startsWith("image/")) { - flags |= DocumentsContract.FLAG_SUPPORTS_THUMBNAIL; + flags |= Documents.FLAG_SUPPORTS_THUMBNAIL; } final String docId = fileToDocId(root, file); final long id = docId.hashCode(); final String displayName; - if (DocumentsContract.ROOT_DOC_ID.equals(docId)) { + if (Documents.DOC_ID_ROOT.equals(docId)) { displayName = root.title; } else { displayName = file.getName(); @@ -236,6 +239,12 @@ public class ExternalStorageProvider extends ContentProvider { @Override public String getType(Uri uri) { switch (sMatcher.match(uri)) { + case URI_ROOTS: { + return Roots.MIME_TYPE_DIR; + } + case URI_ROOTS_ID: { + return Roots.MIME_TYPE_ITEM; + } case URI_DOCS_ID: { final Root root = mRoots.get(DocumentsContract.getRootId(uri)); final String docId = DocumentsContract.getDocId(uri); @@ -249,7 +258,7 @@ public class ExternalStorageProvider extends ContentProvider { private String getTypeForFile(File file) { if (file.isDirectory()) { - return DocumentsContract.MIME_TYPE_DIRECTORY; + return Documents.MIME_TYPE_DIR; } else { return getTypeForName(file.getName()); } @@ -299,7 +308,7 @@ public class ExternalStorageProvider extends ContentProvider { values.getAsString(DocumentColumns.DISPLAY_NAME), mimeType); final File file = new File(parent, name); - if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { + if (Documents.MIME_TYPE_DIR.equals(mimeType)) { if (!file.mkdir()) { return null; } @@ -359,7 +368,7 @@ public class ExternalStorageProvider extends ContentProvider { } private String validateDisplayName(String displayName, String mimeType) { - if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { + if (Documents.MIME_TYPE_DIR.equals(mimeType)) { return displayName; } else { // Try appending meaningful extension if needed |
