Merge "Leave from the current root when the root is removed."
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 9c0a04c..a241667 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -39,7 +39,6 @@
 import android.support.annotation.LayoutRes;
 import android.support.annotation.Nullable;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -60,6 +59,7 @@
 import com.android.documentsui.model.DocumentStack;
 import com.android.documentsui.model.DurableUtils;
 import com.android.documentsui.model.RootInfo;
+import com.android.internal.util.Preconditions;
 
 import libcore.io.IoUtils;
 
@@ -111,6 +111,13 @@
         setContentView(mLayoutId);
 
         mRoots = DocumentsApplication.getRootsCache(this);
+        mRoots.setOnCacheUpdateListener(
+                new RootsCache.OnCacheUpdateListener() {
+                    @Override
+                    public void onCacheUpdate() {
+                        new HandleRootsChangedTask().execute(getCurrentRoot());
+                    }
+                });
         mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
         mSearchManager = new SearchManager();
 
@@ -203,7 +210,25 @@
         if (mRoots.isRecentsRoot(root)) {
             onCurrentDirectoryChanged(ANIM_SIDE);
         } else {
-            new PickRootTask(root).executeOnExecutor(getExecutorForCurrentDirectory());
+            new PickRootTask(root, true).executeOnExecutor(getExecutorForCurrentDirectory());
+        }
+    }
+
+    void setRoot(RootInfo root) {
+        // Clear entire backstack and start in new root
+        mState.stack.root = root;
+        mState.stack.clear();
+        mState.stackTouched = false;
+
+        mSearchManager.update(root);
+
+        // Recents is always in memory, so we just load it directly.
+        // Otherwise we delegate loading data from disk to a task
+        // to ensure a responsive ui.
+        if (mRoots.isRecentsRoot(root)) {
+            onCurrentDirectoryChanged(ANIM_SIDE);
+        } else {
+            new PickRootTask(root, false).executeOnExecutor(getExecutorForCurrentDirectory());
         }
     }
 
@@ -483,9 +508,11 @@
 
     final class PickRootTask extends AsyncTask<Void, Void, DocumentInfo> {
         private RootInfo mRoot;
+        private boolean mTouched;
 
-        public PickRootTask(RootInfo root) {
+        public PickRootTask(RootInfo root, boolean touched) {
             mRoot = root;
+            mTouched = touched;
         }
 
         @Override
@@ -504,7 +531,7 @@
         protected void onPostExecute(DocumentInfo result) {
             if (result != null) {
                 mState.stack.push(result);
-                mState.stackTouched = true;
+                mState.stackTouched = mTouched;
                 onCurrentDirectoryChanged(ANIM_SIDE);
             }
         }
@@ -591,6 +618,34 @@
         }
     }
 
+    final class HandleRootsChangedTask extends AsyncTask<RootInfo, Void, RootInfo> {
+        @Override
+        protected RootInfo doInBackground(RootInfo... roots) {
+            Preconditions.checkArgument(roots.length == 1);
+            final RootInfo currentRoot = roots[0];
+            final Collection<RootInfo> cachedRoots = mRoots.getRootsBlocking();
+            RootInfo homeRoot = null;
+            for (final RootInfo root : cachedRoots) {
+                if (root.isHome()) {
+                    homeRoot = root;
+                }
+                if (root.getUri().equals(currentRoot.getUri())) {
+                    // We don't need to change the current root as the current root was not removed.
+                    return null;
+                }
+            }
+            Preconditions.checkNotNull(homeRoot);
+            return homeRoot;
+        }
+
+        @Override
+        protected void onPostExecute(RootInfo result) {
+            if (result != null) {
+                setRoot(result);
+            }
+        }
+    }
+
     final class ItemSelectedListener implements OnItemSelectedListener {
 
         boolean mIgnoreNextNavigation;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 72ee6cbab..21e7566 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -63,6 +63,7 @@
 
     private final Context mContext;
     private final ContentObserver mObserver;
+    private OnCacheUpdateListener mCacheUpdateListener;
 
     private final RootInfo mRecentsRoot = new RootInfo();
 
@@ -94,6 +95,10 @@
         }
     }
 
+    static interface OnCacheUpdateListener {
+        void onCacheUpdate();
+    }
+
     /**
      * Gather roots from all known storage providers.
      */
@@ -209,6 +214,13 @@
             return null;
         }
 
+        @Override
+        protected void onPostExecute(Void result) {
+            if (mCacheUpdateListener != null) {
+                mCacheUpdateListener.onCacheUpdate();
+            }
+        }
+
         private void handleDocumentsProvider(ProviderInfo info) {
             // Ignore stopped packages for now; we might query them
             // later during UI interaction.
@@ -348,6 +360,10 @@
         }
     }
 
+    public void setOnCacheUpdateListener(OnCacheUpdateListener cacheUpdateListener) {
+        mCacheUpdateListener = cacheUpdateListener;
+    }
+
     @VisibleForTesting
     static List<RootInfo> getMatchingRoots(Collection<RootInfo> roots, State state) {
         final List<RootInfo> matching = new ArrayList<>();