Merge "Adding tests for fallback recents when a 3rd party launcher is installed" into ub-launcher3-master
This commit is contained in:
commit
02e900c3c9
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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 @@ import java.util.concurrent.Executor;
|
|||
* 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 class QuickStepOnOffRule implements TestRule {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@ import static org.junit.Assert.assertNotNull;
|
|||
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.Utilities;
|
|||
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 @@ public abstract class AbstractLauncherUiTest {
|
|||
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 @@ public abstract class AbstractLauncherUiTest {
|
|||
@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 abstract class AbstractLauncherUiTest {
|
|||
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 @@ public abstract class AbstractLauncherUiTest {
|
|||
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 @@ public abstract class AbstractLauncherUiTest {
|
|||
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)
|
||||
|
|
|
@ -11,10 +11,8 @@ import androidx.test.uiautomator.Until;
|
|||
|
||||
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 @@ import org.junit.runner.RunWith;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
public class AllAppsIconToHomeTest extends AbstractLauncherUiTest {
|
||||
|
||||
@Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testDragIcon_portrait() throws Throwable {
|
||||
|
|
|
@ -15,10 +15,8 @@ import android.view.MotionEvent;
|
|||
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 @@ import org.junit.runner.RunWith;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
public class ShortcutsLaunchTest extends AbstractLauncherUiTest {
|
||||
|
||||
@Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testAppLauncher_portrait() throws Exception {
|
||||
|
|
|
@ -15,10 +15,8 @@ import android.view.MotionEvent;
|
|||
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 @@ import org.junit.runner.RunWith;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
public class ShortcutsToHomeTest extends AbstractLauncherUiTest {
|
||||
|
||||
@Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher();
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testDragIcon_portrait() throws Throwable {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -22,19 +22,14 @@ import static org.junit.Assert.assertTrue;
|
|||
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;
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ import static org.junit.Assert.assertNotNull;
|
|||
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.LauncherAppWidgetProviderInfo;
|
|||
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;
|
||||
|
@ -136,8 +138,7 @@ public class AddConfigWidgetTest extends AbstractLauncherUiTest {
|
|||
}
|
||||
|
||||
private void setResult(boolean success) {
|
||||
|
||||
TestHelpers.getInstrumentation().getTargetContext().sendBroadcast(
|
||||
getInstrumentation().getTargetContext().sendBroadcast(
|
||||
WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class,
|
||||
success ? "clickOK" : "clickCancel"));
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.junit.Before;
|
|||
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 @@ import java.util.concurrent.TimeUnit;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
public class BindWidgetTest extends AbstractLauncherUiTest {
|
||||
|
||||
@Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind();
|
||||
|
||||
private ContentResolver mResolver;
|
||||
private AppWidgetManagerCompat mWidgetManager;
|
||||
|
||||
|
|
|
@ -60,10 +60,9 @@ import java.util.UUID;
|
|||
*/
|
||||
@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;
|
||||
|
|
|
@ -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 @@ public class LauncherActivityRule implements TestRule {
|
|||
* 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 {
|
||||
|
|
|
@ -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 @@ import java.io.IOException;
|
|||
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 class ShellCommandRule implements TestRule {
|
|||
*/
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 @@ public final class Background extends Home {
|
|||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package com.android.launcher3.tapl;
|
||||
|
||||
import androidx.test.uiautomator.UiObject2;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
|
@ -28,33 +26,28 @@ import androidx.annotation.NonNull;
|
|||
* 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);
|
||||
}
|
||||
}
|
|
@ -28,13 +28,6 @@ import android.util.Log;
|
|||
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 org.junit.Assert;
|
|||
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 @@ public final class LauncherInstrumentation {
|
|||
// 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 @@ public final class LauncherInstrumentation {
|
|||
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 @@ public final class LauncherInstrumentation {
|
|||
// 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 @@ public final class LauncherInstrumentation {
|
|||
} 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: {
|
||||
|
@ -309,6 +310,17 @@ public final class LauncherInstrumentation {
|
|||
return new Overview(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -18,18 +18,15 @@ package com.android.launcher3.tapl;
|
|||
|
||||
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,54 +34,10 @@ public final class Overview extends LauncherInstrumentation.VisibleContainer {
|
|||
}
|
||||
|
||||
@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.
|
||||
*
|
||||
|
|
|
@ -26,9 +26,9 @@ import androidx.test.uiautomator.Until;
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -38,11 +38,6 @@ public final class Workspace extends Home {
|
|||
mHotseat = launcher.waitForLauncherObject("hotseat");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LauncherInstrumentation.ContainerType getContainerType() {
|
||||
return LauncherInstrumentation.ContainerType.WORKSPACE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swipes up to All Apps.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue