summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2017-01-25 11:19:59 -0800
committerSunny Goyal <sunnygoyal@google.com>2017-02-22 15:46:40 -0800
commitd9843357d0fa8e4bbe0d42007bfdfebe37db7451 (patch)
tree51e42bda7af1c611d5fbcff242068e12493e8b68 /tests
parent9f0fa84439bb177ed48758b6d15a8e62c80f1bf4 (diff)
downloadandroid_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')
-rw-r--r--tests/AndroidManifest-common.xml18
-rw-r--r--tests/res/drawable/test_drawable_pin_item.xml38
-rw-r--r--tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java126
-rw-r--r--tests/src/com/android/launcher3/testcomponent/RequestPinItemActivity.java89
-rw-r--r--tests/src/com/android/launcher3/testcomponent/WidgetConfigActivity.java38
-rw-r--r--tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java1
-rw-r--r--tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java77
-rw-r--r--tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java1
-rw-r--r--tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java1
-rw-r--r--tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java45
-rw-r--r--tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java1
-rw-r--r--tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java210
12 files changed, 575 insertions, 70 deletions
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 24882aa89..0a2914772 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -23,7 +23,9 @@
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
- <receiver android:name="com.android.launcher3.testcomponent.AppWidgetNoConfig">
+ <receiver
+ android:name="com.android.launcher3.testcomponent.AppWidgetNoConfig"
+ android:label="No Config">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
@@ -31,7 +33,9 @@
android:resource="@xml/appwidget_no_config" />
</receiver>
- <receiver android:name="com.android.launcher3.testcomponent.AppWidgetWithConfig">
+ <receiver
+ android:name="com.android.launcher3.testcomponent.AppWidgetWithConfig"
+ android:label="With Config">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
@@ -45,5 +49,15 @@
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
+ <activity
+ android:name="com.android.launcher3.testcomponent.RequestPinItemActivity"
+ android:label="Test Pin Item"
+ android:icon="@drawable/test_drawable_pin_item">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/res/drawable/test_drawable_pin_item.xml b/tests/res/drawable/test_drawable_pin_item.xml
new file mode 100644
index 000000000..1d0725690
--- /dev/null
+++ b/tests/res/drawable/test_drawable_pin_item.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+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.
+-->
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+
+ <path
+ android:fillColor="#66000000"
+ android:pathData="M0,24a24,24 0 1,0 48,0a24,24 0 1,0 -48,0"/>
+ <path
+ android:fillColor="#FF1B5E20"
+ android:pathData="M2,24a22,22 0 1,0 44,0a22,22 0 1,0 -44,0"/>
+
+ <group
+ android:translateX="12"
+ android:translateY="12">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M16,12V4H17V2H7V4H8V12L6,14V16H11.2V22H12.8V16H18V14L16,12Z"/>
+ </group>
+</vector> \ No newline at end of file
diff --git a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
new file mode 100644
index 000000000..904590cb8
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
@@ -0,0 +1,126 @@
+/*
+ * 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.testcomponent;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Base activity with utility methods to help automate testing.
+ */
+public class BaseTestingActivity extends Activity implements View.OnClickListener {
+
+ public static final String SUFFIX_COMMAND = "-command";
+ public static final String EXTRA_METHOD = "method";
+ public static final String EXTRA_PARAM = "param_";
+
+ private static final int MARGIN_DP = 20;
+
+ private final String mAction = this.getClass().getName();
+
+ private LinearLayout mView;
+ private int mMargin;
+
+ private final BroadcastReceiver mCommandReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ handleCommand(intent);
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mMargin = Math.round(TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, MARGIN_DP, getResources().getDisplayMetrics()));
+ mView = new LinearLayout(this);
+ mView.setPadding(mMargin, mMargin, mMargin, mMargin);
+ mView.setOrientation(LinearLayout.VERTICAL);
+ setContentView(mView);
+
+ registerReceiver(mCommandReceiver, new IntentFilter(mAction + SUFFIX_COMMAND));
+ }
+
+ protected void addButton(String title, String method) {
+ Button button = new Button(this);
+ button.setText(title);
+ button.setTag(method);
+ button.setOnClickListener(this);
+
+ LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ lp.bottomMargin = mMargin;
+ mView.addView(button, lp);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ sendBroadcast(new Intent(mAction).putExtra(Intent.EXTRA_INTENT, getIntent()));
+ }
+
+ @Override
+ protected void onDestroy() {
+ unregisterReceiver(mCommandReceiver);
+ super.onDestroy();
+ }
+
+ @Override
+ public void onClick(View view) {
+ handleCommand(new Intent().putExtra(EXTRA_METHOD, (String) view.getTag()));
+ }
+
+ private void handleCommand(Intent cmd) {
+ String methodName = cmd.getStringExtra(EXTRA_METHOD);
+ try {
+ Method method = null;
+ for (Method m : this.getClass().getDeclaredMethods()) {
+ if (methodName.equals(m.getName()) &&
+ !Modifier.isStatic(m.getModifiers()) &&
+ Modifier.isPublic(m.getModifiers())) {
+ method = m;
+ break;
+ }
+ }
+ Object[] args = new Object[method.getParameterTypes().length];
+ Bundle extras = cmd.getExtras();
+ for (int i = 0; i < args.length; i++) {
+ args[i] = extras.get(EXTRA_PARAM + i);
+ }
+ method.invoke(this, args);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Intent getCommandIntent(Class<?> clazz, String method) {
+ return new Intent(clazz.getName() + SUFFIX_COMMAND)
+ .putExtra(EXTRA_METHOD, method);
+ }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/RequestPinItemActivity.java b/tests/src/com/android/launcher3/testcomponent/RequestPinItemActivity.java
new file mode 100644
index 000000000..c2dd2259d
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/RequestPinItemActivity.java
@@ -0,0 +1,89 @@
+/*
+ * 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.testcomponent;
+
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.IntentSender;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+
+/**
+ * Sample activity to request pinning an item.
+ */
+@TargetApi(26)
+public class RequestPinItemActivity extends BaseTestingActivity {
+
+ private PendingIntent mCallback = null;
+ private String mShortcutId;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addButton("Pin Shortcut", "pinShortcut");
+ addButton("Pin Widget without config ", "pinWidgetNoConfig");
+ addButton("Pin Widget with config", "pinWidgetWithConfig");
+ }
+
+ public void setCallback(PendingIntent callback) {
+ mCallback = callback;
+ }
+
+ public void setShortcutId(String id) {
+ mShortcutId = id;
+ }
+
+ public void pinShortcut() {
+ ShortcutManager sm = getSystemService(ShortcutManager.class);
+
+ // Generate icon
+ int r = sm.getIconMaxWidth() / 2;
+ Bitmap icon = Bitmap.createBitmap(r * 2, r * 2, Bitmap.Config.ARGB_8888);
+ Paint p = new Paint();
+ p.setColor(Color.RED);
+ new Canvas(icon).drawCircle(r, r, r, p);
+
+ ShortcutInfo info = new ShortcutInfo.Builder(this, mShortcutId)
+ .setIntent(getPackageManager().getLaunchIntentForPackage(getPackageName()))
+ .setIcon(Icon.createWithBitmap(icon))
+ .setShortLabel("Test shortcut")
+ .build();
+
+ IntentSender callback = mCallback == null ? null : mCallback.getIntentSender();
+ sm.requestPinShortcut(info, callback);
+ }
+
+ public void pinWidgetNoConfig() {
+ requestWidget(new ComponentName(this, AppWidgetNoConfig.class));
+ }
+
+ public void pinWidgetWithConfig() {
+ requestWidget(new ComponentName(this, AppWidgetWithConfig.class));
+ }
+
+ private void requestWidget(ComponentName cn) {
+ AppWidgetManager.getInstance(this).requestPinAppWidget(cn, mCallback);
+ }
+}
diff --git a/tests/src/com/android/launcher3/testcomponent/WidgetConfigActivity.java b/tests/src/com/android/launcher3/testcomponent/WidgetConfigActivity.java
index c0509bc24..d76ad0499 100644
--- a/tests/src/com/android/launcher3/testcomponent/WidgetConfigActivity.java
+++ b/tests/src/com/android/launcher3/testcomponent/WidgetConfigActivity.java
@@ -15,50 +15,30 @@
*/
package com.android.launcher3.testcomponent;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.os.Bundle;
/**
* Simple activity for widget configuration
*/
-public class WidgetConfigActivity extends Activity {
+public class WidgetConfigActivity extends BaseTestingActivity {
public static final String SUFFIX_FINISH = "-finish";
public static final String EXTRA_CODE = "code";
- public static final String EXTRA_INTENT = "intent";
-
- private final BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- WidgetConfigActivity.this.setResult(
- intent.getIntExtra(EXTRA_CODE, RESULT_CANCELED),
- (Intent) intent.getParcelableExtra(EXTRA_INTENT));
- WidgetConfigActivity.this.finish();
- }
- };
-
- private final String mAction = this.getClass().getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- registerReceiver(mFinishReceiver, new IntentFilter(mAction + SUFFIX_FINISH));
+ addButton("Cancel", "clickCancel");
+ addButton("OK", "clickOK");
}
- @Override
- protected void onResume() {
- super.onResume();
- sendBroadcast(new Intent(mAction).putExtra(Intent.EXTRA_INTENT, getIntent()));
+ public void clickCancel() {
+ setResult(RESULT_CANCELED);
+ finish();
}
- @Override
- protected void onDestroy() {
- unregisterReceiver(mFinishReceiver);
- super.onDestroy();
+ public void clickOK() {
+ setResult(RESULT_OK);
+ finish();
}
}
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;
+ }
+ }
+}