Merge "Poll jobs' status to update notifications."
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index 85e7a7a..ed47bbc 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -58,13 +58,6 @@
             android:showAsAction="never"
             android:visible="false" />
         <item
-            android:id="@+id/menu_paste_from_clipboard"
-            android:title="@string/menu_paste_from_clipboard"
-            android:alphabeticShortcut="v"
-            android:showAsAction="never"
-            android:visible="false" />
-        <!-- Copy action is defined in mode_directory.xml -->
-        <item
             android:id="@+id/menu_sort"
             android:title="@string/menu_sort"
             android:icon="@drawable/ic_menu_sortby"
diff --git a/packages/DocumentsUI/res/menu/context_menu.xml b/packages/DocumentsUI/res/menu/context_menu.xml
new file mode 100644
index 0000000..7474859
--- /dev/null
+++ b/packages/DocumentsUI/res/menu/context_menu.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/menu_cut_to_clipboard"
+        android:title="@string/menu_cut_to_clipboard" />
+    <item
+        android:id="@+id/menu_copy_to_clipboard"
+        android:title="@string/menu_copy_to_clipboard" />
+    <item
+        android:id="@+id/menu_paste_from_clipboard"
+        android:title="@string/menu_paste_from_clipboard" />
+</menu>
diff --git a/packages/DocumentsUI/res/menu/mode_directory.xml b/packages/DocumentsUI/res/menu/mode_directory.xml
index 6f9bfb5..e2125ad 100644
--- a/packages/DocumentsUI/res/menu/mode_directory.xml
+++ b/packages/DocumentsUI/res/menu/mode_directory.xml
@@ -30,11 +30,6 @@
         android:title="@string/menu_delete"
         android:showAsAction="always" />
     <item
-        android:id="@+id/menu_copy_to_clipboard"
-        android:title="@string/menu_copy_to_clipboard"
-        android:showAsAction="never"
-        android:visible="false" />
-    <item
         android:id="@+id/menu_select_all"
         android:title="@string/menu_select_all"
         android:showAsAction="never" />
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index f7124e6..bf34461 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -56,6 +56,8 @@
 
     <!-- Menu item title that creates a new window in the activity [CHAR LIMIT=24] -->
     <string name="menu_new_window">New window</string>
+    <!-- Menu item title that cuts the selected documents to clipboard [CHAR LIMIT=24] -->
+    <string name="menu_cut_to_clipboard">Cut</string>
     <!-- Menu item title that copies the selected documents to clipboard [CHAR LIMIT=24] -->
     <string name="menu_copy_to_clipboard">Copy</string>
     <!-- Menu item title that pastes files from the clipboard [CHAR LIMIT=24] -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index e13e982..6f17b54 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -50,6 +50,7 @@
 import android.view.MenuItem;
 import android.widget.Spinner;
 
+import com.android.documentsui.MenuManager.DirectoryDetails;
 import com.android.documentsui.SearchViewManager.SearchManagerListener;
 import com.android.documentsui.State.ViewMode;
 import com.android.documentsui.dirlist.AnimationView;
@@ -98,6 +99,7 @@
     public abstract void onDocumentsPicked(List<DocumentInfo> docs);
     public abstract FragmentTuner createFragmentTuner();
     public abstract MenuManager getMenuManager();
+    public abstract DirectoryDetails getDirectoryDetails();
 
     abstract void onTaskFinished(Uri... uris);
     abstract void refreshDirectory(int anim);
@@ -302,13 +304,6 @@
                 setViewMode(State.MODE_LIST);
                 return true;
 
-            case R.id.menu_paste_from_clipboard:
-                DirectoryFragment dir = getDirectoryFragment();
-                if (dir != null) {
-                    dir.pasteFromClipboard();
-                }
-                return true;
-
             case R.id.menu_advanced:
                 setDisplayAdvancedDevices(!mState.showAdvanced);
                 return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 830b118..b8559bc1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -414,6 +414,11 @@
         return mMenuManager;
     }
 
+    @Override
+    public DirectoryDetails getDirectoryDetails() {
+        return mDetails;
+    }
+
     /**
      * Loads the last used path (stack) from Recents (history).
      * The path selected is based on the calling package name. So the last
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsMenuManager.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsMenuManager.java
index e7f0e74..0b86894 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsMenuManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsMenuManager.java
@@ -25,63 +25,94 @@
 import android.view.Menu;
 import android.view.MenuItem;
 
-final class DocumentsMenuManager implements MenuManager {
+final class DocumentsMenuManager extends MenuManager {
 
-  private final State mState;
-  private final SearchViewManager mSearchManager;
+    private final State mState;
+    private final SearchViewManager mSearchManager;
+    private boolean mPicking;
 
-  public DocumentsMenuManager(SearchViewManager searchManager, State displayState) {
-       mSearchManager = searchManager;
-       mState = displayState;
-  }
+    public DocumentsMenuManager(SearchViewManager searchManager, State displayState) {
+        mSearchManager = searchManager;
+        mState = displayState;
 
-  @Override
-  public void updateActionMenu(Menu menu, MenuManager.SelectionDetails selection) {
-      MenuItem open = menu.findItem(R.id.menu_open);
-      MenuItem share = menu.findItem(R.id.menu_share);
-      MenuItem delete = menu.findItem(R.id.menu_delete);
-      MenuItem rename = menu.findItem(R.id.menu_rename);
-      MenuItem selectAll = menu.findItem(R.id.menu_select_all);
-
-      open.setVisible(mState.action == ACTION_GET_CONTENT
-              || mState.action == ACTION_OPEN);
-      share.setVisible(false);
-      delete.setVisible(false);
-      rename.setVisible(false);
-      selectAll.setVisible(mState.allowMultiple);
-
-      Menus.disableHiddenItems(menu);
-  }
+        mPicking = mState.action == ACTION_CREATE
+                || mState.action == ACTION_OPEN_TREE
+                || mState.action == ACTION_PICK_COPY_DESTINATION;
+    }
 
     @Override
     public void updateOptionMenu(Menu menu, DirectoryDetails details) {
-
-        boolean picking = mState.action == ACTION_CREATE
-                || mState.action == ACTION_OPEN_TREE
-                || mState.action == ACTION_PICK_COPY_DESTINATION;
-
-        if (picking) {
+        super.updateOptionMenu(menu, details);
+        if (mPicking) {
             // May already be hidden because the root
             // doesn't support search.
             mSearchManager.showMenu(false);
         }
+    }
 
-        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
-        final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
-
-        createDir.setVisible(picking);
-        createDir.setEnabled(details.canCreateDirectory());
-
-        // No display options in recent directories
-        if (picking && details.isInRecents()) {
-            final MenuItem grid = menu.findItem(R.id.menu_grid);
-            final MenuItem list = menu.findItem(R.id.menu_list);
+    @Override
+    void updateModePicker(MenuItem grid, MenuItem list, DirectoryDetails directoryDetails) {
+     // No display options in recent directories
+        if (mPicking && directoryDetails.isInRecents()) {
             grid.setVisible(false);
             list.setVisible(false);
         }
+    }
 
-        fileSize.setVisible(fileSize.isVisible() && !picking);
+    @Override
+    void updateFileSize(MenuItem fileSize, DirectoryDetails directoryDetails) {
+        fileSize.setVisible(fileSize.isVisible() && !mPicking);
+    }
 
-        Menus.disableHiddenItems(menu);
+    @Override
+    void updateSettings(MenuItem settings, DirectoryDetails directoryDetails) {
+        assert(!settings.isVisible());
+    }
+
+    @Override
+    void updateNewWindow(MenuItem newWindow, DirectoryDetails directoryDetails) {
+        assert(!newWindow.isVisible());
+    }
+
+    @Override
+    void updateSelectAll(MenuItem selectAll, SelectionDetails selectionDetails) {
+        selectAll.setVisible(mState.allowMultiple);
+    }
+
+    @Override
+    void updateCreateDir(MenuItem createDir, DirectoryDetails directoryDetails) {
+        createDir.setVisible(mPicking);
+        createDir.setEnabled(mPicking && directoryDetails.canCreateDirectory());
+    }
+
+    @Override
+    void updateOpen(MenuItem open, SelectionDetails selectionDetails) {
+        open.setVisible(mState.action == ACTION_GET_CONTENT
+                || mState.action == ACTION_OPEN);
+    }
+
+    @Override
+    void updateShare(MenuItem share, SelectionDetails selectionDetails) {
+        share.setVisible(false);
+    }
+
+    @Override
+    void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
+        delete.setVisible(false);
+    }
+
+    @Override
+    void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
+        rename.setVisible(false);
+    }
+
+    @Override
+    void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
+        assert(!moveTo.isVisible());
+    }
+
+    @Override
+    void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
+        assert(!copyTo.isVisible());
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Events.java b/packages/DocumentsUI/src/com/android/documentsui/Events.java
index d131f2e..27293e1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Events.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Events.java
@@ -128,6 +128,8 @@
         boolean isActionUp();
 
         Point getOrigin();
+        float getX();
+        float getY();
 
         /** Returns true if the there is an item under the finger/cursor. */
         boolean isOverItem();
@@ -216,6 +218,16 @@
         }
 
         @Override
+        public float getX() {
+            return mEvent.getX();
+        }
+
+        @Override
+        public float getY() {
+            return mEvent.getY();
+        }
+
+        @Override
         public boolean isOverItem() {
             return getItemPosition() != RecyclerView.NO_POSITION;
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 59b9e9b..be20c0e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -468,6 +468,11 @@
       return mMenuManager;
     }
 
+    @Override
+    public DirectoryDetails getDirectoryDetails() {
+        return mDetails;
+    }
+
     /**
      * Builds a stack for the specific Uris. Multi roots are not supported, as it's impossible
      * to know which root to select. Also, the stack doesn't contain intermediate directories.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesMenuManager.java b/packages/DocumentsUI/src/com/android/documentsui/FilesMenuManager.java
index f7256ff..4b27a7e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesMenuManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesMenuManager.java
@@ -19,9 +19,7 @@
 import android.view.Menu;
 import android.view.MenuItem;
 
-import com.android.documentsui.R;
-
-final class FilesMenuManager implements MenuManager {
+final class FilesMenuManager extends MenuManager {
 
     private final SearchViewManager mSearchManager;
 
@@ -30,58 +28,76 @@
     }
 
     @Override
-    public void updateActionMenu(Menu menu, SelectionDetails selection) {
-
-        menu.findItem(R.id.menu_open).setVisible(false); // "open" is never used in Files.
-
-        // Commands accessible only via keyboard...
-        MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
-        MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
-
-        // Commands visible in the UI...
-        MenuItem rename = menu.findItem(R.id.menu_rename);
-        MenuItem moveTo = menu.findItem(R.id.menu_move_to);
-        MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
-        MenuItem share = menu.findItem(R.id.menu_share);
-        MenuItem delete = menu.findItem(R.id.menu_delete);
-
-        // Commands usually on action-bar, so we always manage visibility.
-        share.setVisible(!selection.containsDirectories() && !selection.containsPartialFiles());
-        delete.setVisible(selection.canDelete());
-
-        // Commands always in overflow, so we don't bother showing/hiding...
-        copyTo.setVisible(true);
-        moveTo.setVisible(true);
-        rename.setVisible(true);
-
-        // copy is not visible, keyboard only
-        copy.setEnabled(!selection.containsPartialFiles());
-
-        copyTo.setEnabled(!selection.containsPartialFiles());
-        moveTo.setEnabled(!selection.containsPartialFiles() && selection.canDelete());
-        rename.setEnabled(!selection.containsPartialFiles() && selection.canRename());
-
-        Menus.disableHiddenItems(menu, copy, paste);
-    }
-
-    @Override
     public void updateOptionMenu(Menu menu, DirectoryDetails details) {
-
-        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
-        final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
-        final MenuItem settings = menu.findItem(R.id.menu_settings);
-        final MenuItem newWindow = menu.findItem(R.id.menu_new_window);
-
-        createDir.setVisible(true);
-        createDir.setEnabled(details.canCreateDirectory());
-        pasteFromCb.setEnabled(details.hasItemsToPaste());
-        settings.setVisible(details.hasRootSettings());
-        newWindow.setVisible(details.shouldShowFancyFeatures());
-
-        Menus.disableHiddenItems(menu, pasteFromCb);
+        super.updateOptionMenu(menu, details);
 
         // It hides icon if searching in progress
         mSearchManager.updateMenu();
     }
 
-}
+    @Override
+    void updateModePicker(MenuItem grid, MenuItem list, DirectoryDetails directoryDetails) {
+        assert(!grid.isVisible());
+        assert(list.isVisible());
+    }
+
+    @Override
+    void updateFileSize(MenuItem fileSize, DirectoryDetails directoryDetails) {
+        assert(fileSize.isVisible());
+    }
+
+    @Override
+    void updateSettings(MenuItem settings, DirectoryDetails directoryDetails) {
+        settings.setVisible(directoryDetails.hasRootSettings());
+    }
+
+    @Override
+    void updateNewWindow(MenuItem newWindow, DirectoryDetails directoryDetails) {
+        newWindow.setVisible(directoryDetails.shouldShowFancyFeatures());
+    }
+
+    @Override
+    void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
+        moveTo.setVisible(true);
+        moveTo.setEnabled(!selectionDetails.containsPartialFiles() && selectionDetails.canDelete());
+    }
+
+    @Override
+    void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
+        copyTo.setVisible(true);
+        copyTo.setEnabled(!selectionDetails.containsPartialFiles());
+    }
+
+    @Override
+    void updateSelectAll(MenuItem selectAll, SelectionDetails selectionDetails) {
+        assert(selectAll.isVisible());
+    }
+
+    @Override
+    void updateCreateDir(MenuItem createDir, DirectoryDetails directoryDetails) {
+        createDir.setVisible(true);
+        createDir.setEnabled(directoryDetails.canCreateDirectory());
+    }
+
+    @Override
+    void updateOpen(MenuItem open, SelectionDetails selectionDetails) {
+        open.setVisible(false);
+    }
+
+    @Override
+    void updateShare(MenuItem share, SelectionDetails selectionDetails) {
+        share.setVisible(!selectionDetails.containsDirectories()
+                && !selectionDetails.containsPartialFiles());
+    }
+
+    @Override
+    void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
+        delete.setVisible(selectionDetails.canDelete());
+    }
+
+    @Override
+    void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
+        rename.setVisible(true);
+        rename.setEnabled(!selectionDetails.containsPartialFiles() && selectionDetails.canRename());
+    }
+}
\ No newline at end of file
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MenuManager.java b/packages/DocumentsUI/src/com/android/documentsui/MenuManager.java
index b14fab3..24bc4f1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MenuManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MenuManager.java
@@ -16,53 +16,124 @@
 
 package com.android.documentsui;
 
+import android.annotation.Nullable;
 import android.view.Menu;
+import android.view.MenuItem;
 
-public interface MenuManager {
+public abstract class MenuManager {
 
-  /** @See DirectoryFragment.SelectionModeListener#updateActionMenu */
-  void updateActionMenu(Menu mMenu, MenuManager.SelectionDetails selectionDetails);
-  /** @See Activity#onPrepareOptionsMenu */
-  void updateOptionMenu(Menu menu, DirectoryDetails details);
+    /** @See DirectoryFragment.SelectionModeListener#updateActionMenu */
+    public void updateActionMenu(Menu menu, SelectionDetails selection) {
+        updateOpen(menu.findItem(R.id.menu_open), selection);
+        updateDelete(menu.findItem(R.id.menu_delete), selection);
+        updateShare(menu.findItem(R.id.menu_share), selection);
+        updateRename(menu.findItem(R.id.menu_rename), selection);
+        updateSelectAll(menu.findItem(R.id.menu_select_all), selection);
+        updateMoveTo(menu.findItem(R.id.menu_move_to), selection);
+        updateCopyTo(menu.findItem(R.id.menu_copy_to), selection);
 
-  /**
-   * Access to meta data about the selection.
-   */
-  interface SelectionDetails {
-    boolean containsDirectories();
-    boolean containsPartialFiles();
+        Menus.disableHiddenItems(menu);
+    }
 
-    // TODO: Update these to express characteristics instead of answering concrete questions,
-    // since the answer to those questions is (or can be) activity specific.
-    boolean canDelete();
-    boolean canRename();
-  }
+    /** @See Activity#onPrepareOptionsMenu */
+    public void updateOptionMenu(Menu menu, DirectoryDetails details) {
+        updateCreateDir(menu.findItem(R.id.menu_create_dir), details);
+        updateSettings(menu.findItem(R.id.menu_settings), details);
+        updateNewWindow(menu.findItem(R.id.menu_new_window), details);
+        updateFileSize(menu.findItem(R.id.menu_file_size), details);
+        updateModePicker(menu.findItem(R.id.menu_grid), menu.findItem(R.id.menu_list), details);
 
-  public static class DirectoryDetails {
-      private final BaseActivity mActivity;
+        Menus.disableHiddenItems(menu);
+    }
 
-      public DirectoryDetails(BaseActivity activity) {
-        mActivity = activity;
-      }
+    /** @See DirectoryFragment.onCreateContextMenu */
+    public void updateContextMenu(Menu menu,
+            @Nullable SelectionDetails selectionDetails,
+            DirectoryDetails directoryDetails) {
 
-      public boolean shouldShowFancyFeatures() {
-        return Shared.shouldShowFancyFeatures(mActivity);
-      }
+        MenuItem cut = menu.findItem(R.id.menu_cut_to_clipboard);
+        MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
+        MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
+        MenuItem delete = menu.findItem(R.id.menu_delete);
+        MenuItem rename = menu.findItem(R.id.menu_rename);
+        MenuItem createDir = menu.findItem(R.id.menu_create_dir);
 
-      public boolean hasRootSettings() {
-        return mActivity.getCurrentRoot().hasSettings();
-      }
+        if (selectionDetails == null) {
+            cut.setEnabled(false);
+            copy.setEnabled(false);
+            rename.setEnabled(false);
+            delete.setEnabled(false);
+        } else {
+            copy.setEnabled(!selectionDetails.containsPartialFiles());
+            cut.setEnabled(
+                    !selectionDetails.containsPartialFiles() && selectionDetails.canDelete());
+            updateRename(rename, selectionDetails);
+            updateDelete(delete, selectionDetails);
+        }
+        menu.findItem(R.id.menu_paste_from_clipboard)
+                .setEnabled(directoryDetails.hasItemsToPaste());
+        updateCreateDir(createDir, directoryDetails);
 
-      public boolean hasItemsToPaste() {
-          return false;
-      }
+        //Cut, Copy, Paste and Delete should always be visible
+        cut.setVisible(true);
+        copy.setVisible(true);
+        paste.setVisible(true);
+        delete.setVisible(true);
+    }
 
-      public boolean isInRecents() {
-        return mActivity.getCurrentDirectory() == null;
-      }
+    abstract void updateModePicker(MenuItem grid, MenuItem list, DirectoryDetails directoryDetails);
+    abstract void updateFileSize(MenuItem fileSize, DirectoryDetails directoryDetails);
+    abstract void updateSettings(MenuItem settings, DirectoryDetails directoryDetails);
+    abstract void updateNewWindow(MenuItem newWindow, DirectoryDetails directoryDetails);
+    abstract void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails);
+    abstract void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails);
+    abstract void updateSelectAll(MenuItem selectAll, SelectionDetails selectionDetails);
+    abstract void updateCreateDir(MenuItem createDir, DirectoryDetails directoryDetails);
+    abstract void updateOpen(MenuItem open, SelectionDetails selectionDetails);
+    abstract void updateShare(MenuItem share, SelectionDetails selectionDetails);
+    abstract void updateRename(MenuItem rename, SelectionDetails selectionDetails);
+    abstract void updateDelete(MenuItem delete, SelectionDetails selectionDetails);
 
-      public boolean canCreateDirectory() {
-        return mActivity.canCreateDirectory();
-      }
-  }
-}
\ No newline at end of file
+    /**
+     * Access to meta data about the selection.
+     */
+    public interface SelectionDetails {
+        boolean containsDirectories();
+
+        boolean containsPartialFiles();
+
+        // TODO: Update these to express characteristics instead of answering concrete questions,
+        // since the answer to those questions is (or can be) activity specific.
+        boolean canDelete();
+
+        boolean canRename();
+    }
+
+    public static class DirectoryDetails {
+        private final BaseActivity mActivity;
+
+        public DirectoryDetails(BaseActivity activity) {
+            mActivity = activity;
+        }
+
+        public boolean shouldShowFancyFeatures() {
+            return Shared.shouldShowFancyFeatures(mActivity);
+        }
+
+        public boolean hasRootSettings() {
+            return mActivity.getCurrentRoot().hasSettings();
+        }
+
+        public boolean hasItemsToPaste() {
+            return false;
+        }
+
+        public boolean isInRecents() {
+            return mActivity.getCurrentDirectory() == null;
+        }
+
+        public boolean canCreateDirectory() {
+            return mActivity.canCreateDirectory();
+        }
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 303db2e..7f35854 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -61,15 +61,18 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.ActionMode;
+import android.view.ContextMenu;
 import android.view.DragEvent;
 import android.view.GestureDetector;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -147,6 +150,7 @@
     private MultiSelectManager mSelectionManager;
     private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
     private ItemEventListener mItemEventListener = new ItemEventListener();
+    private SelectionModeListener mSelectionModeListener;
     private FocusManager mFocusManager;
 
     private IconHelper mIconHelper;
@@ -297,6 +301,7 @@
                 new ListeningGestureDetector(this.getContext(), mDragHelper, new GestureListener());
 
         mRecView.addOnItemTouchListener(mGestureDetector);
+        mEmptyView.setOnTouchListener(mGestureDetector);
 
         // TODO: instead of inserting the view into the constructor, extract listener-creation code
         // and set the listener on the view after the fact.  Then the view doesn't need to be passed
@@ -313,7 +318,8 @@
             mBandController = new BandController(mRecView, mAdapter, mSelectionManager);
         }
 
-        mSelectionManager.addCallback(new SelectionModeListener());
+        mSelectionModeListener = new SelectionModeListener();
+        mSelectionManager.addCallback(mSelectionModeListener);
 
         mModel = new Model();
         mModel.addUpdateListener(mAdapter);
@@ -362,6 +368,31 @@
         }
     }
 
+    @Override
+    public void onCreateContextMenu(ContextMenu menu,
+            View v,
+            ContextMenu.ContextMenuInfo menuInfo) {
+        super.onCreateContextMenu(menu, v, menuInfo);
+        MenuInflater inflater = getActivity().getMenuInflater();
+        inflater.inflate(R.menu.context_menu, menu);
+
+        menu.add(Menu.NONE, R.id.menu_create_dir, Menu.NONE, R.string.menu_create_dir);
+        menu.add(Menu.NONE, R.id.menu_delete, Menu.NONE, R.string.menu_delete);
+        menu.add(Menu.NONE, R.id.menu_rename, Menu.NONE, R.string.menu_rename);
+
+        if (v == mRecView || v == mEmptyView) {
+            mMenuManager.updateContextMenu(menu, null, getBaseActivity().getDirectoryDetails());
+        } else {
+            mMenuManager.updateContextMenu(menu, mSelectionModeListener,
+                    getBaseActivity().getDirectoryDetails());
+        }
+    }
+
+    @Override
+    public boolean onContextItemSelected(MenuItem item) {
+        return handleMenuItemClick(item);
+    }
+
     private void handleCopyResult(int resultCode, Intent data) {
         if (resultCode == Activity.RESULT_CANCELED || data == null) {
             // User pressed the back button or otherwise cancelled the destination pick. Don't
@@ -382,9 +413,9 @@
                 mFileOpCallback);
     }
 
-    protected boolean onDoubleTap(MotionEvent e) {
-        if (Events.isMouseEvent(e)) {
-            String id = getModelId(e);
+    protected boolean onDoubleTap(MotionInputEvent event) {
+        if (event.isMouseEvent()) {
+            String id = getModelId(event);
             if (id != null) {
                 return handleViewItem(id);
             }
@@ -392,6 +423,41 @@
         return false;
     }
 
+    protected boolean onRightClick(MotionInputEvent e) {
+        // First get target to see if it's a blank window or a file/doc
+        DocumentHolder holder = getTarget(e);
+        if (holder != null) {
+          String modelId = getModelId(holder.itemView);
+          if (!mSelectionManager.getSelection().contains(modelId)) {
+              mSelectionManager.clearSelection();
+              // Set selection on the one single item
+              List<String> ids = Collections.singletonList(modelId);
+              mSelectionManager.setItemsSelected(ids, true);
+          }
+
+          // We are registering for context menu here so long-press doesn't trigger this
+          // floating context menu, and then quickly unregister right afterwards
+          registerForContextMenu(holder.itemView);
+          mRecView.showContextMenuForChild(holder.itemView,
+              e.getX() - holder.itemView.getLeft(), e.getY() - holder.itemView.getTop());
+          unregisterForContextMenu(holder.itemView);
+        }
+        // If there was no holder item, that means user right-clicked on the blank pane
+        // We would want to show different options then, and not select any item
+        // The blank pane could be the recyclerView or the emptyView, so we need to register
+        // according to whichever one is visible
+        else if (mEmptyView.getVisibility() == View.VISIBLE) {
+            registerForContextMenu(mEmptyView);
+            mEmptyView.showContextMenu(e.getX(), e.getY());
+            unregisterForContextMenu(mEmptyView);
+        } else {
+            registerForContextMenu(mRecView);
+            mRecView.showContextMenu(e.getX(), e.getY());
+            unregisterForContextMenu(mRecView);
+        }
+        return true;
+    }
+
     private boolean handleViewItem(String id) {
         final Cursor cursor = mModel.getItem(id);
 
@@ -690,58 +756,74 @@
 
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-            Selection selection = mSelectionManager.getSelection(new Selection());
+            return handleMenuItemClick(item);
+        }
+    }
 
-            switch (item.getItemId()) {
-                case R.id.menu_open:
-                    openDocuments(selection);
-                    mode.finish();
-                    return true;
+    private boolean handleMenuItemClick(MenuItem item) {
+        Selection selection = mSelectionManager.getSelection(new Selection());
 
-                case R.id.menu_share:
-                    shareDocuments(selection);
-                    // TODO: Only finish selection if share action is completed.
-                    mode.finish();
-                    return true;
+        switch (item.getItemId()) {
+            case R.id.menu_open:
+                openDocuments(selection);
+                mActionMode.finish();
+                return true;
 
-                case R.id.menu_delete:
-                    // deleteDocuments will end action mode if the documents are deleted.
-                    // It won't end action mode if user cancels the delete.
-                    deleteDocuments(selection);
-                    return true;
+            case R.id.menu_share:
+                shareDocuments(selection);
+                // TODO: Only finish selection if share action is completed.
+                mActionMode.finish();
+                return true;
 
-                case R.id.menu_copy_to:
-                    transferDocuments(selection, FileOperationService.OPERATION_COPY);
-                    // TODO: Only finish selection mode if copy-to is not canceled.
-                    // Need to plum down into handling the way we do with deleteDocuments.
-                    mode.finish();
-                    return true;
+            case R.id.menu_delete:
+                // deleteDocuments will end action mode if the documents are deleted.
+                // It won't end action mode if user cancels the delete.
+                deleteDocuments(selection);
+                return true;
 
-                case R.id.menu_move_to:
-                    // Exit selection mode first, so we avoid deselecting deleted documents.
-                    mode.finish();
-                    transferDocuments(selection, FileOperationService.OPERATION_MOVE);
-                    return true;
+            case R.id.menu_copy_to:
+                transferDocuments(selection, FileOperationService.OPERATION_COPY);
+                // TODO: Only finish selection mode if copy-to is not canceled.
+                // Need to plum down into handling the way we do with deleteDocuments.
+                mActionMode.finish();
+                return true;
 
-                case R.id.menu_copy_to_clipboard:
-                    copySelectedToClipboard();
-                    return true;
+            case R.id.menu_move_to:
+                // Exit selection mode first, so we avoid deselecting deleted documents.
+                mActionMode.finish();
+                transferDocuments(selection, FileOperationService.OPERATION_MOVE);
+                return true;
 
-                case R.id.menu_select_all:
-                    selectAllFiles();
-                    return true;
+            case R.id.menu_cut_to_clipboard:
+                cutSelectedToClipboard();
+                return true;
 
-                case R.id.menu_rename:
-                    // Exit selection mode first, so we avoid deselecting deleted
-                    // (renamed) documents.
-                    mode.finish();
-                    renameDocuments(selection);
-                    return true;
+            case R.id.menu_copy_to_clipboard:
+                copySelectedToClipboard();
+                return true;
 
-                default:
+            case R.id.menu_paste_from_clipboard:
+                pasteFromClipboard();
+                return true;
+
+            case R.id.menu_select_all:
+                selectAllFiles();
+                return true;
+
+            case R.id.menu_rename:
+                // Exit selection mode first, so we avoid deselecting deleted
+                // (renamed) documents.
+                mActionMode.finish();
+                renameDocuments(selection);
+                return true;
+
+            default:
+                // See if BaseActivity can handle this particular MenuItem
+                if (!getBaseActivity().onOptionsItemSelected(item)) {
                     if (DEBUG) Log.d(TAG, "Unhandled menu item selected: " + item);
                     return false;
-            }
+                }
+                return true;
         }
     }
 
@@ -1258,12 +1340,8 @@
     /**
      * Gets the model ID for a given motion event (using the event position)
      */
-    private String getModelId(MotionEvent e) {
-        View view = mRecView.findChildViewUnder(e.getX(), e.getY());
-        if (view == null) {
-            return null;
-        }
-        RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(view);
+    private String getModelId(MotionInputEvent e) {
+        RecyclerView.ViewHolder vh = getTarget(e);
         if (vh instanceof DocumentHolder) {
             return ((DocumentHolder) vh).modelId;
         } else {
@@ -1271,13 +1349,22 @@
         }
     }
 
+    private @Nullable DocumentHolder getTarget(MotionInputEvent e) {
+        View childView = mRecView.findChildViewUnder(e.getX(), e.getY());
+        if (childView != null) {
+            return (DocumentHolder) mRecView.getChildViewHolder(childView);
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Gets the model ID for a given RecyclerView item.
      * @param view A View that is a document item view, or a child of a document item view.
      * @return The Model ID for the given document, or null if the given view is not associated with
      *     a document item view.
      */
-    protected String getModelId(View view) {
+    protected @Nullable String getModelId(View view) {
         View itemView = mRecView.findContainingItemView(view);
         if (itemView != null) {
             RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(itemView);
@@ -1565,29 +1652,24 @@
     // to GestureDetector. We're still doing that here, but with a single class
     // that reduces overall complexity in our glue code.
     private static final class ListeningGestureDetector extends GestureDetector
-            implements OnItemTouchListener {
+            implements OnItemTouchListener, OnTouchListener {
 
-        private int mLastTool = -1;
         private DragStartHelper mDragHelper;
+        private GestureListener mGestureListener;
 
         public ListeningGestureDetector(
                 Context context, DragStartHelper dragHelper, GestureListener listener) {
             super(context, listener);
             mDragHelper = dragHelper;
+            mGestureListener = listener;
             setOnDoubleTapListener(listener);
         }
 
-        boolean mouseSpawnedLastEvent() {
-            return Events.isMouseType(mLastTool);
-        }
-
-        boolean touchSpawnedLastEvent() {
-            return Events.isTouchType(mLastTool);
-        }
-
         @Override
         public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
-            mLastTool = e.getToolType(0);
+            if (e.getAction() == MotionEvent.ACTION_DOWN && Events.isMouseEvent(e)) {
+                mGestureListener.setLastButtonState(e.getButtonState());
+            }
 
             // Detect drag events. When a drag is detected, intercept the rest of the gesture.
             View itemView = rv.findChildViewUnder(e.getX(), e.getY());
@@ -1612,6 +1694,15 @@
 
         @Override
         public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
+
+        // For mEmptyView right-click context menu
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            if (event.getButtonState() == MotionEvent.BUTTON_SECONDARY) {
+                return mGestureListener.onSingleTapConfirmed(event);
+            }
+            return false;
+        }
     }
 
     /**
@@ -1619,11 +1710,32 @@
      * events to the target DocumentHolder, whence they are routed to the appropriate listener.
      */
     private class GestureListener extends GestureDetector.SimpleOnGestureListener {
+        // From the RecyclerView, we get two events sent to
+        // ListeningGestureDetector#onInterceptTouchEvent on a mouse click; we first get an
+        // ACTION_DOWN Event for clicking on the mouse, and then an ACTION_UP event from releasing
+        // the mouse click. ACTION_UP event doesn't have information regarding the button (primary
+        // vs. secondary), so we have to save that somewhere first from ACTION_DOWN, and then reuse
+        // it later. The ACTION_DOWN event doesn't get forwarded to GestureListener, so we have open
+        // up a public set method to set it.
+        private int mLastButtonState = -1;
+
+        public void setLastButtonState(int state) {
+            mLastButtonState = state;
+        }
+
         @Override
         public boolean onSingleTapUp(MotionEvent e) {
             // Single tap logic:
+            // We first see if it's a mouse event, and if it was right click by checking on
+            // @{code ListeningGestureDetector#mLastButtonState}
             // If the selection manager is active, it gets first whack at handling tap
             // events. Otherwise, tap events are routed to the target DocumentHolder.
+            if (Events.isMouseEvent(e) && mLastButtonState == MotionEvent.BUTTON_SECONDARY) {
+                mLastButtonState = -1;
+                final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
+                return DirectoryFragment.this.onRightClick(event);
+            }
+
             final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
             try {
                 boolean handled = mSelectionManager.onSingleTapUp(event);
@@ -1633,7 +1745,7 @@
                 }
 
                 // Give the DocumentHolder a crack at the event.
-                DocumentHolder holder = getTarget(e);
+                DocumentHolder holder = DirectoryFragment.this.getTarget(event);
                 if (holder != null) {
                     handled = holder.onSingleTapUp(e);
                 }
@@ -1660,16 +1772,8 @@
         public boolean onDoubleTap(MotionEvent e) {
             // Double-tap events are handled directly by the DirectoryFragment. They can be changed
             // to route through the DocumentHolder if necessary.
-            return DirectoryFragment.this.onDoubleTap(e);
-        }
-
-        private @Nullable DocumentHolder getTarget(MotionEvent e) {
-            View childView = mRecView.findChildViewUnder(e.getX(), e.getY());
-            if (childView != null) {
-                return (DocumentHolder) mRecView.getChildViewHolder(childView);
-            } else {
-                return null;
-            }
+            final MotionInputEvent event = MotionInputEvent.obtain(e, mRecView);
+            return DirectoryFragment.this.onDoubleTap(event);
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index 0922fb7..497887c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -249,7 +249,6 @@
         handleAdapterEvent(input);
     }
 
-    @VisibleForTesting
     boolean onSingleTapUp(InputEvent input) {
         if (DEBUG) Log.d(TAG, "Processing tap event.");
         if (!hasSelection()) {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsMenuManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsMenuManagerTest.java
index e0c99d8..ce8bc03 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsMenuManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsMenuManagerTest.java
@@ -48,6 +48,9 @@
     private TestMenuItem fileSize;
     private TestMenuItem grid;
     private TestMenuItem list;
+    private TestMenuItem cut;
+    private TestMenuItem copy;
+    private TestMenuItem paste;
 
     private TestSelectionDetails selectionDetails;
     private TestDirectoryDetails directoryDetails;
@@ -66,6 +69,9 @@
         fileSize = testMenu.findItem(R.id.menu_file_size);
         grid = testMenu.findItem(R.id.menu_grid);
         list = testMenu.findItem(R.id.menu_list);
+        cut = testMenu.findItem(R.id.menu_cut_to_clipboard);
+        copy = testMenu.findItem(R.id.menu_copy_to_clipboard);
+        paste = testMenu.findItem(R.id.menu_paste_from_clipboard);
 
         selectionDetails = new TestSelectionDetails();
         directoryDetails = new TestDirectoryDetails();
@@ -145,4 +151,29 @@
         grid.assertInvisible();
         list.assertInvisible();
     }
+
+    @Test
+    public void testContextMenu_NoSelection() {
+        FilesMenuManager mgr = new FilesMenuManager(testSearchManager);
+        mgr.updateContextMenu(testMenu, null, directoryDetails);
+        cut.assertVisible();
+        copy.assertVisible();
+        cut.assertDisabled();
+        copy.assertDisabled();
+        paste.assertVisible();
+        createDir.assertVisible();
+        delete.assertVisible();
+    }
+
+    @Test
+    public void testContextMenu_Selection() {
+        FilesMenuManager mgr = new FilesMenuManager(testSearchManager);
+        mgr.updateContextMenu(testMenu, selectionDetails, directoryDetails);
+        cut.assertVisible();
+        copy.assertVisible();
+        paste.assertVisible();
+        rename.assertVisible();
+        createDir.assertVisible();
+        delete.assertVisible();
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesMenuManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesMenuManagerTest.java
index 244f7ec..8b2eeb5 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesMenuManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesMenuManagerTest.java
@@ -41,9 +41,11 @@
     private TestMenuItem share;
     private TestMenuItem delete;
     private TestMenuItem createDir;
-    private TestMenuItem pasteFromCb;
     private TestMenuItem settings;
     private TestMenuItem newWindow;
+    private TestMenuItem cut;
+    private TestMenuItem copy;
+    private TestMenuItem paste;
     private TestSelectionDetails selectionDetails;
     private TestDirectoryDetails directoryDetails;
     private TestSearchViewManager testSearchManager;
@@ -57,9 +59,16 @@
         share = testMenu.findItem(R.id.menu_share);
         delete = testMenu.findItem(R.id.menu_delete);
         createDir = testMenu.findItem(R.id.menu_create_dir);
-        pasteFromCb = testMenu.findItem(R.id.menu_paste_from_clipboard);
         settings = testMenu.findItem(R.id.menu_settings);
         newWindow = testMenu.findItem(R.id.menu_new_window);
+        cut = testMenu.findItem(R.id.menu_cut_to_clipboard);
+        copy = testMenu.findItem(R.id.menu_copy_to_clipboard);
+        paste = testMenu.findItem(R.id.menu_paste_from_clipboard);
+
+        // These items by default are visible
+        testMenu.findItem(R.id.menu_select_all).setVisible(true);
+        testMenu.findItem(R.id.menu_list).setVisible(true);
+        testMenu.findItem(R.id.menu_file_size).setVisible(true);
 
         selectionDetails = new TestSelectionDetails();
         directoryDetails = new TestDirectoryDetails();
@@ -133,15 +142,6 @@
     }
 
     @Test
-    public void testOptionMenu_hasItemsToPaste() {
-        directoryDetails.hasItemsToPaste = true;
-        FilesMenuManager mgr = new FilesMenuManager(testSearchManager);
-        mgr.updateOptionMenu(testMenu, directoryDetails);
-
-        pasteFromCb.assertEnabled();
-    }
-
-    @Test
     public void testOptionMenu_hasRootSettings() {
         directoryDetails.hasRootSettings = true;
         FilesMenuManager mgr = new FilesMenuManager(testSearchManager);
@@ -158,4 +158,29 @@
 
         newWindow.assertVisible();
     }
+
+    @Test
+    public void testContextMenu_NoSelection() {
+        FilesMenuManager mgr = new FilesMenuManager(testSearchManager);
+        mgr.updateContextMenu(testMenu, null, directoryDetails);
+        cut.assertVisible();
+        copy.assertVisible();
+        cut.assertDisabled();
+        copy.assertDisabled();
+        paste.assertVisible();
+        createDir.assertVisible();
+        delete.assertVisible();
+    }
+
+    @Test
+    public void testContextMenu_Selection() {
+        FilesMenuManager mgr = new FilesMenuManager(testSearchManager);
+        mgr.updateContextMenu(testMenu, selectionDetails, directoryDetails);
+        cut.assertVisible();
+        copy.assertVisible();
+        paste.assertVisible();
+        rename.assertVisible();
+        createDir.assertVisible();
+        delete.assertVisible();
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/TestInputEvent.java b/packages/DocumentsUI/tests/src/com/android/documentsui/TestInputEvent.java
index ec5321a..a215488 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/TestInputEvent.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/TestInputEvent.java
@@ -56,6 +56,16 @@
     }
 
     @Override
+    public float getX() {
+        return location.x;
+    }
+
+    @Override
+    public float getY() {
+        return location.y;
+    }
+
+    @Override
     public boolean isOverItem() {
         return position != Integer.MIN_VALUE && position != RecyclerView.NO_POSITION;
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/testing/TestMenu.java b/packages/DocumentsUI/tests/src/com/android/documentsui/testing/TestMenu.java
index 78f26df..88a56db 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/testing/TestMenu.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/testing/TestMenu.java
@@ -38,20 +38,21 @@
     public static TestMenu create() {
         return create(R.id.menu_open,
                 R.id.menu_rename,
-                R.id.menu_copy_to_clipboard,
-                R.id.menu_paste_from_clipboard,
                 R.id.menu_move_to,
                 R.id.menu_copy_to,
+                R.id.menu_cut_to_clipboard,
+                R.id.menu_copy_to_clipboard,
+                R.id.menu_paste_from_clipboard,
                 R.id.menu_share,
                 R.id.menu_delete,
                 R.id.menu_create_dir,
-                R.id.menu_paste_from_clipboard,
                 R.id.menu_settings,
                 R.id.menu_new_window,
                 R.id.menu_select_all,
                 R.id.menu_file_size,
                 R.id.menu_grid,
-                R.id.menu_list);
+                R.id.menu_list,
+                R.id.menu_sort);
     }
 
     public static TestMenu create(int... ids) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index a4742c1..6658c14 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -319,9 +319,6 @@
     private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
         @Override
         protected List<DashboardCategory> doInBackground(Void... params) {
-            if (sConfigTracker == null || sTileCache == null) {
-                getDashboardCategories();
-            }
             if (sConfigTracker.applyNewConfig(getResources())) {
                 sTileCache.clear();
             }