Preparing QuickstepOnOff for running in 3 navigation modes

Change-Id: I7855e756c9886a21bfc2584cf42e7921147fb256
This commit is contained in:
vadimt 2019-03-28 13:47:09 -07:00
parent 60353faa2e
commit c5b06f4cf6
6 changed files with 91 additions and 71 deletions

View File

@ -27,5 +27,5 @@ import org.junit.rules.TestRule;
public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest { public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest {
@Rule @Rule
public TestRule mQuickstepOnOffExecutor = public TestRule mQuickstepOnOffExecutor =
new QuickStepOnOffRule(mMainThreadExecutor, mLauncher); new NavigationModeSwitchRule(mLauncher);
} }

View File

@ -17,26 +17,31 @@ package com.android.quickstep;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS; 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.getHomeIntentInPackage;
import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess; 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.disableHeadsUpNotification;
import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand; import static com.android.launcher3.util.rule.ShellCommandRule.getLauncherCommand;
import static com.android.quickstep.QuickStepOnOffRule.Mode.OFF; import static com.android.quickstep.NavigationModeSwitchRule.Mode.THREE_BUTTON;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import android.app.Instrumentation; import android.app.Instrumentation;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import com.android.launcher3.MainThreadExecutor; 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;
import com.android.launcher3.tapl.LauncherInstrumentation; import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.testcomponent.TestCommandReceiver; import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff; import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -44,12 +49,6 @@ import org.junit.rules.TestRule;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.model.Statement; 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 @LargeTest
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
/** /**
@ -72,7 +71,7 @@ public class FallbackRecentsTest {
mDevice = UiDevice.getInstance(instrumentation); mDevice = UiDevice.getInstance(instrumentation);
mLauncher = new LauncherInstrumentation(instrumentation); mLauncher = new LauncherInstrumentation(instrumentation);
mQuickstepOnOffExecutor = new QuickStepOnOffRule(new MainThreadExecutor(), mLauncher); mQuickstepOnOffExecutor = new NavigationModeSwitchRule(mLauncher);
mOtherLauncherActivity = context.getPackageManager().queryIntentActivities( mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
getHomeIntentInPackage(context), getHomeIntentInPackage(context),
MATCH_DISABLED_COMPONENTS).get(0).activityInfo; MATCH_DISABLED_COMPONENTS).get(0).activityInfo;
@ -94,7 +93,7 @@ public class FallbackRecentsTest {
}; };
} }
@QuickstepOnOff(mode = OFF) @NavigationModeSwitch(mode = THREE_BUTTON)
@Test @Test
public void goToOverviewFromHome() { public void goToOverviewFromHome() {
mDevice.pressHome(); mDevice.pressHome();
@ -104,7 +103,7 @@ public class FallbackRecentsTest {
mLauncher.getBackground().switchToOverview(); mLauncher.getBackground().switchToOverview();
} }
@QuickstepOnOff(mode = OFF) @NavigationModeSwitch(mode = THREE_BUTTON)
@Test @Test
public void goToOverviewFromApp() { public void goToOverviewFromApp() {
startAppFast("com.android.settings"); startAppFast("com.android.settings");

View File

@ -18,9 +18,9 @@ package com.android.quickstep;
import static androidx.test.InstrumentationRegistry.getInstrumentation; import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static com.android.quickstep.QuickStepOnOffRule.Mode.BOTH; import static com.android.quickstep.NavigationModeSwitchRule.Mode.ALL;
import static com.android.quickstep.QuickStepOnOffRule.Mode.OFF; import static com.android.quickstep.NavigationModeSwitchRule.Mode.THREE_BUTTON;
import static com.android.quickstep.QuickStepOnOffRule.Mode.ON; import static com.android.quickstep.NavigationModeSwitchRule.Mode.TWO_BUTTON;
import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_2BUTTON_OVERLAY; import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_2BUTTON_OVERLAY;
import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_3BUTTON_OVERLAY; import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_3BUTTON_OVERLAY;
import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_GESTURAL_OVERLAY; import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_GESTURAL_OVERLAY;
@ -34,49 +34,46 @@ import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers; import com.android.launcher3.tapl.TestHelpers;
import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.QuickStepContract;
import org.junit.Assert;
import org.junit.rules.TestRule; import org.junit.rules.TestRule;
import org.junit.runner.Description; import org.junit.runner.Description;
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;
import java.io.IOException;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.concurrent.Executor;
/** /**
* Test rule that allows executing a test with Quickstep on and then Quickstep off. * Test rule that allows executing a test with Quickstep on and then Quickstep off.
* The test should be annotated with @QuickstepOnOff. * The test should be annotated with @QuickstepOnOff.
*/ */
public class QuickStepOnOffRule implements TestRule { public class NavigationModeSwitchRule implements TestRule {
static final String TAG = "QuickStepOnOffRule"; static final String TAG = "QuickStepOnOffRule";
public enum Mode { public enum Mode {
ON, OFF, BOTH THREE_BUTTON, TWO_BUTTON, ZERO_BUTTON, ALL
} }
// Annotation for tests that need to be run with quickstep enabled and disabled. // Annotation for tests that need to be run with quickstep enabled and disabled.
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface QuickstepOnOff { public @interface NavigationModeSwitch {
Mode mode() default BOTH; Mode mode() default ALL;
} }
private final Executor mMainThreadExecutor;
private final LauncherInstrumentation mLauncher; private final LauncherInstrumentation mLauncher;
public QuickStepOnOffRule(Executor mainThreadExecutor, LauncherInstrumentation launcher) { public NavigationModeSwitchRule(LauncherInstrumentation launcher) {
mLauncher = launcher; mLauncher = launcher;
this.mMainThreadExecutor = mainThreadExecutor;
} }
@Override @Override
public Statement apply(Statement base, Description description) { public Statement apply(Statement base, Description description) {
if (TestHelpers.isInLauncherProcess() && if (TestHelpers.isInLauncherProcess() &&
description.getAnnotation(QuickstepOnOff.class) != null) { description.getAnnotation(NavigationModeSwitch.class) != null) {
Mode mode = description.getAnnotation(QuickstepOnOff.class).mode(); Mode mode = description.getAnnotation(NavigationModeSwitch.class).mode();
return new Statement() { return new Statement() {
@Override @Override
public void evaluate() throws Throwable { public void evaluate() throws Throwable {
@ -86,15 +83,20 @@ public class QuickStepOnOffRule implements TestRule {
: QuickStepContract.isSwipeUpMode(context) : QuickStepContract.isSwipeUpMode(context)
? NAV_BAR_MODE_2BUTTON_OVERLAY ? NAV_BAR_MODE_2BUTTON_OVERLAY
: NAV_BAR_MODE_3BUTTON_OVERLAY; : NAV_BAR_MODE_3BUTTON_OVERLAY;
final LauncherInstrumentation.NavigationModel originalMode =
mLauncher.getNavigationModel();
try { try {
if (mode == ON || mode == BOTH) { // if (mode == ZERO_BUTTON || mode == ALL) {
evaluateWithQuickstepOn(); // evaluateWithZeroButtons();
// }
if (mode == TWO_BUTTON || mode == ALL) {
evaluateWithTwoButtons();
} }
if (mode == OFF || mode == BOTH) { if (mode == THREE_BUTTON || mode == ALL) {
evaluateWithQuickstepOff(); evaluateWithThreeButtons();
} }
} finally { } finally {
setActiveOverlay(prevOverlayPkg); setActiveOverlay(prevOverlayPkg, originalMode);
} }
} }
@ -102,17 +104,26 @@ public class QuickStepOnOffRule implements TestRule {
base.evaluate(); base.evaluate();
} }
private void evaluateWithQuickstepOff() throws Throwable { private void evaluateWithThreeButtons() throws Throwable {
setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY); setActiveOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY,
LauncherInstrumentation.NavigationModel.THREE_BUTTON);
evaluateWithoutChangingSetting(base); evaluateWithoutChangingSetting(base);
} }
private void evaluateWithQuickstepOn() throws Throwable { private void evaluateWithTwoButtons() throws Throwable {
setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY); setActiveOverlay(NAV_BAR_MODE_2BUTTON_OVERLAY,
LauncherInstrumentation.NavigationModel.TWO_BUTTON);
base.evaluate(); base.evaluate();
} }
private void setActiveOverlay(String overlayPackage) { private void evaluateWithZeroButtons() throws Throwable {
setActiveOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY,
LauncherInstrumentation.NavigationModel.ZERO_BUTTON);
base.evaluate();
}
private void setActiveOverlay(String overlayPackage,
LauncherInstrumentation.NavigationModel expectedMode) throws Exception {
setOverlayPackageEnabled(NAV_BAR_MODE_3BUTTON_OVERLAY, setOverlayPackageEnabled(NAV_BAR_MODE_3BUTTON_OVERLAY,
overlayPackage == NAV_BAR_MODE_3BUTTON_OVERLAY); overlayPackage == NAV_BAR_MODE_3BUTTON_OVERLAY);
setOverlayPackageEnabled(NAV_BAR_MODE_2BUTTON_OVERLAY, setOverlayPackageEnabled(NAV_BAR_MODE_2BUTTON_OVERLAY,
@ -120,18 +131,19 @@ public class QuickStepOnOffRule implements TestRule {
setOverlayPackageEnabled(NAV_BAR_MODE_GESTURAL_OVERLAY, setOverlayPackageEnabled(NAV_BAR_MODE_GESTURAL_OVERLAY,
overlayPackage == NAV_BAR_MODE_GESTURAL_OVERLAY); overlayPackage == NAV_BAR_MODE_GESTURAL_OVERLAY);
// TODO: Wait until nav bar mode has applied for (int i = 0; i != 100; ++i) {
if (mLauncher.getNavigationModel() == expectedMode) return;
Thread.sleep(100);
}
Assert.fail("Couldn't switch to " + overlayPackage);
} }
private void setOverlayPackageEnabled(String overlayPackage, boolean enable) { private void setOverlayPackageEnabled(String overlayPackage, boolean enable)
throws Exception {
Log.d(TAG, "setOverlayPackageEnabled: " + overlayPackage + " " + enable); Log.d(TAG, "setOverlayPackageEnabled: " + overlayPackage + " " + enable);
final String action = enable ? "enable" : "disable"; final String action = enable ? "enable" : "disable";
try { UiDevice.getInstance(getInstrumentation()).executeShellCommand(
UiDevice.getInstance(getInstrumentation()).executeShellCommand( "cmd overlay " + action + " " + overlayPackage);
"cmd overlay " + action + " " + overlayPackage);
} catch (IOException e) {
e.printStackTrace();
}
} }
}; };
} else { } else {

View File

@ -26,8 +26,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.util.RaceConditionReproducer; import com.android.launcher3.util.RaceConditionReproducer;
import com.android.quickstep.QuickStepOnOffRule.Mode; import com.android.quickstep.NavigationModeSwitchRule.Mode;
import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff; import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
@ -62,7 +62,7 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
@Test @Test
@Ignore // Ignoring until gestural navigation event sequence settles @Ignore // Ignoring until gestural navigation event sequence settles
@QuickstepOnOff(mode = Mode.ON) @NavigationModeSwitch(mode = Mode.TWO_BUTTON)
public void testPressHome() { public void testPressHome() {
runTest(enterEvt(Launcher.ON_CREATE_EVT), runTest(enterEvt(Launcher.ON_CREATE_EVT),
exitEvt(Launcher.ON_CREATE_EVT), exitEvt(Launcher.ON_CREATE_EVT),
@ -77,14 +77,14 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
@Test @Test
@Ignore // Ignoring until gestural navigation event sequence settles @Ignore // Ignoring until gestural navigation event sequence settles
@QuickstepOnOff(mode = Mode.ON) @NavigationModeSwitch(mode = Mode.TWO_BUTTON)
public void testSwipeToOverview() { public void testSwipeToOverview() {
closeLauncherActivity(); closeLauncherActivity();
mLauncher.getBackground().switchToOverview(); mLauncher.getBackground().switchToOverview();
} }
@Test @Test
@QuickstepOnOff @NavigationModeSwitch
public void testStressPressHome() { public void testStressPressHome() {
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) { for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
// Destroy Launcher activity. // Destroy Launcher activity.
@ -96,7 +96,7 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
} }
@Test @Test
@QuickstepOnOff @NavigationModeSwitch
public void testStressSwipeToOverview() { public void testStressSwipeToOverview() {
for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) { for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
// Destroy Launcher activity. // Destroy Launcher activity.

View File

@ -37,7 +37,7 @@ import com.android.launcher3.tapl.Overview;
import com.android.launcher3.tapl.OverviewTask; import com.android.launcher3.tapl.OverviewTask;
import com.android.launcher3.tapl.TestHelpers; import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.ui.TaplTestsLauncher3; import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff; import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import org.junit.Before; import org.junit.Before;
@ -79,7 +79,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
} }
@Test @Test
@QuickstepOnOff @NavigationModeSwitch
@PortraitLandscape @PortraitLandscape
public void testWorkspaceSwitchToAllApps() { public void testWorkspaceSwitchToAllApps() {
assertNotNull("switchToAllApps() returned null", assertNotNull("switchToAllApps() returned null",
@ -198,7 +198,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
} }
@Test @Test
@QuickstepOnOff @NavigationModeSwitch
@PortraitLandscape @PortraitLandscape
public void testSwitchToOverview() throws Exception { public void testSwitchToOverview() throws Exception {
assertNotNull("Workspace.switchToOverview() returned null", assertNotNull("Workspace.switchToOverview() returned null",
@ -208,7 +208,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
} }
@Test @Test
@QuickstepOnOff @NavigationModeSwitch
@PortraitLandscape @PortraitLandscape
public void testBackground() throws Exception { public void testBackground() throws Exception {
startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));

View File

@ -166,23 +166,28 @@ public final class LauncherInstrumentation {
} }
public NavigationModel getNavigationModel() { public NavigationModel getNavigationModel() {
return isSwipeUpEnabled() ? NavigationModel.TWO_BUTTON : NavigationModel.THREE_BUTTON;
}
static boolean needSlowGestures() {
return Build.MODEL.contains("Cuttlefish");
}
private boolean isSwipeUpEnabled() {
final Context baseContext = mInstrumentation.getTargetContext(); final Context baseContext = mInstrumentation.getTargetContext();
try { try {
// Workaround, use constructed context because both the instrumentation context and the // Workaround, use constructed context because both the instrumentation context and the
// app context are not constructed with resources that take overlays into account // app context are not constructed with resources that take overlays into account
Context ctx = baseContext.createPackageContext(getLauncherPackageName(), 0); final Context ctx = baseContext.createPackageContext("android", 0);
return !QuickStepContract.isLegacyMode(ctx); if (QuickStepContract.isGesturalMode(ctx)) {
return NavigationModel.ZERO_BUTTON;
} else if (QuickStepContract.isSwipeUpMode(ctx)) {
return NavigationModel.TWO_BUTTON;
} else if (QuickStepContract.isLegacyMode(ctx)) {
return NavigationModel.THREE_BUTTON;
} else {
fail("Can't detect navigation mode");
}
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
return false; fail(e.toString());
} }
return NavigationModel.THREE_BUTTON;
}
static boolean needSlowGestures() {
return Build.MODEL.contains("Cuttlefish");
} }
static void log(String message) { static void log(String message) {
@ -233,9 +238,13 @@ public final class LauncherInstrumentation {
private UiObject2 verifyContainerType(ContainerType containerType) { private UiObject2 verifyContainerType(ContainerType containerType) {
assertEquals("Unexpected display rotation", assertEquals("Unexpected display rotation",
mExpectedRotation, mDevice.getDisplayRotation()); mExpectedRotation, mDevice.getDisplayRotation());
assertTrue("Presence of recents button doesn't match isSwipeUpEnabled()", final NavigationModel navigationModel = getNavigationModel();
isSwipeUpEnabled() == assertTrue("Presence of recents button doesn't match the interaction mode",
(mDevice.findObject(By.res(SYSTEMUI_PACKAGE, "recent_apps")) == null)); (navigationModel == NavigationModel.THREE_BUTTON) ==
mDevice.hasObject(By.res(SYSTEMUI_PACKAGE, "recent_apps")));
assertTrue("Presence of home button doesn't match the interaction mode",
(navigationModel != NavigationModel.ZERO_BUTTON) ==
mDevice.hasObject(By.res(SYSTEMUI_PACKAGE, "home")));
log("verifyContainerType: " + containerType); log("verifyContainerType: " + containerType);
try (Closable c = addContextLayer( try (Closable c = addContextLayer(