diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2017-01-25 11:19:59 -0800 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2017-02-22 15:46:40 -0800 |
commit | d9843357d0fa8e4bbe0d42007bfdfebe37db7451 (patch) | |
tree | 51e42bda7af1c611d5fbcff242068e12493e8b68 /tests/src/com/android/launcher3/ui | |
parent | 9f0fa84439bb177ed48758b6d15a8e62c80f1bf4 (diff) | |
download | android_packages_apps_Trebuchet-d9843357d0fa8e4bbe0d42007bfdfebe37db7451.tar.gz android_packages_apps_Trebuchet-d9843357d0fa8e4bbe0d42007bfdfebe37db7451.tar.bz2 android_packages_apps_Trebuchet-d9843357d0fa8e4bbe0d42007bfdfebe37db7451.zip |
Adding some tests for request pin shortcut/widget flow
Bug: 33584624
Change-Id: I49df36f60d2ae071b9d2c77c9c3300e010cd3bb9
Diffstat (limited to 'tests/src/com/android/launcher3/ui')
7 files changed, 297 insertions, 39 deletions
diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java index 3f77bfdcd..936175087 100644 --- a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java +++ b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java @@ -22,6 +22,7 @@ public class AllAppsIconToHomeTest extends LauncherInstrumentationTestCase { @Override protected void setUp() throws Exception { super.setUp(); + setDefaultLauncher(); mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext) .getActivityList("com.android.settings", Process.myUserHandle()).get(0); diff --git a/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java b/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java index 4bc40c68f..1ed4a240e 100644 --- a/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java +++ b/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java @@ -15,10 +15,14 @@ */ package com.android.launcher3.ui; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Point; import android.os.ParcelFileDescriptor; import android.os.Process; @@ -46,16 +50,24 @@ import com.android.launcher3.testcomponent.AppWidgetNoConfig; import com.android.launcher3.testcomponent.AppWidgetWithConfig; import com.android.launcher3.util.ManagedProfileHeuristic; +import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; import java.util.Locale; import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * Base class for all instrumentation tests providing various utility methods. */ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { + public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10); + public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5; + public static final long DEFAULT_UI_TIMEOUT = 3000; public static final long DEFAULT_WORKER_TIMEOUT_SECS = 5; @@ -89,11 +101,14 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { * Starts the launcher activity in the target package and returns the Launcher instance. */ protected Launcher startLauncher() { - Intent homeIntent = new Intent(Intent.ACTION_MAIN) + return (Launcher) getInstrumentation().startActivitySync(getHomeIntent()); + } + + protected Intent getHomeIntent() { + return new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) .setPackage(mTargetPackage) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - return (Launcher) getInstrumentation().startActivitySync(homeIntent); } /** @@ -104,16 +119,31 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { if (mTargetContext.getPackageManager().checkPermission( mTargetPackage, android.Manifest.permission.BIND_APPWIDGET) != PackageManager.PERMISSION_GRANTED) { - ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation().executeShellCommand( - "appwidget grantbind --package " + mTargetPackage); - // Read the input stream fully. - FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); - while (fis.read() != -1); - fis.close(); + runShellCommand("appwidget grantbind --package " + mTargetPackage); } } /** + * Sets the target launcher as default launcher. + */ + protected void setDefaultLauncher() throws IOException { + ActivityInfo launcher = mTargetContext.getPackageManager() + .queryIntentActivities(getHomeIntent(), 0).get(0).activityInfo; + runShellCommand("cmd package set-home-activity " + + new ComponentName(launcher.packageName, launcher.name).flattenToString()); + } + + protected void runShellCommand(String command) throws IOException { + ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation() + .executeShellCommand(command); + + // Read the input stream fully. + FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + while (fis.read() != -1); + fis.close(); + } + + /** * Opens all apps and returns the recycler view */ protected UiObject2 openAllApps() { @@ -285,4 +315,35 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { String name = mTargetContext.getResources().getResourceEntryName(id); return By.res(mTargetPackage, name); } + + + /** + * Broadcast receiver which blocks until the result is received. + */ + public class BlockingBroadcastReceiver extends BroadcastReceiver { + + private final CountDownLatch latch = new CountDownLatch(1); + private Intent mIntent; + + public BlockingBroadcastReceiver(String action) { + mTargetContext.registerReceiver(this, new IntentFilter(action)); + } + + @Override + public void onReceive(Context context, Intent intent) { + mIntent = intent; + latch.countDown(); + } + + public Intent blockingGetIntent() throws InterruptedException { + latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS); + mTargetContext.unregisterReceiver(this); + return mIntent; + } + + public Intent blockingGetExtraIntent() throws InterruptedException { + Intent intent = blockingGetIntent(); + return intent == null ? null : (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT); + } + } } diff --git a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java b/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java index c6828f064..ee3a62803 100644 --- a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java +++ b/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java @@ -25,6 +25,7 @@ public class ShortcutsLaunchTest extends LauncherInstrumentationTestCase { @Override protected void setUp() throws Exception { super.setUp(); + setDefaultLauncher(); mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext) .getActivityList("com.android.settings", Process.myUserHandle()).get(0); diff --git a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java b/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java index d573eeaec..061e86530 100644 --- a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java +++ b/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java @@ -25,6 +25,7 @@ public class ShortcutsToHomeTest extends LauncherInstrumentationTestCase { @Override protected void setUp() throws Exception { super.setUp(); + setDefaultLauncher(); mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext) .getActivityList("com.android.settings", Process.myUserHandle()).get(0); diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java index 7cbd29283..0b4e34f94 100644 --- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java @@ -18,10 +18,7 @@ package com.android.launcher3.ui.widget; import android.app.Activity; import android.app.Application; import android.appwidget.AppWidgetManager; -import android.content.BroadcastReceiver; -import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; import android.test.suitebuilder.annotation.LargeTest; @@ -41,8 +38,6 @@ import com.android.launcher3.util.Wait; import com.android.launcher3.widget.WidgetCell; import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; /** * Test to verify widget configuration is properly shown. @@ -50,9 +45,6 @@ import java.util.concurrent.TimeUnit; @LargeTest public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { - public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10); - public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5; - private LauncherAppWidgetProviderInfo mWidgetInfo; private SimpleActivityMonitor mActivityMonitor; private MainThreadExecutor mMainThreadExecutor; @@ -69,6 +61,8 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { .registerActivityLifecycleCallbacks(mActivityMonitor); mMainThreadExecutor = new MainThreadExecutor(); mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext); + + grantWidgetPermission(); } @Override @@ -126,12 +120,11 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { // Verify that the widget id is valid and bound assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId)); + setResult(acceptConfig); if (acceptConfig) { - setResult(Activity.RESULT_OK); assertTrue(Wait.atMost(new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT)); assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId)); } else { - setResult(Activity.RESULT_CANCELED); // Verify that the widget id is deleted. assertTrue(Wait.atMost(new Condition() { @Override @@ -142,10 +135,11 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { } } - private void setResult(int resultCode) { - String action = WidgetConfigActivity.class.getName() + WidgetConfigActivity.SUFFIX_FINISH; + private void setResult(boolean success) { + getInstrumentation().getTargetContext().sendBroadcast( - new Intent(action).putExtra(WidgetConfigActivity.EXTRA_CODE, resultCode)); + WidgetConfigActivity.getCommandIntent(WidgetConfigActivity.class, + success ? "clickOK" : "clickCancel")); } /** @@ -185,28 +179,17 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { /** * Broadcast receiver for receiving widget config activity status. */ - private class WidgetConfigStartupMonitor extends BroadcastReceiver { - - private final CountDownLatch latch = new CountDownLatch(1); - private Intent mIntent; + private class WidgetConfigStartupMonitor extends BlockingBroadcastReceiver { - WidgetConfigStartupMonitor() { - getInstrumentation().getTargetContext().registerReceiver(this, - new IntentFilter(WidgetConfigActivity.class.getName())); - } - - @Override - public void onReceive(Context context, Intent intent) { - mIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT); - latch.countDown(); + public WidgetConfigStartupMonitor() { + super(WidgetConfigActivity.class.getName()); } public int getWidgetId() throws InterruptedException { - latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS); - getInstrumentation().getTargetContext().unregisterReceiver(this); - assertNotNull(mIntent); - assertEquals(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, mIntent.getAction()); - int widgetId = mIntent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, + Intent intent = blockingGetExtraIntent(); + assertNotNull(intent); + assertEquals(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE, intent.getAction()); + int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, LauncherAppWidgetInfo.NO_ID); assertNotSame(widgetId, LauncherAppWidgetInfo.NO_ID); return widgetId; diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java index b7e1ca903..3c92c578d 100644 --- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java @@ -41,6 +41,7 @@ public class AddWidgetTest extends LauncherInstrumentationTestCase { @Override protected void setUp() throws Exception { super.setUp(); + grantWidgetPermission(); widgetInfo = findWidgetProvider(false /* hasConfigureScreen */); } diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java new file mode 100644 index 000000000..5ef5ec1c3 --- /dev/null +++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2017 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.widget; + +import android.app.Activity; +import android.app.Application; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.content.Intent; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.Until; +import android.test.suitebuilder.annotation.LargeTest; +import android.view.View; + +import com.android.launcher3.ItemInfo; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppWidgetInfo; +import com.android.launcher3.LauncherSettings.Favorites; +import com.android.launcher3.MainThreadExecutor; +import com.android.launcher3.R; +import com.android.launcher3.ShortcutInfo; +import com.android.launcher3.Utilities; +import com.android.launcher3.Workspace.ItemOperator; +import com.android.launcher3.shortcuts.ShortcutKey; +import com.android.launcher3.testcomponent.AppWidgetNoConfig; +import com.android.launcher3.testcomponent.AppWidgetWithConfig; +import com.android.launcher3.testcomponent.RequestPinItemActivity; +import com.android.launcher3.ui.LauncherInstrumentationTestCase; +import com.android.launcher3.util.Condition; +import com.android.launcher3.util.SimpleActivityMonitor; +import com.android.launcher3.util.Wait; +import com.android.launcher3.widget.WidgetCell; + +import java.util.UUID; +import java.util.concurrent.Callable; + +/** + * Test to verify pin item request flow. + */ +@LargeTest +public class RequestPinItemTest extends LauncherInstrumentationTestCase { + + private SimpleActivityMonitor mActivityMonitor; + private MainThreadExecutor mMainThreadExecutor; + + private String mCallbackAction; + private String mShortcutId; + private int mAppWidgetId; + + @Override + protected void setUp() throws Exception { + super.setUp(); + grantWidgetPermission(); + setDefaultLauncher(); + + mActivityMonitor = new SimpleActivityMonitor(); + ((Application) getInstrumentation().getTargetContext().getApplicationContext()) + .registerActivityLifecycleCallbacks(mActivityMonitor); + mMainThreadExecutor = new MainThreadExecutor(); + + mCallbackAction = UUID.randomUUID().toString(); + mShortcutId = UUID.randomUUID().toString(); + } + + @Override + protected void tearDown() throws Exception { + ((Application) getInstrumentation().getTargetContext().getApplicationContext()) + .unregisterActivityLifecycleCallbacks(mActivityMonitor); + super.tearDown(); + } + + public void testPinWidgetNoConfig() throws Throwable { + runTest("pinWidgetNoConfig", true, new ItemOperator() { + @Override + public boolean evaluate(ItemInfo info, View view) { + return info instanceof LauncherAppWidgetInfo && + ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId && + ((LauncherAppWidgetInfo) info).providerName.getClassName() + .equals(AppWidgetNoConfig.class.getName()); + } + }); + } + + public void testPinWidgetWithConfig() throws Throwable { + runTest("pinWidgetWithConfig", true, new ItemOperator() { + @Override + public boolean evaluate(ItemInfo info, View view) { + return info instanceof LauncherAppWidgetInfo && + ((LauncherAppWidgetInfo) info).appWidgetId == mAppWidgetId && + ((LauncherAppWidgetInfo) info).providerName.getClassName() + .equals(AppWidgetWithConfig.class.getName()); + } + }); + } + + + public void testPinWidgetShortcut() throws Throwable { + runTest("pinShortcut", false, new ItemOperator() { + @Override + public boolean evaluate(ItemInfo info, View view) { + return info instanceof ShortcutInfo && + info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT && + ShortcutKey.fromItemInfo(info).getId().equals(mShortcutId); + } + }); + } + + private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher) + throws Throwable { + if (!Utilities.isAtLeastO()) { + return; + } + lockRotation(true); + + clearHomescreen(); + startLauncher(); + + // Open all apps and wait for load complete + final UiObject2 appsContainer = openAllApps(); + assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT)); + + // Open Pin item activity + BlockingBroadcastReceiver openMonitor = new BlockingBroadcastReceiver( + RequestPinItemActivity.class.getName()); + scrollAndFind(appsContainer, By.text("Test Pin Item")).click(); + assertNotNull(openMonitor.blockingGetExtraIntent()); + + // Set callback + PendingIntent callback = PendingIntent.getBroadcast(mTargetContext, 0, + new Intent(mCallbackAction), PendingIntent.FLAG_ONE_SHOT); + mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent( + RequestPinItemActivity.class, "setCallback").putExtra( + RequestPinItemActivity.EXTRA_PARAM + "0", callback)); + + if (!isWidget) { + // Set shortcut id + mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent( + RequestPinItemActivity.class, "setShortcutId").putExtra( + RequestPinItemActivity.EXTRA_PARAM + "0", mShortcutId)); + } + + // call the requested method to start the flow + mTargetContext.sendBroadcast(RequestPinItemActivity.getCommandIntent( + RequestPinItemActivity.class, activityMethod)); + UiObject2 widgetCell = mDevice.wait( + Until.findObject(By.clazz(WidgetCell.class)), DEFAULT_ACTIVITY_TIMEOUT); + assertNotNull(widgetCell); + + // Accept confirmation: + BlockingBroadcastReceiver resultReceiver = new BlockingBroadcastReceiver(mCallbackAction); + mDevice.wait(Until.findObject(By.text(mTargetContext.getString( + R.string.place_automatically).toUpperCase())), DEFAULT_UI_TIMEOUT).click(); + Intent result = resultReceiver.blockingGetIntent(); + assertNotNull(result); + mAppWidgetId = result.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); + if (isWidget) { + assertNotSame(-1, mAppWidgetId); + } + + // Go back to home + mTargetContext.startActivity(getHomeIntent()); + assertTrue(Wait.atMost(new ItemSearchCondition(itemMatcher), DEFAULT_ACTIVITY_TIMEOUT)); + } + + /** + * Condition for for an item + */ + private class ItemSearchCondition extends Condition implements Callable<Boolean> { + + private final ItemOperator mOp; + + ItemSearchCondition(ItemOperator op) { + mOp = op; + } + + @Override + public boolean isTrue() throws Throwable { + return mMainThreadExecutor.submit(this).get(); + } + + @Override + public Boolean call() throws Exception { + // Find the resumed launcher + Launcher launcher = null; + for (Activity a : mActivityMonitor.resumed) { + if (a instanceof Launcher) { + launcher = (Launcher) a; + } + } + if (launcher == null) { + return false; + } + return launcher.getWorkspace().getFirstMatch(mOp) != null; + } + } +} |