OSDN Git Service

Move search to roots; Documents root; hide empty.
authorJeff Sharkey <jsharkey@android.com>
Fri, 13 Sep 2013 04:59:06 +0000 (21:59 -0700)
committerJeff Sharkey <jsharkey@android.com>
Fri, 13 Sep 2013 18:35:04 +0000 (11:35 -0700)
Documents searches now happen root-wide, instead of only under a
subdirectory.  Updates abstract class and flags to match.  Add flag
for a root to indicate it's empty, and hide empty roots in UI unless
creating.

Define "Documents" public directory and storage backend to contain
files.

Bug: 107120571071086510710758
Change-Id: I8716367568969f9cb1d83927b2bf5a7013809350

12 files changed:
api/current.txt
core/java/android/os/Environment.java
core/java/android/provider/DocumentsContract.java
core/java/android/provider/DocumentsProvider.java
packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
packages/ExternalStorageProvider/res/values/strings.xml
packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java

index ac3948f..d4e23f3 100644 (file)
@@ -17974,6 +17974,7 @@ package android.os {
     method public static boolean isExternalStorageRemovable();
     field public static java.lang.String DIRECTORY_ALARMS;
     field public static java.lang.String DIRECTORY_DCIM;
+    field public static java.lang.String DIRECTORY_DOCUMENTS;
     field public static java.lang.String DIRECTORY_DOWNLOADS;
     field public static java.lang.String DIRECTORY_MOVIES;
     field public static java.lang.String DIRECTORY_MUSIC;
@@ -20811,10 +20812,9 @@ package android.provider {
     field public static final java.lang.String COLUMN_MIME_TYPE = "mime_type";
     field public static final java.lang.String COLUMN_SIZE = "_size";
     field public static final java.lang.String COLUMN_SUMMARY = "summary";
-    field public static final int FLAG_DIR_PREFERS_GRID = 32; // 0x20
-    field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 64; // 0x40
+    field public static final int FLAG_DIR_PREFERS_GRID = 16; // 0x10
+    field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
     field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
-    field public static final int FLAG_DIR_SUPPORTS_SEARCH = 16; // 0x10
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
@@ -20832,9 +20832,11 @@ package android.provider {
     field public static final java.lang.String COLUMN_SUMMARY = "summary";
     field public static final java.lang.String COLUMN_TITLE = "title";
     field public static final int FLAG_ADVANCED = 4; // 0x4
+    field public static final int FLAG_EMPTY = 32; // 0x20
     field public static final int FLAG_LOCAL_ONLY = 2; // 0x2
     field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1
     field public static final int FLAG_SUPPORTS_RECENTS = 8; // 0x8
+    field public static final int FLAG_SUPPORTS_SEARCH = 16; // 0x10
     field public static final int ROOT_TYPE_DEVICE = 3; // 0x3
     field public static final int ROOT_TYPE_SERVICE = 1; // 0x1
     field public static final int ROOT_TYPE_SHORTCUT = 2; // 0x2
index c6e8c3e..5b36bca 100644 (file)
@@ -460,7 +460,13 @@ public class Environment {
      * top-level public directory, as this convention makes no sense elsewhere.
      */
     public static String DIRECTORY_DCIM = "DCIM";
-    
+
+    /**
+     * Standard directory in which to place documents that have been created by
+     * the user.
+     */
+    public static String DIRECTORY_DOCUMENTS = "Documents";
+
     /**
      * Get a top-level public external storage directory for placing files of
      * a particular type.  This is where the user will typically place and
index 37ce065..231e6a6 100644 (file)
@@ -64,9 +64,9 @@ public final class DocumentsContract {
     // content://com.example/root/
     // content://com.example/root/sdcard/
     // content://com.example/root/sdcard/recent/
+    // content://com.example/root/sdcard/search/?query=pony
     // content://com.example/document/12/
     // content://com.example/document/12/children/
-    // content://com.example/document/12/search/?query=pony
 
     private DocumentsContract() {
     }
@@ -174,7 +174,6 @@ public final class DocumentsContract {
          * @see #FLAG_SUPPORTS_THUMBNAIL
          * @see #FLAG_DIR_PREFERS_GRID
          * @see #FLAG_DIR_SUPPORTS_CREATE
-         * @see #FLAG_DIR_SUPPORTS_SEARCH
          */
         public static final String COLUMN_FLAGS = "flags";
 
@@ -241,16 +240,6 @@ public final class DocumentsContract {
         public static final int FLAG_DIR_SUPPORTS_CREATE = 1 << 3;
 
         /**
-         * Flag indicating that a directory supports search. Only valid when
-         * {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}.
-         *
-         * @see #COLUMN_FLAGS
-         * @see DocumentsProvider#querySearchDocuments(String, String,
-         *      String[])
-         */
-        public static final int FLAG_DIR_SUPPORTS_SEARCH = 1 << 4;
-
-        /**
          * Flag indicating that a directory prefers its contents be shown in a
          * larger format grid. Usually suitable when a directory contains mostly
          * pictures. Only valid when {@link #COLUMN_MIME_TYPE} is
@@ -258,7 +247,7 @@ public final class DocumentsContract {
          *
          * @see #COLUMN_FLAGS
          */
-        public static final int FLAG_DIR_PREFERS_GRID = 1 << 5;
+        public static final int FLAG_DIR_PREFERS_GRID = 1 << 4;
 
         /**
          * Flag indicating that a directory prefers its contents be sorted by
@@ -267,7 +256,7 @@ public final class DocumentsContract {
          *
          * @see #COLUMN_FLAGS
          */
-        public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 1 << 6;
+        public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 1 << 5;
     }
 
     /**
@@ -306,9 +295,12 @@ public final class DocumentsContract {
          * <p>
          * Type: INTEGER (int)
          *
+         * @see #FLAG_ADVANCED
+         * @see #FLAG_EMPTY
          * @see #FLAG_LOCAL_ONLY
          * @see #FLAG_SUPPORTS_CREATE
-         * @see #FLAG_ADVANCED
+         * @see #FLAG_SUPPORTS_RECENTS
+         * @see #FLAG_SUPPORTS_SEARCH
          */
         public static final String COLUMN_FLAGS = "flags";
 
@@ -422,6 +414,27 @@ public final class DocumentsContract {
          * @see DocumentsContract#buildRecentDocumentsUri(String, String)
          */
         public static final int FLAG_SUPPORTS_RECENTS = 1 << 3;
+
+        /**
+         * Flag indicating that this root supports search.
+         *
+         * @see #COLUMN_FLAGS
+         * @see DocumentsProvider#querySearchDocuments(String, String,
+         *      String[])
+         */
+        public static final int FLAG_SUPPORTS_SEARCH = 1 << 4;
+
+        /**
+         * Flag indicating that this root is currently empty. This may be used
+         * to hide the root when opening documents, but the root will still be
+         * shown when creating documents and {@link #FLAG_SUPPORTS_CREATE} is
+         * also set.
+         *
+         * @see #COLUMN_FLAGS
+         * @see DocumentsProvider#querySearchDocuments(String, String,
+         *      String[])
+         */
+        public static final int FLAG_EMPTY = 1 << 5;
     }
 
     /**
@@ -493,9 +506,9 @@ public final class DocumentsContract {
     }
 
     /**
-     * Build Uri representing the recently modified documents of a specific
-     * root. When queried, a provider will return zero or more rows with columns
-     * defined by {@link Document}.
+     * Build Uri representing the recently modified documents of a specific root
+     * in a document provider. When queried, a provider will return zero or more
+     * rows with columns defined by {@link Document}.
      *
      * @see DocumentsProvider#queryRecentDocuments(String, String[])
      * @see #getRootId(Uri)
@@ -538,21 +551,17 @@ public final class DocumentsContract {
 
     /**
      * Build Uri representing a search for matching documents under a specific
-     * directory in a document provider. When queried, a provider will return
-     * zero or more rows with columns defined by {@link Document}.
+     * root in a document provider. When queried, a provider will return zero or
+     * more rows with columns defined by {@link Document}.
      *
-     * @param parentDocumentId the document to return children for, which must
-     *            be both a directory with MIME type of
-     *            {@link Document#MIME_TYPE_DIR} and have
-     *            {@link Document#FLAG_DIR_SUPPORTS_SEARCH} set.
      * @see DocumentsProvider#querySearchDocuments(String, String, String[])
-     * @see #getDocumentId(Uri)
+     * @see #getRootId(Uri)
      * @see #getSearchDocumentsQuery(Uri)
      */
     public static Uri buildSearchDocumentsUri(
-            String authority, String parentDocumentId, String query) {
+            String authority, String rootId, String query) {
         return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority)
-                .appendPath(PATH_DOCUMENT).appendPath(parentDocumentId).appendPath(PATH_SEARCH)
+                .appendPath(PATH_ROOT).appendPath(rootId).appendPath(PATH_SEARCH)
                 .appendQueryParameter(PARAM_QUERY, query).build();
     }
 
index d801827..bc4e28b 100644 (file)
@@ -75,9 +75,9 @@ public abstract class DocumentsProvider extends ContentProvider {
     private static final int MATCH_ROOTS = 1;
     private static final int MATCH_ROOT = 2;
     private static final int MATCH_RECENT = 3;
-    private static final int MATCH_DOCUMENT = 4;
-    private static final int MATCH_CHILDREN = 5;
-    private static final int MATCH_SEARCH = 6;
+    private static final int MATCH_SEARCH = 4;
+    private static final int MATCH_DOCUMENT = 5;
+    private static final int MATCH_CHILDREN = 6;
 
     private String mAuthority;
 
@@ -94,9 +94,9 @@ public abstract class DocumentsProvider extends ContentProvider {
         mMatcher.addURI(mAuthority, "root", MATCH_ROOTS);
         mMatcher.addURI(mAuthority, "root/*", MATCH_ROOT);
         mMatcher.addURI(mAuthority, "root/*/recent", MATCH_RECENT);
+        mMatcher.addURI(mAuthority, "root/*/search", MATCH_SEARCH);
         mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT);
         mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN);
-        mMatcher.addURI(mAuthority, "document/*/search", MATCH_SEARCH);
 
         // Sanity check our setup
         if (!info.exported) {
@@ -176,13 +176,12 @@ public abstract class DocumentsProvider extends ContentProvider {
     }
 
     /**
-     * Return documents that that match the given query, starting the search at
-     * the given directory.
+     * Return documents that that match the given query.
      *
-     * @param parentDocumentId the directory to start search at.
+     * @param rootId the root to search under.
      */
     @SuppressWarnings("unused")
-    public Cursor querySearchDocuments(String parentDocumentId, String query, String[] projection)
+    public Cursor querySearchDocuments(String rootId, String query, String[] projection)
             throws FileNotFoundException {
         throw new UnsupportedOperationException("Search not supported");
     }
@@ -267,6 +266,9 @@ public abstract class DocumentsProvider extends ContentProvider {
                     return queryRoots(projection);
                 case MATCH_RECENT:
                     return queryRecentDocuments(getRootId(uri), projection);
+                case MATCH_SEARCH:
+                    return querySearchDocuments(
+                            getRootId(uri), getSearchDocumentsQuery(uri), projection);
                 case MATCH_DOCUMENT:
                     return queryDocument(getDocumentId(uri), projection);
                 case MATCH_CHILDREN:
@@ -276,9 +278,6 @@ public abstract class DocumentsProvider extends ContentProvider {
                     } else {
                         return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
                     }
-                case MATCH_SEARCH:
-                    return querySearchDocuments(
-                            getDocumentId(uri), getSearchDocumentsQuery(uri), projection);
                 default:
                     throw new UnsupportedOperationException("Unsupported Uri " + uri);
             }
index b2981db..aee865b 100644 (file)
@@ -125,9 +125,8 @@ public class DirectoryFragment extends Fragment {
         show(fm, TYPE_NORMAL, root, doc, null);
     }
 
-    public static void showSearch(
-            FragmentManager fm, RootInfo root, DocumentInfo doc, String query) {
-        show(fm, TYPE_SEARCH, root, doc, query);
+    public static void showSearch(FragmentManager fm, RootInfo root, String query) {
+        show(fm, TYPE_SEARCH, root, null, query);
     }
 
     public static void showRecentsOpen(FragmentManager fm) {
@@ -205,7 +204,7 @@ public class DirectoryFragment extends Fragment {
                                 context, mType, root, doc, contentsUri, state.userSortOrder);
                     case TYPE_SEARCH:
                         contentsUri = DocumentsContract.buildSearchDocumentsUri(
-                                doc.authority, doc.documentId, query);
+                                root.authority, root.rootId, query);
                         if (state.action == ACTION_MANAGE) {
                             contentsUri = DocumentsContract.setManageMode(contentsUri);
                         }
@@ -274,7 +273,7 @@ public class DirectoryFragment extends Fragment {
         final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
         final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
 
-        if (root != null) {
+        if (root != null && doc != null) {
             final Uri stateUri = RecentsProvider.buildState(
                     root.authority, root.rootId, doc.documentId);
             final ContentValues values = new ContentValues();
index 334e262..8627ecf 100644 (file)
@@ -32,6 +32,7 @@ import android.database.Cursor;
 import android.net.Uri;
 import android.os.CancellationSignal;
 import android.os.OperationCanceledException;
+import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.util.Log;
 
@@ -42,6 +43,8 @@ import com.android.documentsui.model.RootInfo;
 
 import libcore.io.IoUtils;
 
+import java.io.FileNotFoundException;
+
 class DirectoryResult implements AutoCloseable {
     ContentProviderClient client;
     Cursor cursor;
@@ -64,7 +67,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
 
     private final int mType;
     private final RootInfo mRoot;
-    private final DocumentInfo mDoc;
+    private DocumentInfo mDoc;
     private final Uri mUri;
     private final int mUserSortOrder;
 
@@ -97,6 +100,19 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
 
         int userMode = State.MODE_UNKNOWN;
 
+        // Use default document when searching
+        if (mType == DirectoryFragment.TYPE_SEARCH) {
+            final Uri docUri = DocumentsContract.buildDocumentUri(
+                    mRoot.authority, mRoot.documentId);
+            try {
+                mDoc = DocumentInfo.fromUri(resolver, docUri);
+            } catch (FileNotFoundException e) {
+                Log.w(TAG, "Failed to query", e);
+                result.exception = e;
+                return result;
+            }
+        }
+
         // Pick up any custom modes requested by user
         Cursor cursor = null;
         try {
@@ -157,7 +173,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
 
             result.cursor = cursor;
         } catch (Exception e) {
-            Log.d(TAG, "Failed to query", e);
+            Log.w(TAG, "Failed to query", e);
             result.exception = e;
             ContentProviderClient.closeQuietly(result.client);
         } finally {
index eb51fb5..b1e51a0 100644 (file)
@@ -45,6 +45,7 @@ import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Root;
 import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.widget.DrawerLayout;
@@ -442,6 +443,8 @@ public class DocumentsActivity extends Activity {
         super.onPrepareOptionsMenu(menu);
 
         final FragmentManager fm = getFragmentManager();
+
+        final RootInfo root = getCurrentRoot();
         final DocumentInfo cwd = getCurrentDirectory();
 
         final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
@@ -503,7 +506,9 @@ public class DocumentsActivity extends Activity {
             SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
         } else {
             createDir.setVisible(false);
-            searchVisible = cwd != null && cwd.isSearchSupported();
+
+            searchVisible = root != null
+                    && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0);
         }
 
         // TODO: close any search in-progress when hiding
@@ -722,7 +727,7 @@ public class DocumentsActivity extends Activity {
         } else {
             if (mState.currentSearch != null) {
                 // Ongoing search
-                DirectoryFragment.showSearch(fm, root, cwd, mState.currentSearch);
+                DirectoryFragment.showSearch(fm, root, mState.currentSearch);
             } else {
                 // Normal boring directory
                 DirectoryFragment.showNormal(fm, root, cwd);
index b48674c..4d313e8 100644 (file)
@@ -176,6 +176,7 @@ public class RootsCache {
             final boolean supportsCreate = (root.flags & Root.FLAG_SUPPORTS_CREATE) != 0;
             final boolean advanced = (root.flags & Root.FLAG_ADVANCED) != 0;
             final boolean localOnly = (root.flags & Root.FLAG_LOCAL_ONLY) != 0;
+            final boolean empty = (root.flags & Root.FLAG_EMPTY) != 0;
 
             // Exclude read-only devices when creating
             if (state.action == State.ACTION_CREATE && !supportsCreate) continue;
@@ -183,6 +184,8 @@ public class RootsCache {
             if (!state.showAdvanced && advanced) continue;
             // Exclude non-local devices when local only
             if (state.localOnly && !localOnly) continue;
+            // Only show empty roots when creating
+            if (state.action != State.ACTION_CREATE && empty) continue;
 
             // Only include roots that serve requested content
             final boolean overlap =
index c69103e..ab55d94 100644 (file)
@@ -188,10 +188,6 @@ public class DocumentInfo implements Durable, Parcelable {
         return (flags & Document.FLAG_DIR_SUPPORTS_CREATE) != 0;
     }
 
-    public boolean isSearchSupported() {
-        return (flags & Document.FLAG_DIR_SUPPORTS_SEARCH) != 0;
-    }
-
     public boolean isThumbnailSupported() {
         return (flags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
     }
index b5a198c..1afc80a 100644 (file)
@@ -161,15 +161,21 @@ public class RootInfo implements Durable, Parcelable {
 
         // TODO: remove these special case icons
         if ("com.android.externalstorage.documents".equals(authority)) {
-            derivedIcon = R.drawable.ic_root_sdcard;
+            if ("documents".equals(rootId)) {
+                derivedIcon = R.drawable.ic_doc_text;
+            } else {
+                derivedIcon = R.drawable.ic_root_sdcard;
+            }
         }
         if ("com.android.providers.downloads.documents".equals(authority)) {
             derivedIcon = R.drawable.ic_root_download;
         }
         if ("com.android.providers.media.documents".equals(authority)) {
-            if ("image".equals(rootId)) {
+            if ("images_root".equals(rootId)) {
                 derivedIcon = R.drawable.ic_doc_image;
-            } else if ("audio".equals(rootId)) {
+            } else if ("videos_root".equals(rootId)) {
+                derivedIcon = R.drawable.ic_doc_video;
+            } else if ("audio_root".equals(rootId)) {
                 derivedIcon = R.drawable.ic_doc_audio;
             }
         }
index 0eaf500..f1c1ade 100644 (file)
 -->
 
 <resources>
+    <!-- Title of the external storage application [CHAR LIMIT=32] -->
     <string name="app_label">External Storage</string>
+
+    <!-- Title for documents backend that offers internal storage. [CHAR LIMIT=24] -->
     <string name="root_internal_storage">Internal storage</string>
+    <!-- Title for documents backend that offers documents. [CHAR LIMIT=24] -->
+    <string name="root_documents">Documents</string>
 </resources>
index ada3ad7..3e2cd15 100644 (file)
@@ -62,7 +62,6 @@ public class ExternalStorageProvider extends DocumentsProvider {
         public String rootId;
         public int rootType;
         public int flags;
-        public int icon;
         public String title;
         public String docId;
     }
@@ -85,9 +84,10 @@ public class ExternalStorageProvider extends DocumentsProvider {
             mIdToPath.put(rootId, path);
 
             final RootInfo root = new RootInfo();
-            root.rootId = "primary";
+            root.rootId = rootId;
             root.rootType = Root.ROOT_TYPE_DEVICE;
-            root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED;
+            root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
+                    | Root.FLAG_SUPPORTS_SEARCH;
             root.title = getContext().getString(R.string.root_internal_storage);
             root.docId = getDocIdForFile(path);
             mRoots.add(root);
@@ -96,6 +96,25 @@ public class ExternalStorageProvider extends DocumentsProvider {
             throw new IllegalStateException(e);
         }
 
+        try {
+            final String rootId = "documents";
+            final File path = Environment.getExternalStoragePublicDirectory(
+                    Environment.DIRECTORY_DOCUMENTS);
+            mIdToPath.put(rootId, path);
+
+            final RootInfo root = new RootInfo();
+            root.rootId = rootId;
+            root.rootType = Root.ROOT_TYPE_SHORTCUT;
+            root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY
+                    | Root.FLAG_SUPPORTS_SEARCH;
+            root.title = getContext().getString(R.string.root_documents);
+            root.docId = getDocIdForFile(path);
+            mRoots.add(root);
+            mIdToRoot.put(rootId, root);
+        } catch (FileNotFoundException e) {
+            throw new IllegalStateException(e);
+        }
+
         return true;
     }
 
@@ -146,6 +165,9 @@ public class ExternalStorageProvider extends DocumentsProvider {
         if (target == null) {
             throw new FileNotFoundException("No root for " + tag);
         }
+        if (!target.exists()) {
+            target.mkdirs();
+        }
         target = new File(target, path);
         if (!target.exists()) {
             throw new FileNotFoundException("Missing file for " + docId + " at " + target);
@@ -163,9 +185,6 @@ public class ExternalStorageProvider extends DocumentsProvider {
 
         int flags = 0;
 
-        if (file.isDirectory()) {
-            flags |= Document.FLAG_DIR_SUPPORTS_SEARCH;
-        }
         if (file.isDirectory() && file.canWrite()) {
             flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
         }
@@ -200,7 +219,6 @@ public class ExternalStorageProvider extends DocumentsProvider {
             row.add(Root.COLUMN_ROOT_ID, root.rootId);
             row.add(Root.COLUMN_ROOT_TYPE, root.rootType);
             row.add(Root.COLUMN_FLAGS, root.flags);
-            row.add(Root.COLUMN_ICON, root.icon);
             row.add(Root.COLUMN_TITLE, root.title);
             row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
             row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
@@ -260,10 +278,10 @@ public class ExternalStorageProvider extends DocumentsProvider {
     }
 
     @Override
-    public Cursor querySearchDocuments(String parentDocumentId, String query, String[] projection)
+    public Cursor querySearchDocuments(String rootId, String query, String[] projection)
             throws FileNotFoundException {
         final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
-        final File parent = getFileForDocId(parentDocumentId);
+        final File parent = mIdToPath.get(rootId);
 
         final LinkedList<File> pending = new LinkedList<File>();
         pending.add(parent);