Load layout specific breadcrumb view.

Because two diffrn't view types can't share an resource id....
else we get ClassCastExceptions bubbling out of Spinner when
tryihng to restore from RecyclerView state.

Also:
Move Bots to own file and make BaseBot inner to that.
Extract searchbot from UiBot.
Fix broken search icon logic in phone layout.
Separate somewhat complicated breadcrumb bot functioanlity in a separate bot.
Simplify Search test.
Check for drawer vs. fixed layout instead of "tablet" mode...which didn't
    work when rotating tablets.
Update a dialog entry to use Espresso.
Update breadcrumb stuff to use Espresso.
Move *default state* checking to a different test so we can
    enjoy the default location support from ActivityTest.

Change-Id: I0a60ba93a1cbbb990ec3b36d4f9fd5dc8b86ff00
diff --git a/packages/DocumentsUI/res/layout/drawer_layout.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
index 4898f13..32ba6d0 100644
--- a/packages/DocumentsUI/res/layout/drawer_layout.xml
+++ b/packages/DocumentsUI/res/layout/drawer_layout.xml
@@ -42,7 +42,7 @@
                 android:popupTheme="?actionBarPopupTheme">
 
                 <com.android.documentsui.DropdownBreadcrumb
-                    android:id="@+id/breadcrumb"
+                    android:id="@+id/dropdown_breadcrumb"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_marginStart="4dp"
diff --git a/packages/DocumentsUI/res/layout/fixed_layout.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
index 6c65437..9882e94 100644
--- a/packages/DocumentsUI/res/layout/fixed_layout.xml
+++ b/packages/DocumentsUI/res/layout/fixed_layout.xml
@@ -40,7 +40,7 @@
             android:popupTheme="?actionBarPopupTheme">
 
             <com.android.documentsui.HorizontalBreadcrumb
-                android:id="@+id/breadcrumb"
+                android:id="@+id/horizontal_breadcrumb"
                 android:layout_marginRight="20dp"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
diff --git a/packages/DocumentsUI/res/values-sw720dp-land/config.xml b/packages/DocumentsUI/res/values-sw720dp-land/config.xml
deleted file mode 100644
index 6893d7a..0000000
--- a/packages/DocumentsUI/res/values-sw720dp-land/config.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-
-<resources>
-</resources>
diff --git a/packages/DocumentsUI/res/values/layouts.xml b/packages/DocumentsUI/res/values/layouts.xml
index c9308a1..a60ce87 100644
--- a/packages/DocumentsUI/res/values/layouts.xml
+++ b/packages/DocumentsUI/res/values/layouts.xml
@@ -17,5 +17,4 @@
 <resources>
     <item name="documents_activity" type="layout">@layout/drawer_layout</item>
     <item name="files_activity" type="layout">@layout/drawer_layout</item>
-    <item name="downloads_activity" type="layout">@layout/single_pane_layout</item>
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index a2f588b..3d1a176 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -141,8 +141,12 @@
         mSearchManager = new SearchViewManager(this, icicle);
 
         DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar);
-        Breadcrumb breadcrumb = (Breadcrumb) findViewById(R.id.breadcrumb);
         setActionBar(toolbar);
+
+        Breadcrumb breadcrumb =
+                Shared.findView(this, R.id.dropdown_breadcrumb, R.id.horizontal_breadcrumb);
+        assert(breadcrumb != null);
+
         mNavigator = new NavigationViewManager(mDrawer, toolbar, mState, this, breadcrumb);
 
         // Base classes must update result in their onCreate.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 2a81c48..c1db87d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -33,6 +33,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.annotation.Nullable;
+
 /** @hide */
 public final class Shared {
 
@@ -221,4 +223,15 @@
             Log.e(TAG, "Calling from non-UI thread!");
         }
     }
+
+    public static @Nullable <T> T findView(Activity activity, int... resources) {
+        for (int id : resources) {
+            @SuppressWarnings("unchecked")
+            T r = (T) activity.findViewById(id);
+            if (r != null) {
+                return r;
+            }
+        }
+        return null;
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
index 683fd6c..8ad30d7 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
@@ -20,7 +20,6 @@
 import static com.android.documentsui.StubProvider.ROOT_0_ID;
 import static com.android.documentsui.StubProvider.ROOT_1_ID;
 
-import android.annotation.Nullable;
 import android.app.Activity;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -32,17 +31,14 @@
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
 import android.view.MotionEvent;
 
-import com.android.documentsui.BaseActivity;
-import com.android.documentsui.EventListener;
-import com.android.documentsui.bots.DirectoryListBot;
-import com.android.documentsui.bots.KeyboardBot;
-import com.android.documentsui.bots.RootsListBot;
+import com.android.documentsui.bots.Bots;
 import com.android.documentsui.bots.UiBot;
 import com.android.documentsui.model.RootInfo;
 
+import javax.annotation.Nullable;
+
 /**
  * Provides basic test environment for UI tests:
  * - Launches activity
@@ -55,6 +51,7 @@
 
     // Testing files. For custom ones, override initTestFiles().
     public static final String dirName1 = "Dir1";
+    public static final String childDir1 = "ChildDir1";
     public static final String fileName1 = "file1.log";
     public static final String fileName2 = "file12.png";
     public static final String fileName3 = "anotherFile0.log";
@@ -81,8 +78,7 @@
      * Override the method if you want to open different root on start.
      * @return Root that will be opened. Return null if you want to open activity's default root.
      */
-    @Nullable
-    protected RootInfo getInitialRoot() {
+    protected @Nullable RootInfo getInitialRoot() {
         return rootDir0;
     }
 
@@ -157,29 +153,16 @@
     }
 
     void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException {
+        bots.directory.waitForDocument(fileName1);
+        bots.directory.waitForDocument(fileName2);
+        bots.directory.waitForDocument(dirName1);
+        bots.directory.waitForDocument(fileNameNoRename);
         bots.directory.assertDocumentsCount(4);
-        bots.directory.assertDocumentsPresent(fileName1, fileName2, dirName1, fileNameNoRename);
     }
 
     void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException {
+        bots.directory.waitForDocument(fileName3);
+        bots.directory.waitForDocument(fileName4);
         bots.directory.assertDocumentsCount(2);
-        bots.directory.assertDocumentsPresent(fileName3, fileName4);
-    }
-
-    /**
-     * Handy collection of bots for working with Files app.
-     */
-    public static final class Bots {
-        public final UiBot main;
-        public final RootsListBot roots;
-        public final DirectoryListBot directory;
-        public final KeyboardBot keyboard;
-
-        private Bots(UiDevice device, Context context, int timeout) {
-            this.main = new UiBot(device, context, TIMEOUT);
-            this.roots = new RootsListBot(device, context, TIMEOUT);
-            this.directory = new DirectoryListBot(device, context, TIMEOUT);
-            this.keyboard = new KeyboardBot(device, context, TIMEOUT);
-        }
     }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FileManagementUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FileManagementUiTest.java
new file mode 100644
index 0000000..dd9709d
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FileManagementUiTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.StubProvider.ROOT_0_ID;
+import static com.android.documentsui.StubProvider.ROOT_1_ID;
+
+import android.net.Uri;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.KeyEvent;
+
+@LargeTest
+public class FileManagementUiTest extends ActivityTest<FilesActivity> {
+
+    public FileManagementUiTest() {
+        super(FilesActivity.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        initTestFiles();
+    }
+
+    @Override
+    public void initTestFiles() throws RemoteException {
+        Uri uri = mDocsHelper.createFolder(rootDir0, dirName1);
+        mDocsHelper.createFolder(uri, childDir1);
+
+        mDocsHelper.createDocument(rootDir0, "text/plain", "file0.log");
+        mDocsHelper.createDocument(rootDir0, "image/png", "file1.png");
+        mDocsHelper.createDocument(rootDir0, "text/csv", "file2.csv");
+
+        mDocsHelper.createDocument(rootDir1, "text/plain", "anotherFile0.log");
+        mDocsHelper.createDocument(rootDir1, "text/plain", "poodles.text");
+    }
+
+    public void testCreateDirectory() throws Exception {
+        bots.main.openOverflowMenu();
+        device.waitForIdle();
+
+        bots.main.clickToolbarOverflowItem("New folder");
+        device.waitForIdle();
+
+        bots.main.setDialogText("Kung Fu Panda");
+        device.waitForIdle();
+
+        bots.keyboard.pressEnter();
+
+        bots.directory.waitForDocument("Kung Fu Panda");
+    }
+
+    public void testDeleteDocument() throws Exception {
+        bots.directory.clickDocument("file1.png");
+        device.waitForIdle();
+        bots.main.clickToolbarItem(R.id.menu_delete);
+
+        bots.main.clickDialogOkButton();
+        device.waitForIdle();
+
+        bots.directory.assertDocumentsAbsent("file1.png");
+    }
+
+    public void testKeyboard_CutDocument() throws Exception {
+        bots.directory.clickDocument("file1.png");
+        device.waitForIdle();
+        bots.keyboard.pressKey(KeyEvent.KEYCODE_X, KeyEvent.META_CTRL_ON);
+
+        device.waitForIdle();
+
+        bots.roots.openRoot(ROOT_1_ID);
+        bots.keyboard.pressKey(KeyEvent.KEYCODE_V, KeyEvent.META_CTRL_ON);
+
+        bots.directory.waitForDocument("file1.png");
+        bots.directory.assertDocumentsPresent("file1.png");
+
+        bots.roots.openRoot(ROOT_0_ID);
+        bots.directory.assertDocumentsAbsent("file1.png");
+    }
+
+    public void testKeyboard_CopyDocument() throws Exception {
+        bots.directory.clickDocument("file1.png");
+        device.waitForIdle();
+        bots.keyboard.pressKey(KeyEvent.KEYCODE_C, KeyEvent.META_CTRL_ON);
+
+        device.waitForIdle();
+
+        bots.roots.openRoot(ROOT_1_ID);
+        bots.keyboard.pressKey(KeyEvent.KEYCODE_V, KeyEvent.META_CTRL_ON);
+
+        bots.directory.waitForDocument("file1.png");
+
+        bots.roots.openRoot(ROOT_0_ID);
+        bots.directory.waitForDocument("file1.png");
+    }
+
+    public void testDeleteDocument_Cancel() throws Exception {
+        bots.directory.clickDocument("file1.png");
+        device.waitForIdle();
+        bots.main.clickToolbarItem(R.id.menu_delete);
+
+        bots.main.clickDialogCancelButton();
+
+        bots.directory.waitForDocument("file1.png");
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityDefaultsUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityDefaultsUiTest.java
new file mode 100644
index 0000000..d0ec9d7
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityDefaultsUiTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.StubProvider.ROOT_0_ID;
+import static com.android.documentsui.StubProvider.ROOT_1_ID;
+
+import android.content.Intent;
+import android.provider.DocumentsContract;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.documentsui.model.RootInfo;
+
+@LargeTest
+public class FilesActivityDefaultsUiTest extends ActivityTest<FilesActivity> {
+
+    public FilesActivityDefaultsUiTest() {
+        super(FilesActivity.class);
+    }
+
+    @Override
+    protected RootInfo getInitialRoot() {
+        return null;  // test the default, unaffected state of the app.
+    }
+
+    public void testDefaultDirectory() throws Exception {
+        device.waitForIdle();
+
+        // Separate logic for "Documents" root, which presence depends on the config setting
+        if (docsRootEnabled()) {
+            bots.main.assertWindowTitle("Documents");
+        } else {
+            bots.main.assertWindowTitle("Downloads");
+        }
+    }
+
+    public void testDefaultRoots() throws Exception {
+        device.waitForIdle();
+
+        // Should also have Drive, but that requires pre-configuration of devices
+        // We omit for now.
+        bots.roots.assertRootsPresent(
+                "Images",
+                "Videos",
+                "Audio",
+                "Downloads",
+                ROOT_0_ID,
+                ROOT_1_ID);
+
+        // Separate logic for "Documents" root, which presence depends on the config setting
+        if (docsRootEnabled()) {
+            bots.roots.assertRootsPresent("Documents");
+        } else {
+            bots.roots.assertRootsAbsent("Documents");
+        }
+    }
+
+    private boolean docsRootEnabled() {
+        return Shared.shouldShowDocumentsRoot(context, new Intent(DocumentsContract.ACTION_BROWSE));
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 75843b0..1b47705 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -16,24 +16,9 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.StubProvider.ROOT_0_ID;
-import static com.android.documentsui.StubProvider.ROOT_1_ID;
-
-import android.app.DownloadManager;
-import android.app.DownloadManager.Request;
-import android.content.Context;
-import android.content.Intent;
 import android.net.Uri;
 import android.os.RemoteException;
-import android.provider.DocumentsContract;
-import android.support.test.uiautomator.Configurator;
-import android.support.test.uiautomator.UiObject;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-
-import com.android.documentsui.model.RootInfo;
 
 @LargeTest
 public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
@@ -43,13 +28,15 @@
     }
 
     @Override
-    protected RootInfo getInitialRoot() {
-        return null;
+    public void setUp() throws Exception {
+        super.setUp();
+        initTestFiles();
     }
 
     @Override
     public void initTestFiles() throws RemoteException {
-        mDocsHelper.createFolder(rootDir0, dirName1);
+        Uri uri = mDocsHelper.createFolder(rootDir0, dirName1);
+        mDocsHelper.createFolder(uri, childDir1);
 
         mDocsHelper.createDocument(rootDir0, "text/plain", "file0.log");
         mDocsHelper.createDocument(rootDir0, "image/png", "file1.png");
@@ -59,58 +46,16 @@
         mDocsHelper.createDocument(rootDir1, "text/plain", "poodles.text");
     }
 
-    public void testRootsListed() throws Exception {
-        initTestFiles();
-
-        // Should also have Drive, but that requires pre-configuration of devices
-        // We omit for now.
-        bots.roots.assertRootsPresent(
-                "Images",
-                "Videos",
-                "Audio",
-                "Downloads",
-                ROOT_0_ID,
-                ROOT_1_ID);
-
-        // Separate logic for "Documents" root, which presence depends on the config setting
-        if (docsRootEnabled()) {
-            bots.roots.assertRootsPresent("Documents");
-        } else {
-            bots.roots.assertRootsAbsent("Documents");
-        }
-    }
-
     public void testFilesListed() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
         bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
     }
 
-    public void testLoadsDefaultDirectory() throws Exception {
-        initTestFiles();
-
-        device.waitForIdle();
-
-        // Separate logic for "Documents" root, which presence depends on the config setting
-        if (docsRootEnabled()) {
-            bots.main.assertWindowTitle("Documents");
-        } else {
-            bots.main.assertWindowTitle("Downloads");
-        }
-    }
-
-    public void testRootClickSetsWindowTitle() throws Exception {
-        initTestFiles();
-
+    public void testRootClick_SetsWindowTitle() throws Exception {
         bots.roots.openRoot("Images");
         bots.main.assertWindowTitle("Images");
     }
 
     public void testFilesList_LiveUpdate() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
         mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
 
         bots.directory.waitForDocument("Ham & Cheese.sandwich");
@@ -118,185 +63,16 @@
                 "file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
     }
 
-    public void testCreateDirectory() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
-
-        bots.main.openOverflowMenu();
-        bots.main.menuNewFolder().click();
-        bots.main.setDialogText("Kung Fu Panda");
-
-        bots.keyboard.pressEnter();
-
-        bots.directory.assertDocumentsPresent("Kung Fu Panda");
-    }
-
-    public void testOpenBreadcrumb() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
-
+    public void testNavigateByBreadcrumb() throws Exception {
         bots.directory.openDocument(dirName1);
-        if (bots.main.isTablet()) {
-            openBreadcrumbTabletHelper();
-        } else {
-            openBreadcrumbPhoneHelper();
-        }
-        bots.main.assertBreadcrumbItemsPresent(dirName1, "TEST_ROOT_0");
-        bots.main.clickBreadcrumbItem("TEST_ROOT_0");
+        bots.directory.waitForDocument(childDir1);  // wait for known content
+        bots.directory.assertDocumentsPresent(childDir1);
 
-        bots.directory.assertDocumentsPresent(dirName1);
-    }
-
-    private void openBreadcrumbTabletHelper() throws Exception {
-    }
-
-    private void openBreadcrumbPhoneHelper() throws Exception {
-        bots.main.clickDropdownBreadcrumb();
-    }
-
-    public void testDeleteDocument() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
-
-        bots.directory.clickDocument("file1.png");
+        bots.breadcrumb.revealAsNeeded();
         device.waitForIdle();
-        bots.main.menuDelete().click();
+        bots.breadcrumb.assertItemsPresent(dirName1, "TEST_ROOT_0");
 
-        bots.main.clickDialogOkButton();
-
-        bots.directory.assertDocumentsAbsent("file1.png");
-    }
-
-    public void testKeyboard_CutDocument() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
-
-        bots.directory.clickDocument("file1.png");
-        device.waitForIdle();
-        bots.main.pressKey(KeyEvent.KEYCODE_X, KeyEvent.META_CTRL_ON);
-
-        device.waitForIdle();
-
-        bots.roots.openRoot(ROOT_1_ID);
-        bots.main.pressKey(KeyEvent.KEYCODE_V, KeyEvent.META_CTRL_ON);
-
-        bots.directory.waitForDocument("file1.png");
-        bots.directory.assertDocumentsPresent("file1.png");
-
-        bots.roots.openRoot(ROOT_0_ID);
-        bots.directory.assertDocumentsAbsent("file1.png");
-    }
-
-    public void testKeyboard_CopyDocument() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
-
-        bots.directory.clickDocument("file1.png");
-        device.waitForIdle();
-        bots.main.pressKey(KeyEvent.KEYCODE_C, KeyEvent.META_CTRL_ON);
-
-        device.waitForIdle();
-
-        bots.roots.openRoot(ROOT_1_ID);
-        bots.main.pressKey(KeyEvent.KEYCODE_V, KeyEvent.META_CTRL_ON);
-
-        bots.directory.waitForDocument("file1.png");
-        bots.directory.assertDocumentsPresent("file1.png");
-
-        bots.roots.openRoot(ROOT_0_ID);
-        bots.directory.assertDocumentsPresent("file1.png");
-    }
-
-    public void testDeleteDocument_Cancel() throws Exception {
-        initTestFiles();
-
-        bots.roots.openRoot(ROOT_0_ID);
-
-        bots.directory.clickDocument("file1.png");
-        device.waitForIdle();
-        bots.main.menuDelete().click();
-
-        bots.main.clickDialogCancelButton();
-
-        bots.directory.assertDocumentsPresent("file1.png");
-    }
-
-    // Tests that pressing tab switches focus between the roots and directory listings.
-    @Suppress
-    public void testKeyboard_tab() throws Exception {
-        bots.main.pressKey(KeyEvent.KEYCODE_TAB);
-        bots.roots.assertHasFocus();
-        bots.main.pressKey(KeyEvent.KEYCODE_TAB);
-        bots.directory.assertHasFocus();
-    }
-
-    // Tests that arrow keys do not switch focus away from the dir list.
-    @Suppress
-    public void testKeyboard_arrowsDirList() throws Exception {
-        for (int i = 0; i < 10; i++) {
-            bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
-            bots.directory.assertHasFocus();
-        }
-        for (int i = 0; i < 10; i++) {
-            bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
-            bots.directory.assertHasFocus();
-        }
-    }
-
-    // Tests that arrow keys do not switch focus away from the roots list.
-    public void testKeyboard_arrowsRootsList() throws Exception {
-        bots.main.pressKey(KeyEvent.KEYCODE_TAB);
-        for (int i = 0; i < 10; i++) {
-            bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
-            bots.roots.assertHasFocus();
-        }
-        for (int i = 0; i < 10; i++) {
-            bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
-            bots.roots.assertHasFocus();
-        }
-    }
-
-    // We don't really need to test the entirety of download support
-    // since downloads is (almost) just another provider.
-    @Suppress
-    public void testDownload_Queued() throws Exception {
-        DownloadManager dm = (DownloadManager) context.getSystemService(
-                Context.DOWNLOAD_SERVICE);
-        // This downloads ends up being queued (because DNS can't be resolved).
-        // We'll still see an entry in the downloads UI with a "Queued" label.
-        dm.enqueue(new Request(Uri.parse("http://hammychamp.toodles")));
-
-        bots.roots.openRoot("Downloads");
-        bots.directory.assertDocumentsPresent("Queued");
-    }
-
-    @Suppress
-    public void testDownload_RetryUnsuccessful() throws Exception {
-        DownloadManager dm = (DownloadManager) context.getSystemService(
-                Context.DOWNLOAD_SERVICE);
-        // This downloads fails! But it'll still show up.
-        dm.enqueue(new Request(Uri.parse("http://www.google.com/hamfancy")));
-
-        bots.roots.openRoot("Downloads");
-        UiObject doc = bots.directory.findDocument("Unsuccessful");
-        doc.waitForExists(TIMEOUT);
-
-        int toolType = Configurator.getInstance().getToolType();
-        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
-        doc.click();
-        Configurator.getInstance().setToolType(toolType);
-
-        assertTrue(bots.main.findDownloadRetryDialog().exists());
-
-        device.pressBack(); // to clear the dialog.
-    }
-
-    private boolean docsRootEnabled() {
-        return Shared.shouldShowDocumentsRoot(context, new Intent(DocumentsContract.ACTION_BROWSE));
+        bots.breadcrumb.clickItem("TEST_ROOT_0");
+        bots.directory.waitForDocument(dirName1);
     }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/IntegratedDownloadsUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/IntegratedDownloadsUiTest.java
new file mode 100644
index 0000000..ef4a68d
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/IntegratedDownloadsUiTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package com.android.documentsui;
+
+import android.app.DownloadManager;
+import android.app.DownloadManager.Request;
+import android.content.Context;
+import android.net.Uri;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiObject;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.view.MotionEvent;
+
+// TODO: As of this writing all tests in this class are disabled. Please fix.
+@LargeTest
+public class IntegratedDownloadsUiTest extends ActivityTest<FilesActivity> {
+
+    public IntegratedDownloadsUiTest() {
+        super(FilesActivity.class);
+    }
+
+    // We don't really need to test the entirety of download support
+    // since downloads is (almost) just another provider.
+    @Suppress
+    public void testDownload_Queued() throws Exception {
+        DownloadManager dm = (DownloadManager) context.getSystemService(
+                Context.DOWNLOAD_SERVICE);
+        // This downloads ends up being queued (because DNS can't be resolved).
+        // We'll still see an entry in the downloads UI with a "Queued" label.
+        dm.enqueue(new Request(Uri.parse("http://hammychamp.toodles")));
+
+        bots.roots.openRoot("Downloads");
+        bots.directory.assertDocumentsPresent("Queued");
+    }
+
+    @Suppress
+    public void testDownload_RetryUnsuccessful() throws Exception {
+        DownloadManager dm = (DownloadManager) context.getSystemService(
+                Context.DOWNLOAD_SERVICE);
+        // This downloads fails! But it'll still show up.
+        dm.enqueue(new Request(Uri.parse("http://www.google.com/hamfancy")));
+
+        bots.roots.openRoot("Downloads");
+        UiObject doc = bots.directory.findDocument("Unsuccessful");
+        doc.waitForExists(TIMEOUT);
+
+        int toolType = Configurator.getInstance().getToolType();
+        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
+        doc.click();
+        Configurator.getInstance().setToolType(toolType);
+
+        assertTrue(bots.main.findDownloadRetryDialog().exists());
+
+        device.pressBack(); // to clear the dialog.
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/KeyboardNavigationUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/KeyboardNavigationUiTest.java
new file mode 100644
index 0000000..1657a87
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/KeyboardNavigationUiTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+package com.android.documentsui;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.view.KeyEvent;
+
+@LargeTest
+public class KeyboardNavigationUiTest extends ActivityTest<FilesActivity> {
+
+    public KeyboardNavigationUiTest() {
+        super(FilesActivity.class);
+    }
+
+    // Tests that pressing tab switches focus between the roots and directory listings.
+    @Suppress
+    public void testKeyboard_tab() throws Exception {
+        bots.keyboard.pressKey(KeyEvent.KEYCODE_TAB);
+        bots.roots.assertHasFocus();
+        bots.keyboard.pressKey(KeyEvent.KEYCODE_TAB);
+        bots.directory.assertHasFocus();
+    }
+
+    // Tests that arrow keys do not switch focus away from the dir list.
+    @Suppress
+    public void testKeyboard_arrowsDirList() throws Exception {
+        for (int i = 0; i < 10; i++) {
+            bots.keyboard.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
+            bots.directory.assertHasFocus();
+        }
+        for (int i = 0; i < 10; i++) {
+            bots.keyboard.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
+            bots.directory.assertHasFocus();
+        }
+    }
+
+    // Tests that arrow keys do not switch focus away from the roots list.
+    public void testKeyboard_arrowsRootsList() throws Exception {
+        bots.keyboard.pressKey(KeyEvent.KEYCODE_TAB);
+        for (int i = 0; i < 10; i++) {
+            bots.keyboard.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
+            bots.roots.assertHasFocus();
+        }
+        for (int i = 0; i < 10; i++) {
+            bots.keyboard.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
+            bots.roots.assertHasFocus();
+        }
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
index 1f831ee..e7ac293 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java
@@ -16,15 +16,8 @@
 
 package com.android.documentsui;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
-import static android.support.test.espresso.action.ViewActions.swipeLeft;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static com.android.documentsui.StubProvider.ROOT_0_ID;
-import static com.android.documentsui.StubProvider.ROOT_1_ID;
-
+import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
 
 @LargeTest
 public class RenameDocumentUiTest extends ActivityTest<FilesActivity> {
@@ -42,6 +35,7 @@
         bots.roots.closeDrawer();
     }
 
+    // TODO: Move this over to the FilesMenuManagerTest.
     public void testRenameEnabled_SingleSelection() throws Exception {
         bots.directory.selectDocument(fileName1);
         bots.main.openOverflowMenu();
@@ -51,6 +45,7 @@
         device.pressBack();
     }
 
+    // TODO: Move this over to the FilesMenuManagerTest.
     public void testNoRenameSupport_SingleSelection() throws Exception {
         bots.directory.selectDocument(fileNameNoRename);
         bots.main.openOverflowMenu();
@@ -60,6 +55,7 @@
         device.pressBack();
     }
 
+    // TODO: Move this over to the FilesMenuManagerTest.
     public void testOneHasRenameSupport_MultipleSelection() throws Exception {
         bots.directory.selectDocument(fileName1);
         bots.directory.selectDocument(fileNameNoRename);
@@ -70,6 +66,7 @@
         device.pressBack();
     }
 
+    // TODO: Move this over to the FilesMenuManagerTest.
     public void testRenameDisabled_MultipleSelection() throws Exception {
         bots.directory.selectDocument(fileName1);
         bots.directory.selectDocument(fileName2);
@@ -82,34 +79,41 @@
 
     public void testRenameFile_OkButton() throws Exception {
         bots.directory.selectDocument(fileName1);
-        bots.main.openOverflowMenu();
-        bots.main.menuRename().click();
+
+        clickRename();
+
+        device.waitForIdle();
         bots.main.setDialogText(newName);
 
+        device.waitForIdle();
         bots.main.clickDialogOkButton();
 
+        bots.directory.waitForDocument(newName);
         bots.directory.assertDocumentsAbsent(fileName1);
-        bots.directory.assertDocumentsPresent(newName);
         bots.directory.assertDocumentsCount(4);
     }
 
     public void testRenameFile_Enter() throws Exception {
         bots.directory.selectDocument(fileName1);
-        bots.main.openOverflowMenu();
-        bots.main.menuRename().click();
+
+        clickRename();
+
+        device.waitForIdle();
         bots.main.setDialogText(newName);
 
+        device.waitForIdle();
         bots.keyboard.pressEnter();
 
+        bots.directory.waitForDocument(newName);
         bots.directory.assertDocumentsAbsent(fileName1);
-        bots.directory.assertDocumentsPresent(newName);
         bots.directory.assertDocumentsCount(4);
     }
 
     public void testRenameFile_Cancel() throws Exception {
         bots.directory.selectDocument(fileName1);
-        bots.main.openOverflowMenu();
-        bots.main.menuRename().click();
+
+        clickRename();
+
         bots.main.setDialogText(newName);
 
         bots.main.clickDialogCancelButton();
@@ -122,10 +126,10 @@
     public void testRenameDir() throws Exception {
         String oldName = "Dir1";
         String newName = "Dir123";
-
         bots.directory.selectDocument(oldName);
-        bots.main.openOverflowMenu();
-        bots.main.menuRename().click();
+
+        clickRename();
+
         bots.main.setDialogText(newName);
 
         bots.keyboard.pressEnter();
@@ -139,8 +143,9 @@
         // Check that document with the new name exists
         bots.directory.assertDocumentsPresent(fileName2);
         bots.directory.selectDocument(fileName1);
-        bots.main.openOverflowMenu();
-        bots.main.menuRename().click();
+
+        clickRename();
+
         bots.main.setDialogText(fileName2);
 
         bots.keyboard.pressEnter();
@@ -150,4 +155,9 @@
         bots.directory.assertDocumentsPresent(fileName2);
         bots.directory.assertDocumentsCount(4);
     }
+
+    private void clickRename() throws UiObjectNotFoundException {
+        bots.main.clickActionbarOverflowItem("Rename");
+        device.waitForIdle();
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
index 038a208..4edfd8a 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java
@@ -39,7 +39,7 @@
 
     public void testRootTapped_GoToRootFromChildDir() throws Exception {
         bots.directory.openDocument(dirName1);
-        bots.main.assertBreadcrumbTitle(dirName1);
+        bots.breadcrumb.assertTitle(dirName1);
         bots.roots.openRoot(ROOT_0_ID);
         bots.main.assertWindowTitle(ROOT_0_ID);
         assertDefaultContentOfTestDir0();
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
index 1c99db1..cba51a7 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java
@@ -16,16 +16,13 @@
 
 package com.android.documentsui;
 
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.swipeLeft;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
 import static com.android.documentsui.StubProvider.ROOT_0_ID;
 import static com.android.documentsui.StubProvider.ROOT_1_ID;
 
-import android.content.res.Configuration;
+import android.support.test.filters.Suppress;
+import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.v7.recyclerview.R;
 import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
 
 @LargeTest
 public class SearchViewUiTest extends ActivityTest<FilesActivity> {
@@ -37,168 +34,150 @@
     @Override
     public void setUp() throws Exception {
       super.setUp();
+      initTestFiles();
       // Drawer interferes with a lot of search action; going to try to close any opened ones
       bots.roots.closeDrawer();
+
+      openRoot(ROOT_0_ID);  // Even if this is the default root...it `wait`s for more better tests
+    }
+
+    public void testSearchIconVisible_RootWithSearchSupport() throws Exception {
+        bots.search.assertInputExists(false);
+        bots.search.assertIconVisible(true);
+    }
+
+    public void testSearchIconHidden_RootNoSearchSupport() throws Exception {
+        openRoot(ROOT_1_ID);
+
+        bots.search.assertIconVisible(false);
+        bots.search.assertInputExists(false);
     }
 
     public void testSearchView_ExpandsOnClick() throws Exception {
-        bots.main.openSearchView();
-        bots.main.assertSearchTextFiledAndIcon(true, false);
+        bots.search.clickIcon();
+        device.waitForIdle();
+
+        bots.search.assertInputExists(true);
+        bots.search.assertInputFocused(true);
+
+        // FIXME: Matchers fail the not-present check if we've ever clicked this.
+        // bots.search.assertIconVisible(false);
     }
 
     public void testSearchView_CollapsesOnBack() throws Exception {
-        bots.main.openSearchView();
-
+        bots.search.clickIcon();
         device.pressBack();
 
-        bots.main.assertSearchTextFiledAndIcon(false, true);
+        bots.search.assertIconVisible(true);
+        bots.search.assertInputExists(false);
     }
 
     public void testSearchView_ClearsTextOnBack() throws Exception {
-        String query = "file2";
-        bots.main.openSearchView();
-        bots.main.setSearchQuery(query);
+        bots.search.clickIcon();
+        bots.search.setInputText("file2");
 
         device.pressBack();
 
-        bots.main.assertSearchTextFiledAndIcon(false, true);
+        // Wait for a file in the default directory to be listed.
+        bots.directory.waitForDocument(dirName1);
+
+        bots.search.assertIconVisible(true);
+        bots.search.assertInputExists(false);
+    }
+
+    public void testSearchView_StateAfterSearch() throws Exception {
+        bots.search.clickIcon();
+        bots.search.setInputText("file1");
+        bots.keyboard.pressEnter();
+        device.waitForIdle();
+
+        bots.search.assertInputEquals("file1");
+        bots.search.assertInputFocused(false);
     }
 
     public void testSearch_ResultsFound() throws Exception {
-        initTestFiles();
-        assertDefaultContentOfTestDir0();
-
-        String query = "file1";
-        bots.main.openSearchView();
-        bots.main.setSearchQuery(query);
-        bots.main.assertSearchTextField(true, query);
-
+        bots.search.clickIcon();
+        bots.search.setInputText("file1");
         bots.keyboard.pressEnter();
 
         bots.directory.assertDocumentsCountOnList(true, 2);
         bots.directory.assertDocumentsPresent(fileName1, fileName2);
-
-        bots.main.assertSearchTextField(false, query);
-    }
-
-    public void testSearchDownloads() throws Exception {
-        initTestFiles();
-        bots.roots.openRoot(ROOT_0_ID);
-
-        bots.directory.copyFilesToClipboard(fileName1, fileName2);
-        device.waitForIdle();
-
-        bots.roots.openRoot("Downloads");
-        bots.directory.pasteFilesFromClipboard();
-
-        //TODO: Why do we need to click on Downloads again so this will work?
-        bots.roots.openRoot(ROOT_0_ID);
-        bots.roots.openRoot("Downloads");
-        device.waitForIdle();
-
-        String query = "file12";
-        bots.main.openSearchView();
-        bots.main.setSearchQuery(query);
-
-        bots.keyboard.pressEnter();
-
-        bots.directory.assertDocumentsCountOnList(true, 1);
-        bots.directory.assertDocumentsPresent(fileName2);
-
-        device.pressBack();
-    }
-
-    public void testSearchResultsFound_ClearsOnBack() throws Exception {
-        initTestFiles();
-        assertDefaultContentOfTestDir0();
-
-        String query = fileName1;
-        bots.main.openSearchView();
-        bots.main.setSearchQuery(query);
-
-        bots.keyboard.pressEnter();
-        device.pressBack();
-
-        assertDefaultContentOfTestDir0();
     }
 
     public void testSearch_NoResults() throws Exception {
-        initTestFiles();
-        assertDefaultContentOfTestDir0();
-
-        String query = "chocolate";
-        bots.main.openSearchView();
-        bots.main.setSearchQuery(query);
+        bots.search.clickIcon();
+        bots.search.setInputText("chocolate");
 
         bots.keyboard.pressEnter();
 
         String msg = String.valueOf(context.getString(R.string.no_results));
         bots.directory.assertMessageTextView(String.format(msg, "TEST_ROOT_0"));
-
-        bots.main.assertSearchTextField(false, query);
     }
 
-    public void testSearchNoResults_ClearsOnBack() throws Exception {
-        initTestFiles();
-        assertDefaultContentOfTestDir0();
-
-        String query = "chocolate";
-        bots.main.openSearchView();
-        bots.main.setSearchQuery(query);
+    @Suppress
+    public void testSearchResultsFound_ClearsOnBack() throws Exception {
+        bots.search.clickIcon();
+        bots.search.setInputText(fileName1);
 
         bots.keyboard.pressEnter();
         device.pressBack();
-
         device.waitForIdle();
+
         assertDefaultContentOfTestDir0();
     }
 
+    @Suppress
+    public void testSearchNoResults_ClearsOnBack() throws Exception {
+        bots.search.clickIcon();
+        bots.search.setInputText("chocolate bunny");
 
-    public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception {
-         // Skipping this test for phones since currently there's no way to open the drawer on
-         // phones after doing a search (it's a back button instead of a hamburger button)
-         if (!bots.main.isTablet()) {
-           return;
-         }
+        bots.keyboard.pressEnter();
+        device.pressBack();
+        device.waitForIdle();
 
-        initTestFiles();
         assertDefaultContentOfTestDir0();
+    }
 
-        String query = fileName1;
-        bots.main.openSearchView();
-        bots.main.setSearchQuery(query);
+    @Suppress
+    public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception {
+        // Skipping this test for phones since currently there's no way to open the drawer on
+        // phones after doing a search (it's a back button instead of a hamburger button)
+        if (!bots.main.inFixedLayout()) {
+            return;
+        }
+
+        bots.search.clickIcon();
+
+        bots.search.setInputText(fileName1);
 
         bots.keyboard.pressEnter();
 
-        bots.roots.openRoot(ROOT_1_ID);
+        openRoot(ROOT_1_ID);
+        device.waitForIdle();
         assertDefaultContentOfTestDir1();
 
-        bots.roots.openRoot(ROOT_0_ID);
+        openRoot(ROOT_0_ID);
+        device.waitForIdle();
+
         assertDefaultContentOfTestDir0();
     }
 
-    public void testSearchIconVisible_RootWithSearchSupport() throws Exception {
-        bots.roots.openRoot(ROOT_0_ID);
-        bots.main.assertSearchTextFiledAndIcon(false, true);
-    }
-
-    public void testSearchIconHidden_RootNoSearchSupport() throws Exception {
-        bots.roots.openRoot(ROOT_1_ID);
-        bots.main.assertSearchTextFiledAndIcon(false, false);
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        try {
-            // Proper clean up of #testSearchDownloads
-            bots.directory.clickDocument(fileName1 + ".txt");
-            bots.directory.clickDocument(fileName2);
-            device.waitForIdle();
-            bots.main.menuDelete().click();
-            bots.main.clickDialogOkButton();
-        } catch (Exception e) {
-        } finally {
-            super.tearDown();
+    void openRoot(String rootId) throws UiObjectNotFoundException {
+        bots.roots.openRoot(rootId);
+        // Open the named root and wait for a known file in it.
+        // You can find known files by looking in super.initTestFiles();
+        switch(rootId) {
+            case ROOT_0_ID:
+                bots.directory.waitForDocument(fileName1);
+                break;
+            case ROOT_1_ID:
+                bots.directory.waitForDocument(fileName3);
+                break;
+            case "Downloads":
+                device.waitForIdle();
+                break;
+            default:
+                throw new IllegalArgumentException("Unsupported root: " + rootId);
         }
     }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java
deleted file mode 100644
index 1d2b47f..0000000
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-package com.android.documentsui.bots;
-
-import static junit.framework.Assert.assertNotNull;
-
-import android.content.Context;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
-
-/**
- * A test helper class that provides support for controlling directory list
- * and making assertions against the state of it.
- */
-abstract class BaseBot {
-    final UiDevice mDevice;
-    final Context mContext;
-    final int mTimeout;
-
-    BaseBot(UiDevice device, Context context, int timeout) {
-        mDevice = device;
-        mContext = context;
-        mTimeout = timeout;
-    }
-
-    /**
-     * Asserts that the specified view or one of its descendents has focus.
-     */
-    protected void assertHasFocus(String resourceName) {
-        UiObject2 candidate = mDevice.findObject(By.res(resourceName));
-        assertNotNull("Expected " + resourceName + " to have focus, but it didn't.",
-            candidate.findObject(By.focused(true)));
-    }
-
-    protected UiObject2 find(BySelector selector) {
-        mDevice.wait(Until.findObject(selector), mTimeout);
-        return mDevice.findObject(selector);
-    }
-
-    protected UiObject findObject(String resourceId) {
-        final UiSelector object = new UiSelector().resourceId(resourceId);
-        return mDevice.findObject(object);
-    }
-
-    protected UiObject findObject(String parentResourceId, String childResourceId) {
-        final UiSelector selector = new UiSelector()
-                .resourceId(parentResourceId)
-                .childSelector(new UiSelector().resourceId(childResourceId));
-        return mDevice.findObject(selector);
-    }
-
-    protected void waitForIdle() {
-        mDevice.waitForIdle(mTimeout);
-    }
-}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/Bots.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/Bots.java
new file mode 100644
index 0000000..4bda531
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/Bots.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package com.android.documentsui.bots;
+
+import static junit.framework.Assert.assertNotNull;
+
+import android.content.Context;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+
+/**
+ * Handy collection of bots for working with Files app.
+ */
+public final class Bots {
+
+    private static final int TIMEOUT = 5000;
+
+    public final BreadBot breadcrumb;
+    public final DirectoryListBot directory;
+    public final KeyboardBot keyboard;
+    public final RootsListBot roots;
+    public final SearchBot search;
+    public final UiBot main;
+
+    public Bots(UiDevice device, Context context, int timeout) {
+        main = new UiBot(device, context, TIMEOUT);
+        breadcrumb = new BreadBot(device, context, TIMEOUT, main);
+        roots = new RootsListBot(device, context, TIMEOUT);
+        directory = new DirectoryListBot(device, context, TIMEOUT);
+        keyboard = new KeyboardBot(device, context, TIMEOUT);
+        search = new SearchBot(device, context, TIMEOUT);
+    }
+
+    /**
+     * A test helper class that provides support for controlling directory list
+     * and making assertions against the state of it.
+     */
+    static abstract class BaseBot {
+        final UiDevice mDevice;
+        final Context mContext;
+        final int mTimeout;
+
+        BaseBot(UiDevice device, Context context, int timeout) {
+            mDevice = device;
+            mContext = context;
+            mTimeout = timeout;
+        }
+
+        /**
+         * Asserts that the specified view or one of its descendents has focus.
+         */
+        protected void assertHasFocus(String resourceName) {
+            UiObject2 candidate = mDevice.findObject(By.res(resourceName));
+            assertNotNull("Expected " + resourceName + " to have focus, but it didn't.",
+                candidate.findObject(By.focused(true)));
+        }
+
+        protected UiObject2 find(BySelector selector) {
+            mDevice.wait(Until.findObject(selector), mTimeout);
+            return mDevice.findObject(selector);
+        }
+
+        protected UiObject findObject(String resourceId) {
+            final UiSelector object = new UiSelector().resourceId(resourceId);
+            return mDevice.findObject(object);
+        }
+
+        protected UiObject findObject(String parentResourceId, String childResourceId) {
+            final UiSelector selector = new UiSelector()
+                    .resourceId(parentResourceId)
+                    .childSelector(new UiSelector().resourceId(childResourceId));
+            return mDevice.findObject(selector);
+        }
+
+        protected void waitForIdle() {
+            mDevice.waitForIdle(mTimeout);
+        }
+    }
+
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BreadBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BreadBot.java
new file mode 100644
index 0000000..8024ff4
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BreadBot.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package com.android.documentsui.bots;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.is;
+
+import android.content.Context;
+import android.support.test.espresso.ViewInteraction;
+import android.support.test.espresso.matcher.BoundedMatcher;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+
+import com.android.documentsui.DragOverTextView;
+import com.android.documentsui.DropdownBreadcrumb;
+import com.android.documentsui.model.DocumentInfo;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Predicate;
+
+import junit.framework.Assert;
+
+/**
+ * A test helper class that provides support for controlling the UI Breadcrumb
+ * programmatically, and making assertions against the state of the UI.
+ * <p>
+ * Support for working directly with Roots and Directory view can be found in the respective bots.
+ */
+public class BreadBot extends Bots.BaseBot {
+
+    public static final String TARGET_PKG = "com.android.documentsui";
+    private UiBot mMain;
+
+    public BreadBot(UiDevice device, Context context, int timeout, UiBot main) {
+        super(device, context, timeout);
+        mMain = main;
+    }
+
+    public void assertTitle(String expected) {
+        // There is no discrete title part on the horizontal breadcrumb...
+        // so we only test on dropdown.
+        if (mMain.inDrawerLayout()) {
+            Matcher<Object> titleMatcher = dropdownTitleMatcher(expected);
+            onView(Matchers.BREADCRUMB)
+                    .check(matches(titleMatcher));
+        }
+    }
+
+    /**
+     * Reveals the bread crumb if it was hidden. This will likely be the case
+     * when the app is in drawer mode.
+     */
+    public void revealAsNeeded() throws Exception {
+        if (mMain.inDrawerLayout()) {
+            onView(Matchers.DROPDOWN_BREADCRUMB).perform(click());
+        }
+    }
+
+    public void clickItem(String label) throws UiObjectNotFoundException {
+        if (mMain.inFixedLayout()) {
+            findHorizontalEntry(label).perform(click());
+        } else {
+            mMain.findMenuWithName(label).click();
+        }
+    }
+
+    public void assertItemsPresent(String... items) {
+        Predicate<String> checker = mMain.inFixedLayout()
+                    ? this::hasHorizontalEntry
+                    : mMain::hasMenuWithName;
+
+        assertItemsPresent(items, checker);
+    }
+
+    public void assertItemsPresent(String[] items, Predicate<String> predicate) {
+        List<String> absent = new ArrayList<>();
+        for (String item : items) {
+            if (!predicate.test(item)) {
+                absent.add(item);
+            }
+        }
+        if (!absent.isEmpty()) {
+            Assert.fail("Expected iteams " + Arrays.asList(items)
+                    + ", but missing " + absent);
+        }
+    }
+
+    public boolean hasHorizontalEntry(String label) {
+        return Matchers.present(findHorizontalEntry(label), withText(label));
+    }
+
+    @SuppressWarnings("unchecked")
+    public ViewInteraction findHorizontalEntry(String label) {
+        // Matchers.HORIZONTAL_BREADCRUMB
+        return onView(allOf(isAssignableFrom(DragOverTextView.class), withText(label)));
+    }
+
+    private static Matcher<Object> dropdownTitleMatcher(String expected) {
+        final Matcher<String> textMatcher = is(expected);
+        return new BoundedMatcher<Object, DropdownBreadcrumb>(DropdownBreadcrumb.class) {
+            @Override
+            public boolean matchesSafely(DropdownBreadcrumb breadcrumb) {
+                DocumentInfo selectedDoc = (DocumentInfo) breadcrumb.getSelectedItem();
+                return textMatcher.matches(selectedDoc.displayName);
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("with breadcrumb title: ");
+                textMatcher.describeTo(description);
+            }
+        };
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java
index e2aabc7..fa1e09c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java
@@ -21,6 +21,8 @@
 import static junit.framework.Assert.assertTrue;
 
 import android.content.Context;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.matcher.ViewMatchers;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.Configurator;
@@ -30,9 +32,12 @@
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiSelector;
 import android.support.test.uiautomator.Until;
+import android.support.v7.widget.RecyclerView;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 
+import com.android.documentsui.R;
+
 import junit.framework.Assert;
 
 import java.util.ArrayList;
@@ -44,7 +49,7 @@
  * A test helper class that provides support for controlling directory list
  * and making assertions against the state of it.
  */
-public class DirectoryListBot extends BaseBot {
+public class DirectoryListBot extends Bots.BaseBot {
     private static final String DIR_LIST_ID = "com.android.documentsui:id/dir_list";
 
     private static final BySelector SNACK_DELETE =
@@ -125,6 +130,7 @@
     }
 
     public UiObject selectDocument(String label) throws UiObjectNotFoundException {
+        waitForDocument(label);
         UiObject doc = findDocument(label);
         doc.longClick();
         return doc;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java
index b0a4d76..2e71577 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java
@@ -28,7 +28,7 @@
 /**
  * A test helper class that provides support for keyboard manipulation.
  */
-public class KeyboardBot extends BaseBot {
+public class KeyboardBot extends Bots.BaseBot {
 
     public KeyboardBot(UiDevice device, Context context, int timeout) {
         super(device, context, timeout);
@@ -53,4 +53,12 @@
       // See b/28399576
         onView(isAssignableFrom(EditText.class)).perform(pressImeActionButton());
     }
+
+    public void pressKey(int keyCode) {
+        mDevice.pressKeyCode(keyCode);
+    }
+
+    public void pressKey(int keyCode, int metaState) {
+        mDevice.pressKeyCode(keyCode, metaState);
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/Matchers.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/Matchers.java
index 2343a49..8962ccb 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/Matchers.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/Matchers.java
@@ -16,15 +16,22 @@
 
 package com.android.documentsui.bots;
 
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
 import static android.support.test.espresso.matcher.ViewMatchers.withResourceName;
 import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.Matchers.endsWith;
 
+import android.support.test.espresso.ViewInteraction;
+import android.support.test.espresso.matcher.ViewMatchers;
+import android.support.v7.widget.RecyclerView;
 import android.view.View;
 import android.widget.ImageView;
-import android.widget.Spinner;
 import android.widget.Toolbar;
 
 import com.android.documentsui.R;
@@ -35,14 +42,66 @@
 /**
  * Handy matchers useful for finding stuff in the UI. Use with Espresso testing.
  */
-final class Matchers {
-    static final Matcher<View> TOOLBAR = allOf(isAssignableFrom(Toolbar.class),
+@SuppressWarnings("unchecked")
+public final class Matchers {
+
+    private Matchers() {}
+
+    public static final Matcher<View> TOOLBAR = allOf(
+            isAssignableFrom(Toolbar.class),
             withId(R.id.toolbar));
-    static final Matcher<View> SEARCH_MENU = allOf(withId(R.id.menu_search), isDisplayed());
-    static final Matcher<View> SEARCH_BUTTON = allOf(isAssignableFrom(ImageView.class),
+
+    public static final Matcher<View> ACTIONBAR = allOf(
+            withClassName(endsWith("ActionBarContextView")));
+
+    public static final Matcher<View> SEARCH_MENU = allOf(
+            withId(R.id.menu_search),
+            isDisplayed());
+
+    public static final Matcher<View> SEARCH_BUTTON = allOf(
+            isAssignableFrom(ImageView.class),
             withResourceName("search_button"));
-    static final Matcher<View> BREADCRUMB = allOf(isAssignableFrom(Spinner.class),
-            withId(R.id.breadcrumb));
-    static final Matcher<View> MENU_SEARCH = allOf(isAssignableFrom(ActionMenuItemView.class),
+
+    public static final Matcher<View> MENU_SEARCH = allOf(
+            isAssignableFrom(ActionMenuItemView.class),
             withResourceName("menu_search"));
+
+    public static final Matcher<View> DROPDOWN_BREADCRUMB = withId(
+            R.id.dropdown_breadcrumb);
+
+    public static final Matcher<View> HORIZONTAL_BREADCRUMB = withId(
+            R.id.horizontal_breadcrumb);
+
+    // When any 'ol breadcrumb will do. Could be dropdown or horizontal.
+    public static final Matcher<View> BREADCRUMB = anyOf(
+            DROPDOWN_BREADCRUMB, HORIZONTAL_BREADCRUMB);
+
+    public static final Matcher<View> TEXT_ENTRY = allOf(
+            withClassName(endsWith("EditText")));
+
+    public static final Matcher<View> TOOLBAR_OVERFLOW = allOf(
+            withClassName(endsWith("OverflowMenuButton")),
+            ViewMatchers.isDescendantOfA(TOOLBAR));
+
+    public static final Matcher<View> ACTIONBAR_OVERFLOW = allOf(
+            withClassName(endsWith("OverflowMenuButton")),
+            ViewMatchers.isDescendantOfA(ACTIONBAR));
+
+    public static final Matcher<View> DIRECTORY_LIST = allOf(
+            isAssignableFrom(RecyclerView.class),
+            withId(R.id.dir_list));
+
+    public static boolean present(Matcher<View> matcher) {
+        return present(onView(matcher), isDisplayed());
+    }
+
+    public static boolean present(ViewInteraction vi, Matcher<View> matcher) {
+        try {
+            vi.check(matches(matcher));
+            vi.check(matches(isDisplayed()));
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
index ef22bb5..c73cec2 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java
@@ -17,38 +17,32 @@
 package com.android.documentsui.bots;
 
 import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
 import static android.support.test.espresso.action.ViewActions.swipeLeft;
 import static android.support.test.espresso.action.ViewActions.swipeRight;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
 
 import android.content.Context;
-import android.support.test.espresso.UiController;
-import android.support.test.espresso.ViewAction;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiScrollable;
 import android.support.test.uiautomator.UiSelector;
-import android.support.v4.view.GravityCompat;
 import android.util.Log;
-
 import android.view.View;
-import junit.framework.Assert;
+
+import com.android.documentsui.R;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import org.hamcrest.Matcher;
-
-import com.android.documentsui.R;
+import junit.framework.Assert;
 
 /**
  * A test helper class that provides support for controlling and asserting against
  * the roots list drawer.
  */
-public class RootsListBot extends BaseBot {
+public class RootsListBot extends Bots.BaseBot {
     private static final String ROOTS_LIST_ID = "com.android.documentsui:id/roots_list";
     private static final String TAG = "RootsListBot";
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/SearchBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/SearchBot.java
new file mode 100644
index 0000000..1c70732
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/SearchBot.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+package com.android.documentsui.bots;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.typeText;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.v7.recyclerview.R;
+
+/**
+ * A test helper class that provides support for controlling the search UI
+ * programmatically, and making assertions against the state of the UI.
+ * <p>
+ * Support for working directly with Roots and Directory view can be found in the respective bots.
+ */
+public class SearchBot extends Bots.BaseBot {
+
+    public static final String TARGET_PKG = "com.android.documentsui";
+
+    public SearchBot(UiDevice device, Context context, int timeout) {
+        super(device, context, timeout);
+    }
+
+    public void clickIcon() throws UiObjectNotFoundException {
+        UiObject searchView = findSearchView();
+        searchView.click();
+        assertTrue(searchView.exists());
+    }
+
+    public void setInputText(String query) throws UiObjectNotFoundException {
+        onView(Matchers.SEARCH_MENU).perform(typeText(query));
+    }
+
+    public void assertIconVisible(boolean visible) {
+        if (visible) {
+            assertTrue(
+                    "Search icon should be visible.",
+                    Matchers.present(Matchers.SEARCH_BUTTON));
+        } else {
+            assertFalse(
+                    "Search icon should not be visible.",
+                    Matchers.present(Matchers.SEARCH_BUTTON));
+        }
+    }
+
+    public void assertInputEquals(String query)
+            throws UiObjectNotFoundException {
+        UiObject textField = findSearchViewTextField();
+
+        assertTrue(textField.exists());
+        assertEquals(query, textField.getText());
+    }
+
+    public void assertInputFocused(boolean focused)
+            throws UiObjectNotFoundException {
+        UiObject textField = findSearchViewTextField();
+
+        assertTrue(textField.exists());
+        assertEquals(focused, textField.isFocused());
+    }
+
+    public void assertInputExists(boolean exists)
+            throws UiObjectNotFoundException {
+        assertEquals(exists, findSearchViewTextField().exists());
+    }
+
+    private UiObject findSearchView() {
+        return findObject("com.android.documentsui:id/menu_search");
+    }
+
+    private UiObject findSearchViewTextField() {
+        return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
+    }
+
+    private UiObject findSearchViewIcon() {
+        return mContext.getResources().getBoolean(R.bool.full_bar_search_view)
+                ? findObject("com.android.documentsui:id/menu_search")
+                : findObject("com.android.documentsui:id/menu_search", "android:id/search_button");
+    }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
index f33d90b..fa818a0 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
@@ -18,20 +18,16 @@
 
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
-import static android.support.test.espresso.action.ViewActions.typeText;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
 import static org.hamcrest.CoreMatchers.is;
 
 import android.content.Context;
-import android.content.res.Configuration;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.action.ViewActions;
 import android.support.test.espresso.matcher.BoundedMatcher;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
@@ -39,30 +35,24 @@
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiSelector;
-import android.widget.Spinner;
+import android.util.TypedValue;
 import android.widget.Toolbar;
 
 import com.android.documentsui.R;
-import com.android.documentsui.model.DocumentInfo;
 
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
-import junit.framework.Assert;
-import junit.framework.AssertionFailedError;
-
 /**
  * A test helper class that provides support for controlling DocumentsUI activities
  * programmatically, and making assertions against the state of the UI.
  * <p>
  * Support for working directly with Roots and Directory view can be found in the respective bots.
  */
-public class UiBot extends BaseBot {
+public class UiBot extends Bots.BaseBot {
 
     public static final String TARGET_PKG = "com.android.documentsui";
 
@@ -75,54 +65,17 @@
                 .check(matches(withToolbarTitle(is(expected))));
     }
 
-    public void assertBreadcrumbTitle(String expected) {
-        if (!isTablet()) {
-            onView(Matchers.BREADCRUMB)
-                    .check(matches(withBreadcrumbTitle(is(expected))));
-        }
-    }
-
     public void assertMenuEnabled(int id, boolean enabled) {
         UiObject2 menu = findMenuWithName(mContext.getString(id));
         assertNotNull(menu);
         assertEquals(enabled, menu.isEnabled());
     }
 
-    public void assertSearchTextField(boolean isFocused, String query)
-            throws UiObjectNotFoundException {
-        UiObject textField = findSearchViewTextField();
-        boolean searchIconVisible = isSearchIconVisible();
-
-        assertFalse(searchIconVisible);
-        assertTrue(textField.exists());
-        assertEquals(isFocused, textField.isFocused());
-        if (query != null) {
-            assertEquals(query, textField.getText());
-        }
-    }
-
-    public void assertSearchTextFiledAndIcon(
-            boolean searchTextFieldExists, boolean searchIconExists) {
-        assertEquals(searchTextFieldExists, findSearchViewTextField().exists());
-        boolean searchIconVisible = isSearchIconVisible();
-        assertEquals(searchIconExists, searchIconVisible);
-    }
-
     public void assertInActionMode(boolean inActionMode) {
         UiObject actionModeBar = findActionModeBar();
         assertEquals(inActionMode, actionModeBar.exists());
     }
 
-    public void openSearchView() throws UiObjectNotFoundException {
-        UiObject searchView = findSearchView();
-        searchView.click();
-        assertTrue(searchView.exists());
-    }
-
-    public void setSearchQuery(String query) throws UiObjectNotFoundException {
-        onView(Matchers.SEARCH_MENU).perform(typeText(query));
-    }
-
     public UiObject openOverflowMenu() throws UiObjectNotFoundException {
         UiObject obj = findMenuMoreOptions();
         obj.click();
@@ -131,12 +84,21 @@
     }
 
     public void setDialogText(String text) throws UiObjectNotFoundException {
-        findDialogEditText().setText(text);
+        onView(Matchers.TEXT_ENTRY)
+                .perform(ViewActions.replaceText(text));
     }
 
-    public boolean isTablet() {
-        return (mContext.getResources().getConfiguration().screenLayout &
-                Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
+    public boolean inFixedLayout() {
+        TypedValue val = new TypedValue();
+        // We alias files_activity to either fixed or drawer layouts based
+        // on screen dimensions. In order to determine which layout
+        // has been selected, we check the resolved value.
+        mContext.getResources().getValue(R.layout.files_activity, val, true);
+        return val.resourceId == R.layout.fixed_layout;
+    }
+
+    public boolean inDrawerLayout() {
+        return !inFixedLayout();
     }
 
     void switchViewMode() {
@@ -148,26 +110,6 @@
         }
     }
 
-    boolean isSearchIconVisible() {
-        boolean searchIconVisible = true;
-        boolean isTablet = isTablet();
-        try {
-            if (isTablet) {
-                // Tablets use ImageView for its search icon, and has search_button as its res name
-                onView(Matchers.SEARCH_BUTTON)
-                        .check(matches(isDisplayed()));
-            } else {
-                // Phones use ActionMenuItemView for its search icon, and has menu_search as its res
-                // name
-                onView(Matchers.MENU_SEARCH)
-                        .check(matches(isDisplayed()));
-            }
-        } catch (Exception | AssertionFailedError e) {
-            searchIconVisible = false;
-        }
-        return searchIconVisible;
-    }
-
     UiObject2 menuGridMode() {
         // Note that we're using By.desc rather than By.res, because of b/25285770
         return find(By.desc("Grid view"));
@@ -178,79 +120,33 @@
         return find(By.desc("List view"));
     }
 
-    public UiObject2 menuDelete() {
-        return find(By.res("com.android.documentsui:id/menu_delete"));
+    public void clickToolbarItem(int id) {
+        onView(withId(id)).perform(click());
     }
 
-    public UiObject2 menuShare() {
-        return find(By.res("com.android.documentsui:id/menu_share"));
+    public void clickNewFolder() {
+        onView(Matchers.ACTIONBAR_OVERFLOW).perform(click());
+
+        // Click the item by label, since Espresso doesn't support lookup by id on overflow.
+        onView(withText("New folder")).perform(click());
     }
 
-    public UiObject2 menuRename() {
-        return findMenuWithName(mContext.getString(R.string.menu_rename));
+    public void clickActionbarOverflowItem(String label) {
+        onView(Matchers.ACTIONBAR_OVERFLOW).perform(click());
+        // Click the item by label, since Espresso doesn't support lookup by id on overflow.
+        onView(withText(label)).perform(click());
     }
 
-    public UiObject2 menuNewFolder() {
-        return findMenuWithName(mContext.getString(R.string.menu_create_dir));
-    }
-
-    UiObject findSearchView() {
-        return findObject("com.android.documentsui:id/menu_search");
-    }
-
-    UiObject findSearchViewTextField() {
-        return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text");
-    }
-
-    UiObject findSearchViewIcon() {
-        return mContext.getResources().getBoolean(R.bool.full_bar_search_view)
-                ? findObject("com.android.documentsui:id/menu_search")
-                : findObject("com.android.documentsui:id/menu_search", "android:id/search_button");
-    }
-
-    public void clickBreadcrumbItem(String label) throws UiObjectNotFoundException {
-        if (isTablet()) {
-            findBreadcrumb(label).click();
-        } else {
-            findMenuWithName(label).click();
-        }
-    }
-
-    public void clickDropdownBreadcrumb() throws UiObjectNotFoundException {
-        assertFalse(isTablet());
-        onView(isAssignableFrom(Spinner.class)).perform(click());
-    }
-
-    public UiObject findBreadcrumb(String label) throws UiObjectNotFoundException {
-        final UiSelector breadcrumbList = new UiSelector().resourceId(
-                "com.android.documentsui:id/breadcrumb");
-
-        // Wait for the first list item to appear
-        new UiObject(breadcrumbList.childSelector(new UiSelector())).waitForExists(mTimeout);
-
-        return mDevice.findObject(breadcrumbList.childSelector(new UiSelector().text(label)));
-    }
-
-    public void assertBreadcrumbItemsPresent(String... labels) throws UiObjectNotFoundException {
-        List<String> absent = new ArrayList<>();
-        for (String label : labels) {
-            // For non-Tablet devices, a dropdown List menu is shown instead
-            if (isTablet() ? !findBreadcrumb(label).exists() : findMenuWithName(label) == null) {
-                absent.add(label);
-            }
-        }
-        if (!absent.isEmpty()) {
-            Assert.fail("Expected documents " + Arrays.asList(labels)
-                    + ", but missing " + absent);
-        }
+    public void clickToolbarOverflowItem(String label) {
+        onView(Matchers.TOOLBAR_OVERFLOW).perform(click());
+        // Click the item by label, since Espresso doesn't support lookup by id on overflow.
+        onView(withText(label)).perform(click());
     }
 
     UiObject findActionModeBar() {
-        return findObject("android:id/action_mode_bar");
-    }
-
-    public UiObject findDialogEditText() {
-        return findObject("android:id/content", "android:id/text1");
+        UiObject bar = findObject("android:id/action_mode_bar");
+        bar.waitForExists(mTimeout);
+        return bar;
     }
 
     public UiObject findDownloadRetryDialog() {
@@ -263,13 +159,15 @@
     public void clickDialogOkButton() {
         // Espresso has flaky results when keyboard shows up, so hiding it for now
         // before trying to click on any dialog button
-        onView(withId(android.R.id.button1)).perform(closeSoftKeyboard(), click());
+        Espresso.closeSoftKeyboard();
+        onView(withId(android.R.id.button1)).perform(click());
     }
 
     public void clickDialogCancelButton() throws UiObjectNotFoundException {
         // Espresso has flaky results when keyboard shows up, so hiding it for now
         // before trying to click on any dialog button
-        onView(withId(android.R.id.button2)).perform(closeSoftKeyboard(), click());
+        Espresso.closeSoftKeyboard();
+        onView(withId(android.R.id.button2)).perform(click());
     }
 
     UiObject findMenuLabelWithName(String label) {
@@ -292,6 +190,10 @@
         return menuItem;
     }
 
+    boolean hasMenuWithName(String label) {
+        return findMenuWithName(label) != null;
+    }
+
     UiObject findMenuMoreOptions() {
         UiSelector selector = new UiSelector().className("android.widget.ImageButton")
                 .descriptionContains("More options");
@@ -299,14 +201,6 @@
         return mDevice.findObject(selector);
     }
 
-    public void pressKey(int keyCode) {
-        mDevice.pressKeyCode(keyCode);
-    }
-
-    public void pressKey(int keyCode, int metaState) {
-        mDevice.pressKeyCode(keyCode, metaState);
-    }
-
     private static Matcher<Object> withToolbarTitle(
             final Matcher<CharSequence> textMatcher) {
         return new BoundedMatcher<Object, Toolbar>(Toolbar.class) {
@@ -322,21 +216,4 @@
             }
         };
     }
-
-    private static Matcher<Object> withBreadcrumbTitle(
-            final Matcher<CharSequence> textMatcher) {
-        return new BoundedMatcher<Object, Spinner>(Spinner.class) {
-            @Override
-            public boolean matchesSafely(Spinner breadcrumb) {
-                DocumentInfo selectedDoc = (DocumentInfo) breadcrumb.getSelectedItem();
-                return textMatcher.matches(selectedDoc.displayName);
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("with breadcrumb title: ");
-                textMatcher.describeTo(description);
-            }
-        };
-    }
 }