Adding tests for fallback recents when a 3rd party launcher is installed

Change-Id: I1d4da13cc779f49832008b12b9628d01631faffe
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
new file mode 100644
index 0000000..88b50d9
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2018 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.quickstep;
+
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+
+import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
+import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage;
+import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess;
+import static com.android.launcher3.util.rule.ShellCommandRule.disableHeadsUpNotification;
+import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
+import static com.android.quickstep.QuickStepOnOffRule.Mode.OFF;
+
+import static org.junit.Assert.assertTrue;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.testcomponent.TestCommandReceiver;
+import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+/**
+ * TODO: Fix fallback when quickstep is enabled
+ */
+public class FallbackRecentsTest {
+
+    private final UiDevice mDevice;
+    private final LauncherInstrumentation mLauncher;
+    private final ActivityInfo mOtherLauncherActivity;
+
+    @Rule public final TestRule mDisableHeadsUpNotification = disableHeadsUpNotification();
+    @Rule public final TestRule mQuickstepOnOffExecutor;
+
+    @Rule public final TestRule mSetLauncherCommand;
+
+    public FallbackRecentsTest() {
+        Instrumentation instrumentation = getInstrumentation();
+        Context context = instrumentation.getContext();
+        mDevice = UiDevice.getInstance(instrumentation);
+        mLauncher = new LauncherInstrumentation(instrumentation);
+
+        mQuickstepOnOffExecutor = new QuickStepOnOffRule(new MainThreadExecutor(), mLauncher);
+        mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
+                getHomeIntentInPackage(context),
+                MATCH_DISABLED_COMPONENTS).get(0).activityInfo;
+
+        mSetLauncherCommand = (base, desc) -> new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                TestCommandReceiver.callCommand(TestCommandReceiver.ENABLE_TEST_LAUNCHER);
+                UiDevice.getInstance(getInstrumentation()).executeShellCommand(
+                        getLauncherCommand(mOtherLauncherActivity));
+                try {
+                    base.evaluate();
+                } finally {
+                    TestCommandReceiver.callCommand(TestCommandReceiver.DISABLE_TEST_LAUNCHER);
+                    UiDevice.getInstance(getInstrumentation()).executeShellCommand(
+                            getLauncherCommand(getLauncherInMyProcess()));
+                }
+            }
+        };
+    }
+
+    @QuickstepOnOff(mode = OFF)
+    @Test
+    public void goToOverviewFromHome() {
+        mDevice.pressHome();
+        assertTrue("Fallback Launcher not visible", mDevice.wait(Until.hasObject(By.pkg(
+                mOtherLauncherActivity.packageName)), WAIT_TIME_MS));
+
+        mLauncher.getBackground().switchToOverview();
+    }
+
+    @QuickstepOnOff(mode = OFF)
+    @Test
+    public void goToOverviewFromApp() {
+        startAppFast("com.android.settings");
+
+        mLauncher.getBackground().switchToOverview();
+    }
+
+    private void startAppFast(String packageName) {
+        final Instrumentation instrumentation = getInstrumentation();
+        final Intent intent = instrumentation.getContext().getPackageManager().
+                getLaunchIntentForPackage(packageName);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        instrumentation.getTargetContext().startActivity(intent);
+        assertTrue(packageName + " didn't start",
+                mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), WAIT_TIME_MS));
+    }
+
+}
diff --git a/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java b/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java
index 6a149b7..b801b4f 100644
--- a/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java
+++ b/quickstep/tests/src/com/android/quickstep/QuickStepOnOffRule.java
@@ -16,10 +16,14 @@
 
 package com.android.quickstep;
 
+import static com.android.quickstep.QuickStepOnOffRule.Mode.BOTH;
+import static com.android.quickstep.QuickStepOnOffRule.Mode.OFF;
+import static com.android.quickstep.QuickStepOnOffRule.Mode.ON;
+
 import androidx.test.InstrumentationRegistry;
 
 import com.android.launcher3.tapl.LauncherInstrumentation;
-import com.android.launcher3.ui.TestHelpers;
+import com.android.launcher3.tapl.TestHelpers;
 
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
@@ -36,10 +40,16 @@
  * The test should be annotated with @QuickstepOnOff.
  */
 public class QuickStepOnOffRule implements TestRule {
+
+    public enum Mode {
+        ON, OFF, BOTH
+    }
+
     // Annotation for tests that need to be run with quickstep enabled and disabled.
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.METHOD)
     public @interface QuickstepOnOff {
+        Mode mode() default BOTH;
     }
 
     private final Executor mMainThreadExecutor;
@@ -54,12 +64,17 @@
     public Statement apply(Statement base, Description description) {
         if (TestHelpers.isInLauncherProcess() &&
                 description.getAnnotation(QuickstepOnOff.class) != null) {
+            Mode mode = description.getAnnotation(QuickstepOnOff.class).mode();
             return new Statement() {
                 @Override
                 public void evaluate() throws Throwable {
                     try {
-                        evaluateWithQuickstepOn();
-                        evaluateWithQuickstepOff();
+                        if (mode == ON || mode == BOTH) {
+                            evaluateWithQuickstepOn();
+                        }
+                        if (mode == OFF || mode == BOTH) {
+                            evaluateWithQuickstepOff();
+                        }
                     } finally {
                         overrideSwipeUpEnabled(null);
                     }
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 89ca7f3..439058c 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -67,5 +67,33 @@
                 <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
+
+        <provider
+            android:name="com.android.launcher3.testcomponent.TestCommandReceiver"
+            android:authorities="${packageName}.commands"
+            android:exported="true" />
+
+        <activity
+            android:name="com.android.launcher3.testcomponent.TestLauncherActivity"
+            android:launchMode="singleTask"
+            android:clearTaskOnLaunch="true"
+            android:label="Test launcher"
+            android:stateNotNeeded="true"
+            android:theme="@android:style/Theme.DeviceDefault.Light"
+            android:windowSoftInputMode="adjustPan"
+            android:screenOrientation="unspecified"
+            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
+            android:resizeableActivity="true"
+            android:taskAffinity=""
+            android:process=":testLauncherProcess"
+            android:enabled="false">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.HOME" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.MONKEY"/>
+                <category android:name="android.intent.category.LAUNCHER_APP" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java b/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
new file mode 100644
index 0000000..04c04f5
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/TestCommandReceiver.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 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.launcher3.testcomponent;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.DONT_KILL_APP;
+
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.test.InstrumentationRegistry;
+
+/**
+ * Content provider to receive commands from tests
+ */
+public class TestCommandReceiver extends ContentProvider {
+
+    public static final String ENABLE_TEST_LAUNCHER = "enable-test-launcher";
+    public static final String DISABLE_TEST_LAUNCHER = "disable-test-launcher";
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
+    @Override
+    public Bundle call(String method, String arg, Bundle extras) {
+        switch (method) {
+            case ENABLE_TEST_LAUNCHER: {
+                getContext().getPackageManager().setComponentEnabledSetting(
+                        new ComponentName(getContext(), TestLauncherActivity.class),
+                        COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
+                return null;
+            }
+            case DISABLE_TEST_LAUNCHER: {
+                getContext().getPackageManager().setComponentEnabledSetting(
+                        new ComponentName(getContext(), TestLauncherActivity.class),
+                        COMPONENT_ENABLED_STATE_DISABLED, DONT_KILL_APP);
+                return null;
+            }
+
+        }
+        return super.call(method, arg, extras);
+    }
+
+    public static Bundle callCommand(String command) {
+        Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+        Uri uri = Uri.parse("content://" + inst.getContext().getPackageName() + ".commands");
+        return inst.getTargetContext().getContentResolver().call(uri, command, null, null);
+    }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/TestLauncherActivity.java b/tests/src/com/android/launcher3/testcomponent/TestLauncherActivity.java
new file mode 100644
index 0000000..357a232
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/TestLauncherActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 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.launcher3.testcomponent;
+
+import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_LAUNCHER;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
+
+import android.app.LauncherActivity;
+import android.content.Intent;
+
+public class TestLauncherActivity extends LauncherActivity {
+
+    @Override
+    protected Intent getTargetIntent() {
+        return new Intent(ACTION_MAIN, null)
+                .addCategory(CATEGORY_LAUNCHER)
+                .addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+    }
+}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 00df4e7..773ec9d 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
 import android.app.Instrumentation;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -53,10 +55,12 @@
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.tapl.LauncherInstrumentation;
+import com.android.launcher3.tapl.TestHelpers;
 import com.android.launcher3.testcomponent.AppWidgetNoConfig;
 import com.android.launcher3.testcomponent.AppWidgetWithConfig;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.LauncherActivityRule;
+import com.android.launcher3.util.rule.ShellCommandRule;
 
 import org.junit.After;
 import org.junit.Before;
@@ -95,7 +99,7 @@
     private static final String TAG = "AbstractLauncherUiTest";
 
     protected AbstractLauncherUiTest() {
-        final Instrumentation instrumentation = TestHelpers.getInstrumentation();
+        final Instrumentation instrumentation = getInstrumentation();
         mDevice = UiDevice.getInstance(instrumentation);
         try {
             mDevice.setOrientationNatural();
@@ -109,6 +113,11 @@
     @Rule
     public LauncherActivityRule mActivityMonitor = new LauncherActivityRule();
 
+    @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
+
+    @Rule public ShellCommandRule mDisableHeadsUpNotification =
+            ShellCommandRule.disableHeadsUpNotification();
+
     // Annotation for tests that need to be run in portrait and landscape modes.
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.METHOD)
@@ -156,12 +165,10 @@
     public void setUp() throws Exception {
         mTargetContext = InstrumentationRegistry.getTargetContext();
         mTargetPackage = mTargetContext.getPackageName();
-        mDevice.executeShellCommand("settings put global heads_up_notifications_enabled 0");
     }
 
     @After
     public void tearDown() throws Exception {
-        mDevice.executeShellCommand("settings put global heads_up_notifications_enabled 1");
         // Limits UI tests affecting tests running after them.
         resetLoaderState();
     }
@@ -282,7 +289,7 @@
     protected void sendPointer(int action, Point point) {
         MotionEvent event = MotionEvent.obtain(SystemClock.uptimeMillis(),
                 SystemClock.uptimeMillis(), action, point.x, point.y, 0);
-        TestHelpers.getInstrumentation().sendPointerSync(event);
+        getInstrumentation().sendPointerSync(event);
         event.recycle();
     }
 
@@ -374,7 +381,7 @@
                 getOnUiThread(new Callable<LauncherAppWidgetProviderInfo>() {
             @Override
             public LauncherAppWidgetProviderInfo call() throws Exception {
-                ComponentName cn = new ComponentName(TestHelpers.getInstrumentation().getContext(),
+                ComponentName cn = new ComponentName(getInstrumentation().getContext(),
                         hasConfigureScreen ? AppWidgetWithConfig.class : AppWidgetNoConfig.class);
                 Log.d(TAG, "findWidgetProvider componentName=" + cn.flattenToString());
                 return AppWidgetManagerCompat.getInstance(mTargetContext)
diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
index a0f4620..600d390 100644
--- a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
+++ b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
@@ -11,10 +11,8 @@
 
 import com.android.launcher3.util.Condition;
 import com.android.launcher3.util.Wait;
-import com.android.launcher3.util.rule.ShellCommandRule;
 
 import org.junit.Ignore;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -25,8 +23,6 @@
 @RunWith(AndroidJUnit4.class)
 public class AllAppsIconToHomeTest extends AbstractLauncherUiTest {
 
-    @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
-
     @Test
     @Ignore
     public void testDragIcon_portrait() throws Throwable {
diff --git a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java b/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java
index 83a6734..6a007ae 100644
--- a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java
+++ b/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java
@@ -15,10 +15,8 @@
 import com.android.launcher3.R;
 import com.android.launcher3.util.Condition;
 import com.android.launcher3.util.Wait;
-import com.android.launcher3.util.rule.ShellCommandRule;
 
 import org.junit.Ignore;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -29,8 +27,6 @@
 @RunWith(AndroidJUnit4.class)
 public class ShortcutsLaunchTest extends AbstractLauncherUiTest {
 
-    @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
-
     @Test
     @Ignore
     public void testAppLauncher_portrait() throws Exception {
diff --git a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java b/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java
index 793bd8f..c23f6ef 100644
--- a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java
+++ b/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java
@@ -15,10 +15,8 @@
 import com.android.launcher3.R;
 import com.android.launcher3.util.Condition;
 import com.android.launcher3.util.Wait;
-import com.android.launcher3.util.rule.ShellCommandRule;
 
 import org.junit.Ignore;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -29,8 +27,6 @@
 @RunWith(AndroidJUnit4.class)
 public class ShortcutsToHomeTest extends AbstractLauncherUiTest {
 
-    @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
-
     @Test
     @Ignore
     public void testDragIcon_portrait() throws Throwable {
diff --git a/tests/src/com/android/launcher3/ui/TestHelpers.java b/tests/src/com/android/launcher3/ui/TestHelpers.java
deleted file mode 100644
index da21a5d..0000000
--- a/tests/src/com/android/launcher3/ui/TestHelpers.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2018 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.launcher3.ui;
-
-import android.app.Instrumentation;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.uiautomator.UiDevice;
-
-public class TestHelpers {
-    private static final boolean IS_IN_LAUNCHER_PROCESS =
-            getInstrumentation().getTargetContext().getPackageName().equals(
-                    UiDevice.getInstance(getInstrumentation()).getLauncherPackageName());
-
-    public static Instrumentation getInstrumentation() {
-        return InstrumentationRegistry.getInstrumentation();
-    }
-
-    public static boolean isInLauncherProcess() {
-        return IS_IN_LAUNCHER_PROCESS;
-    }
-}
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index 044b7f3..c93c20a 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -22,19 +22,14 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.launcher3.util.rule.ShellCommandRule;
-
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public class WorkTabTest extends AbstractLauncherUiTest {
-    @Rule
-    public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
 
     private int mProfileUserId;
 
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index eed63f4..f72bacb 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -20,6 +20,8 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
 
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
 import android.appwidget.AppWidgetManager;
 import android.content.Intent;
 import androidx.test.filters.LargeTest;
@@ -34,7 +36,7 @@
 import com.android.launcher3.Workspace;
 import com.android.launcher3.testcomponent.WidgetConfigActivity;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
-import com.android.launcher3.ui.TestHelpers;
+import com.android.launcher3.tapl.TestHelpers;
 import com.android.launcher3.util.Condition;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.ShellCommandRule;
@@ -135,8 +137,7 @@
     }
 
     private void setResult(boolean success) {
-
-        TestHelpers.getInstrumentation().getTargetContext().sendBroadcast(
+        getInstrumentation().getTargetContext().sendBroadcast(
                 WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
                         success ? "clickOK" : "clickCancel"));
     }
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index 94f9e39..738ad84 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -56,6 +56,7 @@
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 import java.util.Set;
@@ -71,8 +72,6 @@
 @RunWith(AndroidJUnit4.class)
 public class BindWidgetTest extends AbstractLauncherUiTest {
 
-    @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind();
-
     private ContentResolver mResolver;
     private AppWidgetManagerCompat mWidgetManager;
 
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index 74f0978..67a7fde 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -60,10 +60,9 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class RequestPinItemTest  extends AbstractLauncherUiTest {
+public class RequestPinItemTest extends AbstractLauncherUiTest {
 
     @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind();
-    @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
 
     private String mCallbackAction;
     private String mShortcutId;
diff --git a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
index 1c7160f..145c3c8 100644
--- a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
+++ b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java
@@ -15,10 +15,14 @@
  */
 package com.android.launcher3.util.rule;
 
+import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.InstrumentationRegistry.getTargetContext;
+
 import android.app.Activity;
 import android.app.Application;
 import android.app.Application.ActivityLifecycleCallbacks;
-import android.content.Intent;
 import android.os.Bundle;
 import androidx.test.InstrumentationRegistry;
 
@@ -65,19 +69,12 @@
      * Starts the launcher activity in the target package.
      */
     public void startLauncher() {
-        InstrumentationRegistry.getInstrumentation().startActivitySync(getHomeIntent());
+        getInstrumentation().startActivitySync(getHomeIntentInPackage(getTargetContext()));
     }
 
     public void returnToHome() {
-        InstrumentationRegistry.getTargetContext().startActivity(getHomeIntent());
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-    }
-
-    public static Intent getHomeIntent() {
-        return new Intent(Intent.ACTION_MAIN)
-                .addCategory(Intent.CATEGORY_HOME)
-                .setPackage(InstrumentationRegistry.getTargetContext().getPackageName())
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getTargetContext().startActivity(getHomeIntentInPackage(getTargetContext()));
+        getInstrumentation().waitForIdleSync();
     }
 
     private class MyStatement extends Statement implements ActivityLifecycleCallbacks {
diff --git a/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java b/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java
index 9f0db2b..4531ab1 100644
--- a/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java
+++ b/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java
@@ -15,17 +15,20 @@
  */
 package com.android.launcher3.util.rule;
 
+import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
-import android.os.ParcelFileDescriptor;
-import androidx.test.InstrumentationRegistry;
 
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
-import java.io.FileInputStream;
-import java.io.IOException;
+import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
 
 /**
  * Test rule which executes a shell command at the start of the test.
@@ -33,40 +36,28 @@
 public class ShellCommandRule implements TestRule {
 
     private final String mCmd;
+    private final String mRevertCommand;
 
-    public ShellCommandRule(String cmd) {
+    public ShellCommandRule(String cmd, @Nullable String revertCommand) {
         mCmd = cmd;
+        mRevertCommand = revertCommand;
     }
 
     @Override
     public Statement apply(Statement base, Description description) {
-        return new MyStatement(base, mCmd);
-    }
-
-    public static void runShellCommand(String command) throws IOException {
-        ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
-                .executeShellCommand(command);
-
-        // Read the input stream fully.
-        FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
-        while (fis.read() != -1);
-        fis.close();
-    }
-
-    private static class MyStatement extends Statement {
-        private final Statement mBase;
-        private final String mCmd;
-
-        public MyStatement(Statement base, String cmd) {
-            mBase = base;
-            mCmd = cmd;
-        }
-
-        @Override
-        public void evaluate() throws Throwable {
-            runShellCommand(mCmd);
-            mBase.evaluate();
-        }
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                UiDevice.getInstance(getInstrumentation()).executeShellCommand(mCmd);
+                try {
+                    base.evaluate();
+                } finally {
+                    if (mRevertCommand != null) {
+                        UiDevice.getInstance(getInstrumentation()).executeShellCommand(mRevertCommand);
+                    }
+                }
+            }
+        };
     }
 
     /**
@@ -74,17 +65,26 @@
      */
     public static ShellCommandRule grandWidgetBind() {
         return new ShellCommandRule("appwidget grantbind --package "
-                + InstrumentationRegistry.getTargetContext().getPackageName());
+                + InstrumentationRegistry.getTargetContext().getPackageName(), null);
     }
 
     /**
      * Sets the target launcher as default launcher.
      */
     public static ShellCommandRule setDefaultLauncher() {
-        ActivityInfo launcher = InstrumentationRegistry.getTargetContext().getPackageManager()
-                .queryIntentActivities(LauncherActivityRule.getHomeIntent(), 0).get(0)
-                .activityInfo;
-        return new ShellCommandRule("cmd package set-home-activity " +
-                new ComponentName(launcher.packageName, launcher.name).flattenToString());
+        return new ShellCommandRule(getLauncherCommand(getLauncherInMyProcess()), null);
+    }
+
+    public static String getLauncherCommand(ActivityInfo launcher) {
+        return "cmd package set-home-activity " +
+                new ComponentName(launcher.packageName, launcher.name).flattenToString();
+    }
+
+    /**
+     * Disables heads up notification for the duration of the test
+     */
+    public static ShellCommandRule disableHeadsUpNotification() {
+        return new ShellCommandRule("settings put global heads_up_notifications_enabled 0",
+                "settings put global heads_up_notifications_enabled 1");
     }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 1aef979..26295c8 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -16,10 +16,22 @@
 
 package com.android.launcher3.tapl;
 
+import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
+
+import static org.junit.Assert.assertTrue;
+
+import static androidx.test.InstrumentationRegistry.getTargetContext;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
 /**
- * Operations on a state when Launcher is inactive because some other app is active.
+ * Indicates the base state with a UI other than Overview running as foreground. It can also
+ * indicate Launcher as long as Launcher is not in Overview state.
  */
-public final class Background extends Home {
+public class Background extends LauncherInstrumentation.VisibleContainer {
 
     Background(LauncherInstrumentation launcher) {
         super(launcher);
@@ -29,4 +41,34 @@
     protected LauncherInstrumentation.ContainerType getContainerType() {
         return LauncherInstrumentation.ContainerType.BACKGROUND;
     }
+
+    /**
+     * Swipes up or presses the square button to switch to Overview.
+     * Returns the base overview, which can be either in Launcher or the fallback recents.
+     *
+     * @return the Overview panel object.
+     */
+    @NonNull
+    public BaseOverview switchToOverview() {
+        verifyActiveContainer();
+        goToOverviewUnchecked();
+        assertTrue("Overview not visible", mLauncher.getDevice().wait(Until.hasObject(By.pkg(
+                getTargetContext().getPackageName())),
+                WAIT_TIME_MS));
+        return new BaseOverview(mLauncher);
+    }
+
+
+    protected void goToOverviewUnchecked() {
+        if (mLauncher.isSwipeUpEnabled()) {
+            final int height = mLauncher.getDevice().getDisplayHeight();
+            final UiObject2 navBar = mLauncher.getSystemUiObject("navigation_bar_frame");
+
+            mLauncher.swipe(
+                    navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
+                    navBar.getVisibleBounds().centerX(), height - 300);
+        } else {
+            mLauncher.getSystemUiObject("recent_apps").click();
+        }
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
new file mode 100644
index 0000000..87d0a79
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 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.launcher3.tapl;
+
+import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
+
+import java.util.Collections;
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.Direction;
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Common overview pane for both Launcher and fallback recents
+ */
+public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
+    private static final int DEFAULT_FLING_SPEED = 15000;
+
+    BaseOverview(LauncherInstrumentation launcher) {
+        super(launcher);
+    }
+
+    @Override
+    protected LauncherInstrumentation.ContainerType getContainerType() {
+        return LauncherInstrumentation.ContainerType.BASE_OVERVIEW;
+    }
+
+    /**
+     * Flings forward (left) and waits the fling's end.
+     */
+    public void flingForward() {
+        final UiObject2 overview = verifyActiveContainer();
+        LauncherInstrumentation.log("Overview.flingForward before fling");
+        overview.fling(Direction.LEFT, DEFAULT_FLING_SPEED);
+        mLauncher.waitForIdle();
+        verifyActiveContainer();
+    }
+
+    /**
+     * Flings backward (right) and waits the fling's end.
+     */
+    public void flingBackward() {
+        final UiObject2 overview = verifyActiveContainer();
+        LauncherInstrumentation.log("Overview.flingBackward before fling");
+        overview.fling(Direction.RIGHT, DEFAULT_FLING_SPEED);
+        mLauncher.waitForIdle();
+        verifyActiveContainer();
+    }
+
+    /**
+     * Gets the current task in the carousel, or fails if the carousel is empty.
+     *
+     * @return the task in the middle of the visible tasks list.
+     */
+    @NonNull
+    public OverviewTask getCurrentTask() {
+        verifyActiveContainer();
+        final List<UiObject2> taskViews = mLauncher.getDevice().findObjects(
+                LauncherInstrumentation.getLauncherObjectSelector("snapshot"));
+        LauncherInstrumentation.assertNotEquals("Unable to find a task", 0, taskViews.size());
+
+        // taskViews contains up to 3 task views: the 'main' (having the widest visible
+        // part) one in the center, and parts of its right and left siblings. Find the
+        // main task view by its width.
+        final UiObject2 widestTask = Collections.max(taskViews,
+                (t1, t2) -> Integer.compare(t1.getVisibleBounds().width(),
+                        t2.getVisibleBounds().width()));
+
+        return new OverviewTask(mLauncher, widestTask, this);
+    }
+}
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index 815a63e..522ce14 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher3.tapl;
 
-import androidx.test.uiautomator.UiObject2;
-
 import androidx.annotation.NonNull;
 
 /**
@@ -28,33 +26,28 @@
  * that essentially represents these two activity states. Any gestures (e.g., switchToOverview) that
  * can be performed in both of these states can be defined here.
  */
-public abstract class Home extends LauncherInstrumentation.VisibleContainer {
+public abstract class Home extends Background {
 
     protected Home(LauncherInstrumentation launcher) {
         super(launcher);
         verifyActiveContainer();
     }
 
+    @Override
+    protected LauncherInstrumentation.ContainerType getContainerType() {
+        return LauncherInstrumentation.ContainerType.WORKSPACE;
+    }
+
     /**
      * Swipes up or presses the square button to switch to Overview.
      *
      * @return the Overview panel object.
      */
     @NonNull
+    @Override
     public Overview switchToOverview() {
         verifyActiveContainer();
-        if (mLauncher.isSwipeUpEnabled()) {
-            final int height = mLauncher.getDevice().getDisplayHeight();
-            final UiObject2 navBar = mLauncher.getSystemUiObject("navigation_bar_frame");
-
-            mLauncher.swipe(
-                    navBar.getVisibleBounds().centerX(), navBar.getVisibleBounds().centerY(),
-                    navBar.getVisibleBounds().centerX(), height - 300
-            );
-        } else {
-            mLauncher.getSystemUiObject("recent_apps").click();
-        }
-
+        goToOverviewUnchecked();
         return new Overview(mLauncher);
     }
 }
\ No newline at end of file
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 66dfe41..31abc53 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -28,13 +28,6 @@
 import android.view.Surface;
 import android.view.accessibility.AccessibilityEvent;
 
-import androidx.annotation.NonNull;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.BySelector;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
 import com.android.launcher3.TestProtocol;
 import com.android.quickstep.SwipeUpSetting;
 
@@ -43,6 +36,13 @@
 import java.lang.ref.WeakReference;
 import java.util.concurrent.TimeoutException;
 
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+
 /**
  * The main tapl object. The only object that can be explicitly constructed by the using code. It
  * produces all other objects.
@@ -54,7 +54,7 @@
     // Types for launcher containers that the user is interacting with. "Background" is a
     // pseudo-container corresponding to inactive launcher covered by another app.
     enum ContainerType {
-        WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND
+        WORKSPACE, ALL_APPS, OVERVIEW, WIDGETS, BACKGROUND, BASE_OVERVIEW
     }
 
     // Base class for launcher containers.
@@ -84,7 +84,7 @@
     private static final String OVERVIEW_RES_ID = "overview_panel";
     private static final String WIDGETS_RES_ID = "widgets_list_view";
     static final String LAUNCHER_PKG = "com.google.android.apps.nexuslauncher";
-    static final int WAIT_TIME_MS = 60000;
+    public static final int WAIT_TIME_MS = 60000;
     private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
 
     private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
@@ -112,11 +112,8 @@
         // Launcher should run in test harness so that custom accessibility protocol between
         // Launcher and TAPL is enabled. In-process tests enable this protocol with a direct call
         // into Launcher.
-        final boolean isInLauncherProcess =
-                instrumentation.getTargetContext().getPackageName().equals(
-                        UiDevice.getInstance(instrumentation).getLauncherPackageName());
         assertTrue("Device must run in a test harness",
-                isInLauncherProcess || ActivityManager.isRunningInTestHarness());
+                TestHelpers.isInLauncherProcess() || ActivityManager.isRunningInTestHarness());
     }
 
     // Used only by TaplTests.
@@ -203,8 +200,12 @@
                 } else {
                     waitUntilGone(APPS_RES_ID);
                 }
+                // Fall through
+            }
+            case BASE_OVERVIEW: {
                 waitUntilGone(WORKSPACE_RES_ID);
                 waitUntilGone(WIDGETS_RES_ID);
+
                 return waitForLauncherObject(OVERVIEW_RES_ID);
             }
             case BACKGROUND: {
@@ -310,6 +311,17 @@
     }
 
     /**
+     * Gets the Base overview object if either Launcher is in overview state or the fallback
+     * overview activity is showing. Fails otherwise.
+     *
+     * @return BaseOverview object.
+     */
+    @NonNull
+    public BaseOverview getBaseOverview() {
+        return new BaseOverview(this);
+    }
+
+    /**
      * Gets the All Apps object if the current state is showing the all apps panel opened by swiping
      * from workspace. Fails if the launcher is not in that state. Please don't call this method if
      * App Apps was opened by swiping up from Overview, as it won't fail and will return an
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index 9841274..9e0c07f 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -18,18 +18,15 @@
 
 import android.graphics.Point;
 
-import androidx.annotation.NonNull;
-import androidx.test.uiautomator.Direction;
-import androidx.test.uiautomator.UiObject2;
+import com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
 
-import java.util.Collections;
-import java.util.List;
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
 
 /**
  * Overview pane.
  */
-public final class Overview extends LauncherInstrumentation.VisibleContainer {
-    private static final int DEFAULT_FLING_SPEED = 15000;
+public final class Overview extends BaseOverview {
 
     Overview(LauncherInstrumentation launcher) {
         super(launcher);
@@ -37,55 +34,11 @@
     }
 
     @Override
-    protected LauncherInstrumentation.ContainerType getContainerType() {
+    protected ContainerType getContainerType() {
         return LauncherInstrumentation.ContainerType.OVERVIEW;
     }
 
     /**
-     * Flings forward (left) and waits the fling's end.
-     */
-    public void flingForward() {
-        final UiObject2 overview = verifyActiveContainer();
-        LauncherInstrumentation.log("Overview.flingForward before fling");
-        overview.fling(Direction.LEFT, DEFAULT_FLING_SPEED);
-        mLauncher.waitForIdle();
-        verifyActiveContainer();
-    }
-
-    /**
-     * Flings backward (right) and waits the fling's end.
-     */
-    public void flingBackward() {
-        final UiObject2 overview = verifyActiveContainer();
-        LauncherInstrumentation.log("Overview.flingBackward before fling");
-        overview.fling(Direction.RIGHT, DEFAULT_FLING_SPEED);
-        mLauncher.waitForIdle();
-        verifyActiveContainer();
-    }
-
-    /**
-     * Gets the current task in the carousel, or fails if the carousel is empty.
-     *
-     * @return the task in the middle of the visible tasks list.
-     */
-    @NonNull
-    public OverviewTask getCurrentTask() {
-        verifyActiveContainer();
-        final List<UiObject2> taskViews = mLauncher.getDevice().findObjects(
-                LauncherInstrumentation.getLauncherObjectSelector("snapshot"));
-        LauncherInstrumentation.assertNotEquals("Unable to find a task", 0, taskViews.size());
-
-        // taskViews contains up to 3 task views: the 'main' (having the widest visible
-        // part) one in the center, and parts of its right and left siblings. Find the
-        // main task view by its width.
-        final UiObject2 widestTask = Collections.max(taskViews,
-                (t1, t2) -> Integer.compare(t1.getVisibleBounds().width(),
-                        t2.getVisibleBounds().width()));
-
-        return new OverviewTask(mLauncher, widestTask, this);
-    }
-
-    /**
      * Swipes up to All Apps.
      *
      * @return the App Apps object.
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 2b67cc0..48686c4 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -26,9 +26,9 @@
 public final class OverviewTask {
     private final LauncherInstrumentation mLauncher;
     private final UiObject2 mTask;
-    private final Overview mOverview;
+    private final BaseOverview mOverview;
 
-    OverviewTask(LauncherInstrumentation launcher, UiObject2 task, Overview overview) {
+    OverviewTask(LauncherInstrumentation launcher, UiObject2 task, BaseOverview overview) {
         mLauncher = launcher;
         mTask = task;
         mOverview = overview;
diff --git a/tests/tapl/com/android/launcher3/tapl/TestHelpers.java b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
new file mode 100644
index 0000000..c393cdf
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TestHelpers.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018 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.launcher3.tapl;
+
+import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.InstrumentationRegistry.getTargetContext;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ResolveInfo;
+
+import java.util.List;
+
+public class TestHelpers {
+
+    private static Boolean sIsInLauncherProcess;
+
+    public static boolean isInLauncherProcess() {
+        if (sIsInLauncherProcess == null) {
+            sIsInLauncherProcess = initIsInLauncherProcess();
+        }
+        return sIsInLauncherProcess;
+    }
+
+    private static boolean initIsInLauncherProcess() {
+        ActivityInfo info = getLauncherInMyProcess();
+
+        // If we are in the same process, we can instantiate the class name.
+        try {
+            Class launcherClazz = Class.forName("com.android.launcher3.Launcher");
+            return launcherClazz.isAssignableFrom(Class.forName(info.name));
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    public static Intent getHomeIntentInPackage(Context context) {
+        return new Intent(Intent.ACTION_MAIN)
+                .addCategory(Intent.CATEGORY_HOME)
+                .setPackage(context.getPackageName())
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+    }
+
+    public static ActivityInfo getLauncherInMyProcess() {
+        Instrumentation instrumentation = getInstrumentation();
+        if (instrumentation.getTargetContext() == null) {
+            return null;
+        }
+
+        List<ResolveInfo> launchers = getTargetContext().getPackageManager()
+                .queryIntentActivities(getHomeIntentInPackage(getTargetContext()), 0);
+        if (launchers.size() != 1) {
+            return null;
+        }
+        return launchers.get(0).activityInfo;
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index f5b01ee..493f26a 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -38,11 +38,6 @@
         mHotseat = launcher.waitForLauncherObject("hotseat");
     }
 
-    @Override
-    protected LauncherInstrumentation.ContainerType getContainerType() {
-        return LauncherInstrumentation.ContainerType.WORKSPACE;
-    }
-
     /**
      * Swipes up to All Apps.
      *